Skip to content

Commit 206994c

Browse files
Merge pull request #26493 from adrian-prantl/49233932
Introduce a DWARFImporter delegate that can look up clang::Decls by name
2 parents 25ac8c0 + 9b045d5 commit 206994c

File tree

12 files changed

+261
-86
lines changed

12 files changed

+261
-86
lines changed

include/swift/AST/ASTContext.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -639,8 +639,10 @@ class ASTContext final {
639639
/// \param isClang \c true if this module loader is responsible for loading
640640
/// Clang modules, which are special-cased in some parts of the
641641
/// compiler.
642+
/// \param isDWARF \c true if this module loader can load Clang modules
643+
/// from DWARF.
642644
void addModuleLoader(std::unique_ptr<ModuleLoader> loader,
643-
bool isClang = false);
645+
bool isClang = false, bool isDWARF = false);
644646

645647
/// Load extensions to the given nominal type from the external
646648
/// module loaders.
@@ -683,6 +685,12 @@ class ASTContext final {
683685
/// The loader is owned by the AST context.
684686
ClangModuleLoader *getClangModuleLoader() const;
685687

688+
/// Retrieve the DWARF module loader for this ASTContext.
689+
///
690+
/// If there is no Clang module loader, returns a null pointer.
691+
/// The loader is owned by the AST context.
692+
ClangModuleLoader *getDWARFModuleLoader() const;
693+
686694
/// Asks every module loader to verify the ASTs it has loaded.
687695
///
688696
/// Does nothing in non-asserts (NDEBUG) builds.

include/swift/AST/ClangModuleLoader.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#define SWIFT_AST_CLANG_MODULE_LOADER_H
1515

1616
#include "swift/AST/ModuleLoader.h"
17+
#include "swift/Demangling/Demangle.h"
1718

1819
namespace clang {
1920
class ASTContext;
@@ -25,6 +26,7 @@ class Sema;
2526
namespace swift {
2627

2728
class DeclContext;
29+
class VisibleDeclConsumer;
2830

2931
class ClangModuleLoader : public ModuleLoader {
3032
private:
@@ -58,6 +60,30 @@ class ClangModuleLoader : public ModuleLoader {
5860
const DeclContext *overlayDC,
5961
const DeclContext *importedDC) = 0;
6062

63+
/// Look for declarations associated with the given name.
64+
///
65+
/// \param name The name we're searching for.
66+
virtual void lookupValue(DeclName name, VisibleDeclConsumer &consumer) {}
67+
68+
/// Look up a type declaration by its Clang name.
69+
///
70+
/// Note that this method does no filtering. If it finds the type in a loaded
71+
/// module, it returns it. This is intended for use in reflection / debugging
72+
/// contexts where access is not a problem.
73+
virtual void lookupTypeDecl(StringRef clangName, Demangle::Node::Kind kind,
74+
llvm::function_ref<void(TypeDecl *)> receiver) {}
75+
76+
/// Look up type a declaration synthesized by the Clang importer itself, using
77+
/// a "related entity kind" to determine which type it should be. For example,
78+
/// this can be used to find the synthesized error struct for an
79+
/// NS_ERROR_ENUM.
80+
///
81+
/// Note that this method does no filtering. If it finds the type in a loaded
82+
/// module, it returns it. This is intended for use in reflection / debugging
83+
/// contexts where access is not a problem.
84+
virtual void
85+
lookupRelatedEntity(StringRef clangName, StringRef relatedEntityKind,
86+
llvm::function_ref<void(TypeDecl *)> receiver) {}
6187
};
6288

6389
} // namespace swift

include/swift/AST/ModuleLoader.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ class ClangImporterOptions;
3535
class ClassDecl;
3636
class ModuleDecl;
3737
class NominalTypeDecl;
38+
class TypeDecl;
3839

3940
enum class KnownProtocolKind : uint8_t;
4041

include/swift/ClangImporter/ClangImporter.h

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ enum class ClangTypeKind {
7575
/// from Clang ASTs over to Swift ASTs.
7676
class ClangImporter final : public ClangModuleLoader {
7777
friend class ClangModuleUnit;
78+
friend class DWARFImporter;
7879

7980
public:
8081
class Implementation;
@@ -160,15 +161,15 @@ class ClangImporter final : public ClangModuleLoader {
160161
/// Look for declarations associated with the given name.
161162
///
162163
/// \param name The name we're searching for.
163-
void lookupValue(DeclName name, VisibleDeclConsumer &consumer);
164+
void lookupValue(DeclName name, VisibleDeclConsumer &consumer) override;
164165

165166
/// Look up a type declaration by its Clang name.
166167
///
167168
/// Note that this method does no filtering. If it finds the type in a loaded
168169
/// module, it returns it. This is intended for use in reflection / debugging
169170
/// contexts where access is not a problem.
170-
void lookupTypeDecl(StringRef clangName, ClangTypeKind kind,
171-
llvm::function_ref<void(TypeDecl*)> receiver);
171+
void lookupTypeDecl(StringRef clangName, Demangle::Node::Kind kind,
172+
llvm::function_ref<void(TypeDecl*)> receiver) override;
172173

173174
/// Look up type a declaration synthesized by the Clang importer itself, using
174175
/// a "related entity kind" to determine which type it should be. For example,
@@ -178,9 +179,9 @@ class ClangImporter final : public ClangModuleLoader {
178179
/// Note that this method does no filtering. If it finds the type in a loaded
179180
/// module, it returns it. This is intended for use in reflection / debugging
180181
/// contexts where access is not a problem.
181-
void lookupRelatedEntity(StringRef clangName, ClangTypeKind kind,
182-
StringRef relatedEntityKind,
183-
llvm::function_ref<void(TypeDecl*)> receiver);
182+
void
183+
lookupRelatedEntity(StringRef clangName, StringRef relatedEntityKind,
184+
llvm::function_ref<void(TypeDecl *)> receiver) override;
184185

185186
/// Look for textually included declarations from the bridging header.
186187
///

include/swift/DWARFImporter/DWARFImporter.h

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
#define SWIFT_DWARF_IMPORTER_H
1919

2020
#include "swift/AST/ClangModuleLoader.h"
21+
#include "swift/AST/Module.h"
22+
#include "swift/Demangling/Demangle.h"
2123

2224
namespace llvm {
2325
}
@@ -27,6 +29,25 @@ namespace clang {
2729

2830
namespace swift {
2931

32+
/// This interface is implemented by LLDB to serve as a fallback when Clang
33+
/// modules can't be imported from source in the debugger.
34+
///
35+
/// During compile time, ClangImporter-imported Clang modules are compiled with
36+
/// -gmodules, which emits a DWARF rendition of all types defined in the module
37+
/// into the .pcm file. On Darwin, these types can be collected by
38+
/// dsymutil. This delegate allows DWARFImporter to ask LLDB to look up a Clang
39+
/// type by name, synthesize a Clang AST from it. DWARFImporter then hands this
40+
/// Clang AST to ClangImporter to import the type into Swift.
41+
class DWARFImporterDelegate {
42+
public:
43+
virtual ~DWARFImporterDelegate() {}
44+
/// Perform a qualified lookup of a Clang type with this name.
45+
/// \param kind Only return results with this type kind.
46+
virtual void lookupValue(StringRef name,
47+
llvm::Optional<Demangle::Node::Kind> kind,
48+
SmallVectorImpl<clang::Decl *> &results) {}
49+
};
50+
3051
/// Class that imports Clang modules into Swift, mapping directly
3152
/// from Clang ASTs over to Swift ASTs.
3253
class DWARFImporter final : public ClangModuleLoader {
@@ -39,6 +60,7 @@ class DWARFImporter final : public ClangModuleLoader {
3960
Implementation &Impl;
4061

4162
DWARFImporter(ASTContext &ctx, const ClangImporterOptions &clangImporterOpts,
63+
std::unique_ptr<DWARFImporterDelegate> delegate,
4264
DependencyTracker *tracker);
4365

4466
public:
@@ -55,8 +77,8 @@ class DWARFImporter final : public ClangModuleLoader {
5577
/// \returns a new DWARF module importer, or null (with a diagnostic) if
5678
/// an error occurred.
5779
static std::unique_ptr<DWARFImporter>
58-
create(ASTContext &ctx,
59-
const ClangImporterOptions &importerOpts,
80+
create(ASTContext &ctx, const ClangImporterOptions &importerOpts,
81+
std::unique_ptr<DWARFImporterDelegate> delegate = {},
6082
DependencyTracker *tracker = nullptr);
6183

6284
DWARFImporter(const DWARFImporter &) = delete;
@@ -80,6 +102,17 @@ class DWARFImporter final : public ClangModuleLoader {
80102
ModuleDecl *
81103
loadModule(SourceLoc importLoc,
82104
ArrayRef<std::pair<Identifier, SourceLoc>> path) override;
105+
106+
ValueDecl *importDecl(clang::Decl *clangDecl);
107+
108+
void lookupValue(DeclName name, VisibleDeclConsumer &consumer) override {}
109+
/// Behaves like \p ClangImporter::lookupValue.
110+
void lookupValue(ModuleDecl::AccessPathTy accessPath, DeclName name,
111+
NLKind lookupKind, SmallVectorImpl<ValueDecl *> &results);
112+
/// Perform a qualified lookup of a Clang type with this name and only return
113+
/// results with the specified type kind.
114+
void lookupTypeDecl(StringRef rawName, Demangle::Node::Kind kind,
115+
llvm::function_ref<void(TypeDecl *)> receiver) override;
83116
bool
84117
isInOverlayModuleForImportedModule(const DeclContext *overlayDC,
85118
const DeclContext *importedDC) override;

lib/AST/ASTContext.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,9 @@ FOR_KNOWN_FOUNDATION_TYPES(CACHE_FOUNDATION_DECL)
255255
/// The module loader used to load Clang modules.
256256
ClangModuleLoader *TheClangModuleLoader = nullptr;
257257

258+
/// The module loader used to load Clang modules from DWARF.
259+
ClangModuleLoader *TheDWARFModuleLoader = nullptr;
260+
258261
/// Map from Swift declarations to raw comments.
259262
llvm::DenseMap<const Decl *, RawComment> RawComments;
260263

@@ -1446,10 +1449,13 @@ void ASTContext::addSearchPath(StringRef searchPath, bool isFramework,
14461449
}
14471450

14481451
void ASTContext::addModuleLoader(std::unique_ptr<ModuleLoader> loader,
1449-
bool IsClang) {
1450-
if (IsClang && !getImpl().TheClangModuleLoader)
1452+
bool IsClang, bool IsDwarf) {
1453+
if (IsClang && !IsDwarf && !getImpl().TheClangModuleLoader)
14511454
getImpl().TheClangModuleLoader =
14521455
static_cast<ClangModuleLoader *>(loader.get());
1456+
if (IsClang && IsDwarf && !getImpl().TheDWARFModuleLoader)
1457+
getImpl().TheDWARFModuleLoader =
1458+
static_cast<ClangModuleLoader *>(loader.get());
14531459

14541460
getImpl().ModuleLoaders.push_back(std::move(loader));
14551461
}
@@ -1493,6 +1499,10 @@ ClangModuleLoader *ASTContext::getClangModuleLoader() const {
14931499
return getImpl().TheClangModuleLoader;
14941500
}
14951501

1502+
ClangModuleLoader *ASTContext::getDWARFModuleLoader() const {
1503+
return getImpl().TheDWARFModuleLoader;
1504+
}
1505+
14961506
ModuleDecl *ASTContext::getLoadedModule(
14971507
ArrayRef<std::pair<Identifier, SourceLoc>> ModulePath) const {
14981508
assert(!ModulePath.empty());

lib/AST/ASTDemangler.cpp

Lines changed: 26 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,14 @@
2222
#include "swift/AST/ASTDemangler.h"
2323

2424
#include "swift/AST/ASTContext.h"
25+
#include "swift/AST/ClangModuleLoader.h"
2526
#include "swift/AST/Decl.h"
2627
#include "swift/AST/GenericSignature.h"
2728
#include "swift/AST/GenericSignatureBuilder.h"
2829
#include "swift/AST/Module.h"
2930
#include "swift/AST/NameLookup.h"
3031
#include "swift/AST/Type.h"
3132
#include "swift/AST/Types.h"
32-
#include "swift/ClangImporter/ClangImporter.h"
3333
#include "swift/Demangling/Demangler.h"
3434
#include "swift/Demangling/ManglingMacros.h"
3535

@@ -1023,31 +1023,14 @@ ASTBuilder::findTypeDecl(DeclContext *dc,
10231023
return result;
10241024
}
10251025

1026-
static Optional<ClangTypeKind>
1027-
getClangTypeKindForNodeKind(Demangle::Node::Kind kind) {
1028-
switch (kind) {
1029-
case Demangle::Node::Kind::Protocol:
1030-
return ClangTypeKind::ObjCProtocol;
1031-
case Demangle::Node::Kind::Class:
1032-
return ClangTypeKind::ObjCClass;
1033-
case Demangle::Node::Kind::TypeAlias:
1034-
return ClangTypeKind::Typedef;
1035-
case Demangle::Node::Kind::Structure:
1036-
case Demangle::Node::Kind::Enum:
1037-
return ClangTypeKind::Tag;
1038-
default:
1039-
return None;
1040-
}
1041-
}
1042-
1043-
GenericTypeDecl *
1044-
ASTBuilder::findForeignTypeDecl(StringRef name,
1045-
StringRef relatedEntityKind,
1046-
ForeignModuleKind foreignKind,
1047-
Demangle::Node::Kind kind) {
1026+
GenericTypeDecl *ASTBuilder::findForeignTypeDecl(StringRef name,
1027+
StringRef relatedEntityKind,
1028+
ForeignModuleKind foreignKind,
1029+
Demangle::Node::Kind kind) {
10481030
// Check to see if we have an importer loaded.
1049-
auto importer = static_cast<ClangImporter *>(Ctx.getClangModuleLoader());
1050-
if (!importer) return nullptr;
1031+
auto importer = Ctx.getClangModuleLoader();
1032+
if (!importer)
1033+
return nullptr;
10511034

10521035
// Find the unique declaration that has the right kind.
10531036
struct Consumer : VisibleDeclConsumer {
@@ -1059,8 +1042,10 @@ ASTBuilder::findForeignTypeDecl(StringRef name,
10591042

10601043
void foundDecl(ValueDecl *decl, DeclVisibilityKind reason,
10611044
DynamicLookupInfo dynamicLookupInfo = {}) override {
1062-
if (HadError) return;
1063-
if (decl == Result) return;
1045+
if (HadError)
1046+
return;
1047+
if (decl == Result)
1048+
return;
10641049
if (!Result) {
10651050
Result = dyn_cast<GenericTypeDecl>(decl);
10661051
HadError |= !Result;
@@ -1071,33 +1056,27 @@ ASTBuilder::findForeignTypeDecl(StringRef name,
10711056
}
10721057
} consumer(kind);
10731058

1059+
auto found = [&](TypeDecl *found) {
1060+
consumer.foundDecl(found, DeclVisibilityKind::VisibleAtTopLevel);
1061+
};
1062+
10741063
switch (foreignKind) {
10751064
case ForeignModuleKind::SynthesizedByImporter:
10761065
if (!relatedEntityKind.empty()) {
1077-
Optional<ClangTypeKind> lookupKind = getClangTypeKindForNodeKind(kind);
1078-
if (!lookupKind)
1079-
return nullptr;
1080-
importer->lookupRelatedEntity(name, lookupKind.getValue(),
1081-
relatedEntityKind, [&](TypeDecl *found) {
1082-
consumer.foundDecl(found, DeclVisibilityKind::VisibleAtTopLevel);
1083-
});
1066+
importer->lookupRelatedEntity(name, relatedEntityKind, found);
10841067
break;
10851068
}
10861069
importer->lookupValue(Ctx.getIdentifier(name), consumer);
1087-
if (consumer.Result) {
1088-
consumer.Result =
1089-
getAcceptableTypeDeclCandidate(consumer.Result,kind);
1090-
}
1070+
if (consumer.Result)
1071+
consumer.Result = getAcceptableTypeDeclCandidate(consumer.Result, kind);
10911072
break;
1092-
case ForeignModuleKind::Imported: {
1093-
Optional<ClangTypeKind> lookupKind = getClangTypeKindForNodeKind(kind);
1094-
if (!lookupKind)
1095-
return nullptr;
1096-
importer->lookupTypeDecl(name, lookupKind.getValue(),
1097-
[&](TypeDecl *found) {
1098-
consumer.foundDecl(found, DeclVisibilityKind::VisibleAtTopLevel);
1099-
});
1100-
}
1073+
case ForeignModuleKind::Imported:
1074+
importer->lookupTypeDecl(name, kind, found);
1075+
1076+
// Try the DWARFImporter if it exists.
1077+
if (!consumer.Result)
1078+
if (auto *dwarf_importer = Ctx.getDWARFModuleLoader())
1079+
dwarf_importer->lookupTypeDecl(name, kind, found);
11011080
}
11021081

11031082
return consumer.Result;

0 commit comments

Comments
 (0)