[llvm] d865437 - [WebAssembly] Fix the order of destructors in the LowerGlobalDtors pass.
Dan Gohman via llvm-commits
llvm-commits at lists.llvm.org
Thu Mar 26 16:19:29 PDT 2020
Author: Dan Gohman
Date: 2020-03-26T16:19:02-07:00
New Revision: d865437d9c82f814dd3b0d0e60042e2c176e201f
URL: https://github.com/llvm/llvm-project/commit/d865437d9c82f814dd3b0d0e60042e2c176e201f
DIFF: https://github.com/llvm/llvm-project/commit/d865437d9c82f814dd3b0d0e60042e2c176e201f.diff
LOG: [WebAssembly] Fix the order of destructors in the LowerGlobalDtors pass.
Fix the LowerGlobalDtors pass to run destructors in the same order as the
regular LLVM destructor lowering -- in reverse order. Adjacent
destructors with the same associated object are grouped, but destructors
are not reordered based on associated objects.
Differential Revision: https://reviews.llvm.org/D70685
Added:
Modified:
llvm/lib/Target/WebAssembly/WebAssemblyLowerGlobalDtors.cpp
llvm/test/CodeGen/WebAssembly/lower-global-dtors.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyLowerGlobalDtors.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyLowerGlobalDtors.cpp
index 750b2233e67a..9ccbee819c35 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyLowerGlobalDtors.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyLowerGlobalDtors.cpp
@@ -76,9 +76,13 @@ bool LowerGlobalDtors::runOnModule(Module &M) {
!ETy->getTypeAtIndex(2U)->isPointerTy())
return false; // Not (int, ptr, ptr).
- // Collect the contents of @llvm.global_dtors, collated by priority and
- // associated symbol.
- std::map<uint16_t, MapVector<Constant *, std::vector<Constant *>>> DtorFuncs;
+ // Collect the contents of @llvm.global_dtors, ordered by priority. Within a
+ // priority, sequences of destructors with the same associated object are
+ // recorded so that we can register them as a group.
+ std::map<
+ uint16_t,
+ std::vector<std::pair<Constant *, std::vector<Constant *>>>
+ > DtorFuncs;
for (Value *O : InitList->operands()) {
auto *CS = dyn_cast<ConstantStruct>(O);
if (!CS)
@@ -96,7 +100,14 @@ bool LowerGlobalDtors::runOnModule(Module &M) {
Constant *Associated = CS->getOperand(2);
Associated = cast<Constant>(Associated->stripPointerCasts());
- DtorFuncs[PriorityValue][Associated].push_back(DtorFunc);
+ auto &AtThisPriority = DtorFuncs[PriorityValue];
+ if (AtThisPriority.empty() || AtThisPriority.back().first != Associated) {
+ std::vector<Constant *> NewList;
+ NewList.push_back(DtorFunc);
+ AtThisPriority.push_back(std::make_pair(Associated, NewList));
+ } else {
+ AtThisPriority.back().second.push_back(DtorFunc);
+ }
}
if (DtorFuncs.empty())
return false;
@@ -131,14 +142,19 @@ bool LowerGlobalDtors::runOnModule(Module &M) {
// first function with __cxa_atexit.
for (auto &PriorityAndMore : DtorFuncs) {
uint16_t Priority = PriorityAndMore.first;
- for (auto &AssociatedAndMore : PriorityAndMore.second) {
+ uint64_t Id = 0;
+ auto &AtThisPriority = PriorityAndMore.second;
+ for (auto &AssociatedAndMore : AtThisPriority) {
Constant *Associated = AssociatedAndMore.first;
+ auto ThisId = Id++;
Function *CallDtors = Function::Create(
AtExitFuncTy, Function::PrivateLinkage,
"call_dtors" +
(Priority != UINT16_MAX ? (Twine(".") + Twine(Priority))
: Twine()) +
+ (AtThisPriority.size() > 1 ? Twine("$") + Twine(ThisId)
+ : Twine()) +
(!Associated->isNullValue() ? (Twine(".") + Associated->getName())
: Twine()),
&M);
@@ -146,7 +162,7 @@ bool LowerGlobalDtors::runOnModule(Module &M) {
FunctionType *VoidVoid = FunctionType::get(Type::getVoidTy(C),
/*isVarArg=*/false);
- for (auto Dtor : AssociatedAndMore.second)
+ for (auto Dtor : reverse(AssociatedAndMore.second))
CallInst::Create(VoidVoid, Dtor, "", BB);
ReturnInst::Create(C, BB);
@@ -155,6 +171,8 @@ bool LowerGlobalDtors::runOnModule(Module &M) {
"register_call_dtors" +
(Priority != UINT16_MAX ? (Twine(".") + Twine(Priority))
: Twine()) +
+ (AtThisPriority.size() > 1 ? Twine("$") + Twine(ThisId)
+ : Twine()) +
(!Associated->isNullValue() ? (Twine(".") + Associated->getName())
: Twine()),
&M);
diff --git a/llvm/test/CodeGen/WebAssembly/lower-global-dtors.ll b/llvm/test/CodeGen/WebAssembly/lower-global-dtors.ll
index 57338e9109f6..38eec787db12 100644
--- a/llvm/test/CodeGen/WebAssembly/lower-global-dtors.ll
+++ b/llvm/test/CodeGen/WebAssembly/lower-global-dtors.ll
@@ -13,11 +13,18 @@ declare void @orig_dtor1b()
declare void @orig_dtor1c0()
declare void @orig_dtor1c1a()
declare void @orig_dtor1c1b()
-declare void @orig_dtor65536()
+declare void @orig_dtor1c2a()
+declare void @orig_dtor1c2b()
+declare void @orig_dtor1c3()
+declare void @orig_dtor1d()
+declare void @orig_dtor65535()
+declare void @orig_dtor65535c0()
declare void @after_the_null()
- at associated1c0 = external global i8
- at associated1c1 = external global i8
+ at associatedc0 = external global i8
+ at associatedc1 = external global i8
+ at associatedc2 = global i8 42
+ at associatedc3 = global i8 84
@llvm.global_ctors = appending global
[1 x { i32, void ()*, i8* }]
@@ -26,15 +33,20 @@ declare void @after_the_null()
]
@llvm.global_dtors = appending global
-[9 x { i32, void ()*, i8* }]
+[14 x { i32, void ()*, i8* }]
[
{ i32, void ()*, i8* } { i32 0, void ()* @orig_dtor0, i8* null },
{ i32, void ()*, i8* } { i32 1, void ()* @orig_dtor1a, i8* null },
{ i32, void ()*, i8* } { i32 1, void ()* @orig_dtor1b, i8* null },
- { i32, void ()*, i8* } { i32 1, void ()* @orig_dtor1c0, i8* @associated1c0 },
- { i32, void ()*, i8* } { i32 1, void ()* @orig_dtor1c1a, i8* @associated1c1 },
- { i32, void ()*, i8* } { i32 1, void ()* @orig_dtor1c1b, i8* @associated1c1 },
- { i32, void ()*, i8* } { i32 65535, void ()* @orig_dtor65536, i8* null },
+ { i32, void ()*, i8* } { i32 1, void ()* @orig_dtor1c0, i8* @associatedc0 },
+ { i32, void ()*, i8* } { i32 1, void ()* @orig_dtor1c1a, i8* @associatedc1 },
+ { i32, void ()*, i8* } { i32 1, void ()* @orig_dtor1c1b, i8* @associatedc1 },
+ { i32, void ()*, i8* } { i32 1, void ()* @orig_dtor1c2a, i8* @associatedc2 },
+ { i32, void ()*, i8* } { i32 1, void ()* @orig_dtor1c2b, i8* @associatedc2 },
+ { i32, void ()*, i8* } { i32 1, void ()* @orig_dtor1c3, i8* @associatedc3 },
+ { i32, void ()*, i8* } { i32 1, void ()* @orig_dtor1d, i8* null },
+ { i32, void ()*, i8* } { i32 65535, void ()* @orig_dtor65535c0, i8* @associatedc0 },
+ { i32, void ()*, i8* } { i32 65535, void ()* @orig_dtor65535, i8* null },
{ i32, void ()*, i8* } { i32 65535, void ()* null, i8* null },
{ i32, void ()*, i8* } { i32 65535, void ()* @after_the_null, i8* null }
]
@@ -54,14 +66,14 @@ declare void @after_the_null()
; CHECK-NEXT: unreachable
; CHECK: end_block
-; CHECK-LABEL: .Lcall_dtors.1:
-; CHECK-NEXT: .functype .Lcall_dtors.1 (i32) -> (){{$}}
-; CHECK-NEXT: call orig_dtor1a{{$}}
+; CHECK-LABEL: .Lcall_dtors.1$0:
+; CHECK-NEXT: .functype .Lcall_dtors.1$0 (i32) -> (){{$}}
; CHECK-NEXT: call orig_dtor1b{{$}}
+; CHECK-NEXT: call orig_dtor1a{{$}}
-; CHECK-LABEL: .Lregister_call_dtors.1:
+; CHECK-LABEL: .Lregister_call_dtors.1$0:
; CHECK: block
-; CHECK-NEXT: i32.const $push2=, .Lcall_dtors.1{{$}}
+; CHECK-NEXT: i32.const $push2=, .Lcall_dtors.1$0{{$}}
; CHECK-NEXT: i32.const $push1=, 0
; CHECK-NEXT: i32.const $push0=, __dso_handle
; CHECK-NEXT: call $push3=, __cxa_atexit, $pop2, $pop1, $pop0{{$}}
@@ -70,13 +82,13 @@ declare void @after_the_null()
; CHECK-NEXT: unreachable
; CHECK: end_block
-; CHECK-LABEL: .Lcall_dtors.1.associated1c0:
-; CHECK-NEXT: .functype .Lcall_dtors.1.associated1c0 (i32) -> (){{$}}
+; CHECK-LABEL: .Lcall_dtors.1$1.associatedc0:
+; CHECK-NEXT: .functype .Lcall_dtors.1$1.associatedc0 (i32) -> (){{$}}
; CHECK-NEXT: call orig_dtor1c0{{$}}
-; CHECK-LABEL: .Lregister_call_dtors.1.associated1c0:
+; CHECK-LABEL: .Lregister_call_dtors.1$1.associatedc0:
; CHECK: block
-; CHECK-NEXT: i32.const $push2=, .Lcall_dtors.1.associated1c0{{$}}
+; CHECK-NEXT: i32.const $push2=, .Lcall_dtors.1$1.associatedc0{{$}}
; CHECK-NEXT: i32.const $push1=, 0
; CHECK-NEXT: i32.const $push0=, __dso_handle
; CHECK-NEXT: call $push3=, __cxa_atexit, $pop2, $pop1, $pop0{{$}}
@@ -84,14 +96,57 @@ declare void @after_the_null()
; CHECK-NEXT: br_if 0, $pop4
; CHECK-NEXT: unreachable
-; CHECK-LABEL: .Lcall_dtors.1.associated1c1:
-; CHECK-NEXT: .functype .Lcall_dtors.1.associated1c1 (i32) -> (){{$}}
-; CHECK-NEXT: call orig_dtor1c1a{{$}}
+; CHECK-LABEL: .Lcall_dtors.1$2.associatedc1:
+; CHECK-NEXT: .functype .Lcall_dtors.1$2.associatedc1 (i32) -> (){{$}}
; CHECK-NEXT: call orig_dtor1c1b{{$}}
+; CHECK-NEXT: call orig_dtor1c1a{{$}}
+
+; CHECK-LABEL: .Lregister_call_dtors.1$2.associatedc1:
+; CHECK: block
+; CHECK-NEXT: i32.const $push2=, .Lcall_dtors.1$2.associatedc1{{$}}
+; CHECK-NEXT: i32.const $push1=, 0
+; CHECK-NEXT: i32.const $push0=, __dso_handle
+; CHECK-NEXT: call $push3=, __cxa_atexit, $pop2, $pop1, $pop0{{$}}
+; CHECK-NEXT: i32.eqz $push4=, $pop3
+; CHECK-NEXT: br_if 0, $pop4
+; CHECK-NEXT: unreachable
+
+; CHECK-LABEL: .Lcall_dtors.1$3.associatedc2:
+; CHECK-NEXT: .functype .Lcall_dtors.1$3.associatedc2 (i32) -> (){{$}}
+; CHECK-NEXT: call orig_dtor1c2b{{$}}
+; CHECK-NEXT: call orig_dtor1c2a{{$}}
+
+; CHECK-LABEL: .Lregister_call_dtors.1$3.associatedc2:
+; CHECK: block
+; CHECK-NEXT: i32.const $push2=, .Lcall_dtors.1$3.associatedc2{{$}}
+; CHECK-NEXT: i32.const $push1=, 0
+; CHECK-NEXT: i32.const $push0=, __dso_handle
+; CHECK-NEXT: call $push3=, __cxa_atexit, $pop2, $pop1, $pop0{{$}}
+; CHECK-NEXT: i32.eqz $push4=, $pop3
+; CHECK-NEXT: br_if 0, $pop4
+; CHECK-NEXT: unreachable
+
+; CHECK-LABEL: .Lcall_dtors.1$4.associatedc3:
+; CHECK-NEXT: .functype .Lcall_dtors.1$4.associatedc3 (i32) -> (){{$}}
+; CHECK-NEXT: call orig_dtor1c3{{$}}
+
+; CHECK-LABEL: .Lregister_call_dtors.1$4.associatedc3:
+; CHECK: block
+; CHECK-NEXT: i32.const $push2=, .Lcall_dtors.1$4.associatedc3{{$}}
+; CHECK-NEXT: i32.const $push1=, 0
+; CHECK-NEXT: i32.const $push0=, __dso_handle
+; CHECK-NEXT: call $push3=, __cxa_atexit, $pop2, $pop1, $pop0{{$}}
+; CHECK-NEXT: i32.eqz $push4=, $pop3
+; CHECK-NEXT: br_if 0, $pop4
+; CHECK-NEXT: unreachable
-; CHECK-LABEL: .Lregister_call_dtors.1.associated1c1:
+; CHECK-LABEL: .Lcall_dtors.1$5:
+; CHECK-NEXT: .functype .Lcall_dtors.1$5 (i32) -> (){{$}}
+; CHECK-NEXT: call orig_dtor1d{{$}}
+
+; CHECK-LABEL: .Lregister_call_dtors.1$5:
; CHECK: block
-; CHECK-NEXT: i32.const $push2=, .Lcall_dtors.1.associated1c1{{$}}
+; CHECK-NEXT: i32.const $push2=, .Lcall_dtors.1$5{{$}}
; CHECK-NEXT: i32.const $push1=, 0
; CHECK-NEXT: i32.const $push0=, __dso_handle
; CHECK-NEXT: call $push3=, __cxa_atexit, $pop2, $pop1, $pop0{{$}}
@@ -99,13 +154,17 @@ declare void @after_the_null()
; CHECK-NEXT: br_if 0, $pop4
; CHECK-NEXT: unreachable
-; CHECK-LABEL: .Lcall_dtors:
-; CHECK-NEXT: .functype .Lcall_dtors (i32) -> (){{$}}
-; CHECK-NEXT: call orig_dtor65536{{$}}
+; CHECK-LABEL: .Lcall_dtors$0.associatedc0:
+; CHECK-NEXT: .functype .Lcall_dtors$0.associatedc0 (i32) -> (){{$}}
+; CHECK-NEXT: call orig_dtor65535c0
+
+; CHECK-LABEL: .Lcall_dtors$1:
+; CHECK-NEXT: .functype .Lcall_dtors$1 (i32) -> (){{$}}
+; CHECK-NEXT: call orig_dtor65535{{$}}
-; CHECK-LABEL: .Lregister_call_dtors:
+; CHECK-LABEL: .Lregister_call_dtors$1:
; CHECK: block
-; CHECK-NEXT: i32.const $push2=, .Lcall_dtors{{$}}
+; CHECK-NEXT: i32.const $push2=, .Lcall_dtors$1{{$}}
; CHECK-NEXT: i32.const $push1=, 0
; CHECK-NEXT: i32.const $push0=, __dso_handle
; CHECK-NEXT: call $push3=, __cxa_atexit, $pop2, $pop1, $pop0{{$}}
@@ -116,11 +175,14 @@ declare void @after_the_null()
; CHECK-LABEL: .section .init_array.0,"",@
; CHECK: .int32 .Lregister_call_dtors.0{{$}}
; CHECK-LABEL: .section .init_array.1,"",@
-; CHECK: .int32 .Lregister_call_dtors.1{{$}}
+; CHECK: .int32 .Lregister_call_dtors.1$0{{$}}
+; CHECK-NEXT: .int32 .Lregister_call_dtors.1$3.associatedc2{{$}}
+; CHECK-NEXT: .int32 .Lregister_call_dtors.1$4.associatedc3{{$}}
+; CHECK-NEXT: .int32 .Lregister_call_dtors.1$5{{$}}
; CHECK-LABEL: .section .init_array.200,"",@
; CHECK: .int32 orig_ctor{{$}}
; CHECK-LABEL: .section .init_array,"",@
-; CHECK: .int32 .Lregister_call_dtors{{$}}
+; CHECK: .int32 .Lregister_call_dtors$1{{$}}
; CHECK-LABEL: .weak __dso_handle
More information about the llvm-commits
mailing list