Skip to content

Commit 8f5a1e7

Browse files
committed
[CodeGen] Generalize trap instruction emission after SP check fail
Generalize some target-specific code that emits traps after stack protector failure in SelectionDAG/GlobalIsel and add some tests.
1 parent 4a2d24e commit 8f5a1e7

File tree

6 files changed

+125
-20
lines changed

6 files changed

+125
-20
lines changed

llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3807,16 +3807,11 @@ bool IRTranslator::emitSPDescriptorFailure(StackProtectorDescriptor &SPD,
38073807
return false;
38083808
}
38093809

3810-
// On PS4/PS5, the "return address" must still be within the calling
3811-
// function, even if it's at the very end, so emit an explicit TRAP here.
3812-
// WebAssembly needs an unreachable instruction after a non-returning call,
3813-
// because the function return type can be different from __stack_chk_fail's
3814-
// return type (void).
3815-
const TargetMachine &TM = MF->getTarget();
3816-
if (TM.getTargetTriple().isPS() || TM.getTargetTriple().isWasm()) {
3817-
LLVM_DEBUG(dbgs() << "Unhandled trap emission for stack protector fail\n");
3818-
return false;
3819-
}
3810+
// Emit a trap instruction if we are required to do so.
3811+
const TargetOptions &TargetOpts = TLI->getTargetMachine().Options;
3812+
if (TargetOpts.TrapUnreachable && !TargetOpts.NoTrapAfterNoreturn)
3813+
CurBuilder->buildInstr(TargetOpcode::G_TRAP);
3814+
38203815
return true;
38213816
}
38223817

llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3183,15 +3183,10 @@ SelectionDAGBuilder::visitSPDescriptorFailure(StackProtectorDescriptor &SPD) {
31833183
SDValue Chain = TLI.makeLibCall(DAG, RTLIB::STACKPROTECTOR_CHECK_FAIL,
31843184
MVT::isVoid, {}, CallOptions, getCurSDLoc())
31853185
.second;
3186-
// On PS4/PS5, the "return address" must still be within the calling
3187-
// function, even if it's at the very end, so emit an explicit TRAP here.
3188-
// Passing 'true' for doesNotReturn above won't generate the trap for us.
3189-
if (TM.getTargetTriple().isPS())
3190-
Chain = DAG.getNode(ISD::TRAP, getCurSDLoc(), MVT::Other, Chain);
3191-
// WebAssembly needs an unreachable instruction after a non-returning call,
3192-
// because the function return type can be different from __stack_chk_fail's
3193-
// return type (void).
3194-
if (TM.getTargetTriple().isWasm())
3186+
3187+
// Emit a trap instruction if we are required to do so.
3188+
const TargetOptions &TargetOpts = DAG.getTarget().Options;
3189+
if (TargetOpts.TrapUnreachable && !TargetOpts.NoTrapAfterNoreturn)
31953190
Chain = DAG.getNode(ISD::TRAP, getCurSDLoc(), MVT::Other, Chain);
31963191

31973192
DAG.setRoot(Chain);
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
; NOTE: Do not autogenerate, we'd lose the .Lfunc_end0 -NEXT checks otherwise.
2+
;; Make sure we emit trap instructions after stack protector checks iff NoTrapAfterNoReturn is false.
3+
4+
; RUN: llc -mtriple=aarch64 -global-isel -verify-machineinstrs \
5+
; RUN: -trap-unreachable=false -o - %s | FileCheck -check-prefix=NO_TRAP_UNREACHABLE %s
6+
; RUN: llc -mtriple=aarch64 -global-isel -verify-machineinstrs \
7+
; RUN: -trap-unreachable -no-trap-after-noreturn -o - %s | FileCheck -check-prefix=NO_TRAP_UNREACHABLE %s
8+
; RUN: llc -mtriple=aarch64 -global-isel -verify-machineinstrs \
9+
; RUN: -trap-unreachable -no-trap-after-noreturn=false -o - %s | FileCheck -check-prefix=TRAP_UNREACHABLE %s
10+
11+
define void @test() nounwind ssp {
12+
; NO_TRAP_UNREACHABLE-LABEL: test:
13+
; NO_TRAP_UNREACHABLE: bl __stack_chk_fail
14+
; NO_TRAP_UNREACHABLE-NOT: brk #0x1
15+
; NO_TRAP_UNREACHABLE-NEXT: .Lfunc_end0
16+
;
17+
; TRAP_UNREACHABLE-LABEL: test:
18+
; TRAP_UNREACHABLE: bl __stack_chk_fail
19+
; TRAP_UNREACHABLE-NEXT: brk #0x1
20+
; TRAP_UNREACHABLE-NEXT: .Lfunc_end0
21+
22+
entry:
23+
%buf = alloca [8 x i8]
24+
%2 = call i32(ptr) @callee(ptr %buf) nounwind
25+
ret void
26+
}
27+
28+
declare i32 @callee(ptr) nounwind
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
; NOTE: Do not autogenerate, we'd lose the .Lfunc_end0 -NEXT checks otherwise.
2+
;; Make sure we emit trap instructions after stack protector checks iff NoTrapAfterNoReturn is false.
3+
4+
; RUN: llc -mtriple=aarch64 -fast-isel=false -global-isel=false -verify-machineinstrs \
5+
; RUN: -trap-unreachable=false -o - %s | FileCheck --check-prefix=NO_TRAP_UNREACHABLE %s
6+
; RUN: llc -mtriple=aarch64 -fast-isel=false -global-isel=false -verify-machineinstrs \
7+
; RUN: -trap-unreachable -no-trap-after-noreturn -o - %s | FileCheck --check-prefix=NO_TRAP_UNREACHABLE %s
8+
; RUN: llc -mtriple=aarch64 -fast-isel=false -global-isel=false -verify-machineinstrs \
9+
; RUN: -trap-unreachable -no-trap-after-noreturn=false -o - %s | FileCheck --check-prefix=TRAP_UNREACHABLE %s
10+
11+
;; Make sure FastISel doesn't break anything.
12+
; RUN: llc -mtriple=aarch64 -fast-isel -verify-machineinstrs \
13+
; RUN: -trap-unreachable=false -o - %s | FileCheck --check-prefix=NO_TRAP_UNREACHABLE %s
14+
; RUN: llc -mtriple=aarch64 -fast-isel -verify-machineinstrs \
15+
; RUN: -trap-unreachable -no-trap-after-noreturn -o - %s | FileCheck --check-prefix=NO_TRAP_UNREACHABLE %s
16+
; RUN: llc -mtriple=aarch64 -fast-isel -verify-machineinstrs \
17+
; RUN: -trap-unreachable -no-trap-after-noreturn=false -o - %s | FileCheck --check-prefix=TRAP_UNREACHABLE %s
18+
19+
define void @test() nounwind ssp {
20+
; NO_TRAP_UNREACHABLE-LABEL: test:
21+
; NO_TRAP_UNREACHABLE: bl __stack_chk_fail
22+
; NO_TRAP_UNREACHABLE-NOT: brk #0x1
23+
; NO_TRAP_UNREACHABLE-NEXT: .Lfunc_end0
24+
;
25+
; TRAP_UNREACHABLE-LABEL: test:
26+
; TRAP_UNREACHABLE: bl __stack_chk_fail
27+
; TRAP_UNREACHABLE-NEXT: brk #0x1
28+
; TRAP_UNREACHABLE-NEXT: .Lfunc_end0
29+
30+
entry:
31+
%buf = alloca [8 x i8]
32+
%2 = call i32(ptr) @callee(ptr %buf) nounwind
33+
ret void
34+
}
35+
36+
declare i32 @callee(ptr) nounwind
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
; NOTE: Do not autogenerate, we'd lose the .Lfunc_end0 -NEXT checks otherwise.
2+
;; Make sure we emit trap instructions after stack protector checks iff NoTrapAfterNoReturn is false.
3+
4+
; RUN: llc -enable-selectiondag-sp -mtriple=x86_64 -fast-isel=false -global-isel=false -verify-machineinstrs \
5+
; RUN: -trap-unreachable=false -o - %s | FileCheck --check-prefix=NO_TRAP_UNREACHABLE %s
6+
; RUN: llc -enable-selectiondag-sp -mtriple=x86_64 -fast-isel=false -global-isel=false -verify-machineinstrs \
7+
; RUN: -trap-unreachable -no-trap-after-noreturn -o - %s | FileCheck --check-prefix=NO_TRAP_UNREACHABLE %s
8+
; RUN: llc -enable-selectiondag-sp -mtriple=x86_64 -fast-isel=false -global-isel=false -verify-machineinstrs \
9+
; RUN: -trap-unreachable -no-trap-after-noreturn=false -o - %s | FileCheck --check-prefix=TRAP_UNREACHABLE %s
10+
11+
; RUN: llc -enable-selectiondag-sp=false -mtriple=x86_64 -fast-isel=false -global-isel=false -verify-machineinstrs \
12+
; RUN: -trap-unreachable=false -o - %s | FileCheck --check-prefix=NO_TRAP_UNREACHABLE %s
13+
; RUN: llc -enable-selectiondag-sp=false -mtriple=x86_64 -fast-isel=false -global-isel=false -verify-machineinstrs \
14+
; RUN: -trap-unreachable -no-trap-after-noreturn -o - %s | FileCheck --check-prefix=NO_TRAP_UNREACHABLE %s
15+
; RUN: llc -enable-selectiondag-sp=false -mtriple=x86_64 -fast-isel=false -global-isel=false -verify-machineinstrs \
16+
; RUN: -trap-unreachable -no-trap-after-noreturn=false -o - %s | FileCheck --check-prefix=TRAP_UNREACHABLE %s
17+
18+
;; Make sure FastISel doesn't break anything.
19+
; RUN: llc -mtriple=x86_64 -fast-isel -global-isel=false -verify-machineinstrs \
20+
; RUN: -trap-unreachable=false -o - %s | FileCheck --check-prefix=NO_TRAP_UNREACHABLE %s
21+
; RUN: llc -mtriple=x86_64 -fast-isel -global-isel=false -verify-machineinstrs \
22+
; RUN: -trap-unreachable -no-trap-after-noreturn -o - %s | FileCheck --check-prefix=NO_TRAP_UNREACHABLE %s
23+
; RUN: llc -mtriple=x86_64 -fast-isel -global-isel=false -verify-machineinstrs \
24+
; RUN: -trap-unreachable -no-trap-after-noreturn=false -o - %s | FileCheck --check-prefix=TRAP_UNREACHABLE %s
25+
26+
define void @test() nounwind ssp {
27+
; NO_TRAP_UNREACHABLE-LABEL: test:
28+
; NO_TRAP_UNREACHABLE: callq __stack_chk_fail
29+
; NO_TRAP_UNREACHABLE-NOT: ud2
30+
; NO_TRAP_UNREACHABLE-NEXT: .Lfunc_end0
31+
32+
; TRAP_UNREACHABLE-LABEL: test:
33+
; TRAP_UNREACHABLE: callq __stack_chk_fail
34+
; TRAP_UNREACHABLE-NEXT: ud2
35+
; TRAP_UNREACHABLE-NEXT: .Lfunc_end0
36+
37+
entry:
38+
%buf = alloca [8 x i8]
39+
%2 = call i32(ptr) @callee(ptr %buf) nounwind
40+
ret void
41+
}
42+
43+
declare i32 @callee(ptr) nounwind

llvm/test/CodeGen/X86/unreachable-trap.ll

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,15 @@
11
; RUN: llc -o - %s -mtriple=x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK
22
; RUN: llc -o - %s -mtriple=x86_64-windows-msvc | FileCheck %s --check-prefixes=CHECK
3-
; RUN: llc -o - %s -mtriple=x86_64-scei-ps4 | FileCheck %s --check-prefixes=CHECK,TRAP_AFTER_NORETURN
43
; RUN: llc -o - %s -mtriple=x86_64-apple-darwin | FileCheck %s --check-prefixes=CHECK,NO_TRAP_AFTER_NORETURN
4+
5+
; On PS4/PS5, always emit trap instructions regardless of of trap-unreachable or no-trap-after-noreturn.
6+
; RUN: llc -o - %s -mtriple=x86_64-scei-ps4 -trap-unreachable | FileCheck %s --check-prefixes=CHECK,TRAP_AFTER_NORETURN
7+
; RUN: llc -o - %s -mtriple=x86_64-sie-ps5 -trap-unreachable | FileCheck %s --check-prefixes=CHECK,TRAP_AFTER_NORETURN
8+
; RUN: llc -o - %s -mtriple=x86_64-scei-ps4 -trap-unreachable=false | FileCheck %s --check-prefixes=CHECK,TRAP_AFTER_NORETURN
9+
; RUN: llc -o - %s -mtriple=x86_64-sie-ps5 -trap-unreachable=false | FileCheck %s --check-prefixes=CHECK,TRAP_AFTER_NORETURN
10+
; RUN: llc -o - %s -mtriple=x86_64-scei-ps4 -trap-unreachable -no-trap-after-noreturn=false | FileCheck %s --check-prefixes=CHECK,TRAP_AFTER_NORETURN
11+
; RUN: llc -o - %s -mtriple=x86_64-sie-ps5 -trap-unreachable -no-trap-after-noreturn=false | FileCheck %s --check-prefixes=CHECK,TRAP_AFTER_NORETURN
12+
513
; RUN: llc --trap-unreachable -o - %s -mtriple=x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,TRAP_AFTER_NORETURN
614
; RUN: llc --trap-unreachable -global-isel -o - %s -mtriple=x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,TRAP_AFTER_NORETURN
715
; RUN: llc --trap-unreachable -fast-isel -o - %s -mtriple=x86_64-linux-gnu | FileCheck %s --check-prefixes=CHECK,TRAP_AFTER_NORETURN

0 commit comments

Comments
 (0)