Skip to content

Commit 1f26ac1

Browse files
authoredJan 25, 2025
[X86] Better handling of impossibly large stack frames (llvm#124217)
If you try to create a stack frame of 4 GiB or larger with a 32-bit stack pointer, we currently emit invalid instructions like `mov eax, 5000000000` (unless you specify `-fstack-clash-protection`, in which case we emit a trap instead). The trap seems nicer, so let's do that in all cases. This avoids emitting invalid instructions, and also fixes the "can't have 32-bit 16GB stack frame" assertion in `X86FrameLowering::emitSPUpdate()` (which used to be triggerable by user code, but is now correct). This was originally part of llvm#124041. @phoebewang
1 parent 8a6b44b commit 1f26ac1

File tree

3 files changed

+14
-33
lines changed

3 files changed

+14
-33
lines changed
 

‎llvm/lib/Target/X86/X86FrameLowering.cpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,14 @@ void X86FrameLowering::emitSPUpdate(MachineBasicBlock &MBB,
234234
MachineInstr::MIFlag Flag =
235235
isSub ? MachineInstr::FrameSetup : MachineInstr::FrameDestroy;
236236

237+
if (!Uses64BitFramePtr && !isUInt<32>(Offset)) {
238+
// We're being asked to adjust a 32-bit stack pointer by 4 GiB or more.
239+
// This might be unreachable code, so don't complain now; just trap if
240+
// it's reached at runtime.
241+
BuildMI(MBB, MBBI, DL, TII.get(X86::TRAP));
242+
return;
243+
}
244+
237245
uint64_t Chunk = (1LL << 31) - 1;
238246

239247
MachineFunction &MF = *MBB.getParent();
@@ -829,10 +837,7 @@ void X86FrameLowering::emitStackProbeInlineGenericLoop(
829837
.addReg(StackPtr)
830838
.setMIFlag(MachineInstr::FrameSetup);
831839
} else {
832-
// We're being asked to probe a stack frame that's 4 GiB or larger,
833-
// but our stack pointer is only 32 bits. This might be unreachable
834-
// code, so don't complain now; just trap if it's reached at runtime.
835-
BuildMI(MBB, MBBI, DL, TII.get(X86::TRAP));
840+
llvm_unreachable("Offset too large for 32-bit stack pointer");
836841
}
837842

838843
// while in the loop, use loop-invariant reg for CFI,

‎llvm/test/CodeGen/X86/huge-stack-offset.ll

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,9 @@ define void @foo() nounwind {
1313
; CHECK-64-NEXT: addq [[RAX]], %rsp
1414

1515
; CHECK-32-LABEL: foo:
16-
; CHECK-32: movl $50000000{{..}}, %eax
17-
; CHECK-32-NEXT: subl %eax, %esp
16+
; CHECK-32: ud2
1817
; CHECK-32-NOT: subl $2147483647, %esp
19-
; CHECK-32: movl $50000000{{..}}, [[EAX:%e..]]
20-
; CHECK-32-NEXT: addl [[EAX]], %esp
18+
; CHECK-32: ud2
2119
%1 = alloca [5000000000 x i8], align 16
2220
call void @bar(ptr %1)
2321
ret void
@@ -46,7 +44,7 @@ define i32 @foo3(i32 inreg %x) nounwind {
4644
; CHECK-64-NEXT: subq %rax, %rsp
4745

4846
; CHECK-32-LABEL: foo3:
49-
; CHECK-32: subl $2147483647, %esp
47+
; CHECK-32: ud2
5048
; CHECK-32-NOT: movl ${{.*}}, %eax
5149
%1 = alloca [5000000000 x i8], align 16
5250
call void @bar(ptr %1)

‎llvm/test/CodeGen/X86/stack-clash-extra-huge.ll

Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -30,44 +30,22 @@ define i32 @foo() local_unnamed_addr #0 {
3030
; CHECK-X86-LABEL: foo:
3131
; CHECK-X86: # %bb.0:
3232
; CHECK-X86-NEXT: ud2
33-
; CHECK-X86-NEXT: .cfi_def_cfa_register %eax
34-
; CHECK-X86-NEXT: .cfi_adjust_cfa_offset 4800000000
35-
; CHECK-X86-NEXT: .LBB0_1: # =>This Inner Loop Header: Depth=1
36-
; CHECK-X86-NEXT: subl $4096, %esp # imm = 0x1000
37-
; CHECK-X86-NEXT: movl $0, (%esp)
38-
; CHECK-X86-NEXT: cmpl %eax, %esp
39-
; CHECK-X86-NEXT: jne .LBB0_1
40-
; CHECK-X86-NEXT: # %bb.2:
41-
; CHECK-X86-NEXT: subl $12, %esp
42-
; CHECK-X86-NEXT: .cfi_def_cfa_register %esp
4333
; CHECK-X86-NEXT: .cfi_def_cfa_offset 4800000016
4434
; CHECK-X86-NEXT: movl $1, 392(%esp)
4535
; CHECK-X86-NEXT: movl $1, 28792(%esp)
4636
; CHECK-X86-NEXT: movl (%esp), %eax
47-
; CHECK-X86-NEXT: movl $4800000012, %ecx # imm = 0x11E1A300C
48-
; CHECK-X86-NEXT: addl %ecx, %esp
37+
; CHECK-X86-NEXT: ud2
4938
; CHECK-X86-NEXT: .cfi_def_cfa_offset 4
5039
; CHECK-X86-NEXT: retl
5140
;
5241
; CHECK-X32-LABEL: foo:
5342
; CHECK-X32: # %bb.0:
5443
; CHECK-X32-NEXT: ud2
55-
; CHECK-X32-NEXT: .cfi_def_cfa_register %r11
56-
; CHECK-X32-NEXT: .cfi_adjust_cfa_offset 4799995904
57-
; CHECK-X32-NEXT: .LBB0_1: # =>This Inner Loop Header: Depth=1
58-
; CHECK-X32-NEXT: subl $4096, %esp # imm = 0x1000
59-
; CHECK-X32-NEXT: movq $0, (%esp)
60-
; CHECK-X32-NEXT: cmpl %r11d, %esp
61-
; CHECK-X32-NEXT: jne .LBB0_1
62-
; CHECK-X32-NEXT: # %bb.2:
63-
; CHECK-X32-NEXT: subl $3976, %esp # imm = 0xF88
64-
; CHECK-X32-NEXT: .cfi_def_cfa_register %rsp
6544
; CHECK-X32-NEXT: .cfi_def_cfa_offset 4799999888
6645
; CHECK-X32-NEXT: movl $1, 264(%esp)
6746
; CHECK-X32-NEXT: movl $1, 28664(%esp)
6847
; CHECK-X32-NEXT: movl -128(%esp), %eax
69-
; CHECK-X32-NEXT: movl $4799999880, %ecx # imm = 0x11E1A2F88
70-
; CHECK-X32-NEXT: addl %ecx, %esp
48+
; CHECK-X32-NEXT: ud2
7149
; CHECK-X32-NEXT: .cfi_def_cfa_offset 8
7250
; CHECK-X32-NEXT: retq
7351
%a = alloca i32, i64 1200000000, align 16

0 commit comments

Comments
 (0)
Please sign in to comment.