Priority = 400;
if (Priority != -1)
- AddGlobalCtor(Fn, Priority, COMDATKey);
+ AddGlobalCtor(Fn, Priority, ~0U, COMDATKey);
else
EmitPointerToInitFunc(D, Addr, Fn, ISA);
} else if (auto *IPA = D->getAttr<InitPriorityAttr>()) {
// SelectAny globals will be comdat-folded. Put the initializer into a
// COMDAT group associated with the global, so the initializers get folded
// too.
-
- AddGlobalCtor(Fn, 65535, COMDATKey);
+ I = DelayedCXXInitPosition.find(D);
+ // CXXGlobalInits.size() is the lex order number for the next deferred
+ // VarDecl. Use it when the current VarDecl is non-deferred. Although this
+ // lex order number is shared between current VarDecl and some following
+ // VarDecls, their order of insertion into `llvm.global_ctors` is the same
+ // as the lexing order and the following stable sort would preserve such
+ // order.
+ unsigned LexOrder =
+ I == DelayedCXXInitPosition.end() ? CXXGlobalInits.size() : I->second;
+ AddGlobalCtor(Fn, 65535, LexOrder, COMDATKey);
if (COMDATKey && (getTriple().isOSBinFormatELF() ||
getTarget().getCXXABI().isMicrosoft())) {
// When COMDAT is used on ELF or in the MS C++ ABI, the key must be in
#include "clang/CodeGen/BackendUtil.h"
#include "clang/CodeGen/ConstantInitBuilder.h"
#include "clang/Frontend/FrontendDiagnostic.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
if (PGOStats.hasDiagnostics())
PGOStats.reportDiagnostics(getDiags(), getCodeGenOpts().MainFileName);
}
+ llvm::stable_sort(GlobalCtors, [](const Structor &L, const Structor &R) {
+ return L.LexOrder < R.LexOrder;
+ });
EmitCtorList(GlobalCtors, "llvm.global_ctors");
EmitCtorList(GlobalDtors, "llvm.global_dtors");
EmitGlobalAnnotations();
/// AddGlobalCtor - Add a function to the list that will be called before
/// main() runs.
void CodeGenModule::AddGlobalCtor(llvm::Function *Ctor, int Priority,
+ unsigned LexOrder,
llvm::Constant *AssociatedData) {
// FIXME: Type coercion of void()* types.
- GlobalCtors.push_back(Structor(Priority, Ctor, AssociatedData));
+ GlobalCtors.push_back(Structor(Priority, LexOrder, Ctor, AssociatedData));
}
/// AddGlobalDtor - Add a function to the list that will be called
}
// FIXME: Type coercion of void()* types.
- GlobalDtors.push_back(Structor(Priority, Dtor, nullptr));
+ GlobalDtors.push_back(Structor(Priority, ~0U, Dtor, nullptr));
}
void CodeGenModule::EmitCtorList(CtorList &Fns, const char *GlobalName) {
public:
struct Structor {
- Structor() : Priority(0), Initializer(nullptr), AssociatedData(nullptr) {}
- Structor(int Priority, llvm::Constant *Initializer,
+ Structor()
+ : Priority(0), LexOrder(~0u), Initializer(nullptr),
+ AssociatedData(nullptr) {}
+ Structor(int Priority, unsigned LexOrder, llvm::Constant *Initializer,
llvm::Constant *AssociatedData)
- : Priority(Priority), Initializer(Initializer),
+ : Priority(Priority), LexOrder(LexOrder), Initializer(Initializer),
AssociatedData(AssociatedData) {}
int Priority;
+ unsigned LexOrder;
llvm::Constant *Initializer;
llvm::Constant *AssociatedData;
};
// FIXME: Hardcoding priority here is gross.
void AddGlobalCtor(llvm::Function *Ctor, int Priority = 65535,
+ unsigned LexOrder = ~0U,
llvm::Constant *AssociatedData = nullptr);
void AddGlobalDtor(llvm::Function *Dtor, int Priority = 65535,
bool IsDtorAttrFunc = false);
}
CGF.FinishFunction();
- AddGlobalCtor(GlobalInitFn, Priority, nullptr);
+ AddGlobalCtor(GlobalInitFn, Priority);
}
if (getCXXABI().useSinitAndSterm())
--- /dev/null
+// RUN: %clang_cc1 -std=c++17 -S -emit-llvm -disable-llvm-passes -o - %s -triple x86_64-linux-gnu | FileCheck %s
+
+struct A {
+ int x;
+ A(int x) : x(x) {}
+ ~A() {}
+};
+
+namespace DeferredSequence {
+inline int a = 1;
+inline int b = a + 1;
+inline int c = b + 1;
+inline int d = c + 1;
+int e = d;
+}
+
+namespace MixedSequence {
+inline A a(1);
+inline int x = a.x + 1;
+inline int y = x + 1;
+inline A b(y);
+inline int z = b.x + 1;
+inline int w = z + 1;
+inline A c(b.x);
+inline A d(c.x);
+int t = w;
+}
+
+namespace NonDeferredSequence {
+inline A a(1);
+inline A b(a.x);
+inline A c(b.x);
+inline A d(c.x);
+}
+
+// CHECK: @llvm.global_ctors = appending global [16 x { i32, ptr, ptr }] [
+// CHECK-SAME: { i32, ptr, ptr } { i32 65535, ptr @__cxx_global_var_init.12, ptr @_ZN16DeferredSequence1bE },
+// CHECK-SAME: { i32, ptr, ptr } { i32 65535, ptr @__cxx_global_var_init.11, ptr @_ZN16DeferredSequence1cE },
+// CHECK-SAME: { i32, ptr, ptr } { i32 65535, ptr @__cxx_global_var_init.10, ptr @_ZN16DeferredSequence1dE },
+// CHECK-SAME: { i32, ptr, ptr } { i32 65535, ptr @__cxx_global_var_init.1, ptr @_ZN13MixedSequence1aE },
+// CHECK-SAME: { i32, ptr, ptr } { i32 65535, ptr @__cxx_global_var_init.14, ptr @_ZN13MixedSequence1xE },
+// CHECK-SAME: { i32, ptr, ptr } { i32 65535, ptr @__cxx_global_var_init.13, ptr @_ZN13MixedSequence1yE },
+// CHECK-SAME: { i32, ptr, ptr } { i32 65535, ptr @__cxx_global_var_init.2, ptr @_ZN13MixedSequence1bE },
+// CHECK-SAME: { i32, ptr, ptr } { i32 65535, ptr @__cxx_global_var_init.16, ptr @_ZN13MixedSequence1zE },
+// CHECK-SAME: { i32, ptr, ptr } { i32 65535, ptr @__cxx_global_var_init.15, ptr @_ZN13MixedSequence1wE },
+// CHECK-SAME: { i32, ptr, ptr } { i32 65535, ptr @__cxx_global_var_init.3, ptr @_ZN13MixedSequence1cE },
+// CHECK-SAME: { i32, ptr, ptr } { i32 65535, ptr @__cxx_global_var_init.4, ptr @_ZN13MixedSequence1dE },
+// CHECK-SAME: { i32, ptr, ptr } { i32 65535, ptr @__cxx_global_var_init.6, ptr @_ZN19NonDeferredSequence1aE },
+// CHECK-SAME: { i32, ptr, ptr } { i32 65535, ptr @__cxx_global_var_init.7, ptr @_ZN19NonDeferredSequence1bE },
+// CHECK-SAME: { i32, ptr, ptr } { i32 65535, ptr @__cxx_global_var_init.8, ptr @_ZN19NonDeferredSequence1cE },
+// CHECK-SAME: { i32, ptr, ptr } { i32 65535, ptr @__cxx_global_var_init.9, ptr @_ZN19NonDeferredSequence1dE },
+// CHECK-SAME: { i32, ptr, ptr } { i32 65535, ptr @_GLOBAL__sub_I_static_init_inline_variable.cpp, ptr null }