Avoid including Module.h from ExternalASTSource.h

Module.h takes 86ms to parse, mostly parsing the class itself. Avoid it
if possible. ASTContext.h depends on ExternalASTSource.h.

A few NFC changes were needed to make this possible:

- Move ASTSourceDescriptor to Module.h. This needs Module to be
  complete, and seems more related to modules and AST files than
  external AST sources.
- Move "import complete" bit from Module* pointer int pair to
  NextLocalImport pointer. Required because PointerIntPair<Module*,...>
  requires Module to be complete, and now it may not be.

Reviewed By: aaron.ballman, hans

Differential Revision: https://reviews.llvm.org/D75784
This commit is contained in:
Reid Kleckner 2020-02-27 18:13:54 -08:00
parent a0cacb6054
commit c915cb957d
17 changed files with 115 additions and 87 deletions

View File

@ -121,6 +121,7 @@ class Preprocessor;
class Stmt;
class StoredDeclsMap;
class TargetAttr;
class TargetInfo;
class TemplateDecl;
class TemplateParameterList;
class TemplateTemplateParmDecl;
@ -881,7 +882,7 @@ public:
void addedLocalImportDecl(ImportDecl *Import);
static ImportDecl *getNextLocalImport(ImportDecl *Import) {
return Import->NextLocalImport;
return Import->getNextLocalImport();
}
using import_range = llvm::iterator_range<import_iterator>;
@ -909,13 +910,7 @@ public:
/// Get the additional modules in which the definition \p Def has
/// been merged.
ArrayRef<Module*> getModulesWithMergedDefinition(const NamedDecl *Def) {
auto MergedIt =
MergedDefModules.find(cast<NamedDecl>(Def->getCanonicalDecl()));
if (MergedIt == MergedDefModules.end())
return None;
return MergedIt->second;
}
ArrayRef<Module*> getModulesWithMergedDefinition(const NamedDecl *Def);
/// Add a declaration to the list of declarations that are initialized
/// for a module. This will typically be a global variable (with internal

View File

@ -4340,17 +4340,18 @@ class ImportDecl final : public Decl,
friend class ASTReader;
friend TrailingObjects;
/// The imported module, along with a bit that indicates whether
/// we have source-location information for each identifier in the module
/// name.
///
/// When the bit is false, we only have a single source location for the
/// end of the import declaration.
llvm::PointerIntPair<Module *, 1, bool> ImportedAndComplete;
/// The imported module.
Module *ImportedModule = nullptr;
/// The next import in the list of imports local to the translation
/// unit being parsed (not loaded from an AST file).
ImportDecl *NextLocalImport = nullptr;
///
/// Includes a bit that indicates whether we have source-location information
/// for each identifier in the module name.
///
/// When the bit is false, we only have a single source location for the
/// end of the import declaration.
llvm::PointerIntPair<ImportDecl *, 1, bool> NextLocalImportAndComplete;
ImportDecl(DeclContext *DC, SourceLocation StartLoc, Module *Imported,
ArrayRef<SourceLocation> IdentifierLocs);
@ -4360,6 +4361,20 @@ class ImportDecl final : public Decl,
ImportDecl(EmptyShell Empty) : Decl(Import, Empty) {}
bool isImportComplete() const { return NextLocalImportAndComplete.getInt(); }
void setImportComplete(bool C) { NextLocalImportAndComplete.setInt(C); }
/// The next import in the list of imports local to the translation
/// unit being parsed (not loaded from an AST file).
ImportDecl *getNextLocalImport() const {
return NextLocalImportAndComplete.getPointer();
}
void setNextLocalImport(ImportDecl *Import) {
NextLocalImportAndComplete.setPointer(Import);
}
public:
/// Create a new module import declaration.
static ImportDecl *Create(ASTContext &C, DeclContext *DC,
@ -4377,7 +4392,7 @@ public:
unsigned NumLocations);
/// Retrieve the module that was imported by the import declaration.
Module *getImportedModule() const { return ImportedAndComplete.getPointer(); }
Module *getImportedModule() const { return ImportedModule; }
/// Retrieves the locations of each of the identifiers that make up
/// the complete module name in the import declaration.

View File

@ -17,7 +17,6 @@
#include "clang/AST/CharUnits.h"
#include "clang/AST/DeclBase.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/Module.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/IntrusiveRefCntPtr.h"
@ -39,6 +38,7 @@ namespace clang {
class ASTConsumer;
class ASTContext;
class ASTSourceDescriptor;
class CXXBaseSpecifier;
class CXXCtorInitializer;
class CXXRecordDecl;
@ -165,31 +165,6 @@ public:
/// object file.
virtual bool DeclIsFromPCHWithObjectFile(const Decl *D) { return false; }
/// Abstracts clang modules and precompiled header files and holds
/// everything needed to generate debug info for an imported module
/// or PCH.
class ASTSourceDescriptor {
StringRef PCHModuleName;
StringRef Path;
StringRef ASTFile;
ASTFileSignature Signature;
const Module *ClangModule = nullptr;
public:
ASTSourceDescriptor() = default;
ASTSourceDescriptor(StringRef Name, StringRef Path, StringRef ASTFile,
ASTFileSignature Signature)
: PCHModuleName(std::move(Name)), Path(std::move(Path)),
ASTFile(std::move(ASTFile)), Signature(Signature) {}
ASTSourceDescriptor(const Module &M);
std::string getModuleName() const;
StringRef getPath() const { return Path; }
StringRef getASTFile() const { return ASTFile; }
ASTFileSignature getSignature() const { return Signature; }
const Module *getModuleOrNull() const { return ClangModule; }
};
/// Return a descriptor for the corresponding module, if one exists.
virtual llvm::Optional<ASTSourceDescriptor> getSourceDescriptor(unsigned ID);

View File

@ -654,6 +654,32 @@ private:
unsigned Generation = 0;
};
/// Abstracts clang modules and precompiled header files and holds
/// everything needed to generate debug info for an imported module
/// or PCH.
class ASTSourceDescriptor {
StringRef PCHModuleName;
StringRef Path;
StringRef ASTFile;
ASTFileSignature Signature;
const Module *ClangModule = nullptr;
public:
ASTSourceDescriptor() = default;
ASTSourceDescriptor(StringRef Name, StringRef Path, StringRef ASTFile,
ASTFileSignature Signature)
: PCHModuleName(std::move(Name)), Path(std::move(Path)),
ASTFile(std::move(ASTFile)), Signature(Signature) {}
ASTSourceDescriptor(const Module &M);
std::string getModuleName() const;
StringRef getPath() const { return Path; }
StringRef getASTFile() const { return ASTFile; }
ASTFileSignature getSignature() const { return Signature; }
const Module *getModuleOrNull() const { return ClangModule; }
};
} // namespace clang
#endif // LLVM_CLANG_BASIC_MODULE_H

View File

@ -13,6 +13,7 @@
#include "clang/StaticAnalyzer/Core/CheckerManager.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/SetVector.h"
#include <cstddef>
#include <vector>

View File

