summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/ItaniumMangle.cpp24
-rw-r--r--clang/lib/AST/MicrosoftMangle.cpp2
-rw-r--r--clang/lib/CodeGen/CGClass.cpp3
-rw-r--r--clang/lib/CodeGen/CodeGenModule.cpp4
-rw-r--r--clang/lib/CodeGen/CodeGenModule.h16
-rw-r--r--clang/lib/CodeGen/CodeGenTypes.h6
-rw-r--r--clang/lib/CodeGen/ItaniumCXXABI.cpp142
7 files changed, 149 insertions, 48 deletions
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index 486fab39eac..bdde133ac43 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -150,6 +150,8 @@ public:
void mangleCXXDtor(const CXXDestructorDecl *D, CXXDtorType Type,
raw_ostream &) override;
+ void mangleCXXCtorComdat(const CXXConstructorDecl *D, raw_ostream &) override;
+ void mangleCXXDtorComdat(const CXXDestructorDecl *D, raw_ostream &) override;
void mangleStaticGuardVariable(const VarDecl *D, raw_ostream &) override;
void mangleDynamicInitializer(const VarDecl *D, raw_ostream &Out) override;
void mangleDynamicAtExitDestructor(const VarDecl *D,
@@ -3249,8 +3251,8 @@ void CXXNameMangler::mangleFunctionParam(const ParmVarDecl *parm) {
void CXXNameMangler::mangleCXXCtorType(CXXCtorType T) {
// <ctor-dtor-name> ::= C1 # complete object constructor
// ::= C2 # base object constructor
- // ::= C3 # complete object allocating constructor
//
+ // In addition, C5 is a comdat name with C1 and C2 in it.
switch (T) {
case Ctor_Complete:
Out << "C1";
@@ -3258,8 +3260,8 @@ void CXXNameMangler::mangleCXXCtorType(CXXCtorType T) {
case Ctor_Base:
Out << "C2";
break;
- case Ctor_CompleteAllocating:
- Out << "C3";
+ case Ctor_Comdat:
+ Out << "C5";
break;
}
}
@@ -3269,6 +3271,7 @@ void CXXNameMangler::mangleCXXDtorType(CXXDtorType T) {
// ::= D1 # complete object destructor
// ::= D2 # base object destructor
//
+ // In addition, D5 is a comdat name with D1, D2 and, if virtual, D0 in it.
switch (T) {
case Dtor_Deleting:
Out << "D0";
@@ -3279,6 +3282,9 @@ void CXXNameMangler::mangleCXXDtorType(CXXDtorType T) {
case Dtor_Base:
Out << "D2";
break;
+ case Dtor_Comdat:
+ Out << "D5";
+ break;
}
}
@@ -3689,6 +3695,18 @@ void ItaniumMangleContextImpl::mangleCXXDtor(const CXXDestructorDecl *D,
Mangler.mangle(D);
}
+void ItaniumMangleContextImpl::mangleCXXCtorComdat(const CXXConstructorDecl *D,
+ raw_ostream &Out) {
+ CXXNameMangler Mangler(*this, Out, D, Ctor_Comdat);
+ Mangler.mangle(D);
+}
+
+void ItaniumMangleContextImpl::mangleCXXDtorComdat(const CXXDestructorDecl *D,
+ raw_ostream &Out) {
+ CXXNameMangler Mangler(*this, Out, D, Dtor_Comdat);
+ Mangler.mangle(D);
+}
+
void ItaniumMangleContextImpl::mangleThunk(const CXXMethodDecl *MD,
const ThunkInfo &Thunk,
raw_ostream &Out) {
diff --git a/clang/lib/AST/MicrosoftMangle.cpp b/clang/lib/AST/MicrosoftMangle.cpp
index ddb49635153..ba057e2084f 100644
--- a/clang/lib/AST/MicrosoftMangle.cpp
+++ b/clang/lib/AST/MicrosoftMangle.cpp
@@ -854,6 +854,8 @@ void MicrosoftCXXNameMangler::mangleCXXDtorType(CXXDtorType T) {
// <operator-name> ::= ?_E # vector deleting destructor
// FIXME: Add a vector deleting dtor type. It goes in the vtable, so we need
// it.
+ case Dtor_Comdat:
+ llvm_unreachable("not expecting a COMDAT");
}
llvm_unreachable("Unsupported dtor type?");
}
diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp
index 72869d8ca9b..941e998bfd7 100644
--- a/clang/lib/CodeGen/CGClass.cpp
+++ b/clang/lib/CodeGen/CGClass.cpp
@@ -1292,6 +1292,9 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
// we'd introduce *two* handler blocks. In the Microsoft ABI, we
// always delegate because we might not have a definition in this TU.
switch (DtorType) {
+ case Dtor_Comdat:
+ llvm_unreachable("not expecting a COMDAT");
+
case Dtor_Deleting: llvm_unreachable("already handled deleting case");
case Dtor_Complete:
diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp
index 9938c2401f9..5e87fc2799c 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -198,6 +198,10 @@ void CodeGenModule::createCUDARuntime() {
CUDARuntime = CreateNVCUDARuntime(*this);
}
+void CodeGenModule::addReplacement(StringRef Name, llvm::Constant *C) {
+ Replacements[Name] = C;
+}
+
void CodeGenModule::applyReplacements() {
for (ReplacementsTy::iterator I = Replacements.begin(),
E = Replacements.end();
diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h
index 6012606e3de..b36d4a66cd8 100644
--- a/clang/lib/CodeGen/CodeGenModule.h
+++ b/clang/lib/CodeGen/CodeGenModule.h
@@ -1058,9 +1058,17 @@ public:
void setFunctionDefinitionAttributes(const FunctionDecl *D,
llvm::Function *F);
-private:
llvm::GlobalValue *GetGlobalValue(StringRef Ref);
+ /// Set attributes which are common to any form of a global definition (alias,
+ /// Objective-C method, function, global variable).
+ ///
+ /// NOTE: This should only be called for definitions.
+ void SetCommonAttributes(const Decl *D, llvm::GlobalValue *GV);
+
+ void addReplacement(StringRef Name, llvm::Constant *C);
+private:
+
llvm::Constant *
GetOrCreateLLVMFunction(StringRef MangledName, llvm::Type *Ty, GlobalDecl D,
bool ForVTable, bool DontDefer = false,
@@ -1070,12 +1078,6 @@ private:
llvm::PointerType *PTy,
const VarDecl *D);
- /// Set attributes which are common to any form of a global definition (alias,
- /// Objective-C method, function, global variable).
- ///
- /// NOTE: This should only be called for definitions.
- void SetCommonAttributes(const Decl *D, llvm::GlobalValue *GV);
-
void setNonAliasAttributes(const Decl *D, llvm::GlobalObject *GO);
/// Set function attributes for a function declaration.
diff --git a/clang/lib/CodeGen/CodeGenTypes.h b/clang/lib/CodeGen/CodeGenTypes.h
index d422f554108..0ca274b8ff2 100644
--- a/clang/lib/CodeGen/CodeGenTypes.h
+++ b/clang/lib/CodeGen/CodeGenTypes.h
@@ -80,8 +80,8 @@ inline StructorType getFromCtorType(CXXCtorType T) {
return StructorType::Complete;
case Ctor_Base:
return StructorType::Base;
- case Ctor_CompleteAllocating:
- llvm_unreachable("invalid enum");
+ case Ctor_Comdat:
+ llvm_unreachable("not expecting a COMDAT");
}
llvm_unreachable("not a CXXCtorType");
}
@@ -106,6 +106,8 @@ inline StructorType getFromDtorType(CXXDtorType T) {
return StructorType::Complete;
case Dtor_Base:
return StructorType::Base;
+ case Dtor_Comdat:
+ llvm_unreachable("not expecting a COMDAT");
}
llvm_unreachable("not a CXXDtorType");
}
diff --git a/clang/lib/CodeGen/ItaniumCXXABI.cpp b/clang/lib/CodeGen/ItaniumCXXABI.cpp
index 91e9d4d7a08..038d890c9d6 100644
--- a/clang/lib/CodeGen/ItaniumCXXABI.cpp
+++ b/clang/lib/CodeGen/ItaniumCXXABI.cpp
@@ -2999,35 +2999,102 @@ ItaniumCXXABI::RTTIUniquenessKind ItaniumCXXABI::classifyRTTIUniqueness(
return RUK_NonUniqueVisible;
}
-static void emitCXXConstructor(CodeGenModule &CGM,
- const CXXConstructorDecl *ctor,
- StructorType ctorType) {
- if (!ctor->getParent()->getNumVBases() &&
- (ctorType == StructorType::Complete || ctorType == StructorType::Base)) {
- // The complete constructor is equivalent to the base constructor
- // for classes with no virtual bases. Try to emit it as an alias.
- bool ProducedAlias = !CGM.TryEmitDefinitionAsAlias(
- GlobalDecl(ctor, Ctor_Complete), GlobalDecl(ctor, Ctor_Base), true);
- if (ctorType == StructorType::Complete && ProducedAlias)
- return;
+// Find out how to codegen the complete destructor and constructor
+namespace {
+enum class StructorCodegen { Emit, RAUW, Alias, COMDAT };
+}
+static StructorCodegen getCodegenToUse(CodeGenModule &CGM,
+ const CXXMethodDecl *MD) {
+ if (!CGM.getCodeGenOpts().CXXCtorDtorAliases)
+ return StructorCodegen::Emit;
+
+ // The complete and base structors are not equivalent if there are any virtual
+ // bases, so emit separate functions.
+ if (MD->getParent()->getNumVBases())
+ return StructorCodegen::Emit;
+
+ GlobalDecl AliasDecl;
+ if (const auto *DD = dyn_cast<CXXDestructorDecl>(MD)) {
+ AliasDecl = GlobalDecl(DD, Dtor_Complete);
+ } else {
+ const auto *CD = cast<CXXConstructorDecl>(MD);
+ AliasDecl = GlobalDecl(CD, Ctor_Complete);
+ }
+ llvm::GlobalValue::LinkageTypes Linkage = CGM.getFunctionLinkage(AliasDecl);
+
+ if (llvm::GlobalValue::isDiscardableIfUnused(Linkage))
+ return StructorCodegen::RAUW;
+
+ // FIXME: Should we allow available_externally aliases?
+ if (!llvm::GlobalAlias::isValidLinkage(Linkage))
+ return StructorCodegen::RAUW;
+
+ if (llvm::GlobalValue::isWeakForLinker(Linkage))
+ return StructorCodegen::COMDAT;
+
+ return StructorCodegen::Alias;
+}
+
+static void emitConstructorDestructorAlias(CodeGenModule &CGM,
+ GlobalDecl AliasDecl,
+ GlobalDecl TargetDecl) {
+ llvm::GlobalValue::LinkageTypes Linkage = CGM.getFunctionLinkage(AliasDecl);
+
+ StringRef MangledName = CGM.getMangledName(AliasDecl);
+ llvm::GlobalValue *Entry = CGM.GetGlobalValue(MangledName);
+ if (Entry && !Entry->isDeclaration())
+ return;
+
+ auto *Aliasee = cast<llvm::GlobalValue>(CGM.GetAddrOfGlobal(TargetDecl));
+ llvm::PointerType *AliasType = Aliasee->getType();
+
+ // Create the alias with no name.
+ auto *Alias = llvm::GlobalAlias::create(
+ AliasType->getElementType(), 0, Linkage, "", Aliasee, &CGM.getModule());
+
+ // Switch any previous uses to the alias.
+ if (Entry) {
+ assert(Entry->getType() == AliasType &&
+ "declaration exists with different type");
+ Alias->takeName(Entry);
+ Entry->replaceAllUsesWith(Alias);
+ Entry->eraseFromParent();
+ } else {
+ Alias->setName(MangledName);
}
- CGM.codegenCXXStructor(ctor, ctorType);
-}
-
-static void emitCXXDestructor(CodeGenModule &CGM, const CXXDestructorDecl *dtor,
- StructorType dtorType) {
- // The complete destructor is equivalent to the base destructor for
- // classes with no virtual bases, so try to emit it as an alias.
- if (!dtor->getParent()->getNumVBases() &&
- (dtorType == StructorType::Complete || dtorType == StructorType::Base)) {
- bool ProducedAlias = !CGM.TryEmitDefinitionAsAlias(
- GlobalDecl(dtor, Dtor_Complete), GlobalDecl(dtor, Dtor_Base), true);
- if (ProducedAlias) {
- if (dtorType == StructorType::Complete)
- return;
- if (dtor->isVirtual())
- CGM.getVTables().EmitThunks(GlobalDecl(dtor, Dtor_Complete));
+ // Finally, set up the alias with its proper name and attributes.
+ CGM.SetCommonAttributes(cast<NamedDecl>(AliasDecl.getDecl()), Alias);
+}
+
+void ItaniumCXXABI::emitCXXStructor(const CXXMethodDecl *MD,
+ StructorType Type) {
+ auto *CD = dyn_cast<CXXConstructorDecl>(MD);
+ const CXXDestructorDecl *DD = CD ? nullptr : cast<CXXDestructorDecl>(MD);
+
+ StructorCodegen CGType = getCodegenToUse(CGM, MD);
+
+ if (Type == StructorType::Complete) {
+ GlobalDecl CompleteDecl;
+ GlobalDecl BaseDecl;
+ if (CD) {
+ CompleteDecl = GlobalDecl(CD, Ctor_Complete);
+ BaseDecl = GlobalDecl(CD, Ctor_Base);
+ } else {
+ CompleteDecl = GlobalDecl(DD, Dtor_Complete);
+ BaseDecl = GlobalDecl(DD, Dtor_Base);
+ }
+
+ if (CGType == StructorCodegen::Alias || CGType == StructorCodegen::COMDAT) {
+ emitConstructorDestructorAlias(CGM, CompleteDecl, BaseDecl);
+ return;
+ }
+
+ if (CGType == StructorCodegen::RAUW) {
+ StringRef MangledName = CGM.getMangledName(CompleteDecl);
+ auto *Aliasee = cast<llvm::GlobalValue>(CGM.GetAddrOfGlobal(BaseDecl));
+ CGM.addReplacement(MangledName, Aliasee);
+ return;
}
}
@@ -3035,17 +3102,20 @@ static void emitCXXDestructor(CodeGenModule &CGM, const CXXDestructorDecl *dtor,
// base class if there is exactly one non-virtual base class with a
// non-trivial destructor, there are no fields with a non-trivial
// destructor, and the body of the destructor is trivial.
- if (dtorType == StructorType::Base && !CGM.TryEmitBaseDestructorAsAlias(dtor))
+ if (DD && Type == StructorType::Base && CGType != StructorCodegen::COMDAT &&
+ !CGM.TryEmitBaseDestructorAsAlias(DD))
return;
- CGM.codegenCXXStructor(dtor, dtorType);
-}
+ llvm::Function *Fn = CGM.codegenCXXStructor(MD, Type);
-void ItaniumCXXABI::emitCXXStructor(const CXXMethodDecl *MD,
- StructorType Type) {
- if (auto *CD = dyn_cast<CXXConstructorDecl>(MD)) {
- emitCXXConstructor(CGM, CD, Type);
- return;
+ if (CGType == StructorCodegen::COMDAT) {
+ SmallString<256> Buffer;
+ llvm::raw_svector_ostream Out(Buffer);
+ if (DD)
+ getMangleContext().mangleCXXDtorComdat(DD, Out);
+ else
+ getMangleContext().mangleCXXCtorComdat(CD, Out);
+ llvm::Comdat *C = CGM.getModule().getOrInsertComdat(Out.str());
+ Fn->setComdat(C);
}
- emitCXXDestructor(CGM, cast<CXXDestructorDecl>(MD), Type);
}
OpenPOWER on IntegriCloud