Skip to content

Commit c650000

Browse files
[lldb][swift] Consider ProtocolWitness when demangling async functions
1 parent 6edeafc commit c650000

File tree

2 files changed

+90
-12
lines changed

2 files changed

+90
-12
lines changed

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

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,15 @@ static bool IsSwiftAsyncFunctionSymbol(swift::Demangle::NodePointer node) {
8282
return false;
8383
if (hasChild(node, Node::Kind::AsyncSuspendResumePartialFunction))
8484
return false;
85-
// Peel off a Static node. If it exists, there will be a single instance and a
86-
// top level node.
87-
if (node->getFirstChild()->getKind() == Node::Kind::Static)
88-
node = node->getFirstChild();
85+
86+
// Peel off a ProtocolWitness node. If it exists, there will be a single
87+
// instance, before Static nodes.
88+
if (NodePointer witness = childAtPath(node, Node::Kind::ProtocolWitness))
89+
node = witness;
90+
91+
// Peel off a Static node. If it exists, there will be a single instance.
92+
if (NodePointer static_node = childAtPath(node, Node::Kind::Static))
93+
node = static_node;
8994

9095
// Get the {Implicit, Explicit} Closure or Function node.
9196
// For nested closures in Swift, the demangle tree is inverted: the
@@ -203,14 +208,16 @@ SwiftLanguageRuntime::AreFuncletsOfSameAsyncFunction(
203208
!IsAnySwiftAsyncFunctionSymbol(node2))
204209
return FuncletComparisonResult::NotBothFunclets;
205210

206-
// Peel off Static nodes.
207-
NodePointer static_wrapper1 = childAtPath(node1, Node::Kind::Static);
208-
NodePointer static_wrapper2 = childAtPath(node2, Node::Kind::Static);
209-
if (static_wrapper1 || static_wrapper2) {
210-
if (!static_wrapper1 | !static_wrapper2)
211-
return FuncletComparisonResult::DifferentAsyncFunctions;
212-
node1 = static_wrapper1;
213-
node2 = static_wrapper2;
211+
// Peel off ProtocolWitnes/Static nodes, in this order.
212+
for (auto wrapper : {Node::Kind::ProtocolWitness, Node::Kind::Static}) {
213+
NodePointer wrapper1 = childAtPath(node1, wrapper);
214+
NodePointer wrapper2 = childAtPath(node2, wrapper);
215+
if (wrapper1 || wrapper2) {
216+
if (!wrapper1 | !wrapper2)
217+
return FuncletComparisonResult::DifferentAsyncFunctions;
218+
node1 = wrapper1;
219+
node2 = wrapper2;
220+
}
214221
}
215222

216223
// If there are closures involved, do the closure-specific comparison.
@@ -230,6 +237,11 @@ SwiftLanguageRuntime::AreFuncletsOfSameAsyncFunction(
230237
// Otherwise, find the corresponding function and compare the two.
231238
NodePointer function1 = childAtPath(node1, Node::Kind::Function);
232239
NodePointer function2 = childAtPath(node2, Node::Kind::Function);
240+
241+
// If we fail to find a function node, conservatively fail.
242+
if (!function1 || !function2)
243+
return FuncletComparisonResult::NotBothFunclets;
244+
233245
return Node::deepEquals(function1, function2)
234246
? FuncletComparisonResult::SameAsyncFunction
235247
: FuncletComparisonResult::DifferentAsyncFunctions;

lldb/unittests/Symbol/TestSwiftDemangler.cpp

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,22 @@ static constexpr auto AreFuncletsOfSameAsyncFunction = [](StringRef name1,
2222

2323
using FuncletComparisonResult = SwiftLanguageRuntime::FuncletComparisonResult;
2424

25+
/// Helpful printer for the tests.
26+
namespace lldb_private {
27+
std::ostream &operator<<(std::ostream &os,
28+
const FuncletComparisonResult &result) {
29+
switch (result) {
30+
case FuncletComparisonResult::NotBothFunclets:
31+
return os << "NotBothFunclets";
32+
case FuncletComparisonResult::SameAsyncFunction:
33+
return os << "SameAsyncFunction";
34+
case FuncletComparisonResult::DifferentAsyncFunctions:
35+
return os << "DifferentAsyncFunctions";
36+
}
37+
return os << "FuncletComparisonResult invalid enumeration";
38+
}
39+
} // namespace lldb_private
40+
2541
/// Checks that all names in \c funclets belong to the same function.
2642
static void CheckGroupOfFuncletsFromSameFunction(ArrayRef<StringRef> funclets) {
2743
for (StringRef funclet1 : funclets)
@@ -140,6 +156,30 @@ TEST(TestSwiftDemangleAsyncNames, BasicAsync) {
140156
// }(10)
141157
// print(await another_explicit_inside_implicit_closure)
142158
//}
159+
// protocol RandomNumberGenerator {
160+
// func random(in range: ClosedRange<Int>) async -> Int
161+
// static func static_random() async -> Int
162+
// }
163+
// class Generator: RandomNumberGenerator {
164+
// func random(in range: ClosedRange<Int>) async -> Int {
165+
// try? await Task.sleep(for: .milliseconds(500))
166+
// return Int.random(in: range)
167+
// }
168+
// static func static_random() async -> Int {
169+
// print("hello")
170+
// try? await Task.sleep(for: .milliseconds(500))
171+
// print("hello")
172+
// return 42
173+
// }
174+
// }
175+
// func doMath<RNG: RandomNumberGenerator>(with rng: RNG) async {
176+
// let x = await rng.random(in: 0...100)
177+
// print("X is \(x)")
178+
// let y = await rng.random(in: 101...200)
179+
// print("Y is \(y)")
180+
// print("The magic number is \(x + y)")
181+
// }
182+
143183

144184
TEST(TestSwiftDemangleAsyncNames, ClosureAsync) {
145185
// These are all async closures
@@ -193,6 +233,28 @@ TEST(TestSwiftDemangleAsyncNames, ClosureAsync) {
193233
"$s1a9sayHello2yyYaFSiyYaYbcfu_S2iYaXEfU0_TQ1_",
194234
"$s1a9sayHello2yyYaFSiyYaYbcfu_S2iYaXEfU0_TY2_",
195235
};
236+
SmallVector<StringRef> witness_funclets = {
237+
"$s1a9GeneratorCAA012RandomNumberA0A2aDP6random2inSiSNySiG_tYaFTW",
238+
"$s1a9GeneratorCAA012RandomNumberA0A2aDP6random2inSiSNySiG_tYaFTWTQ0_",
239+
};
240+
SmallVector<StringRef> actual_funclets = {
241+
"$s1a9GeneratorC6random2inSiSNySiG_tYaF",
242+
"$s1a9GeneratorC6random2inSiSNySiG_tYaFTY0_",
243+
"$s1a9GeneratorC6random2inSiSNySiG_tYaFTQ1_",
244+
"$s1a9GeneratorC6random2inSiSNySiG_tYaFTY2_",
245+
"$s1a9GeneratorC6random2inSiSNySiG_tYaFTY3_",
246+
};
247+
SmallVector<StringRef> static_witness_funclets = {
248+
"$s1a9GeneratorCAA012RandomNumberA0A2aDP13static_randomSiyYaFZTW",
249+
"$s1a9GeneratorCAA012RandomNumberA0A2aDP13static_randomSiyYaFZTWTQ0_",
250+
};
251+
SmallVector<StringRef> static_actual_funclets = {
252+
"$s1a9GeneratorC13static_randomSiyYaFZ",
253+
"$s1a9GeneratorC13static_randomSiyYaFZTY0_",
254+
"$s1a9GeneratorC13static_randomSiyYaFZTQ1_",
255+
"$s1a9GeneratorC13static_randomSiyYaFZTY2_",
256+
"$s1a9GeneratorC13static_randomSiyYaFZTY3_",
257+
};
196258

197259
SmallVector<ArrayRef<StringRef>, 0> funclet_groups = {
198260
nested1_funclets,
@@ -203,6 +265,10 @@ TEST(TestSwiftDemangleAsyncNames, ClosureAsync) {
203265
implicit_closure_inside_explicit_closure,
204266
explicit_closure_inside_implicit_closure,
205267
another_explicit_closure_inside_implicit_closure,
268+
witness_funclets,
269+
actual_funclets,
270+
static_witness_funclets,
271+
static_actual_funclets,
206272
};
207273

208274
for (ArrayRef<StringRef> funclet_group : funclet_groups)

0 commit comments

Comments
 (0)