-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Introduce a DWARFImporter delegate that can look up clang::Decls by name #26493
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
Conversation
test with apple/swift-lldb#1848 |
Build failed |
test with apple/swift-lldb#1848 |
test with apple/swift-lldb#1848 |
1 similar comment
test with apple/swift-lldb#1848 |
test with apple/swift-lldb#1848 |
d58d4a1
to
d8accb8
Compare
test with apple/swift-lldb#1848 |
…ame. Traditionally a serialized binary Swift module (as used in debug info) can only be imported if all of its Clang dependencies can be imported *from source*. - Swift's ClangImporter imports Clang modules by converting Clang AST types into Swift AST types. - LLDB knows how to find Clang types in DWARF or other debug info and can synthesize a Clang AST from that information. This patch introduces a DWARFImporter delegate that is implemented by LLDB to connect these two components. With this, a Clang type can be found (by name) in the debug info and handed over to ClangImporter to create a Swift type from it. This path has lower fidelity than importing the Clang modules from source, since it is missing out on Swiftication annotations and other metadata that is not serialized in DWARF, but it's invaluable as a fallback mechanism for the debugger when source code for the Clang modules isn't available or the modules are otherwise not buildable. rdar://problem/49233932
test with apple/swift-lldb#1848 |
@@ -58,6 +60,30 @@ class ClangModuleLoader : public ModuleLoader { | |||
const DeclContext *overlayDC, | |||
const DeclContext *importedDC) = 0; | |||
|
|||
/// Look for declarations associated with the given name. |
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 virtual methods are necessary to break a cyclic dependency on Linux.
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.
Can you explain further? I'm not sure why there'd be a cycle.
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.
The problem only existed on Linux, and no amount of duplicating llink libraries in the CMakeLists would make it go away. Part of the problem was that ASTDemangler in libAST.a had an explicit cast and a method call to DWARFImporter and libDWARFImporter.a in turn depends on libAST. I do not understand why this wasn't also a problem with ClangImporter, which effectively does the same thing. If you are concerned about the interface/performance I can try a little harder, but I also think having a common interface in the common base class of ClangImporter and DWARFImporter is actually good.
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.
ASTDemangler definitely should not be calling DWARFImporter directly, and I'm sorry I missed that part. Let's come up with a better way to let DWARFImporter intervene in looking up Clang types.
/// | ||
/// If there is no Clang module loader, returns a null pointer. | ||
/// The loader is owned by the AST context. | ||
ClangModuleLoader *getDWARFModuleLoader() const; |
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.
Can you get rid of this? The Clang importer is special because the Swift compiler has to use it for other things. It would definitely be bad if we had to start special-casing the DWARF loader throughout the compiler as well.
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.
The only use of this method is in ASTDemangler.cpp in ASTBuilder::findForeignTypeDecl()
, which tries the DWARFImporter after the ClangImporter failed. We could changing ASTContext::getClangModuleLoader()
to return a list of ClangModuleLoaders sorted by the order in which they should be queried. Would that be better?
/// Clang AST to ClangImporter to import the type into Swift. | ||
class DWARFImporterDelegate { | ||
public: | ||
virtual ~DWARFImporterDelegate() {} |
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.
Nitpick: = default
allows a tiny bit more optimization in some cases.
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.
ClangImporter::lookupTypeDecl(StringRef rawName, ClangTypeKind kind, | ||
llvm::function_ref<void(TypeDecl*)> receiver) { | ||
static Optional<ClangTypeKind> | ||
getClangTypeKindForNodeKind(Demangle::Node::Kind kind) { |
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 really don't like moving this. Why is it the importer's responsibility to resolve manglings?
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.
This is basically based on a misunderstanding on my end that I since dicovered and I can revert this change. Because of how ClangTypeKind folds both enums and structs into ClangTypeKind::Tag I was afraid the we'd be loosing information that could make the type search in DWARF more accurate. Later I discovered that structs, unions and many enums are all mangled as structs anyway, so this point doesn't hold any more. I'll prepare a patch to undo this.
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.
enum class ClangTypeKind {
Typedef,
ObjCClass = Typedef,
/// Structs, enums, and unions.
Tag,
ObjCProtocol,
}
Looks like we would be loosing the ability to distinguish between typedefs and ObjC classes, but that may not be such a big deal.
@@ -13,33 +13,37 @@ | |||
#include "swift/DWARFImporter/DWARFImporter.h" | |||
#include "swift/AST/ASTContext.h" | |||
#include "swift/AST/Module.h" | |||
#include "clang/CodeGen/ObjectFilePCHContainerOperations.h" | |||
#include "clang/Frontend/FrontendActions.h" | |||
#include "../ClangImporter/ImporterImpl.h" |
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.
This is very questionable. ClangImporter::Implementation isn't designed for reuse; the distribution of information between ClangImporter and ClangImporter::Implementation is basically "whatever's most convenient". If we need a common base class, let's factor that out and put it in the include/ folder.
@@ -178,9 +179,9 @@ class ClangImporter final : public ClangModuleLoader { | |||
/// Note that this method does no filtering. If it finds the type in a loaded | |||
/// module, it returns it. This is intended for use in reflection / debugging | |||
/// contexts where access is not a problem. | |||
void lookupRelatedEntity(StringRef clangName, ClangTypeKind kind, |
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 is it okay to drop the "kind" parameter?
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.
Because it was not used by the function.
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.
This was deliberately an interface designed to handle arbitrary mangled names, even though we're not using the kind
for anything yet.
Now that I see that the DWARF importer is injecting decls into the real Clang importer anyway (which makes sense because you want them all in one clang::ASTContext), maybe a new module loader wasn't ever the way to go. Maybe it'd be better for the Clang importer to have a DebugClient like the ASTContext does. |
I think that this is doable. We can move DWARFImporter's mode of pretending it can import anything into a DWARFImporterDelegate callback handled by ClangImporter that only succeeds when a DWARFImporterDelegate is installed (and potentially actually checks whether we have DWARF for that module...). I'll go ahead and try this! |
Revert some unnecessary changes from #26493
-> #26648 Turned out fairly clean. |
Traditionally a serialized binary Swift module (as used in debug info)
can only be imported if all of its Clang dependencies can be imported
from source.
Swift's ClangImporter imports Clang modules by converting Clang AST
types into Swift AST types.
LLDB knows how to find Clang types in DWARF or other debug info and
can synthesize a Clang AST from that information.
This patch introduces a DWARFImporter delegate that is implemented by
LLDB to connect these two components. With this, a Clang type can be
found (by name) in the debug info and handed over to ClangImporter to
create a Swift type from it. This path has lower fidelity than
importing the Clang modules from source, since it is missing out on
Swiftication annotations and other metadata that is not serialized in
DWARF, but it's invaluable as a fallback mechanism for the debugger
when source code for the Clang modules isn't available or the modules
are otherwise not buildable.
rdar://problem/49233932