Merge pull request #26493 from adrian-prantl/49233932

Introduce a DWARFImporter delegate that can look up clang::Decls by name
This commit is contained in:
adrian-prantl
2019-08-07 08:50:23 -07:00
committed by GitHub
12 changed files with 261 additions and 86 deletions

View File

@@ -639,8 +639,10 @@ public:
/// \param isClang \c true if this module loader is responsible for loading /// \param isClang \c true if this module loader is responsible for loading
/// Clang modules, which are special-cased in some parts of the /// Clang modules, which are special-cased in some parts of the
/// compiler. /// compiler.
/// \param isDWARF \c true if this module loader can load Clang modules
/// from DWARF.
void addModuleLoader(std::unique_ptr<ModuleLoader> loader, void addModuleLoader(std::unique_ptr<ModuleLoader> loader,
bool isClang = false); bool isClang = false, bool isDWARF = false);
/// Load extensions to the given nominal type from the external /// Load extensions to the given nominal type from the external
/// module loaders. /// module loaders.
@@ -683,6 +685,12 @@ public:
/// The loader is owned by the AST context. /// The loader is owned by the AST context.
ClangModuleLoader *getClangModuleLoader() const; ClangModuleLoader *getClangModuleLoader() const;
/// Retrieve the DWARF module loader for this ASTContext.
///
/// If there is no Clang module loader, returns a null pointer.
/// The loader is owned by the AST context.
ClangModuleLoader *getDWARFModuleLoader() const;
/// Asks every module loader to verify the ASTs it has loaded. /// Asks every module loader to verify the ASTs it has loaded.
/// ///
/// Does nothing in non-asserts (NDEBUG) builds. /// Does nothing in non-asserts (NDEBUG) builds.

View File

