diff options
author | Anton Korobeynikov <asl@math.spbu.ru> | 2012-11-06 22:44:45 +0000 |
---|---|---|
committer | Anton Korobeynikov <asl@math.spbu.ru> | 2012-11-06 22:44:45 +0000 |
commit | 4179ddd5752ec5a252ca1e1eb77a5c34b5835d3b (patch) | |
tree | fa0696c30f2a3e090dfbb9941e94dd58ad160c75 | |
parent | e5b4666d9b86ea30b90b599691e75d380f84ddd6 (diff) | |
download | clang-4179ddd5752ec5a252ca1e1eb77a5c34b5835d3b.tar.gz clang-4179ddd5752ec5a252ca1e1eb77a5c34b5835d3b.tar.bz2 clang-4179ddd5752ec5a252ca1e1eb77a5c34b5835d3b.tar.xz |
Implement codegen for init_priority attribute properly - make sure it
works between the modules.
No functionality change on Darwin/Windows.
This fixes PR11480.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@167496 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/CodeGen/CGDeclCXX.cpp | 54 | ||||
-rw-r--r-- | lib/CodeGen/CodeGenModule.h | 13 | ||||
-rw-r--r-- | test/CodeGenCXX/init-priority-attr.cpp | 46 |
3 files changed, 94 insertions, 19 deletions
diff --git a/lib/CodeGen/CGDeclCXX.cpp b/lib/CodeGen/CGDeclCXX.cpp index 4a81d8c9ea..65be3c19fb 100644 --- a/lib/CodeGen/CGDeclCXX.cpp +++ b/lib/CodeGen/CGDeclCXX.cpp @@ -16,6 +16,7 @@ #include "CGCXXABI.h" #include "clang/Frontend/CodeGenOptions.h" #include "llvm/Intrinsics.h" +#include "llvm/ADT/StringExtras.h" using namespace clang; using namespace CodeGen; @@ -255,8 +256,7 @@ CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D, OrderGlobalInits Key(order, PrioritizedCXXGlobalInits.size()); PrioritizedCXXGlobalInits.push_back(std::make_pair(Key, Fn)); DelayedCXXInitPosition.erase(D); - } - else { + } else { llvm::DenseMap<const Decl *, unsigned>::iterator I = DelayedCXXInitPosition.find(D); if (I == DelayedCXXInitPosition.end()) { @@ -279,28 +279,50 @@ CodeGenModule::EmitCXXGlobalInitFunc() { llvm::FunctionType *FTy = llvm::FunctionType::get(VoidTy, false); - // Create our global initialization function. - llvm::Function *Fn = - CreateGlobalInitOrDestructFunction(*this, FTy, "_GLOBAL__I_a"); + // Create our global initialization function. 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); - } - LocalCXXGlobalInits.append(CXXGlobalInits.begin(), CXXGlobalInits.end()); - CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, + PrioritizedCXXGlobalInits.end()); + // Iterate over "chunks" of ctors with same priority and emit each chunk + // into separate function. Note - everything is sorted first by priority, + // second - by lex order, so we emit ctor functions in proper order. + for (SmallVectorImpl<GlobalInitData >::iterator + I = PrioritizedCXXGlobalInits.begin(), + E = PrioritizedCXXGlobalInits.end(); I != E; ) { + SmallVectorImpl<GlobalInitData >::iterator + PrioE = std::upper_bound(I + 1, E, *I, GlobalInitPriorityCmp()); + + LocalCXXGlobalInits.clear(); + unsigned Priority = I->first.priority; + // Compute the function suffix from priority. Prepend with zeroes to make + // sure the function names are also ordered as priorities. + std::string PrioritySuffix = llvm::utostr(Priority); + // Priority is always <= 65535 (enforced by sema).. + PrioritySuffix = std::string(6-PrioritySuffix.size(), '0')+PrioritySuffix; + llvm::Function *Fn = + CreateGlobalInitOrDestructFunction(*this, FTy, + "_GLOBAL__I_" + PrioritySuffix); + + for (; I < PrioE; ++I) + LocalCXXGlobalInits.push_back(I->second); + + CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, &LocalCXXGlobalInits[0], LocalCXXGlobalInits.size()); + AddGlobalCtor(Fn, Priority); + } } - else - CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, - &CXXGlobalInits[0], - CXXGlobalInits.size()); + + llvm::Function *Fn = + CreateGlobalInitOrDestructFunction(*this, FTy, "_GLOBAL__I_a"); + + CodeGenFunction(*this).GenerateCXXGlobalInitFunc(Fn, + &CXXGlobalInits[0], + CXXGlobalInits.size()); AddGlobalCtor(Fn); + CXXGlobalInits.clear(); PrioritizedCXXGlobalInits.clear(); } diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h index d51a4670ba..1167c87ce1 100644 --- a/lib/CodeGen/CodeGenModule.h +++ b/lib/CodeGen/CodeGenModule.h @@ -296,11 +296,18 @@ class CodeGenModule : public CodeGenTypeCache { /// order. llvm::DenseMap<const Decl*, unsigned> DelayedCXXInitPosition; + typedef std::pair<OrderGlobalInits, llvm::Function*> GlobalInitData; + + struct GlobalInitPriorityCmp { + bool operator()(const GlobalInitData &LHS, + const GlobalInitData &RHS) const { + return LHS.first.priority < RHS.first.priority; + } + }; + /// - Global variables with initializers whose order of initialization /// is set by init_priority attribute. - - SmallVector<std::pair<OrderGlobalInits, llvm::Function*>, 8> - PrioritizedCXXGlobalInits; + SmallVector<GlobalInitData, 8> PrioritizedCXXGlobalInits; /// CXXGlobalDtors - Global destructor functions and arguments that need to /// run on termination. diff --git a/test/CodeGenCXX/init-priority-attr.cpp b/test/CodeGenCXX/init-priority-attr.cpp new file mode 100644 index 0000000000..ef9343cead --- /dev/null +++ b/test/CodeGenCXX/init-priority-attr.cpp @@ -0,0 +1,46 @@ +// RUN: %clang_cc1 %s -triple x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s +// PR + +void foo(int); + +class A { +public: + A() { foo(1); } +}; + +class A1 { +public: + A1() { foo(2); } +}; + +class B { +public: + B() { foo(3); } +}; + +class C { +public: + static A a; + C() { foo(4); } +}; + + +A C::a = A(); + +// CHECK: @llvm.global_ctors = appending global [3 x { i32, void ()* }] [{ i32, void ()* } { i32 200, void ()* @_GLOBAL__I_000200 }, { i32, void ()* } { i32 300, void ()* @_GLOBAL__I_000300 }, { i32, void ()* } { i32 65535, void ()* @_GLOBAL__I_a }] + +// CHECK: _GLOBAL__I_000200() +// CHECK_NEXT: _Z3fooi(i32 3) + +// CHECK: _GLOBAL__I_000300() +// CHECK_NEXT: _Z3fooi(i32 2) +// CHECK_NEXT: _Z3fooi(i32 1) + +// CHECK: _GLOBAL__I_a() +// CHECK_NEXT: _Z3fooi(i32 1) +// CHECK_NEXT: _Z3fooi(i32 4) + +C c; +A1 a1 __attribute__((init_priority (300))); +A a __attribute__((init_priority (300))); +B b __attribute__((init_priority (200))); |