Skip to content

[clang] Allocate Module instances in BumpPtrAllocator #112795

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Oct 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions clang/include/clang/Basic/Module.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ namespace clang {

class FileManager;
class LangOptions;
class ModuleMap;
class TargetInfo;

/// Describes the name of a module.
Expand Down Expand Up @@ -99,6 +100,15 @@ struct ASTFileSignature : std::array<uint8_t, 20> {
}
};

/// Required to construct a Module.
///
/// This tag type is only constructible by ModuleMap, guaranteeing it ownership
/// of all Module instances.
class ModuleConstructorTag {
explicit ModuleConstructorTag() = default;
friend ModuleMap;
};

/// Describes a module or submodule.
///
/// Aligned to 8 bytes to allow for llvm::PointerIntPair<Module *, 3>.
Expand Down Expand Up @@ -497,8 +507,9 @@ class alignas(8) Module {
std::vector<Conflict> Conflicts;

/// Construct a new module or submodule.
Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,
bool IsFramework, bool IsExplicit, unsigned VisibilityID);
Module(ModuleConstructorTag, StringRef Name, SourceLocation DefinitionLoc,
Module *Parent, bool IsFramework, bool IsExplicit,
unsigned VisibilityID);

~Module();

Expand Down Expand Up @@ -749,7 +760,6 @@ class alignas(8) Module {
///
/// \returns The submodule if found, or NULL otherwise.
Module *findSubmodule(StringRef Name) const;
Module *findOrInferSubmodule(StringRef Name);

/// Get the Global Module Fragment (sub-module) for this module, it there is
/// one.
Expand Down
9 changes: 7 additions & 2 deletions clang/include/clang/Lex/ModuleMap.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,12 @@ class ModuleMap {
/// named LangOpts::CurrentModule, if we've loaded it).
Module *SourceModule = nullptr;

/// The allocator for all (sub)modules.
llvm::SpecificBumpPtrAllocator<Module> ModulesAlloc;

/// Submodules of the current module that have not yet been attached to it.
/// (Ownership is transferred if/when we create an enclosing module.)
llvm::SmallVector<std::unique_ptr<Module>, 8> PendingSubmodules;
/// (Relationship is set up if/when we create an enclosing module.)
llvm::SmallVector<Module *, 8> PendingSubmodules;

/// The top-level modules that are known.
llvm::StringMap<Module *> Modules;
Expand Down Expand Up @@ -502,6 +505,8 @@ class ModuleMap {
/// \returns The named module, if known; otherwise, returns null.
Module *findModule(StringRef Name) const;

Module *findOrInferSubmodule(Module *Parent, StringRef Name);

/// Retrieve a module with the given name using lexical name lookup,
/// starting at the given context.
///
Expand Down
26 changes: 4 additions & 22 deletions clang/lib/Basic/Module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,9 @@

using namespace clang;

Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,
bool IsFramework, bool IsExplicit, unsigned VisibilityID)
Module::Module(ModuleConstructorTag, StringRef Name,
SourceLocation DefinitionLoc, Module *Parent, bool IsFramework,
bool IsExplicit, unsigned VisibilityID)
: Name(Name), DefinitionLoc(DefinitionLoc), Parent(Parent),
VisibilityID(VisibilityID), IsUnimportable(false),
HasIncompatibleModuleFile(false), IsAvailable(true),
Expand All @@ -58,11 +59,7 @@ Module::Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent,
}
}

Module::~Module() {
for (auto *Submodule : SubModules) {
delete Submodule;
}
}
Module::~Module() = default;

