-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[DebugInfo] Emit debug info for witness tables #81661
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: release/6.2
Are you sure you want to change the base?
[DebugInfo] Emit debug info for witness tables #81661
Conversation
augusto2112
commented
May 21, 2025
- Explanation: This change emits debug info for witness tables passed into generic functions when a generic type is constrained to a protocol. This information is required for LLDB's generic expression evaluator to work in such functions.
- Scope: Debug info generation for functions inside generic types with constrained generics.
- Issues: rdar://104446865
- Original PR: [DebugInfo] Emit debug info for witness tables #79171 and Fix accidental deletion of part of test #81660 (where I fix a test which I accidentally removed)
- Risk: Medium, affects debug info generation for types with constrained generics, as well as emitting witness table refs for constrained generic paramenters.
- Testing: Added a new test, updated many existing tests to account for the new debug info.
- Reviewers: @adrian-prantl
This change emits debug info for witness tables passed into generic functions when a generic type is constrained to a protocol. This information is required for LLDB's generic expression evaluator to work in such functions. rdar://104446865 (cherry picked from commit 53d10f4c651934d1ac76b59f2f0ce2f52059f956)
Commit 53d10f4c651934d1ac76b59f2f0ce2f52059f956 accidentally deleted parts of move_function_dbginfo test. This just reintroduces the deleted lines (cherry picked from commit 2a755b8)
@swift-ci test |
@@ -1163,8 +1163,42 @@ class IRGenSILFunction : | |||
emitPackCountDebugVariable(Shape); | |||
} | |||
}); | |||
|
|||
if (auto *BGT = llvm::dyn_cast<BoundGenericType>(Ty)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can also nest non-generic nominals inside other generic nominals, eg
struct G<T> {
struct Inner {}
}
Eg, G<Int>.Inner
is not a BoundGenericType.
Just use getAnyNominal() instead
auto GE = Decl->getGenericEnvironment(); | ||
auto Requirements = BGT->getDecl() | ||
->getGenericEnvironment() | ||
->getGenericSignature() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can replace ->getGenericEnvironment()->getGenericSignature()
with ->getGenericSignature()
auto ProtocolDecl = Requirement.getProtocolDecl(); | ||
auto ConformingType = Requirement.getFirstType(); | ||
Type Archetype; | ||
if (auto GTPT = llvm::dyn_cast<GenericTypeParamType>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These conditionals are unnecessary. mapTypeIntoContext() takes a Type. Also, we use ConformingType->getAs<...>
and not llvm::dyn_cast<>(ConformingType.getPointer())
Archetype = GE->mapTypeIntoContext(GTPT); | ||
else if (auto DMT = llvm::dyn_cast<DependentMemberType>( | ||
ConformingType.getPointer())) | ||
Archetype = GE->mapTypeIntoContext(DMT); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure what this code is trying to do, but it's not correct. The types Requirement
are written with the generic signature of the BoundGenericType
. The GE
you have here on the other hand is a generic environment for the generic signature of the current function. So the mapTypeIntoContext() call will just return an ErrorType
.
Also, you're not looking at the generic arguments of the BGT here. Presumably it should do that?
llvm::SmallString<16> name; | ||
llvm::SmallString<16> displayName; | ||
if (auto DMT = | ||
llvm::dyn_cast<DependentMemberType>(interfaceType.getPointer())) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment about dyn_cast
name.append(member->getName().str()); | ||
displayName.append(member->getName().str()); | ||
}; | ||
name.append(DMT->getRootGenericParam()->getCanonicalName().str()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not just print the generic param as the base case of the recursion? (where member->getBase() is not another DMT)