[clang] Module global init mangling

C++20 modules require emission of an initializer function, which is
called by importers of the module.  This implements the mangling for
that function.  It is the one place the ABI exposes partition names in
symbols -- but fortunately only needed by other TUs of that same module.

Reviewed By: bruno

Differential Revision: https://reviews.llvm.org/D122741
This commit is contained in:
Nathan Sidwell 2022-03-22 10:49:08 -07:00
parent 02d3499a46
commit a1dcfb75ea
2 changed files with 28 additions and 5 deletions

View File

@ -199,6 +199,8 @@ public:
virtual void mangleDynamicStermFinalizer(const VarDecl *D, raw_ostream &) = 0;
virtual void mangleModuleInitializer(const Module *Module, raw_ostream &) = 0;
// This has to live here, otherwise the CXXNameMangler won't have access to
// it.
virtual DiscriminatorOverrideTy getDiscriminatorOverride() const = 0;

View File

@ -130,6 +130,8 @@ public:
void mangleLambdaSig(const CXXRecordDecl *Lambda, raw_ostream &) override;
void mangleModuleInitializer(const Module *Module, raw_ostream &) override;
bool getNextDiscriminator(const NamedDecl *ND, unsigned &disc) {
// Lambda closure types are already numbered.
if (isLambda(ND))
@ -438,7 +440,7 @@ public:
void mangleType(QualType T);
void mangleNameOrStandardSubstitution(const NamedDecl *ND);
void mangleLambdaSig(const CXXRecordDecl *Lambda);
void mangleModuleNamePrefix(StringRef Name);
void mangleModuleNamePrefix(StringRef Name, bool IsPartition = false);
private:
@ -1057,8 +1059,8 @@ void CXXNameMangler::mangleModuleName(const NamedDecl *ND) {
// ::= <module-name> <module-subname>
// ::= <substitution>
// <module-subname> ::= W <source-name>
// ::= W P <source-name> # not (yet) needed
void CXXNameMangler::mangleModuleNamePrefix(StringRef Name) {
// ::= W P <source-name>
void CXXNameMangler::mangleModuleNamePrefix(StringRef Name, bool IsPartition) {
// <substitution> ::= S <seq-id> _
auto It = ModuleSubstitutions.find(Name);
if (It != ModuleSubstitutions.end()) {
@ -1072,10 +1074,14 @@ void CXXNameMangler::mangleModuleNamePrefix(StringRef Name) {
auto Parts = Name.rsplit('.');
if (Parts.second.empty())
Parts.second = Parts.first;
else
mangleModuleNamePrefix(Parts.first);
else {
mangleModuleNamePrefix(Parts.first, IsPartition);
IsPartition = false;
}
Out << 'W';
if (IsPartition)
Out << 'P';
Out << Parts.second.size() << Parts.second;
ModuleSubstitutions.insert({Name, SeqID++});
}
@ -6533,6 +6539,21 @@ void ItaniumMangleContextImpl::mangleLambdaSig(const CXXRecordDecl *Lambda,
Mangler.mangleLambdaSig(Lambda);
}
void ItaniumMangleContextImpl::mangleModuleInitializer(const Module *M,
raw_ostream &Out) {
// <special-name> ::= GI <module-name> # module initializer function
CXXNameMangler Mangler(*this, Out);
Mangler.getStream() << "_ZGI";
Mangler.mangleModuleNamePrefix(M->getPrimaryModuleInterfaceName());
if (M->isModulePartition()) {
// The partition needs including, as partitions can have them too.
auto Partition = M->Name.find(':');
Mangler.mangleModuleNamePrefix(
StringRef(&M->Name[Partition + 1], M->Name.size() - Partition - 1),
/*IsPartition*/ true);
}
}
ItaniumMangleContext *ItaniumMangleContext::create(ASTContext &Context,
DiagnosticsEngine &Diags,
bool IsAux) {