-
Notifications
You must be signed in to change notification settings - Fork 12.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[CodeGen] Generalize trap emission after SP check fail #109744
Conversation
@llvm/pr-subscribers-backend-webassembly @llvm/pr-subscribers-backend-aarch64 Author: duk (duk-37) ChangesGeneralize and improve some target-specific code that emits traps after stack protector failure in SelectionDAG & GlobalIsel. Full diff: https://github.com/llvm/llvm-project/pull/109744.diff 5 Files Affected:
diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
index 8e860a1f740295..8486d9a1477eb6 100644
--- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -3807,16 +3807,11 @@ bool IRTranslator::emitSPDescriptorFailure(StackProtectorDescriptor &SPD,
return false;
}
- // On PS4/PS5, the "return address" must still be within the calling
- // function, even if it's at the very end, so emit an explicit TRAP here.
- // WebAssembly needs an unreachable instruction after a non-returning call,
- // because the function return type can be different from __stack_chk_fail's
- // return type (void).
- const TargetMachine &TM = MF->getTarget();
- if (TM.getTargetTriple().isPS() || TM.getTargetTriple().isWasm()) {
- LLVM_DEBUG(dbgs() << "Unhandled trap emission for stack protector fail\n");
- return false;
- }
+ // Emit a trap instruction if we are required to do so.
+ const TargetOptions &TargetOpts = TLI->getTargetMachine().Options;
+ if (TargetOpts.TrapUnreachable && !TargetOpts.NoTrapAfterNoreturn)
+ CurBuilder->buildInstr(TargetOpcode::G_TRAP);
+
return true;
}
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 25213f587116d5..5004756c0ab9c1 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -3183,15 +3183,10 @@ SelectionDAGBuilder::visitSPDescriptorFailure(StackProtectorDescriptor &SPD) {
SDValue Chain = TLI.makeLibCall(DAG, RTLIB::STACKPROTECTOR_CHECK_FAIL,
MVT::isVoid, {}, CallOptions, getCurSDLoc())
.second;
- // On PS4/PS5, the "return address" must still be within the calling
- // function, even if it's at the very end, so emit an explicit TRAP here.
- // Passing 'true' for doesNotReturn above won't generate the trap for us.
- if (TM.getTargetTriple().isPS())
- Chain = DAG.getNode(ISD::TRAP, getCurSDLoc(), MVT::Other, Chain);
- // WebAssembly needs an unreachable instruction after a non-returning call,
- // because the function return type can be different from __stack_chk_fail's
- // return type (void).
- if (TM.getTargetTriple().isWasm())
+
+ // Emit a trap instruction if we are required to do so.
+ const TargetOptions &TargetOpts = DAG.getTarget().Options;
+ if (TargetOpts.TrapUnreachable && !TargetOpts.NoTrapAfterNoreturn)
Chain = DAG.getNode(ISD::TRAP, getCurSDLoc(), MVT::Other, Chain);
DAG.setRoot(Chain);
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-stack-protector-trap-unreachable.ll b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-stack-protector-trap-unreachable.ll
new file mode 100644
index 00000000000000..8f1eafa6ca9feb
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-stack-protector-trap-unreachable.ll
@@ -0,0 +1,26 @@
+; NOTE: Do not autogenerate, we'll lose the important NOT- check otherwise.
+;; Make sure we emit trap instructions after stack protector checks iff NoTrapAfterNoReturn is false.
+
+; RUN: llc -mtriple=aarch64 -global-isel -verify-machineinstrs \
+; RUN: -trap-unreachable=false -o - %s | FileCheck -check-prefix=NO_TRAP_UNREACHABLE %s
+; RUN: llc -mtriple=aarch64 -global-isel -verify-machineinstrs \
+; RUN: -trap-unreachable -no-trap-after-noreturn -o - %s | FileCheck -check-prefix=NO_TRAP_UNREACHABLE %s
+; RUN: llc -mtriple=aarch64 -global-isel -verify-machineinstrs \
+; RUN: -trap-unreachable -no-trap-after-noreturn=false -o - %s | FileCheck -check-prefix=TRAP_UNREACHABLE %s
+
+define void @test() nounwind ssp {
+; NO_TRAP_UNREACHABLE-LABEL: test:
+; NO_TRAP_UNREACHABLE: bl __stack_chk_fail
+; NO_TRAP_UNREACHABLE-NOT: brk #0x1
+;
+; TRAP_UNREACHABLE-LABEL: test:
+; TRAP_UNREACHABLE: bl __stack_chk_fail
+; TRAP_UNREACHABLE-NEXT: brk #0x1
+
+entry:
+ %buf = alloca [8 x i8]
+ %2 = call i32(ptr) @callee(ptr %buf) nounwind
+ ret void
+}
+
+declare i32 @callee(ptr) nounwind
diff --git a/llvm/test/CodeGen/AArch64/stack-protector-trap-unreachable.ll b/llvm/test/CodeGen/AArch64/stack-protector-trap-unreachable.ll
new file mode 100644
index 00000000000000..3efb71c0f78c32
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/stack-protector-trap-unreachable.ll
@@ -0,0 +1,34 @@
+; NOTE: Do not autogenerate, we'll lose the important NOT- check otherwise.
+;; Make sure we emit trap instructions after stack protector checks iff NoTrapAfterNoReturn is false.
+
+; RUN: llc -mtriple=aarch64 -fast-isel=false -global-isel=false -verify-machineinstrs \
+; RUN: -trap-unreachable=false -o - %s | FileCheck --check-prefix=NO_TRAP_UNREACHABLE %s
+; RUN: llc -mtriple=aarch64 -fast-isel=false -global-isel=false -verify-machineinstrs \
+; RUN: -trap-unreachable -no-trap-after-noreturn -o - %s | FileCheck --check-prefix=NO_TRAP_UNREACHABLE %s
+; RUN: llc -mtriple=aarch64 -fast-isel=false -global-isel=false -verify-machineinstrs \
+; RUN: -trap-unreachable -no-trap-after-noreturn=false -o - %s | FileCheck --check-prefix=TRAP_UNREACHABLE %s
+
+;; Make sure FastISel doesn't break anything.
+; RUN: llc -mtriple=aarch64 -fast-isel -verify-machineinstrs \
+; RUN: -trap-unreachable=false -o - %s | FileCheck --check-prefix=NO_TRAP_UNREACHABLE %s
+; RUN: llc -mtriple=aarch64 -fast-isel -verify-machineinstrs \
+; RUN: -trap-unreachable -no-trap-after-noreturn -o - %s | FileCheck --check-prefix=NO_TRAP_UNREACHABLE %s
+; RUN: llc -mtriple=aarch64 -fast-isel -verify-machineinstrs \
+; RUN: -trap-unreachable -no-trap-after-noreturn=false -o - %s | FileCheck --check-prefix=TRAP_UNREACHABLE %s
+
+define void @test() nounwind ssp {
+; NO_TRAP_UNREACHABLE-LABEL: test:
+; NO_TRAP_UNREACHABLE: bl __stack_chk_fail
+; NO_TRAP_UNREACHABLE-NOT: brk #0x1
+;
+; TRAP_UNREACHABLE-LABEL: test:
+; TRAP_UNREACHABLE: bl __stack_chk_fail
+; TRAP_UNREACHABLE-NEXT: brk #0x1
+
+entry:
+ %buf = alloca [8 x i8]
+ %2 = call i32(ptr) @callee(ptr %buf) nounwind
+ ret void
+}
+
+declare i32 @callee(ptr) nounwind
diff --git a/llvm/test/CodeGen/X86/stack-protector-trap-unreachable.ll b/llvm/test/CodeGen/X86/stack-protector-trap-unreachable.ll
new file mode 100644
index 00000000000000..ecf4c9811d46c6
--- /dev/null
+++ b/llvm/test/CodeGen/X86/stack-protector-trap-unreachable.ll
@@ -0,0 +1,34 @@
+; NOTE: Do not autogenerate, we'll lose the important NOT- check otherwise.
+;; Make sure we emit trap instructions after stack protector checks iff NoTrapAfterNoReturn is false.
+
+; RUN: llc -mtriple=x86_64 -fast-isel=false -global-isel=false -verify-machineinstrs \
+; RUN: -trap-unreachable=false -o - %s | FileCheck --check-prefix=NOTRAP %s
+; RUN: llc -mtriple=x86_64 -fast-isel=false -global-isel=false -verify-machineinstrs \
+; RUN: -trap-unreachable -no-trap-after-noreturn -o - %s | FileCheck --check-prefix=NOTRAP %s
+; RUN: llc -mtriple=x86_64 -fast-isel=false -global-isel=false -verify-machineinstrs \
+; RUN: -trap-unreachable -no-trap-after-noreturn=false -o - %s | FileCheck --check-prefix=TRAP %s
+
+;; Make sure FastISel doesn't break anything.
+; RUN: llc -mtriple=x86_64 -fast-isel -global-isel=false -verify-machineinstrs \
+; RUN: -trap-unreachable=false -o - %s | FileCheck --check-prefix=NOTRAP %s
+; RUN: llc -mtriple=x86_64 -fast-isel -global-isel=false -verify-machineinstrs \
+; RUN: -trap-unreachable -no-trap-after-noreturn -o - %s | FileCheck --check-prefix=NOTRAP %s
+; RUN: llc -mtriple=x86_64 -fast-isel -global-isel=false -verify-machineinstrs \
+; RUN: -trap-unreachable -no-trap-after-noreturn=false -o - %s | FileCheck --check-prefix=TRAP %s
+
+define void @test() nounwind ssp {
+; NOTRAP-LABEL: test
+; NOTRAP: callq __stack_chk_fail
+; NOTRAP-NOT: ud2
+
+; TRAP-LABEL: test
+; TRAP: callq __stack_chk_fail
+; TRAP-NEXT: ud2
+
+entry:
+ %buf = alloca [8 x i8]
+ %2 = call i32(ptr) @callee(ptr %buf) nounwind
+ ret void
+}
+
+declare i32 @callee(ptr) nounwind
|
@llvm/pr-subscribers-llvm-globalisel Author: duk (duk-37) ChangesGeneralize and improve some target-specific code that emits traps after stack protector failure in SelectionDAG & GlobalIsel. Full diff: https://github.com/llvm/llvm-project/pull/109744.diff 5 Files Affected:
diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
index 8e860a1f740295..8486d9a1477eb6 100644
--- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -3807,16 +3807,11 @@ bool IRTranslator::emitSPDescriptorFailure(StackProtectorDescriptor &SPD,
return false;
}
- // On PS4/PS5, the "return address" must still be within the calling
- // function, even if it's at the very end, so emit an explicit TRAP here.
- // WebAssembly needs an unreachable instruction after a non-returning call,
- // because the function return type can be different from __stack_chk_fail's
- // return type (void).
- const TargetMachine &TM = MF->getTarget();
- if (TM.getTargetTriple().isPS() || TM.getTargetTriple().isWasm()) {
- LLVM_DEBUG(dbgs() << "Unhandled trap emission for stack protector fail\n");
- return false;
- }
+ // Emit a trap instruction if we are required to do so.
+ const TargetOptions &TargetOpts = TLI->getTargetMachine().Options;
+ if (TargetOpts.TrapUnreachable && !TargetOpts.NoTrapAfterNoreturn)
+ CurBuilder->buildInstr(TargetOpcode::G_TRAP);
+
return true;
}
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 25213f587116d5..5004756c0ab9c1 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -3183,15 +3183,10 @@ SelectionDAGBuilder::visitSPDescriptorFailure(StackProtectorDescriptor &SPD) {
SDValue Chain = TLI.makeLibCall(DAG, RTLIB::STACKPROTECTOR_CHECK_FAIL,
MVT::isVoid, {}, CallOptions, getCurSDLoc())
.second;
- // On PS4/PS5, the "return address" must still be within the calling
- // function, even if it's at the very end, so emit an explicit TRAP here.
- // Passing 'true' for doesNotReturn above won't generate the trap for us.
- if (TM.getTargetTriple().isPS())
- Chain = DAG.getNode(ISD::TRAP, getCurSDLoc(), MVT::Other, Chain);
- // WebAssembly needs an unreachable instruction after a non-returning call,
- // because the function return type can be different from __stack_chk_fail's
- // return type (void).
- if (TM.getTargetTriple().isWasm())
+
+ // Emit a trap instruction if we are required to do so.
+ const TargetOptions &TargetOpts = DAG.getTarget().Options;
+ if (TargetOpts.TrapUnreachable && !TargetOpts.NoTrapAfterNoreturn)
Chain = DAG.getNode(ISD::TRAP, getCurSDLoc(), MVT::Other, Chain);
DAG.setRoot(Chain);
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-stack-protector-trap-unreachable.ll b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-stack-protector-trap-unreachable.ll
new file mode 100644
index 00000000000000..8f1eafa6ca9feb
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-stack-protector-trap-unreachable.ll
@@ -0,0 +1,26 @@
+; NOTE: Do not autogenerate, we'll lose the important NOT- check otherwise.
+;; Make sure we emit trap instructions after stack protector checks iff NoTrapAfterNoReturn is false.
+
+; RUN: llc -mtriple=aarch64 -global-isel -verify-machineinstrs \
+; RUN: -trap-unreachable=false -o - %s | FileCheck -check-prefix=NO_TRAP_UNREACHABLE %s
+; RUN: llc -mtriple=aarch64 -global-isel -verify-machineinstrs \
+; RUN: -trap-unreachable -no-trap-after-noreturn -o - %s | FileCheck -check-prefix=NO_TRAP_UNREACHABLE %s
+; RUN: llc -mtriple=aarch64 -global-isel -verify-machineinstrs \
+; RUN: -trap-unreachable -no-trap-after-noreturn=false -o - %s | FileCheck -check-prefix=TRAP_UNREACHABLE %s
+
+define void @test() nounwind ssp {
+; NO_TRAP_UNREACHABLE-LABEL: test:
+; NO_TRAP_UNREACHABLE: bl __stack_chk_fail
+; NO_TRAP_UNREACHABLE-NOT: brk #0x1
+;
+; TRAP_UNREACHABLE-LABEL: test:
+; TRAP_UNREACHABLE: bl __stack_chk_fail
+; TRAP_UNREACHABLE-NEXT: brk #0x1
+
+entry:
+ %buf = alloca [8 x i8]
+ %2 = call i32(ptr) @callee(ptr %buf) nounwind
+ ret void
+}
+
+declare i32 @callee(ptr) nounwind
diff --git a/llvm/test/CodeGen/AArch64/stack-protector-trap-unreachable.ll b/llvm/test/CodeGen/AArch64/stack-protector-trap-unreachable.ll
new file mode 100644
index 00000000000000..3efb71c0f78c32
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/stack-protector-trap-unreachable.ll
@@ -0,0 +1,34 @@
+; NOTE: Do not autogenerate, we'll lose the important NOT- check otherwise.
+;; Make sure we emit trap instructions after stack protector checks iff NoTrapAfterNoReturn is false.
+
+; RUN: llc -mtriple=aarch64 -fast-isel=false -global-isel=false -verify-machineinstrs \
+; RUN: -trap-unreachable=false -o - %s | FileCheck --check-prefix=NO_TRAP_UNREACHABLE %s
+; RUN: llc -mtriple=aarch64 -fast-isel=false -global-isel=false -verify-machineinstrs \
+; RUN: -trap-unreachable -no-trap-after-noreturn -o - %s | FileCheck --check-prefix=NO_TRAP_UNREACHABLE %s
+; RUN: llc -mtriple=aarch64 -fast-isel=false -global-isel=false -verify-machineinstrs \
+; RUN: -trap-unreachable -no-trap-after-noreturn=false -o - %s | FileCheck --check-prefix=TRAP_UNREACHABLE %s
+
+;; Make sure FastISel doesn't break anything.
+; RUN: llc -mtriple=aarch64 -fast-isel -verify-machineinstrs \
+; RUN: -trap-unreachable=false -o - %s | FileCheck --check-prefix=NO_TRAP_UNREACHABLE %s
+; RUN: llc -mtriple=aarch64 -fast-isel -verify-machineinstrs \
+; RUN: -trap-unreachable -no-trap-after-noreturn -o - %s | FileCheck --check-prefix=NO_TRAP_UNREACHABLE %s
+; RUN: llc -mtriple=aarch64 -fast-isel -verify-machineinstrs \
+; RUN: -trap-unreachable -no-trap-after-noreturn=false -o - %s | FileCheck --check-prefix=TRAP_UNREACHABLE %s
+
+define void @test() nounwind ssp {
+; NO_TRAP_UNREACHABLE-LABEL: test:
+; NO_TRAP_UNREACHABLE: bl __stack_chk_fail
+; NO_TRAP_UNREACHABLE-NOT: brk #0x1
+;
+; TRAP_UNREACHABLE-LABEL: test:
+; TRAP_UNREACHABLE: bl __stack_chk_fail
+; TRAP_UNREACHABLE-NEXT: brk #0x1
+
+entry:
+ %buf = alloca [8 x i8]
+ %2 = call i32(ptr) @callee(ptr %buf) nounwind
+ ret void
+}
+
+declare i32 @callee(ptr) nounwind
diff --git a/llvm/test/CodeGen/X86/stack-protector-trap-unreachable.ll b/llvm/test/CodeGen/X86/stack-protector-trap-unreachable.ll
new file mode 100644
index 00000000000000..ecf4c9811d46c6
--- /dev/null
+++ b/llvm/test/CodeGen/X86/stack-protector-trap-unreachable.ll
@@ -0,0 +1,34 @@
+; NOTE: Do not autogenerate, we'll lose the important NOT- check otherwise.
+;; Make sure we emit trap instructions after stack protector checks iff NoTrapAfterNoReturn is false.
+
+; RUN: llc -mtriple=x86_64 -fast-isel=false -global-isel=false -verify-machineinstrs \
+; RUN: -trap-unreachable=false -o - %s | FileCheck --check-prefix=NOTRAP %s
+; RUN: llc -mtriple=x86_64 -fast-isel=false -global-isel=false -verify-machineinstrs \
+; RUN: -trap-unreachable -no-trap-after-noreturn -o - %s | FileCheck --check-prefix=NOTRAP %s
+; RUN: llc -mtriple=x86_64 -fast-isel=false -global-isel=false -verify-machineinstrs \
+; RUN: -trap-unreachable -no-trap-after-noreturn=false -o - %s | FileCheck --check-prefix=TRAP %s
+
+;; Make sure FastISel doesn't break anything.
+; RUN: llc -mtriple=x86_64 -fast-isel -global-isel=false -verify-machineinstrs \
+; RUN: -trap-unreachable=false -o - %s | FileCheck --check-prefix=NOTRAP %s
+; RUN: llc -mtriple=x86_64 -fast-isel -global-isel=false -verify-machineinstrs \
+; RUN: -trap-unreachable -no-trap-after-noreturn -o - %s | FileCheck --check-prefix=NOTRAP %s
+; RUN: llc -mtriple=x86_64 -fast-isel -global-isel=false -verify-machineinstrs \
+; RUN: -trap-unreachable -no-trap-after-noreturn=false -o - %s | FileCheck --check-prefix=TRAP %s
+
+define void @test() nounwind ssp {
+; NOTRAP-LABEL: test
+; NOTRAP: callq __stack_chk_fail
+; NOTRAP-NOT: ud2
+
+; TRAP-LABEL: test
+; TRAP: callq __stack_chk_fail
+; TRAP-NEXT: ud2
+
+entry:
+ %buf = alloca [8 x i8]
+ %2 = call i32(ptr) @callee(ptr %buf) nounwind
+ ret void
+}
+
+declare i32 @callee(ptr) nounwind
|
@llvm/pr-subscribers-llvm-selectiondag Author: duk (duk-37) ChangesGeneralize and improve some target-specific code that emits traps after stack protector failure in SelectionDAG & GlobalIsel. Full diff: https://github.com/llvm/llvm-project/pull/109744.diff 5 Files Affected:
diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
index 8e860a1f740295..8486d9a1477eb6 100644
--- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -3807,16 +3807,11 @@ bool IRTranslator::emitSPDescriptorFailure(StackProtectorDescriptor &SPD,
return false;
}
- // On PS4/PS5, the "return address" must still be within the calling
- // function, even if it's at the very end, so emit an explicit TRAP here.
- // WebAssembly needs an unreachable instruction after a non-returning call,
- // because the function return type can be different from __stack_chk_fail's
- // return type (void).
- const TargetMachine &TM = MF->getTarget();
- if (TM.getTargetTriple().isPS() || TM.getTargetTriple().isWasm()) {
- LLVM_DEBUG(dbgs() << "Unhandled trap emission for stack protector fail\n");
- return false;
- }
+ // Emit a trap instruction if we are required to do so.
+ const TargetOptions &TargetOpts = TLI->getTargetMachine().Options;
+ if (TargetOpts.TrapUnreachable && !TargetOpts.NoTrapAfterNoreturn)
+ CurBuilder->buildInstr(TargetOpcode::G_TRAP);
+
return true;
}
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 25213f587116d5..5004756c0ab9c1 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -3183,15 +3183,10 @@ SelectionDAGBuilder::visitSPDescriptorFailure(StackProtectorDescriptor &SPD) {
SDValue Chain = TLI.makeLibCall(DAG, RTLIB::STACKPROTECTOR_CHECK_FAIL,
MVT::isVoid, {}, CallOptions, getCurSDLoc())
.second;
- // On PS4/PS5, the "return address" must still be within the calling
- // function, even if it's at the very end, so emit an explicit TRAP here.
- // Passing 'true' for doesNotReturn above won't generate the trap for us.
- if (TM.getTargetTriple().isPS())
- Chain = DAG.getNode(ISD::TRAP, getCurSDLoc(), MVT::Other, Chain);
- // WebAssembly needs an unreachable instruction after a non-returning call,
- // because the function return type can be different from __stack_chk_fail's
- // return type (void).
- if (TM.getTargetTriple().isWasm())
+
+ // Emit a trap instruction if we are required to do so.
+ const TargetOptions &TargetOpts = DAG.getTarget().Options;
+ if (TargetOpts.TrapUnreachable && !TargetOpts.NoTrapAfterNoreturn)
Chain = DAG.getNode(ISD::TRAP, getCurSDLoc(), MVT::Other, Chain);
DAG.setRoot(Chain);
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-stack-protector-trap-unreachable.ll b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-stack-protector-trap-unreachable.ll
new file mode 100644
index 00000000000000..8f1eafa6ca9feb
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-stack-protector-trap-unreachable.ll
@@ -0,0 +1,26 @@
+; NOTE: Do not autogenerate, we'll lose the important NOT- check otherwise.
+;; Make sure we emit trap instructions after stack protector checks iff NoTrapAfterNoReturn is false.
+
+; RUN: llc -mtriple=aarch64 -global-isel -verify-machineinstrs \
+; RUN: -trap-unreachable=false -o - %s | FileCheck -check-prefix=NO_TRAP_UNREACHABLE %s
+; RUN: llc -mtriple=aarch64 -global-isel -verify-machineinstrs \
+; RUN: -trap-unreachable -no-trap-after-noreturn -o - %s | FileCheck -check-prefix=NO_TRAP_UNREACHABLE %s
+; RUN: llc -mtriple=aarch64 -global-isel -verify-machineinstrs \
+; RUN: -trap-unreachable -no-trap-after-noreturn=false -o - %s | FileCheck -check-prefix=TRAP_UNREACHABLE %s
+
+define void @test() nounwind ssp {
+; NO_TRAP_UNREACHABLE-LABEL: test:
+; NO_TRAP_UNREACHABLE: bl __stack_chk_fail
+; NO_TRAP_UNREACHABLE-NOT: brk #0x1
+;
+; TRAP_UNREACHABLE-LABEL: test:
+; TRAP_UNREACHABLE: bl __stack_chk_fail
+; TRAP_UNREACHABLE-NEXT: brk #0x1
+
+entry:
+ %buf = alloca [8 x i8]
+ %2 = call i32(ptr) @callee(ptr %buf) nounwind
+ ret void
+}
+
+declare i32 @callee(ptr) nounwind
diff --git a/llvm/test/CodeGen/AArch64/stack-protector-trap-unreachable.ll b/llvm/test/CodeGen/AArch64/stack-protector-trap-unreachable.ll
new file mode 100644
index 00000000000000..3efb71c0f78c32
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/stack-protector-trap-unreachable.ll
@@ -0,0 +1,34 @@
+; NOTE: Do not autogenerate, we'll lose the important NOT- check otherwise.
+;; Make sure we emit trap instructions after stack protector checks iff NoTrapAfterNoReturn is false.
+
+; RUN: llc -mtriple=aarch64 -fast-isel=false -global-isel=false -verify-machineinstrs \
+; RUN: -trap-unreachable=false -o - %s | FileCheck --check-prefix=NO_TRAP_UNREACHABLE %s
+; RUN: llc -mtriple=aarch64 -fast-isel=false -global-isel=false -verify-machineinstrs \
+; RUN: -trap-unreachable -no-trap-after-noreturn -o - %s | FileCheck --check-prefix=NO_TRAP_UNREACHABLE %s
+; RUN: llc -mtriple=aarch64 -fast-isel=false -global-isel=false -verify-machineinstrs \
+; RUN: -trap-unreachable -no-trap-after-noreturn=false -o - %s | FileCheck --check-prefix=TRAP_UNREACHABLE %s
+
+;; Make sure FastISel doesn't break anything.
+; RUN: llc -mtriple=aarch64 -fast-isel -verify-machineinstrs \
+; RUN: -trap-unreachable=false -o - %s | FileCheck --check-prefix=NO_TRAP_UNREACHABLE %s
+; RUN: llc -mtriple=aarch64 -fast-isel -verify-machineinstrs \
+; RUN: -trap-unreachable -no-trap-after-noreturn -o - %s | FileCheck --check-prefix=NO_TRAP_UNREACHABLE %s
+; RUN: llc -mtriple=aarch64 -fast-isel -verify-machineinstrs \
+; RUN: -trap-unreachable -no-trap-after-noreturn=false -o - %s | FileCheck --check-prefix=TRAP_UNREACHABLE %s
+
+define void @test() nounwind ssp {
+; NO_TRAP_UNREACHABLE-LABEL: test:
+; NO_TRAP_UNREACHABLE: bl __stack_chk_fail
+; NO_TRAP_UNREACHABLE-NOT: brk #0x1
+;
+; TRAP_UNREACHABLE-LABEL: test:
+; TRAP_UNREACHABLE: bl __stack_chk_fail
+; TRAP_UNREACHABLE-NEXT: brk #0x1
+
+entry:
+ %buf = alloca [8 x i8]
+ %2 = call i32(ptr) @callee(ptr %buf) nounwind
+ ret void
+}
+
+declare i32 @callee(ptr) nounwind
diff --git a/llvm/test/CodeGen/X86/stack-protector-trap-unreachable.ll b/llvm/test/CodeGen/X86/stack-protector-trap-unreachable.ll
new file mode 100644
index 00000000000000..ecf4c9811d46c6
--- /dev/null
+++ b/llvm/test/CodeGen/X86/stack-protector-trap-unreachable.ll
@@ -0,0 +1,34 @@
+; NOTE: Do not autogenerate, we'll lose the important NOT- check otherwise.
+;; Make sure we emit trap instructions after stack protector checks iff NoTrapAfterNoReturn is false.
+
+; RUN: llc -mtriple=x86_64 -fast-isel=false -global-isel=false -verify-machineinstrs \
+; RUN: -trap-unreachable=false -o - %s | FileCheck --check-prefix=NOTRAP %s
+; RUN: llc -mtriple=x86_64 -fast-isel=false -global-isel=false -verify-machineinstrs \
+; RUN: -trap-unreachable -no-trap-after-noreturn -o - %s | FileCheck --check-prefix=NOTRAP %s
+; RUN: llc -mtriple=x86_64 -fast-isel=false -global-isel=false -verify-machineinstrs \
+; RUN: -trap-unreachable -no-trap-after-noreturn=false -o - %s | FileCheck --check-prefix=TRAP %s
+
+;; Make sure FastISel doesn't break anything.
+; RUN: llc -mtriple=x86_64 -fast-isel -global-isel=false -verify-machineinstrs \
+; RUN: -trap-unreachable=false -o - %s | FileCheck --check-prefix=NOTRAP %s
+; RUN: llc -mtriple=x86_64 -fast-isel -global-isel=false -verify-machineinstrs \
+; RUN: -trap-unreachable -no-trap-after-noreturn -o - %s | FileCheck --check-prefix=NOTRAP %s
+; RUN: llc -mtriple=x86_64 -fast-isel -global-isel=false -verify-machineinstrs \
+; RUN: -trap-unreachable -no-trap-after-noreturn=false -o - %s | FileCheck --check-prefix=TRAP %s
+
+define void @test() nounwind ssp {
+; NOTRAP-LABEL: test
+; NOTRAP: callq __stack_chk_fail
+; NOTRAP-NOT: ud2
+
+; TRAP-LABEL: test
+; TRAP: callq __stack_chk_fail
+; TRAP-NEXT: ud2
+
+entry:
+ %buf = alloca [8 x i8]
+ %2 = call i32(ptr) @callee(ptr %buf) nounwind
+ ret void
+}
+
+declare i32 @callee(ptr) nounwind
|
@llvm/pr-subscribers-backend-x86 Author: duk (duk-37) ChangesGeneralize and improve some target-specific code that emits traps after stack protector failure in SelectionDAG & GlobalIsel. Full diff: https://github.com/llvm/llvm-project/pull/109744.diff 5 Files Affected:
diff --git a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
index 8e860a1f740295..8486d9a1477eb6 100644
--- a/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/IRTranslator.cpp
@@ -3807,16 +3807,11 @@ bool IRTranslator::emitSPDescriptorFailure(StackProtectorDescriptor &SPD,
return false;
}
- // On PS4/PS5, the "return address" must still be within the calling
- // function, even if it's at the very end, so emit an explicit TRAP here.
- // WebAssembly needs an unreachable instruction after a non-returning call,
- // because the function return type can be different from __stack_chk_fail's
- // return type (void).
- const TargetMachine &TM = MF->getTarget();
- if (TM.getTargetTriple().isPS() || TM.getTargetTriple().isWasm()) {
- LLVM_DEBUG(dbgs() << "Unhandled trap emission for stack protector fail\n");
- return false;
- }
+ // Emit a trap instruction if we are required to do so.
+ const TargetOptions &TargetOpts = TLI->getTargetMachine().Options;
+ if (TargetOpts.TrapUnreachable && !TargetOpts.NoTrapAfterNoreturn)
+ CurBuilder->buildInstr(TargetOpcode::G_TRAP);
+
return true;
}
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 25213f587116d5..5004756c0ab9c1 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -3183,15 +3183,10 @@ SelectionDAGBuilder::visitSPDescriptorFailure(StackProtectorDescriptor &SPD) {
SDValue Chain = TLI.makeLibCall(DAG, RTLIB::STACKPROTECTOR_CHECK_FAIL,
MVT::isVoid, {}, CallOptions, getCurSDLoc())
.second;
- // On PS4/PS5, the "return address" must still be within the calling
- // function, even if it's at the very end, so emit an explicit TRAP here.
- // Passing 'true' for doesNotReturn above won't generate the trap for us.
- if (TM.getTargetTriple().isPS())
- Chain = DAG.getNode(ISD::TRAP, getCurSDLoc(), MVT::Other, Chain);
- // WebAssembly needs an unreachable instruction after a non-returning call,
- // because the function return type can be different from __stack_chk_fail's
- // return type (void).
- if (TM.getTargetTriple().isWasm())
+
+ // Emit a trap instruction if we are required to do so.
+ const TargetOptions &TargetOpts = DAG.getTarget().Options;
+ if (TargetOpts.TrapUnreachable && !TargetOpts.NoTrapAfterNoreturn)
Chain = DAG.getNode(ISD::TRAP, getCurSDLoc(), MVT::Other, Chain);
DAG.setRoot(Chain);
diff --git a/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-stack-protector-trap-unreachable.ll b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-stack-protector-trap-unreachable.ll
new file mode 100644
index 00000000000000..8f1eafa6ca9feb
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-stack-protector-trap-unreachable.ll
@@ -0,0 +1,26 @@
+; NOTE: Do not autogenerate, we'll lose the important NOT- check otherwise.
+;; Make sure we emit trap instructions after stack protector checks iff NoTrapAfterNoReturn is false.
+
+; RUN: llc -mtriple=aarch64 -global-isel -verify-machineinstrs \
+; RUN: -trap-unreachable=false -o - %s | FileCheck -check-prefix=NO_TRAP_UNREACHABLE %s
+; RUN: llc -mtriple=aarch64 -global-isel -verify-machineinstrs \
+; RUN: -trap-unreachable -no-trap-after-noreturn -o - %s | FileCheck -check-prefix=NO_TRAP_UNREACHABLE %s
+; RUN: llc -mtriple=aarch64 -global-isel -verify-machineinstrs \
+; RUN: -trap-unreachable -no-trap-after-noreturn=false -o - %s | FileCheck -check-prefix=TRAP_UNREACHABLE %s
+
+define void @test() nounwind ssp {
+; NO_TRAP_UNREACHABLE-LABEL: test:
+; NO_TRAP_UNREACHABLE: bl __stack_chk_fail
+; NO_TRAP_UNREACHABLE-NOT: brk #0x1
+;
+; TRAP_UNREACHABLE-LABEL: test:
+; TRAP_UNREACHABLE: bl __stack_chk_fail
+; TRAP_UNREACHABLE-NEXT: brk #0x1
+
+entry:
+ %buf = alloca [8 x i8]
+ %2 = call i32(ptr) @callee(ptr %buf) nounwind
+ ret void
+}
+
+declare i32 @callee(ptr) nounwind
diff --git a/llvm/test/CodeGen/AArch64/stack-protector-trap-unreachable.ll b/llvm/test/CodeGen/AArch64/stack-protector-trap-unreachable.ll
new file mode 100644
index 00000000000000..3efb71c0f78c32
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/stack-protector-trap-unreachable.ll
@@ -0,0 +1,34 @@
+; NOTE: Do not autogenerate, we'll lose the important NOT- check otherwise.
+;; Make sure we emit trap instructions after stack protector checks iff NoTrapAfterNoReturn is false.
+
+; RUN: llc -mtriple=aarch64 -fast-isel=false -global-isel=false -verify-machineinstrs \
+; RUN: -trap-unreachable=false -o - %s | FileCheck --check-prefix=NO_TRAP_UNREACHABLE %s
+; RUN: llc -mtriple=aarch64 -fast-isel=false -global-isel=false -verify-machineinstrs \
+; RUN: -trap-unreachable -no-trap-after-noreturn -o - %s | FileCheck --check-prefix=NO_TRAP_UNREACHABLE %s
+; RUN: llc -mtriple=aarch64 -fast-isel=false -global-isel=false -verify-machineinstrs \
+; RUN: -trap-unreachable -no-trap-after-noreturn=false -o - %s | FileCheck --check-prefix=TRAP_UNREACHABLE %s
+
+;; Make sure FastISel doesn't break anything.
+; RUN: llc -mtriple=aarch64 -fast-isel -verify-machineinstrs \
+; RUN: -trap-unreachable=false -o - %s | FileCheck --check-prefix=NO_TRAP_UNREACHABLE %s
+; RUN: llc -mtriple=aarch64 -fast-isel -verify-machineinstrs \
+; RUN: -trap-unreachable -no-trap-after-noreturn -o - %s | FileCheck --check-prefix=NO_TRAP_UNREACHABLE %s
+; RUN: llc -mtriple=aarch64 -fast-isel -verify-machineinstrs \
+; RUN: -trap-unreachable -no-trap-after-noreturn=false -o - %s | FileCheck --check-prefix=TRAP_UNREACHABLE %s
+
+define void @test() nounwind ssp {
+; NO_TRAP_UNREACHABLE-LABEL: test:
+; NO_TRAP_UNREACHABLE: bl __stack_chk_fail
+; NO_TRAP_UNREACHABLE-NOT: brk #0x1
+;
+; TRAP_UNREACHABLE-LABEL: test:
+; TRAP_UNREACHABLE: bl __stack_chk_fail
+; TRAP_UNREACHABLE-NEXT: brk #0x1
+
+entry:
+ %buf = alloca [8 x i8]
+ %2 = call i32(ptr) @callee(ptr %buf) nounwind
+ ret void
+}
+
+declare i32 @callee(ptr) nounwind
diff --git a/llvm/test/CodeGen/X86/stack-protector-trap-unreachable.ll b/llvm/test/CodeGen/X86/stack-protector-trap-unreachable.ll
new file mode 100644
index 00000000000000..ecf4c9811d46c6
--- /dev/null
+++ b/llvm/test/CodeGen/X86/stack-protector-trap-unreachable.ll
@@ -0,0 +1,34 @@
+; NOTE: Do not autogenerate, we'll lose the important NOT- check otherwise.
+;; Make sure we emit trap instructions after stack protector checks iff NoTrapAfterNoReturn is false.
+
+; RUN: llc -mtriple=x86_64 -fast-isel=false -global-isel=false -verify-machineinstrs \
+; RUN: -trap-unreachable=false -o - %s | FileCheck --check-prefix=NOTRAP %s
+; RUN: llc -mtriple=x86_64 -fast-isel=false -global-isel=false -verify-machineinstrs \
+; RUN: -trap-unreachable -no-trap-after-noreturn -o - %s | FileCheck --check-prefix=NOTRAP %s
+; RUN: llc -mtriple=x86_64 -fast-isel=false -global-isel=false -verify-machineinstrs \
+; RUN: -trap-unreachable -no-trap-after-noreturn=false -o - %s | FileCheck --check-prefix=TRAP %s
+
+;; Make sure FastISel doesn't break anything.
+; RUN: llc -mtriple=x86_64 -fast-isel -global-isel=false -verify-machineinstrs \
+; RUN: -trap-unreachable=false -o - %s | FileCheck --check-prefix=NOTRAP %s
+; RUN: llc -mtriple=x86_64 -fast-isel -global-isel=false -verify-machineinstrs \
+; RUN: -trap-unreachable -no-trap-after-noreturn -o - %s | FileCheck --check-prefix=NOTRAP %s
+; RUN: llc -mtriple=x86_64 -fast-isel -global-isel=false -verify-machineinstrs \
+; RUN: -trap-unreachable -no-trap-after-noreturn=false -o - %s | FileCheck --check-prefix=TRAP %s
+
+define void @test() nounwind ssp {
+; NOTRAP-LABEL: test
+; NOTRAP: callq __stack_chk_fail
+; NOTRAP-NOT: ud2
+
+; TRAP-LABEL: test
+; TRAP: callq __stack_chk_fail
+; TRAP-NEXT: ud2
+
+entry:
+ %buf = alloca [8 x i8]
+ %2 = call i32(ptr) @callee(ptr %buf) nounwind
+ ret void
+}
+
+declare i32 @callee(ptr) nounwind
|
// because the function return type can be different from __stack_chk_fail's | ||
// return type (void). | ||
const TargetMachine &TM = MF->getTarget(); | ||
if (TM.getTargetTriple().isPS() || TM.getTargetTriple().isWasm()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is loosing the target specific behaviors? TargetOptions aren't really options for the target. No test changes for this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are existing tests checking this behavior for these targets -- ps4/5 and wasm explicitly override these options.
18197c6
to
8f5a1e7
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
essentially lgtm
llvm/test/CodeGen/AArch64/GlobalISel/irtranslator-stack-protector-trap-unreachable.ll
Outdated
Show resolved
Hide resolved
8f5a1e7
to
f6521b5
Compare
Generalize some target-specific code that emits traps after stack protector failure in SelectionDAG/GlobalIsel and add some tests.
f6521b5
to
cda3c9a
Compare
LLVM Buildbot has detected a new failure on builder Full details are available at: https://lab.llvm.org/buildbot/#/builders/88/builds/3433 Here is the relevant piece of the build log for the reference
|
Generalize and improve some target-specific code that emits traps after stack protector failure in SelectionDAG & GlobalIsel.
Generalize and improve some target-specific code that emits traps after stack protector failure in SelectionDAG & GlobalIsel.
Generalize and improve some target-specific code that emits traps after stack protector failure in SelectionDAG & GlobalIsel.
Generalize and improve some target-specific code that emits traps after stack protector failure in SelectionDAG & GlobalIsel.