Skip to content

Commit 78c27a3

Browse files
committed
[X86][Win64] Avoid statepoints in trailing call position
The "avoid trailing call pass" makes sure that no function ends with a call instruction for the purpose of the unwinder. It starts of by skipping over any non real instruction, which is approximated via the Pseudo and Meta property. This sadly leads to issues when the last machine instruction is a STATEPOINT, as it is skipped despite it lowering to a call. This patch fixes the use of a statepoint in the trailing call position by making sure call instructions are not skipped. Differential Revision: https://reviews.llvm.org/D119644
1 parent db8ae2f commit 78c27a3

File tree

2 files changed

+25
-3
lines changed

2 files changed

+25
-3
lines changed

llvm/lib/Target/X86/X86AvoidTrailingCall.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,8 @@ INITIALIZE_PASS(X86AvoidTrailingCallPass, AVOIDCALL_NAME, AVOIDCALL_DESC, false,
6969
// A real instruction is a non-meta, non-pseudo instruction. Some pseudos
7070
// expand to nothing, and some expand to code. This logic conservatively assumes
7171
// they might expand to nothing.
72-
static bool isRealInstruction(MachineInstr &MI) {
73-
return !MI.isPseudo() && !MI.isMetaInstruction();
72+
static bool isCallOrRealInstruction(MachineInstr &MI) {
73+
return MI.isCall() || (!MI.isPseudo() && !MI.isMetaInstruction());
7474
}
7575

7676
// Return true if this is a call instruction, but not a tail call.
@@ -100,7 +100,7 @@ bool X86AvoidTrailingCallPass::runOnMachineFunction(MachineFunction &MF) {
100100
continue;
101101

102102
// Find the last real instruction in this block.
103-
auto LastRealInstr = llvm::find_if(reverse(MBB), isRealInstruction);
103+
auto LastRealInstr = llvm::find_if(reverse(MBB), isCallOrRealInstruction);
104104

105105
// If the block is empty or the last real instruction is a call instruction,
106106
// insert an int3. If there is a call instruction, insert the int3 between
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
2+
; RUN: llc -mtriple=x86_64-windows-gnu %s -o - | FileCheck %s
3+
4+
define void @foo() gc "statepoint-example" personality i8* bitcast (i32 (...)* @__gxx_personality_seh0 to i8*) {
5+
; CHECK-LABEL: foo:
6+
; CHECK: # %bb.0:
7+
; CHECK-NEXT: subq $40, %rsp
8+
; CHECK-NEXT: .seh_stackalloc 40
9+
; CHECK-NEXT: .seh_endprologue
10+
; CHECK-NEXT: callq raise
11+
; CHECK-NEXT: .Ltmp0:
12+
; CHECK-NEXT: int3
13+
; CHECK-NEXT: .seh_endproc
14+
%statepoint_token = call token (i64, i32, void ()*, i32, i32, ...) @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 2882400000, i32 0, void ()* elementtype(void ()) @raise, i32 0, i32 0, i32 0, i32 0)
15+
unreachable
16+
}
17+
18+
declare void @raise()
19+
20+
declare dso_local i32 @__gxx_personality_seh0(...)
21+
22+
declare token @llvm.experimental.gc.statepoint.p0f_isVoidf(i64 immarg, i32 immarg, void ()*, i32 immarg, i32 immarg, ...)

0 commit comments

Comments
 (0)