diff --git a/lib/Target/X86/X86FrameLowering.cpp b/lib/Target/X86/X86FrameLowering.cpp index 545248ac100d40b29e71c6546e010839b4b005dc..667beffba0ea0f2030cc15bc07501d1c481f4b1d 100644 --- a/lib/Target/X86/X86FrameLowering.cpp +++ b/lib/Target/X86/X86FrameLowering.cpp @@ -68,7 +68,7 @@ X86FrameLowering::canSimplifyCallFramePseudos(const MachineFunction &MF) const { // needsFrameIndexResolution - Do we need to perform FI resolution for // this function. Normally, this is required only when the function // has any stack objects. However, FI resolution actually has another job, -// not apparent from the title - it resolves callframesetup/destroy +// not apparent from the title - it resolves callframesetup/destroy // that were not simplified earlier. // So, this is required for x86 functions that have push sequences even // when there are no stack objects. @@ -78,6 +78,11 @@ X86FrameLowering::needsFrameIndexResolution(const MachineFunction &MF) const { MF.getInfo<X86MachineFunctionInfo>()->getHasPushSequences(); } +static +bool hasStackSwitch(const MachineFunction &MF) { + return MF.getFunction().hasFnAttribute("stackswitch-sp-symbol"); +} + /// hasFP - Return true if the specified function should have a dedicated frame /// pointer register. This is true if the function has variable sized allocas /// or if frame pointer elimination is disabled. @@ -85,6 +90,7 @@ bool X86FrameLowering::hasFP(const MachineFunction &MF) const { const MachineFrameInfo &MFI = MF.getFrameInfo(); return (MF.getTarget().Options.DisableFramePointerElim(MF) || TRI->needsStackRealignment(MF) || + hasStackSwitch(MF) || MFI.hasVarSizedObjects() || MFI.isFrameAddressTaken() || MFI.hasOpaqueSPAdjustment() || MF.getInfo<X86MachineFunctionInfo>()->getForceFramePointer() || @@ -603,7 +609,7 @@ void X86FrameLowering::emitStackProbeInline(MachineFunction &MF, int64_t RCXShadowSlot = 0; int64_t RDXShadowSlot = 0; - // If inlining in the prolog, save RCX and RDX. + // If inlining in the prolog, save RCX and RDX. // Future optimization: don't save or restore if not live in. if (InProlog) { // Compute the offsets. We need to account for things already @@ -1179,6 +1185,18 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF, } } + // Switch stack. TODO: more doc + if (hasStackSwitch(MF)) { + StringRef stack_symbol = Fn.getFnAttribute("stackswitch-sp-symbol").getValueAsString(); + // X86AddressMode AM; + GlobalValue * GV = Fn.getParent()->getNamedValue(stack_symbol); + X86AddressMode AM; + AM.GV = GV; + addFullAddress(BuildMI(MBB, MBBI, DL, + TII.get(Is64Bit ? X86::MOV64rm : X86::MOV32rm), StackPtr), + AM); + } + // Realign stack after we pushed callee-saved registers (so that we'll be // able to calculate their offsets from the frame pointer). // Don't do this for Win64, it needs to realign the stack after the prologue. @@ -1621,9 +1639,9 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF, // slot before popping them off! Same applies for the case, when stack was // realigned. Don't do this if this was a funclet epilogue, since the funclets // will not do realignment or dynamic stack allocation. - if ((TRI->needsStackRealignment(MF) || MFI.hasVarSizedObjects()) && + if ((TRI->needsStackRealignment(MF) || MFI.hasVarSizedObjects() || hasStackSwitch(MF)) && !IsFunclet) { - if (TRI->needsStackRealignment(MF)) + if (TRI->needsStackRealignment(MF) || hasStackSwitch(MF)) MBBI = FirstCSPop; unsigned SEHFrameOffset = calculateSetFPREG(SEHStackAllocAmt); uint64_t LEAAmount = @@ -2642,7 +2660,7 @@ bool X86FrameLowering::adjustStackWithPops(MachineBasicBlock &MBB, Regs[FoundRegs++] = Regs[0]; for (int i = 0; i < NumPops; ++i) - BuildMI(MBB, MBBI, DL, + BuildMI(MBB, MBBI, DL, TII.get(STI.is64Bit() ? X86::POP64r : X86::POP32r), Regs[i]); return true; @@ -2923,7 +2941,7 @@ struct X86FrameSortingComparator { // in general. Something to keep in mind, though. if (DensityAScaled == DensityBScaled) return A.ObjectAlignment < B.ObjectAlignment; - + return DensityAScaled < DensityBScaled; } }; @@ -2959,7 +2977,7 @@ void X86FrameLowering::orderFrameObjects( if (ObjectSize == 0) // Variable size. Just use 4. SortingObjects[Obj].ObjectSize = 4; - else + else SortingObjects[Obj].ObjectSize = ObjectSize; } diff --git a/lib/Target/X86/X86RegisterInfo.cpp b/lib/Target/X86/X86RegisterInfo.cpp index f979cc51da4f3c8c1c5a052d9d03a374aa87d8eb..690e51aa4fcd99bda4e3728f637a9ddd0233ead9 100644 --- a/lib/Target/X86/X86RegisterInfo.cpp +++ b/lib/Target/X86/X86RegisterInfo.cpp @@ -602,6 +602,9 @@ static bool CantUseSP(const MachineFrameInfo &MFI) { bool X86RegisterInfo::hasBasePointer(const MachineFunction &MF) const { const MachineFrameInfo &MFI = MF.getFrameInfo(); + if (MF.getFunction().hasFnAttribute("stackswitch-sp-symbol")) + return true; + if (!EnableBasePointer) return false; diff --git a/test/CodeGen/X86/stackswitch-symbol-basic.ll b/test/CodeGen/X86/stackswitch-symbol-basic.ll new file mode 100644 index 0000000000000000000000000000000000000000..dc618303cbdafa229f083f28f53a6399a66278b9 --- /dev/null +++ b/test/CodeGen/X86/stackswitch-symbol-basic.ll @@ -0,0 +1,34 @@ +; RUN: llvm-as < %s | llc -mtriple=i386-pc-linux-gnu \ +; RUN: | FileCheck %s + + +@DOSEK_BasicTaskStack = external global i8*, align 8 +@.str = private unnamed_addr constant [3 x i8] c"%s\00", align 1 +@.str1 = private unnamed_addr constant [10 x i8] c"Success!\0A\00", align 1 + +; Function Attrs: nounwind +; Function Attrs: noinline nounwind uwtable +define i32 @foo(i8*) #0 { +; CHECK: movl %esp, %ebp +; CHECK: movl DOSEK_BasicTaskStack, %esp +; CHECK: movl %esp, %esi + %2 = alloca i8*, align 8 + store i8* %0, i8** %2, align 8 + %3 = load i8*, i8** %2, align 8 + %4 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([3 x i8], [3 x i8]* @.str, i32 0, i32 0), i8* %3) + ret i32 %4 +; CHECK: leal -{{[0-9]+}}(%ebp), %esp +; CHECK: popl %esi +} + +declare i32 @printf(i8*, ...) + +; Function Attrs: nounwind +define i32 @main() { + %1 = alloca i32, align 4 + store i32 0, i32* %1, align 4 + %2 = call i32 @foo(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str1, i32 0, i32 0)) + ret i32 %2 +} + +attributes #0 = { "stackswitch-sp-symbol"="DOSEK_BasicTaskStack" } diff --git a/test/CodeGen/X86/stackswitch-symbol-dynamic.ll b/test/CodeGen/X86/stackswitch-symbol-dynamic.ll new file mode 100644 index 0000000000000000000000000000000000000000..dcf4adb74638f3ffe40062f9b9262fd863669c36 --- /dev/null +++ b/test/CodeGen/X86/stackswitch-symbol-dynamic.ll @@ -0,0 +1,26 @@ +; RUN: llvm-as < %s | llc -mtriple=i386-pc-linux-gnu \ +; RUN: | FileCheck %s + +@DOSEK_BasicTaskStack = external global i8*, align 8 + +; Function Attrs: nounwind +define void @mad(i32 %length) #0 { +; CHECK: movl %esp, %ebp +; CHECK: movl DOSEK_BasicTaskStack, %esp +; CHECK: movl %esp, %esi + %m = alloca i32, i32 %length + ret void +; CHECK: leal -{{[0-9]+}}(%ebp), %esp +; CHECK: popl %esi +} + +; Function Attrs: nounwind +define i32 @main(i32 %argc, i8** %argv) { +; CHECK-NOT: DOSEK_BasicTaskStack + call void @mad(i32 32750) + ret i32 0 +} + + +attributes #0 = { "stackswitch-sp-symbol"="DOSEK_BasicTaskStack"} + diff --git a/test/CodeGen/X86/stackswitch-symbol-recursion.ll b/test/CodeGen/X86/stackswitch-symbol-recursion.ll new file mode 100644 index 0000000000000000000000000000000000000000..55f3229b5cabb7380cf64b1c57a8258f0428950a --- /dev/null +++ b/test/CodeGen/X86/stackswitch-symbol-recursion.ll @@ -0,0 +1,30 @@ +; RUN: llvm-as < %s | llc -mtriple=i386-pc-linux-gnu \ +; RUN: | FileCheck %s + +@DOSEK_BasicTaskStack = external global i8*, align 8 + +define i32 @bar(i32 %start) { +; CHECK-NOT: DOSEK_BasicTaskStack + %1 = call i32 @bar(i32 %start) + ret i32 %1 + +} + +; Function Attrs: nounwind +define i32 @foo(i32 %start) #0 { +; CHECK: movl %esp, %ebp +; CHECK: movl DOSEK_BasicTaskStack, %esp + %1 = call i32 @bar(i32 2) + ret i32 %1 +; CHECK: leal -{{[0-9]+}}(%ebp), %esp +} + +; Function Attrs: nounwind +define i32 @main(i32 %argc, i8** %argv) { +; CHECK-NOT: DOSEK_BasicTaskStack + %1 = call i32 @foo(i32 -10000) + ret i32 0 +} + + +attributes #0 = { "stackswitch-sp-symbol"="DOSEK_BasicTaskStack" }