Index: llvm/lib/CodeGen/CodeGenCommonISel.cpp =================================================================== --- llvm/lib/CodeGen/CodeGenCommonISel.cpp +++ llvm/lib/CodeGen/CodeGenCommonISel.cpp @@ -132,6 +132,15 @@ MachineBasicBlock::iterator Start = BB->begin(); MachineBasicBlock::iterator Previous = SplitPoint; + if (SplitPoint == BB->end()) { + // We're in a block ending with a noreturn call followed by an unreachable + // if there's no terminator. Skip past the call and check before it. + do { + --Previous; + } while (Previous->getOpcode() != TII.getCallFrameSetupOpcode() && Previous != Start); + return Previous; + } + do { --Previous; } while (Previous != Start && Previous->isDebugInstr()); Index: llvm/lib/CodeGen/StackProtector.cpp =================================================================== --- llvm/lib/CodeGen/StackProtector.cpp +++ llvm/lib/CodeGen/StackProtector.cpp @@ -637,7 +637,23 @@ } bool StackProtector::shouldEmitSDCheck(const BasicBlock &BB) const { - return HasPrologue && !HasIRCheck && isa(BB.getTerminator()); + if (!HasPrologue || HasIRCheck) + return false; + + // Normal return path, instrument it. + if (isa(BB.getTerminator())) + return true; + + // Now look for an unreachable preceded by a noreturn call. We will insert the + // check before the call. In particular this covers the exception-handling + // call to `_Unwind_Resume`. + if (!isa(BB.getTerminator())) + return false; + + auto *CB = dyn_cast_or_null( + BB.getTerminator()->getPrevNonDebugInstruction()); + + return CB && CB->doesNotReturn(); } void StackProtector::copyToMachineFrameInfo(MachineFrameInfo &MFI) const { Index: llvm/test/CodeGen/AArch64/stackprotect-noreturn.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/AArch64/stackprotect-noreturn.ll @@ -0,0 +1,43 @@ +; RUN: llc -mtriple=arm64-apple-macosx %s -o - | FileCheck %s + +define void @simple() sspreq { +; CHECK-LABEL: simple: +; CHECK: cmp +; CHECK-NEXT: b.ne [[CHECK_FAIL:LBB.*]] + +; CHECK: mov w0, wzr +; CHECK: bl _exit + +; CHECK: [[CHECK_FAIL]]: +; CHECK: bl ___stack_chk_fail + + call void @exit(i32 0) noreturn + unreachable +} + +define void @exception_cleanup() sspreq personality ptr @__gxx_personality_v0 { +; CHECK-LABEL: exception_cleanup: +; CHECK: cmp +; CHECK-NEXT: b.ne [[CHECK_FAIL:LBB.*]] + +; CHECK: cmp +; CHECK-NEXT: b.ne [[CHECK_FAIL]] +; CHECK: bl __Unwind_Resume + +; CHECK: [[CHECK_FAIL]]: +; CHECK: bl ___stack_chk_fail + + invoke void @bar() to label %cont unwind label %cleanup + +cont: + ret void + +cleanup: + %lp = landingpad { ptr, i32 } + cleanup + resume { ptr, i32 } %lp +} + +declare void @exit(i32) noreturn +declare ptr @__gxx_personality_v0(...) +declare void @bar() Index: llvm/test/CodeGen/ARM/stackprotect-noreturn.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/ARM/stackprotect-noreturn.ll @@ -0,0 +1,41 @@ +; RUN: llc -mtriple=thumbv7-linux-gnueabihf %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-EHABI +; RUN: llc -mtriple=thumbv7k-apple-watchos %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-DARWIN + +define void @simple() sspreq { +; CHECK-LABEL: simple: +; CHECK: cmp +; CHECK: it ne +; CHECK: blne {{_?}}__stack_chk_fail + +; CHECK: movs r0, #0 +; CHECK: bl {{_?}}exit + + call void @exit(i32 0) noreturn + unreachable +} + +define void @exception_cleanup() sspreq personality ptr @__gxx_personality_v0 { +; CHECK-LABEL: exception_cleanup: + +; CHECK: bl {{_?}}__stack_chk_fail + +; CHECK: cmp +; CHECK: it ne +; CHECK: blne {{_?}}__stack_chk_fail +; CHECK-DARWIN-NEXT: bl __Unwind_Resume +; CHECK-EHABI-NEXT: bl __cxa_end_cleanup + + invoke void @bar() to label %cont unwind label %cleanup + +cont: + ret void + +cleanup: + %lp = landingpad { ptr, i32 } + cleanup + resume { ptr, i32 } %lp +} + +declare void @exit(i32) noreturn +declare ptr @__gxx_personality_v0(...) +declare void @bar() Index: llvm/test/CodeGen/RISCV/stackprotect-noreturn.ll =================================================================== --- /dev/null +++ llvm/test/CodeGen/RISCV/stackprotect-noreturn.ll @@ -0,0 +1,124 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -mtriple=riscv32 < %s | FileCheck %s --check-prefix=CHECK-32 +; RUN: llc -mtriple=riscv64 < %s | FileCheck %s --check-prefix=CHECK-64 + +define void @simple() sspreq { +; CHECK-32-LABEL: simple: +; CHECK-32: # %bb.0: +; CHECK-32-NEXT: addi sp, sp, -16 +; CHECK-32-NEXT: .cfi_def_cfa_offset 16 +; CHECK-32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; CHECK-32-NEXT: .cfi_offset ra, -4 +; CHECK-32-NEXT: lui a0, %hi(__stack_chk_guard) +; CHECK-32-NEXT: lw a1, %lo(__stack_chk_guard)(a0) +; CHECK-32-NEXT: sw a1, 8(sp) +; CHECK-32-NEXT: lw a0, %lo(__stack_chk_guard)(a0) +; CHECK-32-NEXT: lw a1, 8(sp) +; CHECK-32-NEXT: bne a0, a1, .LBB0_2 +; CHECK-32-NEXT: # %bb.1: +; CHECK-32-NEXT: li a0, 0 +; CHECK-32-NEXT: call exit@plt +; CHECK-32-NEXT: .LBB0_2: +; CHECK-32-NEXT: call __stack_chk_fail@plt +; +; CHECK-64-LABEL: simple: +; CHECK-64: # %bb.0: +; CHECK-64-NEXT: addi sp, sp, -16 +; CHECK-64-NEXT: .cfi_def_cfa_offset 16 +; CHECK-64-NEXT: sd ra, 8(sp) # 8-byte Folded Spill +; CHECK-64-NEXT: .cfi_offset ra, -8 +; CHECK-64-NEXT: lui a0, %hi(__stack_chk_guard) +; CHECK-64-NEXT: ld a1, %lo(__stack_chk_guard)(a0) +; CHECK-64-NEXT: sd a1, 0(sp) +; CHECK-64-NEXT: ld a0, %lo(__stack_chk_guard)(a0) +; CHECK-64-NEXT: ld a1, 0(sp) +; CHECK-64-NEXT: bne a0, a1, .LBB0_2 +; CHECK-64-NEXT: # %bb.1: +; CHECK-64-NEXT: li a0, 0 +; CHECK-64-NEXT: call exit@plt +; CHECK-64-NEXT: .LBB0_2: +; CHECK-64-NEXT: call __stack_chk_fail@plt + call void @exit(i32 0) noreturn + unreachable +} + +define void @exception_cleanup() sspreq personality ptr @__gxx_personality_v0 { +; CHECK-32-LABEL: exception_cleanup: +; CHECK-32: # %bb.0: +; CHECK-32-NEXT: addi sp, sp, -16 +; CHECK-32-NEXT: .cfi_def_cfa_offset 16 +; CHECK-32-NEXT: sw ra, 12(sp) # 4-byte Folded Spill +; CHECK-32-NEXT: sw s0, 8(sp) # 4-byte Folded Spill +; CHECK-32-NEXT: .cfi_offset ra, -4 +; CHECK-32-NEXT: .cfi_offset s0, -8 +; CHECK-32-NEXT: lui s0, %hi(__stack_chk_guard) +; CHECK-32-NEXT: lw a0, %lo(__stack_chk_guard)(s0) +; CHECK-32-NEXT: sw a0, 4(sp) +; CHECK-32-NEXT: .Ltmp0: +; CHECK-32-NEXT: call bar@plt +; CHECK-32-NEXT: .Ltmp1: +; CHECK-32-NEXT: # %bb.1: # %cont +; CHECK-32-NEXT: lw a0, %lo(__stack_chk_guard)(s0) +; CHECK-32-NEXT: lw a1, 4(sp) +; CHECK-32-NEXT: bne a0, a1, .LBB1_5 +; CHECK-32-NEXT: # %bb.2: # %cont +; CHECK-32-NEXT: lw ra, 12(sp) # 4-byte Folded Reload +; CHECK-32-NEXT: lw s0, 8(sp) # 4-byte Folded Reload +; CHECK-32-NEXT: addi sp, sp, 16 +; CHECK-32-NEXT: ret +; CHECK-32-NEXT: .LBB1_3: # %cleanup +; CHECK-32-NEXT: .Ltmp2: +; CHECK-32-NEXT: lw a1, %lo(__stack_chk_guard)(s0) +; CHECK-32-NEXT: lw a2, 4(sp) +; CHECK-32-NEXT: bne a1, a2, .LBB1_5 +; CHECK-32-NEXT: # %bb.4: # %cleanup +; CHECK-32-NEXT: call _Unwind_Resume@plt +; CHECK-32-NEXT: .LBB1_5: # %cleanup +; CHECK-32-NEXT: call __stack_chk_fail@plt +; +; CHECK-64-LABEL: exception_cleanup: +; CHECK-64: # %bb.0: +; CHECK-64-NEXT: addi sp, sp, -32 +; CHECK-64-NEXT: .cfi_def_cfa_offset 32 +; CHECK-64-NEXT: sd ra, 24(sp) # 8-byte Folded Spill +; CHECK-64-NEXT: sd s0, 16(sp) # 8-byte Folded Spill +; CHECK-64-NEXT: .cfi_offset ra, -8 +; CHECK-64-NEXT: .cfi_offset s0, -16 +; CHECK-64-NEXT: lui s0, %hi(__stack_chk_guard) +; CHECK-64-NEXT: ld a0, %lo(__stack_chk_guard)(s0) +; CHECK-64-NEXT: sd a0, 8(sp) +; CHECK-64-NEXT: .Ltmp0: +; CHECK-64-NEXT: call bar@plt +; CHECK-64-NEXT: .Ltmp1: +; CHECK-64-NEXT: # %bb.1: # %cont +; CHECK-64-NEXT: ld a0, %lo(__stack_chk_guard)(s0) +; CHECK-64-NEXT: ld a1, 8(sp) +; CHECK-64-NEXT: bne a0, a1, .LBB1_5 +; CHECK-64-NEXT: # %bb.2: # %cont +; CHECK-64-NEXT: ld ra, 24(sp) # 8-byte Folded Reload +; CHECK-64-NEXT: ld s0, 16(sp) # 8-byte Folded Reload +; CHECK-64-NEXT: addi sp, sp, 32 +; CHECK-64-NEXT: ret +; CHECK-64-NEXT: .LBB1_3: # %cleanup +; CHECK-64-NEXT: .Ltmp2: +; CHECK-64-NEXT: ld a1, %lo(__stack_chk_guard)(s0) +; CHECK-64-NEXT: ld a2, 8(sp) +; CHECK-64-NEXT: bne a1, a2, .LBB1_5 +; CHECK-64-NEXT: # %bb.4: # %cleanup +; CHECK-64-NEXT: call _Unwind_Resume@plt +; CHECK-64-NEXT: .LBB1_5: # %cleanup +; CHECK-64-NEXT: call __stack_chk_fail@plt + invoke void @bar() to label %cont unwind label %cleanup + +cont: + ret void + +cleanup: + %lp = landingpad { ptr, i32 } + cleanup + resume { ptr, i32 } %lp +} + +declare void @exit(i32) noreturn +declare ptr @__gxx_personality_v0(...) +declare void @bar() Index: llvm/test/CodeGen/X86/reverse_branches.ll =================================================================== --- llvm/test/CodeGen/X86/reverse_branches.ll +++ llvm/test/CodeGen/X86/reverse_branches.ll @@ -38,14 +38,14 @@ ; CHECK-NEXT: movq %rsp, %r15 ; CHECK-NEXT: jmp LBB0_1 ; CHECK-NEXT: .p2align 4, 0x90 -; CHECK-NEXT: LBB0_6: ## %for.inc9 +; CHECK-NEXT: LBB0_7: ## %for.inc9 ; CHECK-NEXT: ## in Loop: Header=BB0_1 Depth=1 ; CHECK-NEXT: incl %ebx ; CHECK-NEXT: LBB0_1: ## %for.cond ; CHECK-NEXT: ## =>This Loop Header: Depth=1 ; CHECK-NEXT: ## Child Loop BB0_3 Depth 2 ; CHECK-NEXT: cmpl $999, %ebx ## imm = 0x3E7 -; CHECK-NEXT: jg LBB0_7 +; CHECK-NEXT: jg LBB0_8 ; CHECK-NEXT: ## %bb.2: ## %for.cond1.preheader ; CHECK-NEXT: ## in Loop: Header=BB0_1 Depth=1 ; CHECK-NEXT: movl $-1, %ebp @@ -57,7 +57,7 @@ ; CHECK-NEXT: ## => This Inner Loop Header: Depth=2 ; CHECK-NEXT: incl %ebp ; CHECK-NEXT: cmpl $999, %ebp ## imm = 0x3E7 -; CHECK-NEXT: jg LBB0_6 +; CHECK-NEXT: jg LBB0_7 ; CHECK-NEXT: ## %bb.4: ## %for.body3 ; CHECK-NEXT: ## in Loop: Header=BB0_3 Depth=2 ; CHECK-NEXT: addq $1002, %r12 ## imm = 0x3EA @@ -69,70 +69,75 @@ ; CHECK-NEXT: movq %r13, %rdi ; CHECK-NEXT: je LBB0_3 ; CHECK-NEXT: jmp LBB0_5 -; CHECK-NEXT: LBB0_7: ## %for.end11 +; CHECK-NEXT: LBB0_8: ## %for.end11 ; CHECK-NEXT: leaq L_.str2(%rip), %rdi ; CHECK-NEXT: callq _puts ; CHECK-NEXT: xorl %eax, %eax ; CHECK-NEXT: movq %rsp, %rcx -; CHECK-NEXT: jmp LBB0_8 +; CHECK-NEXT: jmp LBB0_9 ; CHECK-NEXT: .p2align 4, 0x90 -; CHECK-NEXT: LBB0_15: ## %for.inc38 -; CHECK-NEXT: ## in Loop: Header=BB0_8 Depth=1 +; CHECK-NEXT: LBB0_17: ## %for.inc38 +; CHECK-NEXT: ## in Loop: Header=BB0_9 Depth=1 ; CHECK-NEXT: incl %eax -; CHECK-NEXT: LBB0_8: ## %for.cond14 +; CHECK-NEXT: LBB0_9: ## %for.cond14 ; CHECK-NEXT: ## =>This Loop Header: Depth=1 -; CHECK-NEXT: ## Child Loop BB0_10 Depth 2 -; CHECK-NEXT: ## Child Loop BB0_12 Depth 3 +; CHECK-NEXT: ## Child Loop BB0_11 Depth 2 +; CHECK-NEXT: ## Child Loop BB0_13 Depth 3 ; CHECK-NEXT: cmpl $999, %eax ## imm = 0x3E7 -; CHECK-NEXT: jg LBB0_16 -; CHECK-NEXT: ## %bb.9: ## %for.cond18.preheader -; CHECK-NEXT: ## in Loop: Header=BB0_8 Depth=1 +; CHECK-NEXT: jg LBB0_18 +; CHECK-NEXT: ## %bb.10: ## %for.cond18.preheader +; CHECK-NEXT: ## in Loop: Header=BB0_9 Depth=1 ; CHECK-NEXT: movq %rcx, %rdx ; CHECK-NEXT: xorl %esi, %esi ; CHECK-NEXT: xorl %edi, %edi -; CHECK-NEXT: jmp LBB0_10 +; CHECK-NEXT: jmp LBB0_11 ; CHECK-NEXT: .p2align 4, 0x90 -; CHECK-NEXT: LBB0_14: ## %exit -; CHECK-NEXT: ## in Loop: Header=BB0_10 Depth=2 +; CHECK-NEXT: LBB0_15: ## %exit +; CHECK-NEXT: ## in Loop: Header=BB0_11 Depth=2 ; CHECK-NEXT: addq %rsi, %r8 ; CHECK-NEXT: incq %rdi ; CHECK-NEXT: decq %rsi ; CHECK-NEXT: addq $1001, %rdx ## imm = 0x3E9 ; CHECK-NEXT: cmpq $-1000, %r8 ## imm = 0xFC18 ; CHECK-NEXT: jne LBB0_5 -; CHECK-NEXT: LBB0_10: ## %for.cond18 -; CHECK-NEXT: ## Parent Loop BB0_8 Depth=1 +; CHECK-NEXT: LBB0_11: ## %for.cond18 +; CHECK-NEXT: ## Parent Loop BB0_9 Depth=1 ; CHECK-NEXT: ## => This Loop Header: Depth=2 -; CHECK-NEXT: ## Child Loop BB0_12 Depth 3 +; CHECK-NEXT: ## Child Loop BB0_13 Depth 3 ; CHECK-NEXT: cmpl $999, %edi ## imm = 0x3E7 -; CHECK-NEXT: jg LBB0_15 -; CHECK-NEXT: ## %bb.11: ## %for.body20 -; CHECK-NEXT: ## in Loop: Header=BB0_10 Depth=2 +; CHECK-NEXT: jg LBB0_17 +; CHECK-NEXT: ## %bb.12: ## %for.body20 +; CHECK-NEXT: ## in Loop: Header=BB0_11 Depth=2 ; CHECK-NEXT: movq $-1000, %r8 ## imm = 0xFC18 ; CHECK-NEXT: .p2align 4, 0x90 -; CHECK-NEXT: LBB0_12: ## %do.body.i -; CHECK-NEXT: ## Parent Loop BB0_8 Depth=1 -; CHECK-NEXT: ## Parent Loop BB0_10 Depth=2 +; CHECK-NEXT: LBB0_13: ## %do.body.i +; CHECK-NEXT: ## Parent Loop BB0_9 Depth=1 +; CHECK-NEXT: ## Parent Loop BB0_11 Depth=2 ; CHECK-NEXT: ## => This Inner Loop Header: Depth=3 ; CHECK-NEXT: cmpb $120, 1000(%rdx,%r8) -; CHECK-NEXT: je LBB0_14 -; CHECK-NEXT: ## %bb.13: ## %do.cond.i -; CHECK-NEXT: ## in Loop: Header=BB0_12 Depth=3 +; CHECK-NEXT: je LBB0_15 +; CHECK-NEXT: ## %bb.14: ## %do.cond.i +; CHECK-NEXT: ## in Loop: Header=BB0_13 Depth=3 ; CHECK-NEXT: incq %r8 -; CHECK-NEXT: jne LBB0_12 +; CHECK-NEXT: jne LBB0_13 ; CHECK-NEXT: LBB0_5: ## %if.then ; CHECK-NEXT: leaq L_str4(%rip), %rdi ; CHECK-NEXT: callq _puts +; CHECK-NEXT: movq ___stack_chk_guard@GOTPCREL(%rip), %rax +; CHECK-NEXT: movq (%rax), %rax +; CHECK-NEXT: cmpq {{[0-9]+}}(%rsp), %rax +; CHECK-NEXT: jne LBB0_16 +; CHECK-NEXT: ## %bb.6: ## %if.then ; CHECK-NEXT: movl $1, %edi ; CHECK-NEXT: callq _exit -; CHECK-NEXT: LBB0_16: ## %for.end40 +; CHECK-NEXT: LBB0_18: ## %for.end40 ; CHECK-NEXT: leaq L_.str3(%rip), %rdi ; CHECK-NEXT: callq _puts ; CHECK-NEXT: movq ___stack_chk_guard@GOTPCREL(%rip), %rax ; CHECK-NEXT: movq (%rax), %rax ; CHECK-NEXT: cmpq {{[0-9]+}}(%rsp), %rax -; CHECK-NEXT: jne LBB0_18 -; CHECK-NEXT: ## %bb.17: ## %for.end40 +; CHECK-NEXT: jne LBB0_16 +; CHECK-NEXT: ## %bb.19: ## %for.end40 ; CHECK-NEXT: xorl %eax, %eax ; CHECK-NEXT: addq $1001016, %rsp ## imm = 0xF4638 ; CHECK-NEXT: popq %rbx @@ -142,7 +147,7 @@ ; CHECK-NEXT: popq %r15 ; CHECK-NEXT: popq %rbp ; CHECK-NEXT: retq -; CHECK-NEXT: LBB0_18: ## %for.end40 +; CHECK-NEXT: LBB0_16: ## %for.end40 ; CHECK-NEXT: callq ___stack_chk_fail entry: %strs = alloca [1000 x [1001 x i8]], align 16 Index: llvm/test/CodeGen/X86/stack-protector-no-return.ll =================================================================== --- llvm/test/CodeGen/X86/stack-protector-no-return.ll +++ llvm/test/CodeGen/X86/stack-protector-no-return.ll @@ -1,6 +1,7 @@ ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py ; RUN: llc -opaque-pointers=0 %s -mtriple=x86_64-unknown-linux-gnu -o - -verify-dom-info | FileCheck %s ; RUN: llc -opaque-pointers=0 %s -mtriple=x86_64-unknown-linux-gnu -disable-check-noreturn-call=true -o - -verify-dom-info | FileCheck --check-prefix=DISNOTET %s +; RUN: llc %s -mtriple=x86_64-apple-macosx -o - | FileCheck %s --check-prefix=DARWIN ; Function Attrs: sspreq define void @_Z7catchesv() #0 personality i8* null { @@ -73,6 +74,41 @@ ; DISNOTET-NEXT: .LBB0_5: # %CallStackCheckFailBlk ; DISNOTET-NEXT: .cfi_def_cfa_offset 16 ; DISNOTET-NEXT: callq __stack_chk_fail@PLT +; +; DARWIN-LABEL: _Z7catchesv: +; DARWIN: ## %bb.0: ## %entry +; DARWIN-NEXT: pushq %rax +; DARWIN-NEXT: .cfi_def_cfa_offset 16 +; DARWIN-NEXT: movq ___stack_chk_guard@GOTPCREL(%rip), %rax +; DARWIN-NEXT: movq (%rax), %rax +; DARWIN-NEXT: movq %rax, (%rsp) +; DARWIN-NEXT: Ltmp0: +; DARWIN-NEXT: xorl %eax, %eax +; DARWIN-NEXT: xorl %edi, %edi +; DARWIN-NEXT: xorl %esi, %esi +; DARWIN-NEXT: xorl %edx, %edx +; DARWIN-NEXT: callq *%rax +; DARWIN-NEXT: Ltmp1: +; DARWIN-NEXT: ## %bb.1: ## %invoke.cont +; DARWIN-NEXT: Ltmp2: +; DARWIN-NEXT: xorl %eax, %eax +; DARWIN-NEXT: xorl %edi, %edi +; DARWIN-NEXT: callq *%rax +; DARWIN-NEXT: Ltmp3: +; DARWIN-NEXT: ## %bb.2: ## %invoke.cont2 +; DARWIN-NEXT: ud2 +; DARWIN-NEXT: LBB0_3: ## %lpad1 +; DARWIN-NEXT: Ltmp4: +; DARWIN-NEXT: movq ___stack_chk_guard@GOTPCREL(%rip), %rax +; DARWIN-NEXT: movq (%rax), %rax +; DARWIN-NEXT: cmpq (%rsp), %rax +; DARWIN-NEXT: jne LBB0_5 +; DARWIN-NEXT: ## %bb.4: ## %lpad1 +; DARWIN-NEXT: popq %rax +; DARWIN-NEXT: retq +; DARWIN-NEXT: LBB0_5: ## %lpad1 +; DARWIN-NEXT: callq ___stack_chk_fail +; DARWIN-NEXT: Lfunc_end0: entry: %call = invoke i64 null(i32 0, i8* null, i64 0) to label %invoke.cont unwind label %lpad1 @@ -90,8 +126,105 @@ ret void } -; uselistorder directives -uselistorder i8* null, { 1, 0 } +define void @resume_path() #0 personality i8* null { +; CHECK-LABEL: resume_path: +; CHECK: # %bb.0: +; CHECK-NEXT: pushq %rax +; CHECK-NEXT: .cfi_def_cfa_offset 16 +; CHECK-NEXT: movq %fs:40, %rax +; CHECK-NEXT: movq %rax, (%rsp) +; CHECK-NEXT: .Ltmp5: +; CHECK-NEXT: callq bar@PLT +; CHECK-NEXT: .Ltmp6: +; CHECK-NEXT: # %bb.1: # %cont +; CHECK-NEXT: movq %fs:40, %rax +; CHECK-NEXT: cmpq (%rsp), %rax +; CHECK-NEXT: jne .LBB1_5 +; CHECK-NEXT: # %bb.2: # %SP_return +; CHECK-NEXT: popq %rax +; CHECK-NEXT: .cfi_def_cfa_offset 8 +; CHECK-NEXT: retq +; CHECK-NEXT: .LBB1_3: # %cleanup +; CHECK-NEXT: .cfi_def_cfa_offset 16 +; CHECK-NEXT: .Ltmp7: +; CHECK-NEXT: movq %fs:40, %rcx +; CHECK-NEXT: cmpq (%rsp), %rcx +; CHECK-NEXT: jne .LBB1_5 +; CHECK-NEXT: # %bb.4: # %SP_return3 +; CHECK-NEXT: movq %rax, %rdi +; CHECK-NEXT: callq _Unwind_Resume@PLT +; CHECK-NEXT: .LBB1_5: # %CallStackCheckFailBlk +; CHECK-NEXT: callq __stack_chk_fail@PLT +; +; DISNOTET-LABEL: resume_path: +; DISNOTET: # %bb.0: +; DISNOTET-NEXT: pushq %rax +; DISNOTET-NEXT: .cfi_def_cfa_offset 16 +; DISNOTET-NEXT: movq %fs:40, %rax +; DISNOTET-NEXT: movq %rax, (%rsp) +; DISNOTET-NEXT: .Ltmp5: +; DISNOTET-NEXT: callq bar@PLT +; DISNOTET-NEXT: .Ltmp6: +; DISNOTET-NEXT: # %bb.1: # %cont +; DISNOTET-NEXT: movq %fs:40, %rax +; DISNOTET-NEXT: cmpq (%rsp), %rax +; DISNOTET-NEXT: jne .LBB1_4 +; DISNOTET-NEXT: # %bb.2: # %SP_return +; DISNOTET-NEXT: popq %rax +; DISNOTET-NEXT: .cfi_def_cfa_offset 8 +; DISNOTET-NEXT: retq +; DISNOTET-NEXT: .LBB1_4: # %CallStackCheckFailBlk +; DISNOTET-NEXT: .cfi_def_cfa_offset 16 +; DISNOTET-NEXT: callq __stack_chk_fail@PLT +; DISNOTET-NEXT: .LBB1_3: # %cleanup +; DISNOTET-NEXT: .Ltmp7: +; DISNOTET-NEXT: movq %rax, %rdi +; DISNOTET-NEXT: callq _Unwind_Resume@PLT +; +; DARWIN-LABEL: resume_path: +; DARWIN: ## %bb.0: +; DARWIN-NEXT: pushq %rax +; DARWIN-NEXT: .cfi_def_cfa_offset 16 +; DARWIN-NEXT: movq ___stack_chk_guard@GOTPCREL(%rip), %rax +; DARWIN-NEXT: movq (%rax), %rax +; DARWIN-NEXT: movq %rax, (%rsp) +; DARWIN-NEXT: Ltmp5: +; DARWIN-NEXT: callq _bar +; DARWIN-NEXT: Ltmp6: +; DARWIN-NEXT: ## %bb.1: ## %cont +; DARWIN-NEXT: movq ___stack_chk_guard@GOTPCREL(%rip), %rax +; DARWIN-NEXT: movq (%rax), %rax +; DARWIN-NEXT: cmpq (%rsp), %rax +; DARWIN-NEXT: jne LBB1_4 +; DARWIN-NEXT: ## %bb.2: ## %cont +; DARWIN-NEXT: popq %rax +; DARWIN-NEXT: retq +; DARWIN-NEXT: LBB1_3: ## %cleanup +; DARWIN-NEXT: Ltmp7: +; DARWIN-NEXT: movq ___stack_chk_guard@GOTPCREL(%rip), %rcx +; DARWIN-NEXT: movq (%rcx), %rcx +; DARWIN-NEXT: cmpq (%rsp), %rcx +; DARWIN-NEXT: jne LBB1_4 +; DARWIN-NEXT: ## %bb.5: ## %cleanup +; DARWIN-NEXT: movq %rax, %rdi +; DARWIN-NEXT: callq __Unwind_Resume +; DARWIN-NEXT: LBB1_4: ## %cleanup +; DARWIN-NEXT: callq ___stack_chk_fail +; DARWIN-NEXT: Lfunc_end1: + + invoke void @bar() to label %cont unwind label %cleanup + +cont: + ret void + +cleanup: + %lp = landingpad { i8*, i32 } + cleanup + resume { i8*, i32 } %lp +} + +declare void @bar() + attributes #0 = { sspreq } attributes #1 = { noreturn }