//===--- DWARFImporter.cpp - Import Clang modules from DWARF --------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2019 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// #include "ImporterImpl.h" #include "swift/AST/ImportCache.h" #include "swift/AST/Module.h" #include "swift/Basic/Assertions.h" using namespace swift; void DWARFImporterDelegate::anchor() {} /// Represents a Clang module that was "imported" from debug info. Since all the /// loading of types is done on demand, this class is effectively empty. class DWARFModuleUnit final : public LoadedFile { ClangImporter::Implementation &Owner; public: DWARFModuleUnit(ModuleDecl &M, ClangImporter::Implementation &owner) : LoadedFile(FileUnitKind::DWARFModule, M), Owner(owner) {} virtual bool isSystemModule() const override { return false; } /// Forwards the request to the ClangImporter, which forwards it to the /// DWARFimporterDelegate. virtual void lookupValue(DeclName name, NLKind lookupKind, OptionSet Flags, SmallVectorImpl &results) const override { Owner.lookupValueDWARF(name, lookupKind, getParentModule()->getName(), results); } virtual TypeDecl * lookupNestedType(Identifier name, const NominalTypeDecl *baseType) const override { return nullptr; } virtual void lookupVisibleDecls(ImportPath::Access accessPath, VisibleDeclConsumer &consumer, NLKind lookupKind) const override {} virtual void lookupClassMembers(ImportPath::Access accessPath, VisibleDeclConsumer &consumer) const override {} virtual void lookupClassMember(ImportPath::Access accessPath, DeclName name, SmallVectorImpl &decls) const override {} void lookupObjCMethods( ObjCSelector selector, SmallVectorImpl &results) const override {} virtual void getTopLevelDecls(SmallVectorImpl &results) const override {} virtual void getDisplayDecls(SmallVectorImpl &results, bool recursive = false) const override {} virtual void getImportedModules(SmallVectorImpl &imports, ModuleDecl::ImportFilter filter) const override {} virtual void getImportedModulesForLookup( SmallVectorImpl &imports) const override {}; virtual void collectLinkLibraries( ModuleDecl::LinkLibraryCallback callback) const override {}; Identifier getDiscriminatorForPrivateDecl(const Decl *D) const override { llvm_unreachable("no private decls in Clang modules"); } virtual version::Version getLanguageVersionBuiltWith() const override { return version::Version(); } virtual StringRef getFilename() const override { return ""; } virtual const clang::Module *getUnderlyingClangModule() const override { return nullptr; } static bool classof(const FileUnit *file) { return file->getKind() == FileUnitKind::DWARFModule; } static bool classof(const DeclContext *DC) { return isa(DC) && classof(cast(DC)); } }; static_assert(IsTriviallyDestructible::value, "DWARFModuleUnits are BumpPtrAllocated; the d'tor is not called"); ModuleDecl *ClangImporter::Implementation::loadModuleDWARF( SourceLoc importLoc, ImportPath::Module path) { // There's no importing from debug info if no importer is installed. if (!DWARFImporter) return nullptr; // FIXME: Implement submodule support! Identifier name = path[0].Item; auto [it, inserted] = DWARFModuleUnits.try_emplace(name, nullptr); if (!inserted) return it->second->getParentModule(); auto itCopy = it; // Capturing structured bindings is a C++20 feature. auto *M = ModuleDecl::create(name, SwiftContext, [&](ModuleDecl *M, auto addFile) { auto *wrapperUnit = new (SwiftContext) DWARFModuleUnit(*M, *this); itCopy->second = wrapperUnit; addFile(wrapperUnit); }); M->setIsNonSwiftModule(); M->setHasResolvedImports(); // Force load overlay modules for all imported modules. assert(namelookup::getAllImports(M).size() == 1 && namelookup::getAllImports(M).front().importedModule == M && "DWARF module depends on additional modules?"); // Register the module with the ASTContext so it is available for lookups. if (!SwiftContext.getLoadedModule(name)) SwiftContext.addLoadedModule(M); return M; } // This function exists to defeat the lazy member importing mechanism. The // DWARFImporter is not capable of loading individual members, so it cannot // benefit from this optimization yet anyhow. Besides, if you're importing a // type here, you more than likely want to dump it and its fields. Loading all // members populates lookup tables in the Clang Importer and ensures the // absence of cache-fill-related side effects. static void forceLoadAllMembers(IterableDeclContext *IDC) { if (!IDC) return; IDC->loadAllMembers(); } void ClangImporter::Implementation::lookupValueDWARF( DeclName name, NLKind lookupKind, Identifier inModule, SmallVectorImpl &results) { if (lookupKind != NLKind::QualifiedLookup) return; if (!DWARFImporter) return; SmallVector decls; DWARFImporter->lookupValue(name.getBaseName().userFacingName(), std::nullopt, inModule.str(), decls); for (auto *clangDecl : decls) { auto *namedDecl = dyn_cast(clangDecl); if (!namedDecl) continue; auto *swiftDecl = cast_or_null( importDeclReal(namedDecl->getMostRecentDecl(), CurrentVersion)); if (!swiftDecl) continue; if (swiftDecl->getName().matchesRef(name) && swiftDecl->getDeclContext()->isModuleScopeContext()) { forceLoadAllMembers(dyn_cast(swiftDecl)); results.push_back(swiftDecl); } } } void ClangImporter::Implementation::lookupTypeDeclDWARF( StringRef rawName, ClangTypeKind kind, llvm::function_ref receiver) { if (!DWARFImporter) return; /// This function is invoked by ASTDemangler, which doesn't filter by module. SmallVector decls; DWARFImporter->lookupValue(rawName, kind, {}, decls); for (auto *clangDecl : decls) { if (!isa(clangDecl) && !isa(clangDecl) && !isa(clangDecl)) { continue; } auto *namedDecl = cast(clangDecl); Decl *importedDecl = cast_or_null( importDeclReal(namedDecl->getMostRecentDecl(), CurrentVersion)); if (auto *importedType = dyn_cast_or_null(importedDecl)) { forceLoadAllMembers(dyn_cast(importedType)); receiver(importedType); } } } void ClangImporter::setDWARFImporterDelegate(DWARFImporterDelegate &delegate) { Impl.setDWARFImporterDelegate(delegate); } void ClangImporter::Implementation::setDWARFImporterDelegate( DWARFImporterDelegate &delegate) { DWARFImporter = &delegate; }