mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 20:51:52 +01:00
[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
This commit is contained in:
parent
f9ca869bd0
commit
d964845ffe
@ -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);
|
||||
|
@ -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()
|
||||
|
||||
@associated1c0 = external global i8
|
||||
@associated1c1 = external global i8
|
||||
@associatedc0 = external global i8
|
||||
@associatedc1 = external global i8
|
||||
@associatedc2 = global i8 42
|
||||
@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,14 @@ 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.associated1c1:
|
||||
; CHECK-LABEL: .Lregister_call_dtors.1$2.associatedc1:
|
||||
; CHECK: block
|
||||
; CHECK-NEXT: i32.const $push2=, .Lcall_dtors.1.associated1c1{{$}}
|
||||
; 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{{$}}
|
||||
@ -99,13 +111,60 @@ 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.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:
|
||||
; CHECK-LABEL: .Lregister_call_dtors.1$3.associatedc2:
|
||||
; CHECK: block
|
||||
; CHECK-NEXT: i32.const $push2=, .Lcall_dtors{{$}}
|
||||
; 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: .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$5{{$}}
|
||||
; 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$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$1:
|
||||
; CHECK: block
|
||||
; 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
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user