forked from OSchip/llvm-project
Revert [Windows] Disable TrapUnreachable for Win64, add SEH_NoReturn
This reverts r370525 (git commit0bb1630685
) Also reverts r370543 (git commit185ddc08ee
) The approach I took only works for functions marked `noreturn`. In general, a call that is not known to be noreturn may be followed by unreachable for other reasons. For example, there could be multiple call sites to a function that throws sometimes, and at some call sites, it is known to always throw, so it is followed by unreachable. We need to insert an `int3` in these cases to pacify the Windows unwinder. I think this probably deserves its own standalone, Win64-only fixup pass that runs after block placement. Implementing that will take some time, so let's revert to TrapUnreachable in the mean time. llvm-svn: 370829
This commit is contained in:
parent
49e7ee4dd5
commit
3fa07dee94
|
@ -2558,7 +2558,7 @@ bool blockEndIsUnreachable(const MachineBasicBlock &MBB,
|
|||
MBB.succ_begin(), MBB.succ_end(),
|
||||
[](const MachineBasicBlock *Succ) { return Succ->isEHPad(); }) &&
|
||||
std::all_of(MBBI, MBB.end(), [](const MachineInstr &MI) {
|
||||
return MI.isMetaInstruction() || MI.getOpcode() == X86::SEH_NoReturn;
|
||||
return MI.isMetaInstruction();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -4101,17 +4101,6 @@ X86TargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
|
|||
InFlag = Chain.getValue(1);
|
||||
}
|
||||
|
||||
// Insert a pseudo instruction after noreturn calls that expands to int3 if
|
||||
// this would be the last instruction in the funclet. If the return address of
|
||||
// a call refers to the last PC of a function, the Windows SEH machinery can
|
||||
// get confused about which function or scope the return address belongs to.
|
||||
// MSVC inserts int3 after every noreturn function call, but LLVM only places
|
||||
// them when it would cause a problem otherwise.
|
||||
if (CLI.DoesNotReturn && Subtarget.isTargetWin64()) {
|
||||
Chain = DAG.getNode(X86ISD::SEH_NORETURN, dl, NodeTys, Chain, InFlag);
|
||||
InFlag = Chain.getValue(1);
|
||||
}
|
||||
|
||||
// Handle result values, copying them out of physregs into vregs that we
|
||||
// return.
|
||||
return LowerCallResult(Chain, InFlag, CallConv, isVarArg, Ins, dl, DAG,
|
||||
|
@ -28729,7 +28718,6 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const {
|
|||
case X86ISD::VASTART_SAVE_XMM_REGS: return "X86ISD::VASTART_SAVE_XMM_REGS";
|
||||
case X86ISD::VAARG_64: return "X86ISD::VAARG_64";
|
||||
case X86ISD::WIN_ALLOCA: return "X86ISD::WIN_ALLOCA";
|
||||
case X86ISD::SEH_NORETURN: return "X86ISD::SEH_NORETURN";
|
||||
case X86ISD::MEMBARRIER: return "X86ISD::MEMBARRIER";
|
||||
case X86ISD::MFENCE: return "X86ISD::MFENCE";
|
||||
case X86ISD::SEG_ALLOCA: return "X86ISD::SEG_ALLOCA";
|
||||
|
|
|
@ -531,9 +531,6 @@ namespace llvm {
|
|||
// Windows's _chkstk call to do stack probing.
|
||||
WIN_ALLOCA,
|
||||
|
||||
// Expands to int3 or nothing, depending on basic block layout.
|
||||
SEH_NORETURN,
|
||||
|
||||
// For allocating variable amounts of stack space when using
|
||||
// segmented stacks. Check if the current stacklet has enough space, and
|
||||
// falls back to heap allocation if not.
|
||||
|
|
|
@ -239,9 +239,6 @@ let isPseudo = 1, SchedRW = [WriteSystem] in {
|
|||
"#SEH_EndPrologue", []>;
|
||||
def SEH_Epilogue : I<0, Pseudo, (outs), (ins),
|
||||
"#SEH_Epilogue", []>;
|
||||
let hasSideEffects = 1 in
|
||||
def SEH_NoReturn : I<0, Pseudo, (outs), (ins),
|
||||
"#SEH_NoReturn", [(X86SehNoReturn)]>;
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -289,9 +289,6 @@ def X86mul_imm : SDNode<"X86ISD::MUL_IMM", SDTIntBinOp>;
|
|||
def X86WinAlloca : SDNode<"X86ISD::WIN_ALLOCA", SDT_X86WIN_ALLOCA,
|
||||
[SDNPHasChain, SDNPOutGlue]>;
|
||||
|
||||
def X86SehNoReturn : SDNode<"X86ISD::SEH_NORETURN", SDTX86Void,
|
||||
[SDNPHasChain, SDNPInGlue, SDNPOutGlue]>;
|
||||
|
||||
def X86SegAlloca : SDNode<"X86ISD::SEG_ALLOCA", SDT_X86SEG_ALLOCA,
|
||||
[SDNPHasChain]>;
|
||||
|
||||
|
|
|
@ -1921,20 +1921,6 @@ void X86AsmPrinter::EmitInstruction(const MachineInstr *MI) {
|
|||
return;
|
||||
}
|
||||
|
||||
case X86::SEH_NoReturn: {
|
||||
// Materialize an int3 if this instruction is in the last basic block in the
|
||||
// function. The int3 serves the same purpose as the noop emitted above for
|
||||
// SEH_Epilogue, which is to make the Win64 unwinder happy. If the return
|
||||
// address of the preceding call appears to precede an epilogue or a new
|
||||
// function, then the unwinder may get lost.
|
||||
const MachineBasicBlock *MBB = MI->getParent();
|
||||
const MachineBasicBlock *NextMBB = MBB->getNextNode();
|
||||
if (!NextMBB || NextMBB->isEHPad()) {
|
||||
EmitAndCountInstruction(MCInstBuilder(X86::INT3));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Lower PSHUFB and VPERMILP normally but add a comment if we can find
|
||||
// a constant shuffle mask. We won't be able to do this at the MC layer
|
||||
// because the mask isn't an immediate.
|
||||
|
|
|
@ -219,9 +219,17 @@ X86TargetMachine::X86TargetMachine(const Target &T, const Triple &TT,
|
|||
getEffectiveX86CodeModel(CM, JIT, TT.getArch() == Triple::x86_64),
|
||||
OL),
|
||||
TLOF(createTLOF(getTargetTriple())) {
|
||||
// Windows stack unwinder gets confused when execution flow "falls through"
|
||||
// after a call to 'noreturn' function.
|
||||
// To prevent that, we emit a trap for 'unreachable' IR instructions.
|
||||
// (which on X86, happens to be the 'ud2' instruction)
|
||||
// On PS4, the "return address" of a 'noreturn' call must still be within
|
||||
// the calling function, and TrapUnreachable is an easy way to get that.
|
||||
if (TT.isPS4() || TT.isOSBinFormatMachO()) {
|
||||
// The check here for 64-bit windows is a bit icky, but as we're unlikely
|
||||
// to ever want to mix 32 and 64-bit windows code in a single module
|
||||
// this should be fine.
|
||||
if ((TT.isOSWindows() && TT.getArch() == Triple::x86_64) || TT.isPS4() ||
|
||||
TT.isOSBinFormatMachO()) {
|
||||
this->Options.TrapUnreachable = true;
|
||||
this->Options.NoTrapAfterNoreturn = TT.isOSBinFormatMachO();
|
||||
}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
|
||||
; RUN: sed -e s/.Cxx:// %s | llc -mtriple=x86_64-pc-windows-msvc | FileCheck %s --check-prefix=CXX
|
||||
; RUN: sed -e s/.Seh:// %s | llc -mtriple=x86_64-pc-windows-msvc | FileCheck %s --check-prefix=SEH
|
||||
|
||||
|
@ -68,13 +69,13 @@ catch.body.2:
|
|||
; SEH-NEXT: .long .Ltmp0@IMGREL+1
|
||||
; SEH-NEXT: .long .Ltmp1@IMGREL+1
|
||||
; SEH-NEXT: .long dummy_filter@IMGREL
|
||||
; SEH-NEXT: .long .LBB0_5@IMGREL
|
||||
; SEH-NEXT: .long .LBB0_2@IMGREL
|
||||
; SEH-NEXT: .long .Ltmp2@IMGREL+1
|
||||
; SEH-NEXT: .long .Ltmp3@IMGREL+1
|
||||
; SEH-NEXT: .long "?dtor$2@?0?test@4HA"@IMGREL
|
||||
; SEH-NEXT: .long "?dtor$5@?0?test@4HA"@IMGREL
|
||||
; SEH-NEXT: .long 0
|
||||
; SEH-NEXT: .long .Ltmp2@IMGREL+1
|
||||
; SEH-NEXT: .long .Ltmp3@IMGREL+1
|
||||
; SEH-NEXT: .long dummy_filter@IMGREL
|
||||
; SEH-NEXT: .long .LBB0_5@IMGREL
|
||||
; SEH-NEXT: .long .LBB0_2@IMGREL
|
||||
; SEH-NEXT: .Llsda_end0:
|
||||
|
|
|
@ -5,18 +5,18 @@
|
|||
; RUN: llc -mtriple=x86_64-scei-ps4 < %s | FileCheck -check-prefix=PS4 %s
|
||||
|
||||
; X64_DARWIN: orq
|
||||
; X64_DARWIN-NEXT: ud2
|
||||
; X64-DARWIN-NEXT: ud2
|
||||
|
||||
; X64_LINUX: orq %rax, %rcx
|
||||
; X64_LINUX-NEXT: jne
|
||||
; X64_LINUX-NEXT: %bb8.i329
|
||||
|
||||
; X64_WINDOWS: orq %rax, %rcx
|
||||
; X64_WINDOWS-NEXT: jne
|
||||
; X64_WINDOWS-NEXT: ud2
|
||||
|
||||
; X64_WINDOWS_GNU: movq .refptr._ZN11xercesc_2_513SchemaSymbols21fgURI_SCHEMAFORSCHEMAE(%rip), %rax
|
||||
; X64_WINDOWS_GNU: orq .refptr._ZN11xercesc_2_56XMLUni16fgNotationStringE(%rip), %rax
|
||||
; X64_WINDOWS_GNU-NEXT: jne
|
||||
; X64_WINDOWS_GNU-NEXT: ud2
|
||||
|
||||
; PS4: orq %rax, %rcx
|
||||
; PS4-NEXT: ud2
|
||||
|
|
|
@ -7,8 +7,6 @@ declare void @throw()
|
|||
|
||||
declare i32 @__CxxFrameHandler3(...)
|
||||
|
||||
declare void @llvm.trap()
|
||||
|
||||
define void @test1() personality i32 (...)* @__CxxFrameHandler3 {
|
||||
entry:
|
||||
%alloca2 = alloca i8*, align 4
|
||||
|
@ -32,7 +30,6 @@ catch.pad: ; preds = %catch.dispatch
|
|||
%bc2 = bitcast i8** %alloca2 to i8*
|
||||
call void @llvm.lifetime.start.p0i8(i64 4, i8* %bc2)
|
||||
store volatile i8* null, i8** %alloca1
|
||||
call void @llvm.trap()
|
||||
unreachable
|
||||
|
||||
; CHECK-LABEL: "?catch$2@?0?test1@4HA"
|
||||
|
@ -70,7 +67,6 @@ catch.pad: ; preds = %catch.dispatch
|
|||
%bc2 = bitcast i8** %alloca2 to i8*
|
||||
call void @llvm.lifetime.start.p0i8(i64 4, i8* %bc2)
|
||||
store volatile i8* null, i8** %alloca1
|
||||
call void @llvm.trap()
|
||||
unreachable
|
||||
|
||||
; CHECK-LABEL: "?catch$2@?0?test2@4HA"
|
||||
|
|
|
@ -75,7 +75,7 @@ unreachable: ; preds = %entry
|
|||
; CHECK: popq %rbp
|
||||
; CHECK: retq
|
||||
|
||||
; CHECK: "?catch${{[0-9]+}}@?0?global_array@4HA":
|
||||
; CHECK: "?catch$2@?0?global_array@4HA":
|
||||
; CHECK: pushq %rbp
|
||||
; CHECK: movslq {{.*}}, %[[idx:[^ ]*]]
|
||||
; CHECK: leaq array(%rip), %[[base:[^ ]*]]
|
||||
|
@ -122,7 +122,7 @@ unreachable: ; preds = %entry
|
|||
; CHECK: popq %rbp
|
||||
; CHECK: retq
|
||||
|
||||
; CHECK: "?catch${{[0-9]+}}@?0?access_imported@4HA":
|
||||
; CHECK: "?catch$2@?0?access_imported@4HA":
|
||||
; CHECK: pushq %rbp
|
||||
; CHECK: movq __imp_imported(%rip), %[[base:[^ ]*]]
|
||||
; CHECK: movl $222, (%[[base]])
|
||||
|
|
|
@ -6,7 +6,6 @@ target triple = "x86_64-pc-windows-msvc"
|
|||
declare i32 @__CxxFrameHandler3(...)
|
||||
declare void @throw() noreturn uwtable
|
||||
declare i8* @getval()
|
||||
declare void @llvm.trap()
|
||||
|
||||
define i8* @reload_out_of_pad(i8* %arg) #0 personality i32 (...)* @__CxxFrameHandler3 {
|
||||
assertPassed:
|
||||
|
@ -20,7 +19,6 @@ catch:
|
|||
; This block *must* appear after the catchret to test the bug.
|
||||
; FIXME: Make this an MIR test so we can control MBB layout.
|
||||
unreachable:
|
||||
call void @llvm.trap()
|
||||
unreachable
|
||||
|
||||
catch.dispatch:
|
||||
|
@ -37,7 +35,7 @@ return:
|
|||
; CHECK: movq -[[arg_slot]](%rbp), %rax # 8-byte Reload
|
||||
; CHECK: retq
|
||||
|
||||
; CHECK: "?catch${{[0-9]+}}@?0?reload_out_of_pad@4HA":
|
||||
; CHECK: "?catch$3@?0?reload_out_of_pad@4HA":
|
||||
; CHECK-NOT: Reload
|
||||
; CHECK: retq
|
||||
|
||||
|
@ -52,7 +50,6 @@ catch:
|
|||
catchret from %cp to label %return
|
||||
|
||||
unreachable:
|
||||
call void @llvm.trap()
|
||||
unreachable
|
||||
|
||||
catch.dispatch:
|
||||
|
@ -68,7 +65,7 @@ return:
|
|||
; CHECK: movq -[[val_slot:[0-9]+]](%rbp), %rax # 8-byte Reload
|
||||
; CHECK: retq
|
||||
|
||||
; CHECK: "?catch${{[0-9]+}}@?0?spill_in_pad@4HA":
|
||||
; CHECK: "?catch$3@?0?spill_in_pad@4HA":
|
||||
; CHECK: callq getval
|
||||
; CHECK: movq %rax, -[[val_slot]](%rbp) # 8-byte Spill
|
||||
; CHECK: retq
|
||||
|
|
|
@ -15,7 +15,7 @@ entry:
|
|||
|
||||
; CHECK-LABEL: f:
|
||||
; WIN32: nop
|
||||
; WIN64: nop
|
||||
; WIN64: ud2
|
||||
; LINUX-NOT: nop
|
||||
; LINUX-NOT: ud2
|
||||
|
||||
|
|
|
@ -9,8 +9,6 @@ target triple = "x86_64-pc-windows-msvc"
|
|||
@"\01??_7type_info@@6B@" = external constant i8*
|
||||
@"\01??_R0H@8" = internal global %rtti.TypeDescriptor2 { i8** @"\01??_7type_info@@6B@", i8* null, [3 x i8] c".H\00" }
|
||||
|
||||
declare void @llvm.trap()
|
||||
|
||||
define void @test1(i1 %B) personality i32 (...)* @__CxxFrameHandler3 {
|
||||
entry:
|
||||
invoke void @g()
|
||||
|
@ -33,7 +31,6 @@ try.cont:
|
|||
ret void
|
||||
|
||||
unreachable:
|
||||
call void @llvm.trap()
|
||||
unreachable
|
||||
}
|
||||
|
||||
|
@ -79,7 +76,6 @@ try.cont.5: ; preds = %try.cont
|
|||
ret i32 0
|
||||
|
||||
unreachable: ; preds = %catch, %entry
|
||||
call void @llvm.trap()
|
||||
unreachable
|
||||
}
|
||||
|
||||
|
@ -129,13 +125,11 @@ try.cont: ; preds = %entry
|
|||
br i1 %V, label %exit_one, label %exit_two
|
||||
|
||||
exit_one:
|
||||
tail call void @g()
|
||||
call void @llvm.trap()
|
||||
tail call void @exit(i32 0)
|
||||
unreachable
|
||||
|
||||
exit_two:
|
||||
tail call void @g()
|
||||
call void @llvm.trap()
|
||||
tail call void @exit(i32 0)
|
||||
unreachable
|
||||
}
|
||||
|
||||
|
@ -144,7 +138,7 @@ exit_two:
|
|||
; The entry funclet contains %entry and %try.cont
|
||||
; CHECK: # %entry
|
||||
; CHECK: # %try.cont
|
||||
; CHECK: callq g
|
||||
; CHECK: callq exit
|
||||
; CHECK-NOT: # exit_one
|
||||
; CHECK-NOT: # exit_two
|
||||
; CHECK: ud2
|
||||
|
@ -152,12 +146,12 @@ exit_two:
|
|||
; The catch(...) funclet contains %catch.2
|
||||
; CHECK: # %catch.2{{$}}
|
||||
; CHECK: callq exit
|
||||
; CHECK-NEXT: int3
|
||||
; CHECK: ud2
|
||||
|
||||
; The catch(int) funclet contains %catch
|
||||
; CHECK: # %catch{{$}}
|
||||
; CHECK: callq exit
|
||||
; CHECK-NEXT: int3
|
||||
; CHECK: ud2
|
||||
|
||||
declare void @exit(i32) noreturn nounwind
|
||||
declare void @_CxxThrowException(i8*, %eh.ThrowInfo*)
|
||||
|
|
|
@ -1,53 +0,0 @@
|
|||
; RUN: llc < %s -mtriple=x86_64-windows-msvc | FileCheck %s
|
||||
|
||||
; Function Attrs: noinline nounwind optnone uwtable
|
||||
define dso_local i32 @foo() {
|
||||
entry:
|
||||
%call = call i32 @cond()
|
||||
%tobool = icmp ne i32 %call, 0
|
||||
br i1 %tobool, label %if.then, label %if.end
|
||||
|
||||
if.then: ; preds = %entry
|
||||
call void @abort1()
|
||||
unreachable
|
||||
|
||||
if.end: ; preds = %entry
|
||||
%call1 = call i32 @cond()
|
||||
%tobool2 = icmp ne i32 %call1, 0
|
||||
br i1 %tobool2, label %if.then3, label %if.end4
|
||||
|
||||
if.then3: ; preds = %if.end
|
||||
call void @abort2()
|
||||
unreachable
|
||||
|
||||
if.end4: ; preds = %if.end
|
||||
%call5 = call i32 @cond()
|
||||
%tobool6 = icmp ne i32 %call5, 0
|
||||
br i1 %tobool6, label %if.then7, label %if.end8
|
||||
|
||||
if.then7: ; preds = %if.end4
|
||||
call void @abort3()
|
||||
unreachable
|
||||
|
||||
if.end8: ; preds = %if.end4
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
; CHECK-LABEL: foo:
|
||||
; CHECK: callq cond
|
||||
; CHECK: callq cond
|
||||
; CHECK: callq cond
|
||||
; We don't need int3's between these calls to abort, since they won't confuse
|
||||
; the unwinder.
|
||||
; CHECK: callq abort1
|
||||
; CHECK-NEXT: # %if.then3
|
||||
; CHECK: callq abort2
|
||||
; CHECK-NEXT: # %if.then7
|
||||
; CHECK: callq abort3
|
||||
; CHECK-NEXT: int3
|
||||
|
||||
declare dso_local i32 @cond()
|
||||
|
||||
declare dso_local void @abort1() noreturn
|
||||
declare dso_local void @abort2() noreturn
|
||||
declare dso_local void @abort3() noreturn
|
|
@ -31,6 +31,6 @@ define void @g() {
|
|||
unreachable
|
||||
}
|
||||
; CHECK-LABEL: g:
|
||||
; CHECK: nop
|
||||
; CHECK: ud2
|
||||
|
||||
attributes #0 = { nounwind }
|
||||
|
|
|
@ -1,19 +1,13 @@
|
|||
; RUN: llc < %s -mtriple=i686-apple-darwin8 -mcpu=yonah | FileCheck %s -check-prefix=DARWIN
|
||||
; RUN: llc < %s -mtriple=i686-unknown-linux -mcpu=yonah | FileCheck %s -check-prefix=LINUX
|
||||
; RUN: llc < %s -mtriple=x86_64-scei-ps4 | FileCheck %s -check-prefix=PS4
|
||||
; RUN: llc < %s -mtriple=x86_64-windows-msvc | FileCheck %s -check-prefix=WIN64
|
||||
|
||||
; DARWIN-LABEL: test0:
|
||||
; DARWIN: ud2
|
||||
; LINUX-LABEL: test0:
|
||||
; LINUX: ud2
|
||||
; FIXME: PS4 probably doesn't want two ud2s.
|
||||
; PS4-LABEL: test0:
|
||||
; PS4: ud2
|
||||
; PS4: ud2
|
||||
; WIN64-LABEL: test0:
|
||||
; WIN64: ud2
|
||||
; WIN64-NOT: ud2
|
||||
define i32 @test0() noreturn nounwind {
|
||||
entry:
|
||||
tail call void @llvm.trap( )
|
||||
|
@ -26,9 +20,6 @@ entry:
|
|||
; LINUX: int3
|
||||
; PS4-LABEL: test1:
|
||||
; PS4: int $65
|
||||
; WIN64-LABEL: test1:
|
||||
; WIN64: int3
|
||||
; WIN64-NOT: ud2
|
||||
define i32 @test1() noreturn nounwind {
|
||||
entry:
|
||||
tail call void @llvm.debugtrap( )
|
||||
|
|
|
@ -1,13 +1,10 @@
|
|||
; RUN: llc -o - %s -mtriple=x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,NORMAL
|
||||
; RUN: llc -o - %s -mtriple=x86_64-windows-msvc | FileCheck %s --check-prefixes=CHECK,NORMAL
|
||||
; RUN: llc -o - %s -mtriple=x86_64-scei-ps4 | FileCheck %s --check-prefixes=CHECK,TRAP_AFTER_NORETURN
|
||||
; RUN: llc -o - %s -mtriple=x86_64-windows-msvc | FileCheck %s --check-prefixes=CHECK,TRAP_AFTER_NORETURN
|
||||
; RUN: llc -o - %s -mtriple=x86_64-apple-darwin | FileCheck %s --check-prefixes=CHECK,NO_TRAP_AFTER_NORETURN
|
||||
|
||||
; CHECK-LABEL: call_exit:
|
||||
; CHECK: callq {{_?}}exit
|
||||
; TRAP_AFTER_NORETURN: ud2
|
||||
; NO_TRAP_AFTER_NORETURN-NOT: ud2
|
||||
; NORMAL-NOT: ud2
|
||||
define i32 @call_exit() noreturn nounwind {
|
||||
tail call void @exit(i32 0)
|
||||
unreachable
|
||||
|
@ -17,17 +14,13 @@ define i32 @call_exit() noreturn nounwind {
|
|||
; CHECK: ud2
|
||||
; TRAP_AFTER_NORETURN: ud2
|
||||
; NO_TRAP_AFTER_NORETURN-NOT: ud2
|
||||
; NORMAL-NOT: ud2
|
||||
define i32 @trap() noreturn nounwind {
|
||||
tail call void @llvm.trap()
|
||||
unreachable
|
||||
}
|
||||
|
||||
; CHECK-LABEL: unreachable:
|
||||
; TRAP_AFTER_NORETURN: ud2
|
||||
; NO_TRAP_AFTER_NORETURN: ud2
|
||||
; NORMAL-NOT: ud2
|
||||
; NORMAL: # -- End function
|
||||
; CHECK: ud2
|
||||
define i32 @unreachable() noreturn nounwind {
|
||||
unreachable
|
||||
}
|
||||
|
|
|
@ -24,9 +24,10 @@ catch:
|
|||
; WIN64: nop
|
||||
; WIN64: addq ${{[0-9]+}}, %rsp
|
||||
; WIN64: retq
|
||||
; Check for 'int3' after noreturn call.
|
||||
; Check for 'ud2' after noreturn call
|
||||
; WIN64: callq _Unwind_Resume
|
||||
; WIN64-NEXT: int3
|
||||
; WIN64-NEXT: ud2
|
||||
; WIN64: .seh_endproc
|
||||
|
||||
|
||||
; Check it still works when blocks are reordered.
|
||||
|
|
|
@ -125,11 +125,11 @@ endtryfinally:
|
|||
; WIN64-LABEL: foo4:
|
||||
; WIN64: .seh_proc foo4
|
||||
; WIN64: .seh_handler _d_eh_personality, @unwind, @except
|
||||
; NORM: subq $40, %rsp
|
||||
; ATOM: leaq -40(%rsp), %rsp
|
||||
; WIN64: .seh_stackalloc 40
|
||||
; NORM: subq $56, %rsp
|
||||
; ATOM: leaq -56(%rsp), %rsp
|
||||
; WIN64: .seh_stackalloc 56
|
||||
; WIN64: .seh_endprologue
|
||||
; WIN64: addq $40, %rsp
|
||||
; WIN64: addq $56, %rsp
|
||||
; WIN64: ret
|
||||
; WIN64: .seh_handlerdata
|
||||
; WIN64: .seh_endproc
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
; ASM: [[p_b2:\.Ltmp[0-9]+]]:
|
||||
; ASM: #DEBUG_VALUE: p <- $esi
|
||||
; ASM: callq call_noreturn
|
||||
; ASM: int3
|
||||
; ASM: ud2
|
||||
; ASM: .Lfunc_end0:
|
||||
|
||||
; ASM: .short {{.*}} # Record length
|
||||
|
|
Loading…
Reference in New Issue