static bool isPlatformEnvironment(const TargetInfo &Target, StringRef Feature) {
StringRef Platform = Target.getPlatformName();
Expand Down Expand Up @@ -361,21 +358,6 @@ Module *Module::findSubmodule(StringRef Name) const {
return SubModules[Pos->getValue()];
}

Module *Module::findOrInferSubmodule(StringRef Name) {
llvm::StringMap<unsigned>::const_iterator Pos = SubModuleIndex.find(Name);
if (Pos != SubModuleIndex.end())
return SubModules[Pos->getValue()];
if (!InferSubmodules)
return nullptr;
Module *Result = new Module(Name, SourceLocation(), this, false, InferExplicitSubmodules, 0);
Result->InferExplicitSubmodules = InferExplicitSubmodules;
Result->InferSubmodules = InferSubmodules;
Result->InferExportWildcard = InferExportWildcard;
if (Result->InferExportWildcard)
Result->Exports.push_back(Module::ExportDecl(nullptr, true));
return Result;
}

Module *Module::getGlobalModuleFragment() const {
assert(isNamedModuleUnit() && "We should only query the global module "
"fragment from the C++20 Named modules");
Expand Down
72 changes: 42 additions & 30 deletions clang/lib/Lex/ModuleMap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -362,12 +362,7 @@ ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags,
MMapLangOpts.LineComment = true;
}

ModuleMap::~ModuleMap() {
for (auto &M : Modules)
delete M.getValue();
for (auto *M : ShadowModules)
delete M;
}
ModuleMap::~ModuleMap() = default;

void ModuleMap::setTarget(const TargetInfo &Target) {
assert((!this->Target || this->Target == &Target) &&
Expand Down Expand Up @@ -831,6 +826,22 @@ Module *ModuleMap::findModule(StringRef Name) const {
return nullptr;
}

Module *ModuleMap::findOrInferSubmodule(Module *Parent, StringRef Name) {
if (Module *SubM = Parent->findSubmodule(Name))
return SubM;
if (!Parent->InferSubmodules)
return nullptr;
Module *Result = new (ModulesAlloc.Allocate())
Module(ModuleConstructorTag{}, Name, SourceLocation(), Parent, false,
Parent->InferExplicitSubmodules, 0);
Result->InferExplicitSubmodules = Parent->InferExplicitSubmodules;
Result->InferSubmodules = Parent->InferSubmodules;
Result->InferExportWildcard = Parent->InferExportWildcard;
if (Result->InferExportWildcard)
Result->Exports.push_back(Module::ExportDecl(nullptr, true));
return Result;
}

Module *ModuleMap::lookupModuleUnqualified(StringRef Name,
Module *Context) const {
for(; Context; Context = Context->Parent) {
Expand All @@ -857,8 +868,9 @@ std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name,
return std::make_pair(Sub, false);

// Create a new module with this name.
Module *Result = new Module(Name, SourceLocation(), Parent, IsFramework,
IsExplicit, NumCreatedModules++);
Module *Result = new (ModulesAlloc.Allocate())
Module(ModuleConstructorTag{}, Name, SourceLocation(), Parent,
IsFramework, IsExplicit, NumCreatedModules++);
if (!Parent) {
if (LangOpts.CurrentModule == Name)
SourceModule = Result;
Expand All @@ -870,8 +882,9 @@ std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name,

Module *ModuleMap::createGlobalModuleFragmentForModuleUnit(SourceLocation Loc,
Module *Parent) {
auto *Result = new Module("<global>", Loc, Parent, /*IsFramework*/ false,
/*IsExplicit*/ true, NumCreatedModules++);
auto *Result = new (ModulesAlloc.Allocate()) Module(
ModuleConstructorTag{}, "<global>", Loc, Parent, /*IsFramework=*/false,
/*IsExplicit=*/true, NumCreatedModules++);
Result->Kind = Module::ExplicitGlobalModuleFragment;
// If the created module isn't owned by a parent, send it to PendingSubmodules
// to wait for its parent.
Expand All @@ -888,35 +901,33 @@ ModuleMap::createImplicitGlobalModuleFragmentForModuleUnit(SourceLocation Loc,
// Note: Here the `IsExplicit` parameter refers to the semantics in clang
// modules. All the non-explicit submodules in clang modules will be exported
// too. Here we simplify the implementation by using the concept.
auto *Result =
new Module("<implicit global>", Loc, Parent, /*IsFramework=*/false,
/*IsExplicit=*/false, NumCreatedModules++);
auto *Result = new (ModulesAlloc.Allocate())
Module(ModuleConstructorTag{}, "<implicit global>", Loc, Parent,
/*IsFramework=*/false, /*IsExplicit=*/false, NumCreatedModules++);
Result->Kind = Module::ImplicitGlobalModuleFragment;
return Result;
}

Module *
ModuleMap::createPrivateModuleFragmentForInterfaceUnit(Module *Parent,
SourceLocation Loc) {
auto *Result =
new Module("<private>", Loc, Parent, /*IsFramework*/ false,
/*IsExplicit*/ true, NumCreatedModules++);
auto *Result = new (ModulesAlloc.Allocate()) Module(
ModuleConstructorTag{}, "<private>", Loc, Parent, /*IsFramework=*/false,
/*IsExplicit=*/true, NumCreatedModules++);
Result->Kind = Module::PrivateModuleFragment;
return Result;
}

Module *ModuleMap::createModuleUnitWithKind(SourceLocation Loc, StringRef Name,
Module::ModuleKind Kind) {
auto *Result =
new Module(Name, Loc, nullptr, /*IsFramework*/ false,
/*IsExplicit*/ false, NumCreatedModules++);
auto *Result = new (ModulesAlloc.Allocate())
Module(ModuleConstructorTag{}, Name, Loc, nullptr, /*IsFramework=*/false,
/*IsExplicit=*/false, NumCreatedModules++);
Result->Kind = Kind;

// Reparent any current global module fragment as a submodule of this module.
for (auto &Submodule : PendingSubmodules) {
for (auto &Submodule : PendingSubmodules)
Submodule->setParent(Result);
Submodule.release(); // now owned by parent
}
PendingSubmodules.clear();
return Result;
}
Expand Down Expand Up @@ -968,8 +979,9 @@ Module *ModuleMap::createHeaderUnit(SourceLocation Loc, StringRef Name,
assert(LangOpts.CurrentModule == Name && "module name mismatch");
assert(!Modules[Name] && "redefining existing module");

auto *Result = new Module(Name, Loc, nullptr, /*IsFramework*/ false,
/*IsExplicit*/ false, NumCreatedModules++);
auto *Result = new (ModulesAlloc.Allocate())
Module(ModuleConstructorTag{}, Name, Loc, nullptr, /*IsFramework=*/false,
/*IsExplicit=*/false, NumCreatedModules++);
Result->Kind = Module::ModuleHeaderUnit;
Modules[Name] = SourceModule = Result;
addHeader(Result, H, NormalHeader);
Expand Down Expand Up @@ -1082,9 +1094,9 @@ Module *ModuleMap::inferFrameworkModule(DirectoryEntryRef FrameworkDir,
if (!UmbrellaHeader)
return nullptr;

Module *Result = new Module(ModuleName, SourceLocation(), Parent,
/*IsFramework=*/true, /*IsExplicit=*/false,
NumCreatedModules++);
Module *Result = new (ModulesAlloc.Allocate())
Module(ModuleConstructorTag{}, ModuleName, SourceLocation(), Parent,
/*IsFramework=*/true, /*IsExplicit=*/false, NumCreatedModules++);
InferredModuleAllowedBy[Result] = ModuleMapFID;
Result->IsInferred = true;
if (!Parent) {
Expand Down Expand Up @@ -1173,9 +1185,9 @@ Module *ModuleMap::createShadowedModule(StringRef Name, bool IsFramework,
Module *ShadowingModule) {

// Create a new module with this name.
Module *Result =
new Module(Name, SourceLocation(), /*Parent=*/nullptr, IsFramework,
/*IsExplicit=*/false, NumCreatedModules++);
Module *Result = new (ModulesAlloc.Allocate())
Module(ModuleConstructorTag{}, Name, SourceLocation(), /*Parent=*/nullptr,
IsFramework, /*IsExplicit=*/false, NumCreatedModules++);
Result->ShadowingModule = ShadowingModule;
Result->markUnavailable(/*Unimportable*/true);
ModuleScopeIDs[Result] = CurrentModuleScopeID;
Expand Down
3 changes: 2 additions & 1 deletion clang/lib/Lex/Pragma.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1752,14 +1752,15 @@ struct PragmaModuleBeginHandler : public PragmaHandler {
// Find the module we're entering. We require that a module map for it
// be loaded or implicitly loadable.
auto &HSI = PP.getHeaderSearchInfo();
auto &MM = HSI.getModuleMap();
Module *M = HSI.lookupModule(Current, ModuleName.front().second);
if (!M) {
PP.Diag(ModuleName.front().second,
diag::err_pp_module_begin_no_module_map) << Current;
return;
}
for (unsigned I = 1; I != ModuleName.size(); ++I) {
auto *NewM = M->findOrInferSubmodule(ModuleName[I].first->getName());
auto *NewM = MM.findOrInferSubmodule(M, ModuleName[I].first->getName());
if (!NewM) {
PP.Diag(ModuleName[I].second, diag::err_pp_module_begin_no_submodule)
<< M->getFullModuleName() << ModuleName[I].first;
Expand Down
Loading