Files
swift-mirror/lib/ClangImporter/DWARFImporter.cpp
Gabor Horvath 068815c2a3 [cxx-interop] Remove some duplicated lookups
Repeatedly lookup up a key from a dictionary can be justified whenever
the content of the dictionary might change between the lookups (so any
references into the dictionary might get invalidated). We had a couple
of instances where as far as I can tell no such modifications should
happen between two lookups with identical keys. This PR simplifies the
code to remove the extra lookups. It also removes a dictionary that was
completely unused.
2025-02-14 11:04:23 +00:00

215 lines
7.4 KiB
C++

//===--- 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<ModuleLookupFlags> Flags,
SmallVectorImpl<ValueDecl *> &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<ValueDecl *> &decls) const override {}
void lookupObjCMethods(
ObjCSelector selector,
SmallVectorImpl<AbstractFunctionDecl *> &results) const override {}
virtual void
getTopLevelDecls(SmallVectorImpl<Decl *> &results) const override {}
virtual void
getDisplayDecls(SmallVectorImpl<Decl *> &results, bool recursive = false) const override {}
virtual void
getImportedModules(SmallVectorImpl<ImportedModule> &imports,
ModuleDecl::ImportFilter filter) const override {}
virtual void getImportedModulesForLookup(
SmallVectorImpl<ImportedModule> &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<FileUnit>(DC) && classof(cast<FileUnit>(DC));
}
};
static_assert(IsTriviallyDestructible<DWARFModuleUnit>::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<ValueDecl *> &results) {
if (lookupKind != NLKind::QualifiedLookup)
return;
if (!DWARFImporter)
return;
SmallVector<clang::Decl *, 4> decls;
DWARFImporter->lookupValue(name.getBaseName().userFacingName(), std::nullopt,
inModule.str(), decls);
for (auto *clangDecl : decls) {
auto *namedDecl = dyn_cast<clang::NamedDecl>(clangDecl);
if (!namedDecl)
continue;
auto *swiftDecl = cast_or_null<ValueDecl>(
importDeclReal(namedDecl->getMostRecentDecl(), CurrentVersion));
if (!swiftDecl)
continue;
if (swiftDecl->getName().matchesRef(name) &&
swiftDecl->getDeclContext()->isModuleScopeContext()) {
forceLoadAllMembers(dyn_cast<IterableDeclContext>(swiftDecl));
results.push_back(swiftDecl);
}
}
}
void ClangImporter::Implementation::lookupTypeDeclDWARF(
StringRef rawName, ClangTypeKind kind,
llvm::function_ref<void(TypeDecl *)> receiver) {
if (!DWARFImporter)
return;
/// This function is invoked by ASTDemangler, which doesn't filter by module.
SmallVector<clang::Decl *, 1> decls;
DWARFImporter->lookupValue(rawName, kind, {}, decls);
for (auto *clangDecl : decls) {
if (!isa<clang::TypeDecl>(clangDecl) &&
!isa<clang::ObjCContainerDecl>(clangDecl) &&
!isa<clang::ObjCCompatibleAliasDecl>(clangDecl)) {
continue;
}
auto *namedDecl = cast<clang::NamedDecl>(clangDecl);
Decl *importedDecl = cast_or_null<ValueDecl>(
importDeclReal(namedDecl->getMostRecentDecl(), CurrentVersion));
if (auto *importedType = dyn_cast_or_null<TypeDecl>(importedDecl)) {
forceLoadAllMembers(dyn_cast<IterableDeclContext>(importedType));
receiver(importedType);
}
}
}
void ClangImporter::setDWARFImporterDelegate(DWARFImporterDelegate &delegate) {
Impl.setDWARFImporterDelegate(delegate);
}
void ClangImporter::Implementation::setDWARFImporterDelegate(
DWARFImporterDelegate &delegate) {
DWARFImporter = &delegate;
}