@@ -14,6 +14,7 @@
#define SWIFT_AST_CLANG_MODULE_LOADER_H #define SWIFT_AST_CLANG_MODULE_LOADER_H
#include "swift/AST/ModuleLoader.h" #include "swift/AST/ModuleLoader.h"
#include "swift/Demangling/Demangle.h"
namespace clang { namespace clang {
class ASTContext; class ASTContext;
@@ -25,6 +26,7 @@ class Sema;
namespace swift { namespace swift {
class DeclContext; class DeclContext;
class VisibleDeclConsumer;
class ClangModuleLoader : public ModuleLoader { class ClangModuleLoader : public ModuleLoader {
private: private:
@@ -58,6 +60,30 @@ public:
const DeclContext *overlayDC, const DeclContext *overlayDC,
const DeclContext *importedDC) = 0; const DeclContext *importedDC) = 0;
/// Look for declarations associated with the given name.
///
/// \param name The name we're searching for.
virtual void lookupValue(DeclName name, VisibleDeclConsumer &consumer) {}
/// Look up a type declaration by its Clang name.
///
/// 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.
virtual void lookupTypeDecl(StringRef clangName, Demangle::Node::Kind kind,
llvm::function_ref<void(TypeDecl *)> receiver) {}
/// Look up type a declaration synthesized by the Clang importer itself, using
/// a "related entity kind" to determine which type it should be. For example,
/// this can be used to find the synthesized error struct for an
/// NS_ERROR_ENUM.
///
/// 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.
virtual void
lookupRelatedEntity(StringRef clangName, StringRef relatedEntityKind,
llvm::function_ref<void(TypeDecl *)> receiver) {}
}; };
} // namespace swift } // namespace swift

View File

@@ -35,6 +35,7 @@ class ClangImporterOptions;
class ClassDecl; class ClassDecl;
class ModuleDecl; class ModuleDecl;
class NominalTypeDecl; class NominalTypeDecl;
class TypeDecl;
enum class KnownProtocolKind : uint8_t; enum class KnownProtocolKind : uint8_t;

View File

@@ -75,6 +75,7 @@ enum class ClangTypeKind {
/// from Clang ASTs over to Swift ASTs. /// from Clang ASTs over to Swift ASTs.
class ClangImporter final : public ClangModuleLoader { class ClangImporter final : public ClangModuleLoader {
friend class ClangModuleUnit; friend class ClangModuleUnit;
friend class DWARFImporter;
public: public:
class Implementation; class Implementation;
@@ -160,15 +161,15 @@ public:
/// Look for declarations associated with the given name. /// Look for declarations associated with the given name.
/// ///
/// \param name The name we're searching for. /// \param name The name we're searching for.
void lookupValue(DeclName name, VisibleDeclConsumer &consumer); void lookupValue(DeclName name, VisibleDeclConsumer &consumer) override;
/// Look up a type declaration by its Clang name. /// Look up a type declaration by its Clang name.
/// ///
/// Note that this method does no filtering. If it finds the type in a loaded /// 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 /// module, it returns it. This is intended for use in reflection / debugging
/// contexts where access is not a problem. /// contexts where access is not a problem.
void lookupTypeDecl(StringRef clangName, ClangTypeKind kind, void lookupTypeDecl(StringRef clangName, Demangle::Node::Kind kind,
llvm::function_ref<void(TypeDecl*)> receiver); llvm::function_ref<void(TypeDecl*)> receiver) override;
/// Look up type a declaration synthesized by the Clang importer itself, using /// Look up type a declaration synthesized by the Clang importer itself, using
/// a "related entity kind" to determine which type it should be. For example, /// a "related entity kind" to determine which type it should be. For example,
@@ -178,9 +179,9 @@ public:
/// Note that this method does no filtering. If it finds the type in a loaded /// 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 /// module, it returns it. This is intended for use in reflection / debugging
/// contexts where access is not a problem. /// contexts where access is not a problem.
void lookupRelatedEntity(StringRef clangName, ClangTypeKind kind, void
StringRef relatedEntityKind, lookupRelatedEntity(StringRef clangName, StringRef relatedEntityKind,
llvm::function_ref<void(TypeDecl*)> receiver); llvm::function_ref<void(TypeDecl *)> receiver) override;
/// Look for textually included declarations from the bridging header. /// Look for textually included declarations from the bridging header.
/// ///

View File

@@ -18,6 +18,8 @@
#define SWIFT_DWARF_IMPORTER_H #define SWIFT_DWARF_IMPORTER_H
#include "swift/AST/ClangModuleLoader.h" #include "swift/AST/ClangModuleLoader.h"
#include "swift/AST/Module.h"
#include "swift/Demangling/Demangle.h"
namespace llvm { namespace llvm {
} }
@@ -27,6 +29,25 @@ namespace clang {
namespace swift { namespace swift {
/// This interface is implemented by LLDB to serve as a fallback when Clang
/// modules can't be imported from source in the debugger.
///
/// During compile time, ClangImporter-imported Clang modules are compiled with
/// -gmodules, which emits a DWARF rendition of all types defined in the module
/// into the .pcm file. On Darwin, these types can be collected by
/// dsymutil. This delegate allows DWARFImporter to ask LLDB to look up a Clang
/// type by name, synthesize a Clang AST from it. DWARFImporter then hands this
/// Clang AST to ClangImporter to import the type into Swift.
class DWARFImporterDelegate {
public:
virtual ~DWARFImporterDelegate() {}
/// Perform a qualified lookup of a Clang type with this name.
/// \param kind Only return results with this type kind.
virtual void lookupValue(StringRef name,
llvm::Optional<Demangle::Node::Kind> kind,
SmallVectorImpl<clang::Decl *> &results) {}
};
/// Class that imports Clang modules into Swift, mapping directly /// Class that imports Clang modules into Swift, mapping directly
/// from Clang ASTs over to Swift ASTs. /// from Clang ASTs over to Swift ASTs.
class DWARFImporter final : public ClangModuleLoader { class DWARFImporter final : public ClangModuleLoader {
@@ -39,6 +60,7 @@ private:
Implementation &Impl; Implementation &Impl;
DWARFImporter(ASTContext &ctx, const ClangImporterOptions &clangImporterOpts, DWARFImporter(ASTContext &ctx, const ClangImporterOptions &clangImporterOpts,
std::unique_ptr<DWARFImporterDelegate> delegate,
DependencyTracker *tracker); DependencyTracker *tracker);
public: public:
@@ -55,8 +77,8 @@ public:
/// \returns a new DWARF module importer, or null (with a diagnostic) if /// \returns a new DWARF module importer, or null (with a diagnostic) if
/// an error occurred. /// an error occurred.
static std::unique_ptr<DWARFImporter> static std::unique_ptr<DWARFImporter>
create(ASTContext &ctx, create(ASTContext &ctx, const ClangImporterOptions &importerOpts,
const ClangImporterOptions &importerOpts, std::unique_ptr<DWARFImporterDelegate> delegate = {},
DependencyTracker *tracker = nullptr); DependencyTracker *tracker = nullptr);
DWARFImporter(const DWARFImporter &) = delete; DWARFImporter(const DWARFImporter &) = delete;
@@ -80,6 +102,17 @@ public:
ModuleDecl * ModuleDecl *
loadModule(SourceLoc importLoc, loadModule(SourceLoc importLoc,
ArrayRef<std::pair<Identifier, SourceLoc>> path) override; ArrayRef<std::pair<Identifier, SourceLoc>> path) override;
ValueDecl *importDecl(clang::Decl *clangDecl);
void lookupValue(DeclName name, VisibleDeclConsumer &consumer) override {}
/// Behaves like \p ClangImporter::lookupValue.
void lookupValue(ModuleDecl::AccessPathTy accessPath, DeclName name,
NLKind lookupKind, SmallVectorImpl<ValueDecl *> &results);
/// Perform a qualified lookup of a Clang type with this name and only return
/// results with the specified type kind.
void lookupTypeDecl(StringRef rawName, Demangle::Node::Kind kind,
llvm::function_ref<void(TypeDecl *)> receiver) override;
bool bool
isInOverlayModuleForImportedModule(const DeclContext *overlayDC, isInOverlayModuleForImportedModule(const DeclContext *overlayDC,
const DeclContext *importedDC) override; const DeclContext *importedDC) override;

View File

@@ -255,6 +255,9 @@ FOR_KNOWN_FOUNDATION_TYPES(CACHE_FOUNDATION_DECL)
/// The module loader used to load Clang modules. /// The module loader used to load Clang modules.
ClangModuleLoader *TheClangModuleLoader = nullptr; ClangModuleLoader *TheClangModuleLoader = nullptr;
/// The module loader used to load Clang modules from DWARF.
ClangModuleLoader *TheDWARFModuleLoader = nullptr;
/// Map from Swift declarations to raw comments. /// Map from Swift declarations to raw comments.
llvm::DenseMap<const Decl *, RawComment> RawComments; llvm::DenseMap<const Decl *, RawComment> RawComments;
@@ -1446,10 +1449,13 @@ void ASTContext::addSearchPath(StringRef searchPath, bool isFramework,
} }
void ASTContext::addModuleLoader(std::unique_ptr<ModuleLoader> loader, void ASTContext::addModuleLoader(std::unique_ptr<ModuleLoader> loader,
bool IsClang) { bool IsClang, bool IsDwarf) {
if (IsClang && !getImpl().TheClangModuleLoader) if (IsClang && !IsDwarf && !getImpl().TheClangModuleLoader)
getImpl().TheClangModuleLoader = getImpl().TheClangModuleLoader =
static_cast<ClangModuleLoader *>(loader.get()); static_cast<ClangModuleLoader *>(loader.get());
if (IsClang && IsDwarf && !getImpl().TheDWARFModuleLoader)
getImpl().TheDWARFModuleLoader =
static_cast<ClangModuleLoader *>(loader.get());
getImpl().ModuleLoaders.push_back(std::move(loader)); getImpl().ModuleLoaders.push_back(std::move(loader));
} }
@@ -1493,6 +1499,10 @@ ClangModuleLoader *ASTContext::getClangModuleLoader() const {
return getImpl().TheClangModuleLoader; return getImpl().TheClangModuleLoader;
} }
ClangModuleLoader *ASTContext::getDWARFModuleLoader() const {
return getImpl().TheDWARFModuleLoader;
}
ModuleDecl *ASTContext::getLoadedModule( ModuleDecl *ASTContext::getLoadedModule(
ArrayRef<std::pair<Identifier, SourceLoc>> ModulePath) const { ArrayRef<std::pair<Identifier, SourceLoc>> ModulePath) const {
assert(!ModulePath.empty()); assert(!ModulePath.empty());

View File

@@ -22,6 +22,7 @@
#include "swift/AST/ASTDemangler.h" #include "swift/AST/ASTDemangler.h"
#include "swift/AST/ASTContext.h" #include "swift/AST/ASTContext.h"
#include "swift/AST/ClangModuleLoader.h"
#include "swift/AST/Decl.h" #include "swift/AST/Decl.h"
#include "swift/AST/GenericSignature.h" #include "swift/AST/GenericSignature.h"
#include "swift/AST/GenericSignatureBuilder.h" #include "swift/AST/GenericSignatureBuilder.h"
@@ -29,7 +30,6 @@
#include "swift/AST/NameLookup.h" #include "swift/AST/NameLookup.h"
#include "swift/AST/Type.h" #include "swift/AST/Type.h"
#include "swift/AST/Types.h" #include "swift/AST/Types.h"
#include "swift/ClangImporter/ClangImporter.h"
#include "swift/Demangling/Demangler.h" #include "swift/Demangling/Demangler.h"
#include "swift/Demangling/ManglingMacros.h" #include "swift/Demangling/ManglingMacros.h"
@@ -1023,31 +1023,14 @@ ASTBuilder::findTypeDecl(DeclContext *dc,
return result; return result;
} }
static Optional<ClangTypeKind> GenericTypeDecl *ASTBuilder::findForeignTypeDecl(StringRef name,
getClangTypeKindForNodeKind(Demangle::Node::Kind kind) {
switch (kind) {
case Demangle::Node::Kind::Protocol:
return ClangTypeKind::ObjCProtocol;
case Demangle::Node::Kind::Class:
return ClangTypeKind::ObjCClass;
case Demangle::Node::Kind::TypeAlias:
return ClangTypeKind::Typedef;
case Demangle::Node::Kind::Structure:
case Demangle::Node::Kind::Enum:
return ClangTypeKind::Tag;
default:
return None;
}
}
GenericTypeDecl *
ASTBuilder::findForeignTypeDecl(StringRef name,
StringRef relatedEntityKind, StringRef relatedEntityKind,
ForeignModuleKind foreignKind, ForeignModuleKind foreignKind,
Demangle::Node::Kind kind) { Demangle::Node::Kind kind) {
// Check to see if we have an importer loaded. // Check to see if we have an importer loaded.
auto importer = static_cast<ClangImporter *>(Ctx.getClangModuleLoader()); auto importer = Ctx.getClangModuleLoader();
if (!importer) return nullptr; if (!importer)
return nullptr;
// Find the unique declaration that has the right kind. // Find the unique declaration that has the right kind.
struct Consumer : VisibleDeclConsumer { struct Consumer : VisibleDeclConsumer {
@@ -1059,8 +1042,10 @@ ASTBuilder::findForeignTypeDecl(StringRef name,
void foundDecl(ValueDecl *decl, DeclVisibilityKind reason, void foundDecl(ValueDecl *decl, DeclVisibilityKind reason,
DynamicLookupInfo dynamicLookupInfo = {}) override { DynamicLookupInfo dynamicLookupInfo = {}) override {
if (HadError) return; if (HadError)
if (decl == Result) return; return;
if (decl == Result)
return;
if (!Result) { if (!Result) {
Result = dyn_cast<GenericTypeDecl>(decl); Result = dyn_cast<GenericTypeDecl>(decl);
HadError |= !Result; HadError |= !Result;
@@ -1071,33 +1056,27 @@ ASTBuilder::findForeignTypeDecl(StringRef name,
} }
} consumer(kind); } consumer(kind);
auto found = [&](TypeDecl *found) {
consumer.foundDecl(found, DeclVisibilityKind::VisibleAtTopLevel);
};
switch (foreignKind) { switch (foreignKind) {
case ForeignModuleKind::SynthesizedByImporter: case ForeignModuleKind::SynthesizedByImporter:
if (!relatedEntityKind.empty()) { if (!relatedEntityKind.empty()) {
Optional<ClangTypeKind> lookupKind = getClangTypeKindForNodeKind(kind); importer->lookupRelatedEntity(name, relatedEntityKind, found);
if (!lookupKind)
return nullptr;
importer->lookupRelatedEntity(name, lookupKind.getValue(),
relatedEntityKind, [&](TypeDecl *found) {
consumer.foundDecl(found, DeclVisibilityKind::VisibleAtTopLevel);
});
break; break;
} }
importer->lookupValue(Ctx.getIdentifier(name), consumer); importer->lookupValue(Ctx.getIdentifier(name), consumer);
if (consumer.Result) { if (consumer.Result)
consumer.Result = consumer.Result = getAcceptableTypeDeclCandidate(consumer.Result, kind);
getAcceptableTypeDeclCandidate(consumer.Result,kind);
}
break; break;
case ForeignModuleKind::Imported: { case ForeignModuleKind::Imported:
Optional<ClangTypeKind> lookupKind = getClangTypeKindForNodeKind(kind); importer->lookupTypeDecl(name, kind, found);
if (!lookupKind)
return nullptr; // Try the DWARFImporter if it exists.
importer->lookupTypeDecl(name, lookupKind.getValue(), if (!consumer.Result)
[&](TypeDecl *found) { if (auto *dwarf_importer = Ctx.getDWARFModuleLoader())
consumer.foundDecl(found, DeclVisibilityKind::VisibleAtTopLevel); dwarf_importer->lookupTypeDecl(name, kind, found);
});
}
} }
return consumer.Result; return consumer.Result;

View File

@@ -33,6 +33,7 @@
#include "swift/Basic/StringExtras.h" #include "swift/Basic/StringExtras.h"
#include "swift/Basic/Version.h" #include "swift/Basic/Version.h"
#include "swift/ClangImporter/ClangImporterOptions.h" #include "swift/ClangImporter/ClangImporterOptions.h"
#include "swift/Demangling/Demangle.h"
#include "swift/Parse/Lexer.h" #include "swift/Parse/Lexer.h"
#include "swift/Parse/Parser.h" #include "swift/Parse/Parser.h"
#include "swift/Config.h" #include "swift/Config.h"
@@ -2494,14 +2495,34 @@ void ClangImporter::lookupValue(DeclName name, VisibleDeclConsumer &consumer){
}); });
} }
void static Optional<ClangTypeKind>
ClangImporter::lookupTypeDecl(StringRef rawName, ClangTypeKind kind, getClangTypeKindForNodeKind(Demangle::Node::Kind kind) {
switch (kind) {
case Demangle::Node::Kind::Protocol:
return ClangTypeKind::ObjCProtocol;
case Demangle::Node::Kind::Class:
return ClangTypeKind::ObjCClass;
case Demangle::Node::Kind::TypeAlias:
return ClangTypeKind::Typedef;
case Demangle::Node::Kind::Structure:
case Demangle::Node::Kind::Enum:
return ClangTypeKind::Tag;
default:
return None;
}
}
void ClangImporter::lookupTypeDecl(
StringRef rawName, Demangle::Node::Kind kind,
llvm::function_ref<void(TypeDecl *)> receiver) { llvm::function_ref<void(TypeDecl *)> receiver) {
clang::DeclarationName clangName( clang::DeclarationName clangName(
&Impl.Instance->getASTContext().Idents.get(rawName)); &Impl.Instance->getASTContext().Idents.get(rawName));
clang::Sema::LookupNameKind lookupKind; clang::Sema::LookupNameKind lookupKind;
switch (kind) { auto clang_kind = getClangTypeKindForNodeKind(kind);
if (!clang_kind)
return;
switch (*clang_kind) {
case ClangTypeKind::Typedef: case ClangTypeKind::Typedef:
lookupKind = clang::Sema::LookupOrdinaryName; lookupKind = clang::Sema::LookupOrdinaryName;
break; break;
@@ -2532,17 +2553,17 @@ ClangImporter::lookupTypeDecl(StringRef rawName, ClangTypeKind kind,
} }
void ClangImporter::lookupRelatedEntity( void ClangImporter::lookupRelatedEntity(
StringRef rawName, ClangTypeKind kind, StringRef relatedEntityKind, StringRef rawName, StringRef relatedEntityKind,
llvm::function_ref<void(TypeDecl *)> receiver) { llvm::function_ref<void(TypeDecl *)> receiver) {
using CISTAttr = ClangImporterSynthesizedTypeAttr; using CISTAttr = ClangImporterSynthesizedTypeAttr;
if (relatedEntityKind == if (relatedEntityKind ==
CISTAttr::manglingNameForKind(CISTAttr::Kind::NSErrorWrapper) || CISTAttr::manglingNameForKind(CISTAttr::Kind::NSErrorWrapper) ||
relatedEntityKind == relatedEntityKind ==
CISTAttr::manglingNameForKind(CISTAttr::Kind::NSErrorWrapperAnon)) { CISTAttr::manglingNameForKind(CISTAttr::Kind::NSErrorWrapperAnon)) {
auto underlyingKind = ClangTypeKind::Tag; auto underlyingKind = Demangle::Node::Kind::Structure;
if (relatedEntityKind == if (relatedEntityKind ==
CISTAttr::manglingNameForKind(CISTAttr::Kind::NSErrorWrapperAnon)) { CISTAttr::manglingNameForKind(CISTAttr::Kind::NSErrorWrapperAnon)) {
underlyingKind = ClangTypeKind::Typedef; underlyingKind = Demangle::Node::Kind::TypeAlias;
} }
lookupTypeDecl(rawName, underlyingKind, lookupTypeDecl(rawName, underlyingKind,
[this, receiver] (const TypeDecl *foundType) { [this, receiver] (const TypeDecl *foundType) {

View File

@@ -318,6 +318,7 @@ class LLVM_LIBRARY_VISIBILITY ClangImporter::Implementation
public LazyConformanceLoader public LazyConformanceLoader
{ {
friend class ClangImporter; friend class ClangImporter;
friend class DWARFImporter;
using Version = importer::ImportNameVersion; using Version = importer::ImportNameVersion;
public: public:

View File

@@ -13,15 +13,18 @@
#include "swift/DWARFImporter/DWARFImporter.h" #include "swift/DWARFImporter/DWARFImporter.h"
#include "swift/AST/ASTContext.h" #include "swift/AST/ASTContext.h"
#include "swift/AST/Module.h" #include "swift/AST/Module.h"
#include "clang/CodeGen/ObjectFilePCHContainerOperations.h"
#include "clang/Frontend/FrontendActions.h"
#include "../ClangImporter/ImporterImpl.h"
using namespace swift; using namespace swift;
std::unique_ptr<DWARFImporter> std::unique_ptr<DWARFImporter>
DWARFImporter::create(ASTContext &ctx, DWARFImporter::create(ASTContext &ctx, const ClangImporterOptions &importerOpts,
const ClangImporterOptions &importerOpts, std::unique_ptr<DWARFImporterDelegate> delegate,
DependencyTracker *tracker) { DependencyTracker *tracker) {
std::unique_ptr<DWARFImporter> importer{ std::unique_ptr<DWARFImporter> importer{
new DWARFImporter(ctx, importerOpts, tracker) new DWARFImporter(ctx, importerOpts, std::move(delegate), tracker)
}; };
return importer; return importer;
} }
@@ -29,17 +32,18 @@ DWARFImporter::create(ASTContext &ctx,
class DWARFModuleUnit final : public LoadedFile { class DWARFModuleUnit final : public LoadedFile {
~DWARFModuleUnit() = default; ~DWARFModuleUnit() = default;
DWARFImporter::Implementation &owner;
public: public:
DWARFModuleUnit(ModuleDecl &M) DWARFModuleUnit(ModuleDecl &M, DWARFImporter::Implementation &owner)
: LoadedFile(FileUnitKind::DWARFModule, M) {} : LoadedFile(FileUnitKind::DWARFModule, M), owner(owner) {}
virtual bool isSystemModule() const override { return false; } virtual bool isSystemModule() const override { return false; }
virtual void virtual void
lookupValue(ModuleDecl::AccessPathTy accessPath, DeclName name, lookupValue(ModuleDecl::AccessPathTy accessPath, DeclName name,
NLKind lookupKind, NLKind lookupKind,
SmallVectorImpl<ValueDecl *> &results) const override {} SmallVectorImpl<ValueDecl *> &results) const override;
virtual TypeDecl * virtual TypeDecl *
lookupNestedType(Identifier name, lookupNestedType(Identifier name,
@@ -101,14 +105,17 @@ public:
class DWARFImporter::Implementation { class DWARFImporter::Implementation {
public: public:
ASTContext &SwiftContext; ASTContext &SwiftContext;
clang::ASTContext *ClangASTContext = nullptr;
clang::CompilerInstance *Instance = nullptr; std::unique_ptr<DWARFImporterDelegate> delegate;
clang::Preprocessor *PP = nullptr; ClangImporter &clangImporter;
clang::Sema *Sema = nullptr;
llvm::DenseMap<Identifier, DWARFModuleUnit *> ModuleWrappers; llvm::DenseMap<Identifier, DWARFModuleUnit *> ModuleWrappers;
Implementation(ASTContext &ctx, const ClangImporterOptions &clangImporterOpts) Implementation(ASTContext &ctx, const ClangImporterOptions &clangImporterOpts,
: SwiftContext(ctx) {} std::unique_ptr<DWARFImporterDelegate> delegate,
DependencyTracker *tracker)
: SwiftContext(ctx), delegate(std::move(delegate)),
clangImporter(
*static_cast<ClangImporter *>(ctx.getClangModuleLoader())) {}
ModuleDecl *loadModule(SourceLoc importLoc, ModuleDecl *loadModule(SourceLoc importLoc,
ArrayRef<std::pair<Identifier, SourceLoc>> path) { ArrayRef<std::pair<Identifier, SourceLoc>> path) {
@@ -122,22 +129,95 @@ public:
auto *decl = ModuleDecl::create(name, SwiftContext); auto *decl = ModuleDecl::create(name, SwiftContext);
decl->setIsNonSwiftModule(); decl->setIsNonSwiftModule();
decl->setHasResolvedImports(); decl->setHasResolvedImports();
auto wrapperUnit = new (SwiftContext) DWARFModuleUnit(*decl); auto wrapperUnit = new (SwiftContext) DWARFModuleUnit(*decl, *this);
ModuleWrappers.insert({name, wrapperUnit}); ModuleWrappers.insert({name, wrapperUnit});
decl->addFile(*wrapperUnit); decl->addFile(*wrapperUnit);
// Force load overlay modules for all imported modules. // Force load overlay modules for all imported modules.
decl->forAllVisibleModules({}, [](ModuleDecl::ImportedModule import) {}); decl->forAllVisibleModules({}, [](ModuleDecl::ImportedModule import) {});
// Register the module with the ASTContext so it is available for lookups.
ModuleDecl *&loaded = SwiftContext.LoadedModules[name];
if (!loaded)
loaded = decl;
return decl; return decl;
} }
public:
ValueDecl *importDecl(clang::Decl *clangDecl) {
auto *namedDecl = dyn_cast_or_null<clang::NamedDecl>(clangDecl);
if (!namedDecl)
return nullptr;
return cast_or_null<ValueDecl>(clangImporter.Impl.importDeclReal(
namedDecl->getMostRecentDecl(), clangImporter.Impl.CurrentVersion));
}
void lookupValue(ModuleDecl::AccessPathTy accessPath, DeclName name,
NLKind lookupKind, SmallVectorImpl<ValueDecl *> &results) {
if (!swift::ModuleDecl::matchesAccessPath(accessPath, name))
return;
if (lookupKind != NLKind::QualifiedLookup)
return;
if (!delegate)
return;
SmallVector<clang::Decl *, 4> decls;
delegate->lookupValue(name.getBaseIdentifier().str(), llvm::None, decls);
for (auto *clangDecl : decls) {
auto *decl = importDecl(clangDecl);
if (!decl)
continue;
if (decl->getFullName().matchesRef(name) &&
decl->getDeclContext()->isModuleScopeContext())
results.push_back(decl);
}
}
void lookupTypeDecl(StringRef rawName, Demangle::Node::Kind kind,
llvm::function_ref<void(TypeDecl *)> receiver) {
SmallVector<clang::Decl *, 1> decls;
delegate->lookupValue(rawName, kind, decls);
for (auto *clangDecl : decls) {
if (!isa<clang::TypeDecl>(clangDecl) &&
!isa<clang::ObjCContainerDecl>(clangDecl) &&
!isa<clang::ObjCCompatibleAliasDecl>(clangDecl)) {
continue;
}
auto *imported = importDecl(clangDecl);
if (auto *importedType = dyn_cast_or_null<TypeDecl>(imported))
receiver(importedType);
}
}
clang::ASTContext &getClangASTContext() const {
return clangImporter.getClangASTContext();
}
clang::Preprocessor &getClangPreprocessor() const {
return clangImporter.getClangPreprocessor();
}
clang::Sema &getClangSema() const { return clangImporter.getClangSema(); }
const clang::CompilerInstance &getClangInstance() const {
return clangImporter.getClangInstance();
}
}; };
void DWARFModuleUnit::lookupValue(ModuleDecl::AccessPathTy accessPath,
DeclName name, NLKind lookupKind,
SmallVectorImpl<ValueDecl *> &results) const {
owner.lookupValue(accessPath, name, lookupKind, results);
}
DWARFImporter::DWARFImporter(ASTContext &ctx, DWARFImporter::DWARFImporter(ASTContext &ctx,
const ClangImporterOptions &clangImporterOpts, const ClangImporterOptions &clangImporterOpts,
std::unique_ptr<DWARFImporterDelegate> delegate,
DependencyTracker *tracker) DependencyTracker *tracker)
: ClangModuleLoader(tracker), : ClangModuleLoader(tracker),
Impl(*new Implementation(ctx, clangImporterOpts)) {} Impl(*new Implementation(ctx, clangImporterOpts, std::move(delegate),
tracker)) {}
DWARFImporter::~DWARFImporter() { delete &Impl; } DWARFImporter::~DWARFImporter() { delete &Impl; }
@@ -159,6 +239,22 @@ DWARFImporter::loadModule(SourceLoc importLoc,
return Impl.loadModule(importLoc, path); return Impl.loadModule(importLoc, path);
} }
ValueDecl *DWARFImporter::importDecl(clang::Decl *clangDecl) {
return Impl.importDecl(clangDecl);
}
void DWARFImporter::lookupValue(ModuleDecl::AccessPathTy accessPath,
DeclName name, NLKind lookupKind,
SmallVectorImpl<ValueDecl *> &results) {
Impl.lookupValue(accessPath, name, lookupKind, results);
}
void DWARFImporter::lookupTypeDecl(
StringRef rawName, Demangle::Node::Kind kind,
llvm::function_ref<void(TypeDecl *)> receiver) {
Impl.lookupTypeDecl(rawName, kind, receiver);
}
bool DWARFImporter::isInOverlayModuleForImportedModule( bool DWARFImporter::isInOverlayModuleForImportedModule(
const DeclContext *overlayDC, const DeclContext *importedDC) { const DeclContext *overlayDC, const DeclContext *importedDC) {
return false; return false;
@@ -177,14 +273,14 @@ ModuleDecl *DWARFImporter::getImportedHeaderModule() const { return nullptr; }
void DWARFImporter::verifyAllModules() {}; void DWARFImporter::verifyAllModules() {};
clang::ASTContext &DWARFImporter::getClangASTContext() const { clang::ASTContext &DWARFImporter::getClangASTContext() const {
return *Impl.ClangASTContext; return Impl.getClangASTContext();
} }
clang::Preprocessor &DWARFImporter::getClangPreprocessor() const { clang::Preprocessor &DWARFImporter::getClangPreprocessor() const {
return *Impl.PP; return Impl.getClangPreprocessor();
} }
clang::Sema &DWARFImporter::getClangSema() const { return *Impl.Sema; } clang::Sema &DWARFImporter::getClangSema() const { return Impl.getClangSema(); }
const clang::CompilerInstance &DWARFImporter::getClangInstance() const { const clang::CompilerInstance &DWARFImporter::getClangInstance() const {
return *Impl.Instance; return Impl.getClangInstance();
} }
void DWARFImporter::printStatistics() const {} void DWARFImporter::printStatistics() const {}

View File

@@ -380,7 +380,7 @@ bool CompilerInstance::setUpModuleLoaders() {
if (Invocation.getLangOptions().EnableDWARFImporter) { if (Invocation.getLangOptions().EnableDWARFImporter) {
auto dwarfImporter = auto dwarfImporter =
DWARFImporter::create(*Context, Invocation.getClangImporterOptions(), DWARFImporter::create(*Context, Invocation.getClangImporterOptions(),
getDependencyTracker()); nullptr, getDependencyTracker());
if (!dwarfImporter) { if (!dwarfImporter) {
Diagnostics.diagnose(SourceLoc(), diag::error_clang_importer_create_fail); Diagnostics.diagnose(SourceLoc(), diag::error_clang_importer_create_fail);
return true; return true;

View File

@@ -5,7 +5,6 @@ add_swift_host_tool(sil-passpipeline-dumper
target_link_libraries(sil-passpipeline-dumper target_link_libraries(sil-passpipeline-dumper
PRIVATE PRIVATE
swiftClangImporter swiftClangImporter
swiftDWARFImporter
swiftFrontend swiftFrontend
swiftSerialization swiftSerialization
swiftSILGen swiftSILGen