summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Korobeynikov <asl@math.spbu.ru>2012-11-06 22:44:45 +0000
committerAnton Korobeynikov <asl@math.spbu.ru>2012-11-06 22:44:45 +0000
commit4179ddd5752ec5a252ca1e1eb77a5c34b5835d3b (patch)
treefa0696c30f2a3e090dfbb9941e94dd58ad160c75
parente5b4666d9b86ea30b90b599691e75d380f84ddd6 (diff)
downloadclang-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.cpp54
-rw-r--r--lib/CodeGen/CodeGenModule.h13
-rw-r--r--test/CodeGenCXX/init-priority-attr.cpp46
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)));