@ -55,6 +55,7 @@
#include "clang/Basic/LLVM.h"
#include "clang/Basic/LangOptions.h"
#include "clang/Basic/Linkage.h"
#include "clang/Basic/Module.h"
#include "clang/Basic/ObjCRuntime.h"
#include "clang/Basic/SanitizerBlacklist.h"
#include "clang/Basic/SourceLocation.h"
@ -1103,6 +1104,15 @@ void ASTContext::deduplicateMergedDefinitonsFor(NamedDecl *ND) {
Merged.erase(std::remove(Merged.begin(), Merged.end(), nullptr), Merged.end());
}
ArrayRef<Module *>
ASTContext::getModulesWithMergedDefinition(const NamedDecl *Def) {
auto MergedIt =
MergedDefModules.find(cast<NamedDecl>(Def->getCanonicalDecl()));
if (MergedIt == MergedDefModules.end())
return None;
return MergedIt->second;
}
void ASTContext::PerModuleInitializers::resolve(ASTContext &Ctx) {
if (LazyInitializers.empty())
return;
@ -1606,7 +1616,7 @@ void ASTContext::getOverriddenMethods(
}
void ASTContext::addedLocalImportDecl(ImportDecl *Import) {
assert(!Import->NextLocalImport && "Import declaration already in the chain");
assert(!Import->getNextLocalImport() && "Import declaration already in the chain");
assert(!Import->isFromASTFile() && "Non-local import declaration");
if (!FirstLocalImport) {
FirstLocalImport = Import;
@ -1614,7 +1624,7 @@ void ASTContext::addedLocalImportDecl(ImportDecl *Import) {
return;
}
LastLocalImport->NextLocalImport = Import;
LastLocalImport->setNextLocalImport(Import);
LastLocalImport = Import;
}

View File

@ -4896,7 +4896,8 @@ static unsigned getNumModuleIdentifiers(Module *Mod) {
ImportDecl::ImportDecl(DeclContext *DC, SourceLocation StartLoc,
Module *Imported,
ArrayRef<SourceLocation> IdentifierLocs)
: Decl(Import, DC, StartLoc), ImportedAndComplete(Imported, true) {
: Decl(Import, DC, StartLoc), ImportedModule(Imported),
NextLocalImportAndComplete(nullptr, true) {
assert(getNumModuleIdentifiers(Imported) == IdentifierLocs.size());
auto *StoredLocs = getTrailingObjects<SourceLocation>();
std::uninitialized_copy(IdentifierLocs.begin(), IdentifierLocs.end(),
@ -4905,7 +4906,8 @@ ImportDecl::ImportDecl(DeclContext *DC, SourceLocation StartLoc,
ImportDecl::ImportDecl(DeclContext *DC, SourceLocation StartLoc,
Module *Imported, SourceLocation EndLoc)
: Decl(Import, DC, StartLoc), ImportedAndComplete(Imported, false) {
: Decl(Import, DC, StartLoc), ImportedModule(Imported),
NextLocalImportAndComplete(nullptr, false) {
*getTrailingObjects<SourceLocation>() = EndLoc;
}
@ -4934,7 +4936,7 @@ ImportDecl *ImportDecl::CreateDeserialized(ASTContext &C, unsigned ID,
}
ArrayRef<SourceLocation> ImportDecl::getIdentifierLocs() const {
if (!ImportedAndComplete.getInt())
if (!isImportComplete())
return None;
const auto *StoredLocs = getTrailingObjects<SourceLocation>();
@ -4943,7 +4945,7 @@ ArrayRef<SourceLocation> ImportDecl::getIdentifierLocs() const {
}
SourceRange ImportDecl::getSourceRange() const {
if (!ImportedAndComplete.getInt())
if (!isImportComplete())
return SourceRange(getLocation(), *getTrailingObjects<SourceLocation>());
return SourceRange(getLocation(), getIdentifierLocs().back());

View File

@ -29,7 +29,7 @@ char ExternalASTSource::ID;
ExternalASTSource::~ExternalASTSource() = default;
llvm::Optional<ExternalASTSource::ASTSourceDescriptor>
llvm::Optional<ASTSourceDescriptor>
ExternalASTSource::getSourceDescriptor(unsigned ID) {
return None;
}
@ -39,21 +39,6 @@ ExternalASTSource::hasExternalDefinitions(const Decl *D) {
return EK_ReplyHazy;
}
ExternalASTSource::ASTSourceDescriptor::ASTSourceDescriptor(const Module &M)
: Signature(M.Signature), ClangModule(&M) {
if (M.Directory)
Path = M.Directory->getName();
if (auto *File = M.getASTFile())
ASTFile = File->getName();
}
std::string ExternalASTSource::ASTSourceDescriptor::getModuleName() const {
if (ClangModule)
return ClangModule->Name;
else
return std::string(PCHModuleName);
}
void ExternalASTSource::FindFileRegionDecls(FileID File, unsigned Offset,
unsigned Length,
SmallVectorImpl<Decl *> &Decls) {}

View File

@ -13,6 +13,7 @@
// http://itanium-cxx-abi.github.io/cxx-abi/abi.html#mangling
//
//===----------------------------------------------------------------------===//
#include "clang/AST/Mangle.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
@ -27,6 +28,7 @@
#include "clang/AST/ExprObjC.h"
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/ABI.h"
#include "clang/Basic/Module.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/StringExtras.h"

View File

@ -15,6 +15,7 @@
#include "clang/AST/DeclOpenMP.h"
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/LocInfoType.h"
#include "clang/Basic/Module.h"
#include "clang/Basic/SourceManager.h"
using namespace clang;

View File

@ -658,3 +658,18 @@ void VisibleModuleSet::setVisible(Module *M, SourceLocation Loc,
};
VisitModule({M, nullptr});
}
ASTSourceDescriptor::ASTSourceDescriptor(const Module &M)
: Signature(M.Signature), ClangModule(&M) {
if (M.Directory)
Path = M.Directory->getName();
if (auto *File = M.getASTFile())
ASTFile = File->getName();
}
std::string ASTSourceDescriptor::getModuleName() const {
if (ClangModule)
return ClangModule->Name;
else
return std::string(PCHModuleName);
}

View File

@ -2431,9 +2431,8 @@ llvm::DIType *CGDebugInfo::CreateType(const ObjCInterfaceType *Ty,
return CreateTypeDefinition(Ty, Unit);
}
llvm::DIModule *
CGDebugInfo::getOrCreateModuleRef(ExternalASTSource::ASTSourceDescriptor Mod,
bool CreateSkeletonCU) {
llvm::DIModule *CGDebugInfo::getOrCreateModuleRef(ASTSourceDescriptor Mod,
bool CreateSkeletonCU) {
// Use the Module pointer as the key into the cache. This is a
// nullptr if the "Module" is a PCH, which is safe because we don't
// support chained PCH debug info, so there can only be a single PCH.
@ -2498,9 +2497,8 @@ CGDebugInfo::getOrCreateModuleRef(ExternalASTSource::ASTSourceDescriptor Mod,
llvm::DIModule *Parent =
IsRootModule ? nullptr
: getOrCreateModuleRef(
ExternalASTSource::ASTSourceDescriptor(*M->Parent),
CreateSkeletonCU);
: getOrCreateModuleRef(ASTSourceDescriptor(*M->Parent),
CreateSkeletonCU);
llvm::DIModule *DIMod =
DBuilder.createModule(Parent, Mod.getModuleName(), ConfigMacros,
Mod.getPath());
@ -3057,7 +3055,7 @@ llvm::DIModule *CGDebugInfo::getParentModuleOrNull(const Decl *D) {
// option.
if (Module *M = D->getOwningModule()) {
// This is a (sub-)module.
auto Info = ExternalASTSource::ASTSourceDescriptor(*M);
auto Info = ASTSourceDescriptor(*M);
return getOrCreateModuleRef(Info, /*SkeletonCU=*/false);
} else {
// This the precompiled header being built.
@ -4715,7 +4713,7 @@ void CGDebugInfo::EmitImportDecl(const ImportDecl &ID) {
if (CGM.getCodeGenOpts().getDebuggerTuning() != llvm::DebuggerKind::LLDB)
return;
if (Module *M = ID.getImportedModule()) {
auto Info = ExternalASTSource::ASTSourceDescriptor(*M);
auto Info = ASTSourceDescriptor(*M);
auto Loc = ID.getLocation();
DBuilder.createImportedDeclaration(
getCurrentContextDescriptor(cast<Decl>(ID.getDeclContext())),

View File

@ -20,6 +20,7 @@
#include "clang/AST/Type.h"
#include "clang/AST/TypeOrdering.h"
#include "clang/Basic/CodeGenOptions.h"
#include "clang/Basic/Module.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
@ -60,7 +61,7 @@ class CGDebugInfo {
llvm::DIBuilder DBuilder;
llvm::DICompileUnit *TheCU = nullptr;
ModuleMap *ClangModuleMap = nullptr;
ExternalASTSource::ASTSourceDescriptor PCHDescriptor;
ASTSourceDescriptor PCHDescriptor;
SourceLocation CurLoc;
llvm::MDNode *CurInlinedAt = nullptr;
llvm::DIType *VTablePtrType = nullptr;
@ -379,9 +380,7 @@ public:
/// When generating debug information for a clang module or
/// precompiled header, this module map will be used to determine
/// the module of origin of each Decl.
void setPCHDescriptor(ExternalASTSource::ASTSourceDescriptor PCH) {
PCHDescriptor = PCH;
}
void setPCHDescriptor(ASTSourceDescriptor PCH) { PCHDescriptor = PCH; }
/// @}
/// Update the current source location. If \arg loc is invalid it is
@ -590,9 +589,8 @@ private:
/// Get a reference to a clang module. If \p CreateSkeletonCU is true,
/// this also creates a split dwarf skeleton compile unit.
llvm::DIModule *
getOrCreateModuleRef(ExternalASTSource::ASTSourceDescriptor Mod,
bool CreateSkeletonCU);
llvm::DIModule *getOrCreateModuleRef(ASTSourceDescriptor Mod,
bool CreateSkeletonCU);
/// DebugTypeExtRefs: If \p D originated in a clang module, return it.
llvm::DIModule *getParentModuleOrNull(const Decl *D);

View File

@ -8491,10 +8491,10 @@ unsigned ASTReader::getModuleFileID(ModuleFile *F) {
return (I - PCHModules.end()) << 1;
}
llvm::Optional<ExternalASTSource::ASTSourceDescriptor>
llvm::Optional<ASTSourceDescriptor>
ASTReader::getSourceDescriptor(unsigned ID) {
if (const Module *M = getSubmodule(ID))
return ExternalASTSource::ASTSourceDescriptor(*M);
return ASTSourceDescriptor(*M);
// If there is only a single PCH, return it instead.
// Chained PCH are not supported.
@ -8503,8 +8503,8 @@ ASTReader::getSourceDescriptor(unsigned ID) {
ModuleFile &MF = ModuleMgr.getPrimaryModule();
StringRef ModuleName = llvm::sys::path::filename(MF.OriginalSourceFileName);
StringRef FileName = llvm::sys::path::filename(MF.FileName);
return ASTReader::ASTSourceDescriptor(ModuleName, MF.OriginalDir, FileName,
MF.Signature);
return ASTSourceDescriptor(ModuleName, MF.OriginalDir, FileName,
MF.Signature);
}
return None;
}

View File

@ -1968,8 +1968,8 @@ void ASTDeclReader::VisitCXXConversionDecl(CXXConversionDecl *D) {
void ASTDeclReader::VisitImportDecl(ImportDecl *D) {
VisitDecl(D);
D->ImportedAndComplete.setPointer(readModule());
D->ImportedAndComplete.setInt(Record.readInt());
D->ImportedModule = readModule();
D->setImportComplete(Record.readInt());
auto *StoredLocs = D->getTrailingObjects<SourceLocation>();
for (unsigned I = 0, N = Record.back(); I != N; ++I)
StoredLocs[I] = readSourceLocation();

View File

@ -9,6 +9,7 @@
#ifndef LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_ASTUTILS_H
#define LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_ASTUTILS_H
#include "clang/Basic/Module.h"
#include "clang/Sema/Lookup.h"
#include "clang/Sema/MultiplexExternalSemaSource.h"
#include "clang/Sema/Sema.h"
@ -71,7 +72,7 @@ public:
return m_Source->getModule(ID);
}
llvm::Optional<ASTSourceDescriptor>
llvm::Optional<clang::ASTSourceDescriptor>
getSourceDescriptor(unsigned ID) override {
return m_Source->getSourceDescriptor(ID);
}

View File

@ -40,6 +40,10 @@
class DWARFASTParserClang;
class PDBASTParser;
namespace clang {
class FileManager;
}
namespace lldb_private {
class ClangASTMetadata;