Skip to content

Commit 162ee50

Browse files
Merge pull request #10247 from felipepiovezan/felipe/funclet_number
2 parents 47a4709 + 9cb2811 commit 162ee50

File tree

3 files changed

+78
-0
lines changed

3 files changed

+78
-0
lines changed

lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,14 @@ class SwiftLanguageRuntime : public LanguageRuntime {
181181
/// function, or suspend resume partial function symbol.
182182
static bool IsAnySwiftAsyncFunctionSymbol(swift::Demangle::NodePointer node);
183183

184+
/// If node is a Swift async funclet, return its funclet number.
185+
static std::optional<uint64_t>
186+
GetFuncletNumber(swift::Demangle::NodePointer node);
187+
188+
/// If name is a Swift async funclet, return its funclet number.
189+
static std::optional<uint64_t>
190+
GetFuncletNumber(llvm::StringRef name);
191+
184192
/// Return the async context address using the target's specific register.
185193
static lldb::addr_t GetAsyncContext(RegisterContext *regctx);
186194

lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeNames.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,43 @@ AreFuncletsOfSameAsyncClosure(swift::Demangle::NodePointer closure1,
136136
return Node::deepEquals(closure1_function, closure2_function);
137137
}
138138

139+
std::optional<uint64_t>
140+
SwiftLanguageRuntime::GetFuncletNumber(swift::Demangle::NodePointer node) {
141+
if (!node)
142+
return {};
143+
NodePointer node_id =
144+
childAtPath(node, {Node::Kind::AsyncSuspendResumePartialFunction,
145+
Node::Kind::Number});
146+
if (!node_id)
147+
node_id = childAtPath(node, {Node::Kind::AsyncAwaitResumePartialFunction,
148+
Node::Kind::Number});
149+
if (node_id) {
150+
if (node_id->hasIndex())
151+
return node_id->getIndex();
152+
153+
// This should never happen, log it if it does:
154+
std::string node_dump = getNodeTreeAsString(node);
155+
LLDB_LOGF(GetLog(LLDBLog::Demangle),
156+
"%s::Found a number node without a number:\n%s", __FUNCTION__,
157+
node_dump.c_str());
158+
return {};
159+
}
160+
161+
// If this is an async function and there was no number, then this is an entry
162+
// funclet. Assign it number 0.
163+
if (SwiftLanguageRuntime::IsAnySwiftAsyncFunctionSymbol(node))
164+
return 0;
165+
return {};
166+
}
167+
168+
std::optional<uint64_t>
169+
SwiftLanguageRuntime::GetFuncletNumber(llvm::StringRef name) {
170+
using namespace swift::Demangle;
171+
Context ctx;
172+
NodePointer node = SwiftLanguageRuntime::DemangleSymbolAsNode(name, ctx);
173+
return GetFuncletNumber(node);
174+
}
175+
139176
SwiftLanguageRuntime::FuncletComparisonResult
140177
SwiftLanguageRuntime::AreFuncletsOfSameAsyncFunction(llvm::StringRef name1,
141178
llvm::StringRef name2) {

lldb/unittests/Symbol/TestSwiftDemangler.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
#include "gtest/gtest.h"
22

33
#include "Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.h"
4+
#include "llvm/ADT/Sequence.h"
45

56
using namespace lldb;
67
using namespace lldb_private;
78
using namespace llvm;
89
static constexpr auto IsSwiftMangledName =
910
SwiftLanguageRuntime::IsSwiftMangledName;
11+
static constexpr auto GetFuncletNumber = [](StringRef name) {
12+
return SwiftLanguageRuntime::GetFuncletNumber(name);
13+
};
1014
static constexpr auto IsAnySwiftAsyncFunctionSymbol = [](StringRef name) {
1115
return SwiftLanguageRuntime::IsAnySwiftAsyncFunctionSymbol(name);
1216
};
@@ -47,6 +51,13 @@ CheckGroupOfFuncletsFromDifferentFunctions(ArrayRef<StringRef> funclets1,
4751
}
4852
}
4953

54+
/// Check that funclets contain a sequence of funclet names whose "async
55+
/// numbers" go from 0 to size(funclets).
56+
static void CheckFuncletNumbersAreARange(ArrayRef<StringRef> funclets) {
57+
for (auto idx : llvm::seq<int>(0, funclets.size()))
58+
EXPECT_EQ(idx, GetFuncletNumber(funclets[idx]));
59+
}
60+
5061
TEST(TestSwiftDemangleAsyncNames, BasicAsync) {
5162
// "sayBasic" == a basic async function
5263
// "sayGeneric" == a generic async function
@@ -71,6 +82,8 @@ TEST(TestSwiftDemangleAsyncNames, BasicAsync) {
7182
CheckGroupOfFuncletsFromSameFunction(basic_funclets);
7283
CheckGroupOfFuncletsFromSameFunction(generic_funclets);
7384
CheckGroupOfFuncletsFromDifferentFunctions(basic_funclets, generic_funclets);
85+
CheckFuncletNumbersAreARange(basic_funclets);
86+
CheckFuncletNumbersAreARange(generic_funclets);
7487
}
7588

7689
TEST(TestSwiftDemangleAsyncNames, ClosureAsync) {
@@ -127,6 +140,10 @@ TEST(TestSwiftDemangleAsyncNames, ClosureAsync) {
127140
nested2_funclets_top_not_async);
128141
CheckGroupOfFuncletsFromDifferentFunctions(nested2_funclets2,
129142
nested2_funclets_top_not_async);
143+
CheckFuncletNumbersAreARange(nested1_funclets);
144+
CheckFuncletNumbersAreARange(nested2_funclets1);
145+
CheckFuncletNumbersAreARange(nested2_funclets2);
146+
CheckFuncletNumbersAreARange(nested2_funclets_top_not_async);
130147
}
131148

132149
TEST(TestSwiftDemangleAsyncNames, StaticAsync) {
@@ -153,4 +170,20 @@ TEST(TestSwiftDemangleAsyncNames, StaticAsync) {
153170
"$s1a8sayBasicyySSYaF", "$s1a8sayBasicyySSYaFTY0_"};
154171
CheckGroupOfFuncletsFromDifferentFunctions(static_async_funclets,
155172
other_funclets);
173+
CheckFuncletNumbersAreARange(static_async_funclets);
174+
}
175+
176+
TEST(TestSwiftDemangleAsyncNames, NonAsync) {
177+
// func factorial(_ n:Int) -> Int {
178+
{
179+
StringRef func = "$s4test9factorialyS2iF";
180+
EXPECT_EQ(GetFuncletNumber(func), std::nullopt);
181+
}
182+
183+
// func factorial(_ n:Int) async -> Int {
184+
// func inner_factorial(_ n:Int) -> Int {
185+
{
186+
StringRef func = "$s4test9factorialyS2iYaF06inner_B0L_yS2iF";
187+
EXPECT_EQ(GetFuncletNumber(func), std::nullopt);
188+
}
156189
}

0 commit comments

Comments
 (0)