Skip to content

Commit b1dcf78

Browse files
authored
[X86][APX] Fix issue of push2/pop2 instr with stack clash protection (#145303)
When -stack-clash-protection option is specified and APX push2pop2 is enabled, there will be two calls to emitSPUpdate function which emits two STACKALLOC_W_PROBING pseudo instructions. The pseudo instruction for push2 padding is silently ignored which leads to the stack misaligned to 16 bytes and GP exception in runtime. Fixed by directly emitting "push %rax" instruction for push2 padding, instead of calling emitSPUpdate. There was a similar issue on https://reviews.llvm.org/D150033.
1 parent ef04847 commit b1dcf78

File tree

2 files changed

+76
-3
lines changed

2 files changed

+76
-3
lines changed

llvm/lib/Target/X86/X86FrameLowering.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
STATISTIC(NumFrameLoopProbe, "Number of loop stack probes used in prologue");
4242
STATISTIC(NumFrameExtraProbe,
4343
"Number of extra stack probes generated in prologue");
44-
STATISTIC(NumFunctionUsingPush2Pop2, "Number of funtions using push2/pop2");
44+
STATISTIC(NumFunctionUsingPush2Pop2, "Number of functions using push2/pop2");
4545

4646
using namespace llvm;
4747

@@ -3021,8 +3021,12 @@ bool X86FrameLowering::spillCalleeSavedRegisters(
30213021
// Push GPRs. It increases frame size.
30223022
const MachineFunction &MF = *MBB.getParent();
30233023
const X86MachineFunctionInfo *X86FI = MF.getInfo<X86MachineFunctionInfo>();
3024-
if (X86FI->padForPush2Pop2())
3025-
emitSPUpdate(MBB, MI, DL, -(int64_t)SlotSize, /*InEpilogue=*/false);
3024+
if (X86FI->padForPush2Pop2()) {
3025+
assert(SlotSize == 8 && "Unexpected slot size for padding!");
3026+
BuildMI(MBB, MI, DL, TII.get(X86::PUSH64r))
3027+
.addReg(X86::RAX, RegState::Undef)
3028+
.setMIFlag(MachineInstr::FrameSetup);
3029+
}
30263030

30273031
// Update LiveIn of the basic block and decide whether we can add a kill flag
30283032
// to the use.
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
2+
; RUN: llc < %s -mtriple=x86_64 -mattr=+push2pop2 | FileCheck %s
3+
4+
5+
; This test is to check if "pushq %rax" is emitted correctly for push2pop2
6+
; padding when it's built with -stack-clash-protection option.
7+
8+
define i32 @foo(ptr %src1, i32 %len, ptr %src2, ptr %dst, i1 %cmp, i32 %sub) #0 {
9+
; CHECK-LABEL: foo:
10+
; CHECK: # %bb.0: # %entry
11+
; CHECK-NEXT: pushq %rax
12+
; CHECK-NEXT: .cfi_def_cfa_offset 16
13+
; CHECK-NEXT: push2 %r15, %rbp
14+
; CHECK-NEXT: .cfi_def_cfa_offset 32
15+
; CHECK-NEXT: push2 %r13, %r14
16+
; CHECK-NEXT: .cfi_def_cfa_offset 48
17+
; CHECK-NEXT: push2 %rbx, %r12
18+
; CHECK-NEXT: .cfi_def_cfa_offset 64
19+
; CHECK-NEXT: subq $16, %rsp
20+
; CHECK-NEXT: .cfi_def_cfa_offset 80
21+
; CHECK-NEXT: .cfi_offset %rbx, -64
22+
; CHECK-NEXT: .cfi_offset %r12, -56
23+
; CHECK-NEXT: .cfi_offset %r13, -48
24+
; CHECK-NEXT: .cfi_offset %r14, -40
25+
; CHECK-NEXT: .cfi_offset %r15, -32
26+
; CHECK-NEXT: .cfi_offset %rbp, -24
27+
; CHECK-NEXT: movl %r9d, {{[-0-9]+}}(%r{{[sb]}}p) # 4-byte Spill
28+
; CHECK-NEXT: movl %r8d, %ebp
29+
; CHECK-NEXT: movq %rcx, %r14
30+
; CHECK-NEXT: movq %rdx, %r15
31+
; CHECK-NEXT: movl %esi, %r12d
32+
; CHECK-NEXT: movq %rdi, %r13
33+
; CHECK-NEXT: xorl %ebx, %ebx
34+
; CHECK-NEXT: .p2align 4
35+
; CHECK-NEXT: .LBB0_1: # %while.body
36+
; CHECK-NEXT: # =>This Inner Loop Header: Depth=1
37+
; CHECK-NEXT: movq %r15, %rdi
38+
; CHECK-NEXT: movq %r13, %rsi
39+
; CHECK-NEXT: movq %r14, %rdx
40+
; CHECK-NEXT: xorl %ecx, %ecx
41+
; CHECK-NEXT: movl %r12d, %r8d
42+
; CHECK-NEXT: callq *%rbx
43+
; CHECK-NEXT: testb $1, %bpl
44+
; CHECK-NEXT: jne .LBB0_1
45+
; CHECK-NEXT: # %bb.2: # %while.end
46+
; CHECK-NEXT: movl {{[-0-9]+}}(%r{{[sb]}}p), %eax # 4-byte Reload
47+
; CHECK-NEXT: addq $16, %rsp
48+
; CHECK-NEXT: .cfi_def_cfa_offset 64
49+
; CHECK-NEXT: pop2 %r12, %rbx
50+
; CHECK-NEXT: .cfi_def_cfa_offset 48
51+
; CHECK-NEXT: pop2 %r14, %r13
52+
; CHECK-NEXT: .cfi_def_cfa_offset 32
53+
; CHECK-NEXT: pop2 %rbp, %r15
54+
; CHECK-NEXT: .cfi_def_cfa_offset 16
55+
; CHECK-NEXT: popq %rcx
56+
; CHECK-NEXT: .cfi_def_cfa_offset 8
57+
; CHECK-NEXT: retq
58+
entry:
59+
br label %while.body
60+
61+
while.body: ; preds = %while.body, %entry
62+
%call5 = tail call i32 null(ptr %src2, ptr %src1, ptr %dst, i32 0, i32 %len)
63+
br i1 %cmp, label %while.body, label %while.end
64+
65+
while.end: ; preds = %while.body
66+
ret i32 %sub
67+
}
68+
69+
attributes #0 = { "probe-stack"="inline-asm"}

0 commit comments

Comments
 (0)