Hi all. Please find update patch for pr11480.
I made all as it was proposed by Anton in bug description:
http://llvm.org/bugs/show_bug.cgi?id=11480#c0
So, main changes are in EmitCXXGlobalInitFunc and EmitCXXGlobalDtorFunc.
For ctors/dtors with init_priority attribute I just generate separated
init functions instead of single one. The exception is case when there
are some ctors/dtors with same priority. In that case I put its
invokation into a single init/dtor function, in order determined by its
order in code.
I also changed CGCXXABI::registerGlobalDtor. I added VarDecl parameter
here, since we need to now additional attributes of variable for which
it is registered (init_priority for example).
The test-case was also included into the patch.
-Stepan.
Index: test/CodeGenCXX/init_priority.cpp
===================================================================
--- test/CodeGenCXX/init_priority.cpp (revision 0)
+++ test/CodeGenCXX/init_priority.cpp (revision 0)
@@ -0,0 +1,51 @@
+// RUN: %clang_cc1 -emit-llvm %s -o - | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -fno-use-cxa-atexit -fapple-kext %s -o - | FileCheck %s --check-prefix=CHECK_GDTORS
+// RUN: %clang -x c++ -DENABLE_MAIN %s -o %t
+// RUN: chmod u+x %t
+// RUN: %t | FileCheck %s -check-prefix=CHECK_OUTPUT
+// RUN: rm %t
+
+
+// PR11480
+
+extern "C" int printf(...);
+
+class A {
+public:
+ A() { printf("a ctor "); }
+ ~A() { printf("a dtor "); }
+};
+
+class A1 {
+public:
+ A1() { printf("a1 ctor "); }
+ ~A1() { printf("a1 dtor "); }
+};
+
+class B {
+public:
+ B() { printf("b ctor "); }
+ ~B() { printf("b dtor "); }
+};
+
+class C {
+public:
+ C() { printf("c ctor "); }
+ ~C() { printf("c dtor "); }
+};
+
+C arrC;
+A1 arrA1 __attribute__((init_priority (300) ));
+A arrA __attribute__((init_priority (300) ));
+B arrB __attribute__((init_priority (200) ));
+
+//CHECK: @llvm.global_ctors = appending global [3 x { i32, void ()* }] [{ i32, void ()* } { i32 300, void ()* @_SAME_PRIO__I_a }, { i32, void ()* } { i32 200, void ()* @__cxx_global_var_init3 }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_a }]
+
+//CHECK_GDTORS: @llvm.global_dtors = appending global [3 x { i32, void ()* }] [{ i32, void ()* } { i32 65535, void ()* @_GLOBAL__D_a }, { i32, void ()* } { i32 300, void ()* @_SAME_PRIO__D_a }, { i32, void ()* } { i32 200, void ()* @__cxx_global_var_dtor }]
+
+#ifdef ENABLE_MAIN
+int main() { return 0; }
+#endif
+
+//CHECK_OUTPUT: b ctor a1 ctor a ctor c ctor c dtor a dtor a1 dtor b dtor
+
Index: lib/CodeGen/ItaniumCXXABI.cpp
===================================================================
--- lib/CodeGen/ItaniumCXXABI.cpp (revision 161663)
+++ lib/CodeGen/ItaniumCXXABI.cpp (working copy)
@@ -122,7 +122,9 @@
void EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D,
llvm::GlobalVariable *DeclPtr, bool PerformInit);
- void registerGlobalDtor(CodeGenFunction &CGF, llvm::Constant *dtor,
+ void registerGlobalDtor(CodeGenFunction &CGF,
+ const VarDecl &D,
+ llvm::Constant *dtor,
llvm::Constant *addr);
void EmitVTables(const CXXRecordDecl *Class);
@@ -1140,6 +1142,7 @@
/// Register a global destructor as best as we know how.
void ItaniumCXXABI::registerGlobalDtor(CodeGenFunction &CGF,
+ const VarDecl &D,
llvm::Constant *dtor,
llvm::Constant *addr) {
// Use __cxa_atexit if available.
@@ -1151,6 +1154,10 @@
// FIXME: shouldn't this be guarded by some variable?
if (CGM.getContext().getLangOpts().AppleKext) {
// Generate a global destructor entry.
+ if (D.hasAttr<InitPriorityAttr>()) {
+ unsigned int order = D.getAttr<InitPriorityAttr>()->getPriority();
+ return CGM.AddCXXPrioritizedDtorEntry(dtor, order, addr);
+ }
return CGM.AddCXXDtorEntry(dtor, addr);
}
Index: lib/CodeGen/CodeGenModule.h
===================================================================
--- lib/CodeGen/CodeGenModule.h (revision 161663)
+++ lib/CodeGen/CodeGenModule.h (working copy)
@@ -79,25 +79,6 @@
class CGCUDARuntime;
class BlockFieldFlags;
class FunctionArgList;
-
- struct OrderGlobalInits {
- unsigned int priority;
- unsigned int lex_order;
- OrderGlobalInits(unsigned int p, unsigned int l)
- : priority(p), lex_order(l) {}
-
- bool operator==(const OrderGlobalInits &RHS) const {
- return priority == RHS.priority &&
- lex_order == RHS.lex_order;
- }
-
- bool operator<(const OrderGlobalInits &RHS) const {
- if (priority < RHS.priority)
- return true;
-
- return priority == RHS.priority && lex_order < RHS.lex_order;
- }
- };
struct CodeGenTypeCache {
/// void
@@ -299,9 +280,19 @@
/// - Global variables with initializers whose order of initialization
/// is set by init_priority attribute.
- SmallVector<std::pair<OrderGlobalInits, llvm::Function*>, 8>
- PrioritizedCXXGlobalInits;
+ typedef llvm::DenseMap<unsigned int, llvm::SmallVector<llvm::Constant*, 4> >
+ GlobalInitsMap;
+ typedef GlobalInitsMap::iterator GlobalInitsMapIt;
+
+ typedef llvm::DenseMap<unsigned int,
+ std::vector<std::pair<llvm::WeakVH, llvm::Constant*> > >
+ GlobalDtorsMap;
+ typedef GlobalDtorsMap::iterator GlobalDtorsMapIt;
+
+ GlobalInitsMap PrioritizedCXXGlobalInits;
+ GlobalDtorsMap PrioritizedCXXGlobalDtors;
+
/// CXXGlobalDtors - Global destructor functions and arguments that need to
/// run on termination.
std::vector<std::pair<llvm::WeakVH,llvm::Constant*> > CXXGlobalDtors;
@@ -695,6 +686,11 @@
void AddCXXDtorEntry(llvm::Constant *DtorFn, llvm::Constant *Object) {
CXXGlobalDtors.push_back(std::make_pair(DtorFn, Object));
}
+ void AddCXXPrioritizedDtorEntry(llvm::Constant *DtorFn,
+ int Order,
+ llvm::Constant *Object) {
+ PrioritizedCXXGlobalDtors[Order].push_back(std::make_pair(DtorFn, Object));
+ }
/// CreateRuntimeFunction - Create a new runtime function with the specified
/// type and name.
@@ -956,6 +952,8 @@
// FIXME: Hardcoding priority here is gross.
void AddGlobalCtor(llvm::Function *Ctor, int Priority=65535);
void AddGlobalDtor(llvm::Function *Dtor, int Priority=65535);
+ void AddGlobalCtorForGroup(llvm::Constant** Ctors, unsigned Size,
+ const char* Name, int Priority=65535);
/// EmitCtorList - Generates a global array of functions and priorities using
/// the given list and name. This array will have appending linkage and is
Index: lib/CodeGen/CGExpr.cpp
===================================================================
--- lib/CodeGen/CGExpr.cpp (revision 161663)
+++ lib/CodeGen/CGExpr.cpp (working copy)
@@ -495,8 +495,9 @@
if (ReferenceTemporaryDtor) {
llvm::Constant *DtorFn =
CGM.GetAddrOfCXXDestructor(ReferenceTemporaryDtor, Dtor_Complete);
- CGM.getCXXABI().registerGlobalDtor(*this, DtorFn,
- cast<llvm::Constant>(ReferenceTemporary));
+ CGM.getCXXABI().registerGlobalDtor(
+ *this, *VD, DtorFn,
+ cast<llvm::Constant>(ReferenceTemporary));
} else {
assert(!ObjCARCReferenceLifetimeType.isNull());
// Note: We intentionally do not register a global "destructor" to
Index: lib/CodeGen/CGCXXABI.h
===================================================================
--- lib/CodeGen/CGCXXABI.h (revision 161663)
+++ lib/CodeGen/CGCXXABI.h (working copy)
@@ -279,9 +279,13 @@
/// Emit code to force the execution of a destructor during global
/// teardown. The default implementation of this uses atexit.
///
+ /// \param D - a declaration of variable for which the destructor should be
+ /// registered.
/// \param dtor - a function taking a single pointer argument
/// \param addr - a pointer to pass to the destructor function.
- virtual void registerGlobalDtor(CodeGenFunction &CGF, llvm::Constant *dtor,
+ virtual void registerGlobalDtor(CodeGenFunction &CGF,
+ const VarDecl &D,
+ llvm::Constant *dtor,
llvm::Constant *addr);
/***************************** Virtual Tables *******************************/
Index: lib/CodeGen/CGDeclCXX.cpp
===================================================================
--- lib/CodeGen/CGDeclCXX.cpp (revision 161663)
+++ lib/CodeGen/CGDeclCXX.cpp (working copy)
@@ -98,7 +98,7 @@
argument = llvm::Constant::getNullValue(CGF.Int8PtrTy);
}
- CGM.getCXXABI().registerGlobalDtor(CGF, function, argument);
+ CGM.getCXXABI().registerGlobalDtor(CGF, D, function, argument);
}
/// Emit code to cause the variable at the given address to be considered as
@@ -249,8 +249,7 @@
if (D->hasAttr<InitPriorityAttr>()) {
unsigned int order = D->getAttr<InitPriorityAttr>()->getPriority();
- OrderGlobalInits Key(order, PrioritizedCXXGlobalInits.size());
- PrioritizedCXXGlobalInits.push_back(std::make_pair(Key, Fn));
+ PrioritizedCXXGlobalInits[order].push_back(Fn);
DelayedCXXInitPosition.erase(D);
}
else {
@@ -266,6 +265,22 @@
}
}
+void CodeGenModule::AddGlobalCtorForGroup(
+ llvm::Constant** Ctors,
+ unsigned Size,
+ const char* Name,
+ int Priority) {
+
+ llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
+
+ // Create our global initialization function.
+ llvm::Function *Fn =
+ CreateGlobalInitOrDestructFunction(*this, FTy, Name);
+
+ CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, Ctors, Size);
+ AddGlobalCtor(Fn, Priority);
+}
+
void
CodeGenModule::EmitCXXGlobalInitFunc() {
while (!CXXGlobalInits.empty() && !CXXGlobalInits.back())
@@ -274,46 +289,54 @@
if (CXXGlobalInits.empty() && PrioritizedCXXGlobalInits.empty())
return;
- llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
-
- // Create our global initialization function.
- llvm::Function *Fn =
- CreateGlobalInitOrDestructFunction(*this, FTy, "_GLOBAL__I_a");
-
if (!PrioritizedCXXGlobalInits.empty()) {
- SmallVector<llvm::Constant*, 8> LocalCXXGlobalInits;
- llvm::array_pod_sort(PrioritizedCXXGlobalInits.begin(),
- PrioritizedCXXGlobalInits.end());
- for (unsigned i = 0; i < PrioritizedCXXGlobalInits.size(); i++) {
- llvm::Function *Fn = PrioritizedCXXGlobalInits[i].second;
- LocalCXXGlobalInits.push_back(Fn);
+ for (GlobalInitsMapIt i = PrioritizedCXXGlobalInits.begin(),
+ e = PrioritizedCXXGlobalInits.end(); i != e; ++i) {
+ llvm::SmallVector<llvm::Constant*, 4> &SamePrioCtors = i->second;
+
+ if (SamePrioCtors.size() > 1)
+ AddGlobalCtorForGroup(
+ &SamePrioCtors[0], SamePrioCtors.size(), "_SAME_PRIO__I_a", i->first);
+ else {
+ llvm::Function *Fn = cast<llvm::Function>(SamePrioCtors[0]);
+ AddGlobalCtor(Fn, i->first);
+ }
}
- LocalCXXGlobalInits.append(CXXGlobalInits.begin(), CXXGlobalInits.end());
- CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn,
- &LocalCXXGlobalInits[0],
- LocalCXXGlobalInits.size());
}
- else
- CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn,
- &CXXGlobalInits[0],
- CXXGlobalInits.size());
- AddGlobalCtor(Fn);
+ if (!CXXGlobalInits.empty())
+ AddGlobalCtorForGroup(
+ &CXXGlobalInits[0], CXXGlobalInits.size(), "_GLOBAL__I_a");
+
CXXGlobalInits.clear();
PrioritizedCXXGlobalInits.clear();
}
void CodeGenModule::EmitCXXGlobalDtorFunc() {
- if (CXXGlobalDtors.empty())
- return;
- llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
+ if (!CXXGlobalDtors.empty()) {
- // Create our global destructor function.
- llvm::Function *Fn =
- CreateGlobalInitOrDestructFunction(*this, FTy, "_GLOBAL__D_a");
+ llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
+
+ // Create our global destructor function.
+ llvm::Function *Fn =
+ CreateGlobalInitOrDestructFunction(*this, FTy, "_GLOBAL__D_a");
+
+ CodeGenFunction(*this).GenerateCXXGlobalDtorsFunc(Fn, CXXGlobalDtors);
+ AddGlobalDtor(Fn);
+ }
- CodeGenFunction(*this).GenerateCXXGlobalDtorsFunc(Fn, CXXGlobalDtors);
- AddGlobalDtor(Fn);
+ if (!PrioritizedCXXGlobalDtors.empty()) {
+ for (GlobalDtorsMapIt i = PrioritizedCXXGlobalDtors.begin(),
+ e = PrioritizedCXXGlobalDtors.end(); i != e; ++i) {
+ llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false);
+ const char* Name = i->second.size() == 1 ?
+ "__cxx_global_var_dtor" : "_SAME_PRIO__D_a";
+ llvm::Function *Fn =
+ CreateGlobalInitOrDestructFunction(*this, FTy, Name);
+ CodeGenFunction(*this).GenerateCXXGlobalDtorsFunc(Fn, i->second);
+ AddGlobalDtor(Fn, i->first);
+ }
+ }
}
/// Emit the code necessary to initialize the given global variable.
@@ -374,10 +397,11 @@
FunctionArgList(), SourceLocation());
// Emit the dtors, in reverse order from construction.
- for (unsigned i = 0, e = DtorsAndObjects.size(); i != e; ++i) {
- llvm::Value *Callee = DtorsAndObjects[e - i - 1].first;
+ for (unsigned i = DtorsAndObjects.size(); i != 0;) {
+ --i;
+ llvm::Value *Callee = DtorsAndObjects[i].first;
llvm::CallInst *CI = Builder.CreateCall(Callee,
- DtorsAndObjects[e - i - 1].second);
+ DtorsAndObjects[i].second);
// Make sure the call and the callee agree on calling convention.
if (llvm::Function *F = dyn_cast<llvm::Function>(Callee))
CI->setCallingConv(F->getCallingConv());
Index: lib/CodeGen/CGCXXABI.cpp
===================================================================
--- lib/CodeGen/CGCXXABI.cpp (revision 161663)
+++ lib/CodeGen/CGCXXABI.cpp (working copy)
@@ -222,6 +222,7 @@
}
void CGCXXABI::registerGlobalDtor(CodeGenFunction &CGF,
+ const VarDecl &D,
llvm::Constant *dtor,
llvm::Constant *addr) {
// The default behavior is to use atexit.
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits