Skip to content

Commit

Permalink
Fix X86 Target overflows
Browse files Browse the repository at this point in the history
Remove i386 test case since > 4gb allocas cannot be serviced on that platform
  • Loading branch information
wesleywiser committed Aug 11, 2024
1 parent 81515ce commit d7253f1
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 42 deletions.
11 changes: 10 additions & 1 deletion llvm/lib/Target/X86/X86FrameLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "llvm/CodeGen/MachineInstrBuilder.h"
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/CodeGen/WinEHFuncInfo.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/EHPersonalities.h"
Expand Down Expand Up @@ -2616,7 +2617,7 @@ StackOffset X86FrameLowering::getFrameIndexReference(const MachineFunction &MF,
// object.
// We need to factor in additional offsets applied during the prologue to the
// frame, base, and stack pointer depending on which is used.
int Offset = MFI.getObjectOffset(FI) - getOffsetOfLocalArea();
int64_t Offset = MFI.getObjectOffset(FI) - getOffsetOfLocalArea();
const X86MachineFunctionInfo *X86FI = MF.getInfo<X86MachineFunctionInfo>();
unsigned CSSize = X86FI->getCalleeSavedFrameSize();
uint64_t StackSize = MFI.getStackSize();
Expand Down Expand Up @@ -4140,6 +4141,14 @@ void X86FrameLowering::processFunctionBeforeFrameFinalized(
// emitPrologue if it gets called and emits CFI.
MF.setHasWinCFI(false);

MachineFrameInfo &MFI = MF.getFrameInfo();
// If the frame is big enough that we might need to scavenge a register to
// handle huge offsets, reserve a stack slot for that now.
if (!isInt<32>(MFI.estimateStackSize(MF))) {
int FI = MFI.CreateStackObject(SlotSize, Align(SlotSize), false);
RS->addScavengingFrameIndex(FI);
}

// If we are using Windows x64 CFI, ensure that the stack is always 8 byte
// aligned. The format doesn't support misaligned stack adjustments.
if (MF.getTarget().getMCAsmInfo()->usesWindowsCFI())
Expand Down
39 changes: 33 additions & 6 deletions llvm/lib/Target/X86/X86RegisterInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//

#include "X86RegisterInfo.h"
#include "MCTargetDesc/X86BaseInfo.h"
#include "X86FrameLowering.h"
#include "X86MachineFunctionInfo.h"
#include "X86Subtarget.h"
Expand All @@ -24,6 +25,7 @@
#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFunctionPass.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/CodeGen/TargetFrameLowering.h"
#include "llvm/CodeGen/TargetInstrInfo.h"
#include "llvm/CodeGen/TileShapeInfo.h"
Expand Down Expand Up @@ -900,7 +902,7 @@ X86RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
int FrameIndex = MI.getOperand(FIOperandNum).getIndex();

// Determine base register and offset.
int FIOffset;
int64_t FIOffset;
Register BasePtr;
if (MI.isReturn()) {
assert((!hasStackRealignment(MF) ||
Expand Down Expand Up @@ -951,11 +953,36 @@ X86RegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II,
}

if (MI.getOperand(FIOperandNum+3).isImm()) {
// Offset is a 32-bit integer.
int Imm = (int)(MI.getOperand(FIOperandNum + 3).getImm());
int Offset = FIOffset + Imm;
assert((!Is64Bit || isInt<32>((long long)FIOffset + Imm)) &&
"Requesting 64-bit offset in 32-bit immediate!");
int64_t Imm = MI.getOperand(FIOperandNum + 3).getImm();
int64_t Offset = FIOffset + Imm;
bool FitsIn32Bits = isInt<32>(Offset);
// If the offset will not fit in a 32-bit displacement,
// then for 64-bit targets, scavenge a register to hold it.
// Otherwise, for 32-bit targets, this is a bug!
if (Is64Bit && !FitsIn32Bits) {
assert(RS && "RegisterScavenger was NULL");
const X86InstrInfo *TII = MF.getSubtarget<X86Subtarget>().getInstrInfo();
const DebugLoc &DL = MI.getDebugLoc();

RS->enterBasicBlockEnd(MBB);
RS->backward(std::next(II));

Register ScratchReg = RS->scavengeRegisterBackwards(
X86::GR64RegClass, II, /* RestoreAfter */ false, /* SPAdj */ 0,
/* AllowSpill */ true);
assert(ScratchReg != 0 && "scratch reg was 0");
RS->setRegUsed(ScratchReg);

BuildMI(MBB, II, DL, TII->get(X86::MOV64ri), ScratchReg).addImm(Offset);

MI.getOperand(FIOperandNum + 3).setImm(0);
MI.getOperand(FIOperandNum + 2).setReg(ScratchReg);

return false;
}
if (!Is64Bit) {
assert(FitsIn32Bits && "Requesting 64-bit offset in 32-bit immediate!");
}
if (Offset != 0 || !tryOptimizeLEAtoMOV(II))
MI.getOperand(FIOperandNum + 3).ChangeToImmediate(Offset);
} else {
Expand Down
42 changes: 13 additions & 29 deletions llvm/test/CodeGen/X86/huge-stack-offset.ll
Original file line number Diff line number Diff line change
@@ -1,23 +1,15 @@
; RUN: llc < %s -mtriple=x86_64-linux-unknown -verify-machineinstrs | FileCheck %s --check-prefix=CHECK-64
; RUN: llc < %s -mtriple=i386-linux-unknown -verify-machineinstrs | FileCheck %s --check-prefix=CHECK-32
; RUN: llc < %s -mtriple=x86_64-linux-unknown -verify-machineinstrs | FileCheck %s

; Test that a large stack offset uses a single add/sub instruction to
; adjust the stack pointer.

define void @foo() nounwind {
; CHECK-64-LABEL: foo:
; CHECK-64: movabsq $50000000{{..}}, %rax
; CHECK-64-NEXT: subq %rax, %rsp
; CHECK-64-NOT: subq $2147483647, %rsp
; CHECK-64: movabsq $50000000{{..}}, [[RAX:%r..]]
; CHECK-64-NEXT: addq [[RAX]], %rsp

; CHECK-32-LABEL: foo:
; CHECK-32: movl $50000000{{..}}, %eax
; CHECK-32-NEXT: subl %eax, %esp
; CHECK-32-NOT: subl $2147483647, %esp
; CHECK-32: movl $50000000{{..}}, [[EAX:%e..]]
; CHECK-32-NEXT: addl [[EAX]], %esp
; CHECK--LABEL: foo:
; CHECK: movabsq $50000000{{..}}, %rax
; CHECK-NEXT: subq %rax, %rsp
; CHECK-NOT: subq $2147483647, %rsp
; CHECK: movabsq $50000000{{..}}, [[RAX:%r..]]
; CHECK-NEXT: addq [[RAX]], %rsp
%1 = alloca [5000000000 x i8], align 16
call void @bar(ptr %1)
ret void
Expand All @@ -26,13 +18,9 @@ define void @foo() nounwind {
; Verify that we do not clobber the return value.

define i32 @foo2() nounwind {
; CHECK-64-LABEL: foo2:
; CHECK-64: movl $10, %eax
; CHECK-64-NOT: movabsq ${{.*}}, %rax

; CHECK-32-LABEL: foo2:
; CHECK-32: movl $10, %eax
; CHECK-32-NOT: movl ${{.*}}, %eax
; CHECK-LABEL: foo2:
; CHECK: movl $10, %eax
; CHECK-NOT: movabsq ${{.*}}, %rax
%1 = alloca [5000000000 x i8], align 16
call void @bar(ptr %1)
ret i32 10
Expand All @@ -41,13 +29,9 @@ define i32 @foo2() nounwind {
; Verify that we do not clobber EAX when using inreg attribute

define i32 @foo3(i32 inreg %x) nounwind {
; CHECK-64-LABEL: foo3:
; CHECK-64: movabsq $50000000{{..}}, %rax
; CHECK-64-NEXT: subq %rax, %rsp

; CHECK-32-LABEL: foo3:
; CHECK-32: subl $2147483647, %esp
; CHECK-32-NOT: movl ${{.*}}, %eax
; CHECK-LABEL: foo3:
; CHECK: movabsq $50000000{{..}}, %rax
; CHECK-NEXT: subq %rax, %rsp
%1 = alloca [5000000000 x i8], align 16
call void @bar(ptr %1)
ret i32 %x
Expand Down
11 changes: 6 additions & 5 deletions llvm/test/CodeGen/X86/huge-stack.ll
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@
define void @foo() unnamed_addr #0 {
; CHECK-LABEL: foo:
; CHECK: # %bb.0:
; CHECK-NEXT: movabsq $8589934462, %rax # imm = 0x1FFFFFF7E
; CHECK-NEXT: movabsq $8589934472, %rax # imm = 0x1FFFFFF88
; CHECK-NEXT: subq %rax, %rsp
; CHECK-NEXT: .cfi_def_cfa_offset 8589934470
; CHECK-NEXT: movb $42, -129(%rsp)
; CHECK-NEXT: movb $43, -128(%rsp)
; CHECK-NEXT: movabsq $8589934462, %rax # imm = 0x1FFFFFF7E
; CHECK-NEXT: .cfi_def_cfa_offset 8589934480
; CHECK-NEXT: movabsq $4294967177, %rax # imm = 0xFFFFFF89
; CHECK-NEXT: movb $42, (%rsp,%rax)
; CHECK-NEXT: movb $43, -118(%rsp)
; CHECK-NEXT: movabsq $8589934472, %rax # imm = 0x1FFFFFF88
; CHECK-NEXT: addq %rax, %rsp
; CHECK-NEXT: .cfi_def_cfa_offset 8
; CHECK-NEXT: retq
Expand Down
2 changes: 1 addition & 1 deletion llvm/test/CodeGen/X86/win64-stackprobe-overflow.ll
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@ start:
attributes #0 = { nonlazybind uwtable "probe-stack"="probe_stack" "target-cpu"="x86-64" }

; CHECK-LABEL: foo:
; CHECK: movabsq $4294967304, %rax
; CHECK: movabsq $4294967312, %rax
; CHECK-NEXT: callq probe_stack

0 comments on commit d7253f1

Please sign in to comment.