llvm.org GIT mirror llvm / bc1fd91
Move the segmented stack switch to a function attribute This removes the -segmented-stacks command line flag in favor of a per-function "split-stack" attribute. Patch by Luqman Aden and Alex Crichton! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@205997 91177308-0d34-0410-b5e6-96231b3b80d8 Reid Kleckner 6 years ago
17 changed file(s) with 137 addition(s) and 95 deletion(s). Raw diff Collapse all Expand all
1212 done by allocating stack blocks (henceforth called *stacklets*) and linking them
1313 into a doubly linked list. The function prologue is responsible for checking if
1414 the current stacklet has enough space for the function to execute; and if not,
15 call into the libgcc runtime to allocate more stack space. When using ``llc``,
16 segmented stacks can be enabled by adding ``-segmented-stacks`` to the command
17 line.
15 call into the libgcc runtime to allocate more stack space. Segmented stacks are
16 enabled with the ``"split-stack"`` attribute on LLVM functions.
1817
1918 The runtime functionality is `already there in libgcc
2019 `_.
187187 EnablePIE("enable-pie",
188188 cl::desc("Assume the creation of a position independent executable."),
189189 cl::init(false));
190
191 cl::opt
192 SegmentedStacks("segmented-stacks",
193 cl::desc("Use segmented stacks if possible."),
194 cl::init(false));
195190
196191 cl::opt
197192 UseInitArray("use-init-array",
228223 Options.StackAlignmentOverride = OverrideStackAlignment;
229224 Options.TrapFuncName = TrapFuncName;
230225 Options.PositionIndependentExecutable = EnablePIE;
231 Options.EnableSegmentedStacks = SegmentedStacks;
232226 Options.UseInitArray = UseInitArray;
233227 return Options;
234228 }
258258 return MBBNumbering[N];
259259 }
260260
261 /// Should we be emitting segmented stack stuff for the function
262 bool shouldSplitStack();
263
261264 /// getNumBlockIDs - Return the number of MBB ID's allocated.
262265 ///
263266 unsigned getNumBlockIDs() const { return (unsigned)MBBNumbering.size(); }
4848 JITEmitDebugInfoToDisk(false), GuaranteedTailCallOpt(false),
4949 DisableTailCalls(false), StackAlignmentOverride(0),
5050 EnableFastISel(false), PositionIndependentExecutable(false),
51 EnableSegmentedStacks(false), UseInitArray(false),
51 UseInitArray(false),
5252 DisableIntegratedAS(false), CompressDebugSections(false),
5353 TrapFuncName(""), FloatABIType(FloatABI::Default),
5454 AllowFPOpFusion(FPOpFusion::Standard) {}
150150 /// relocation model being in use. It's value is undefined (and irrelevant)
151151 /// if the relocation model is anything other than PIC.
152152 unsigned PositionIndependentExecutable : 1;
153
154 unsigned EnableSegmentedStacks : 1;
155153
156154 /// UseInitArray - Use .init_array instead of .ctors for static
157155 /// constructors.
216214 ARE_EQUAL(StackAlignmentOverride) &&
217215 ARE_EQUAL(EnableFastISel) &&
218216 ARE_EQUAL(PositionIndependentExecutable) &&
219 ARE_EQUAL(EnableSegmentedStacks) &&
220217 ARE_EQUAL(UseInitArray) &&
221218 ARE_EQUAL(TrapFuncName) &&
222219 ARE_EQUAL(FloatABIType) &&
122122 return JumpTableInfo;
123123 }
124124
125 /// Should we be emitting segmented stack stuff for the function
126 bool MachineFunction::shouldSplitStack() {
127 return getFunction()->hasFnAttribute("split-stack");
128 }
129
125130 /// RenumberBlocks - This discards all of the MachineBasicBlock numbers and
126131 /// recomputes them. This guarantees that the MBB numbers are sequential,
127132 /// dense, and match the ordering of the blocks within the function. If a
679679 // we've been asked for it. This, when linked with a runtime with support
680680 // for segmented stacks (libgcc is one), will result in allocating stack
681681 // space in small chunks instead of one large contiguous block.
682 if (Fn.getTarget().Options.EnableSegmentedStacks)
682 if (Fn.shouldSplitStack())
683683 TFI.adjustForSegmentedStacks(Fn);
684684
685685 // Emit additional code that is required to explicitly handle the stack in
139139 Options.StackAlignmentOverride = options.StackAlignmentOverride;
140140 Options.TrapFuncName = options.TrapFuncName;
141141 Options.PositionIndependentExecutable = options.PositionIndependentExecutable;
142 Options.EnableSegmentedStacks = options.EnableSegmentedStacks;
143142 Options.UseInitArray = options.UseInitArray;
144143 }
145144
445445 !MFI->adjustsStack() && // No calls.
446446 !IsWin64 && // Win64 has no Red Zone
447447 !usesTheStack(MF) && // Don't push and pop.
448 !MF.getTarget().Options.EnableSegmentedStacks) { // Regular stack
448 !MF.shouldSplitStack()) { // Regular stack
449449 uint64_t MinSize = X86FI->getCalleeSavedFrameSize();
450450 if (HasFP) MinSize += SlotSize;
451451 StackSize = std::max(MinSize, StackSize > 128 ? StackSize - 128 : 0);
634634 setOperationAction(ISD::STACKSAVE, MVT::Other, Expand);
635635 setOperationAction(ISD::STACKRESTORE, MVT::Other, Expand);
636636
637 if (Subtarget->isOSWindows() && !Subtarget->isTargetMacho())
638 setOperationAction(ISD::DYNAMIC_STACKALLOC, Subtarget->is64Bit() ?
639 MVT::i64 : MVT::i32, Custom);
640 else if (TM.Options.EnableSegmentedStacks)
641 setOperationAction(ISD::DYNAMIC_STACKALLOC, Subtarget->is64Bit() ?
642 MVT::i64 : MVT::i32, Custom);
643 else
644 setOperationAction(ISD::DYNAMIC_STACKALLOC, Subtarget->is64Bit() ?
645 MVT::i64 : MVT::i32, Expand);
637 setOperationAction(ISD::DYNAMIC_STACKALLOC, Subtarget->is64Bit() ?
638 MVT::i64 : MVT::i32, Custom);
646639
647640 if (!TM.Options.UseSoftFloat && X86ScalarSSEf64) {
648641 // f32 and f64 use SSE.
1110111094 SDValue
1110211095 X86TargetLowering::LowerDYNAMIC_STACKALLOC(SDValue Op,
1110311096 SelectionDAG &DAG) const {
11104 assert((Subtarget->isOSWindows() ||
11105 getTargetMachine().Options.EnableSegmentedStacks) &&
11106 "This should be used only on Windows targets or when segmented stacks "
11107 "are being used");
11108 assert(!Subtarget->isTargetMacho() && "Not implemented");
11097 MachineFunction &MF = DAG.getMachineFunction();
11098 bool SplitStack = MF.shouldSplitStack();
11099 bool Lower = (Subtarget->isOSWindows() && !Subtarget->isTargetMacho()) ||
11100 SplitStack;
1110911101 SDLoc dl(Op);
11102
11103 if (!Lower) {
11104 const TargetLowering &TLI = DAG.getTargetLoweringInfo();
11105 SDNode* Node = Op.getNode();
11106
11107 unsigned SPReg = TLI.getStackPointerRegisterToSaveRestore();
11108 assert(SPReg && "Target cannot require DYNAMIC_STACKALLOC expansion and"
11109 " not tell us which reg is the stack pointer!");
11110 EVT VT = Node->getValueType(0);
11111 SDValue Tmp1 = SDValue(Node, 0);
11112 SDValue Tmp2 = SDValue(Node, 1);
11113 SDValue Tmp3 = Node->getOperand(2);
11114 SDValue Chain = Tmp1.getOperand(0);
11115
11116 // Chain the dynamic stack allocation so that it doesn't modify the stack
11117 // pointer when other instructions are using the stack.
11118 Chain = DAG.getCALLSEQ_START(Chain, DAG.getIntPtrConstant(0, true),
11119 SDLoc(Node));
11120
11121 SDValue Size = Tmp2.getOperand(1);
11122 SDValue SP = DAG.getCopyFromReg(Chain, dl, SPReg, VT);
11123 Chain = SP.getValue(1);
11124 unsigned Align = cast(Tmp3)->getZExtValue();
11125 const TargetFrameLowering &TFI = *getTargetMachine().getFrameLowering();
11126 unsigned StackAlign = TFI.getStackAlignment();
11127 Tmp1 = DAG.getNode(ISD::SUB, dl, VT, SP, Size); // Value
11128 if (Align > StackAlign)
11129 Tmp1 = DAG.getNode(ISD::AND, dl, VT, Tmp1,
11130 DAG.getConstant(-(uint64_t)Align, VT));
11131 Chain = DAG.getCopyToReg(Chain, dl, SPReg, Tmp1); // Output chain
11132
11133 Tmp2 = DAG.getCALLSEQ_END(Chain, DAG.getIntPtrConstant(0, true),
11134 DAG.getIntPtrConstant(0, true), SDValue(),
11135 SDLoc(Node));
11136
11137 SDValue Ops[2] = { Tmp1, Tmp2 };
11138 return DAG.getMergeValues(Ops, 2, dl);
11139 }
1111011140
1111111141 // Get the inputs.
1111211142 SDValue Chain = Op.getOperand(0);
1111711147 bool Is64Bit = Subtarget->is64Bit();
1111811148 EVT SPTy = Is64Bit ? MVT::i64 : MVT::i32;
1111911149
11120 if (getTargetMachine().Options.EnableSegmentedStacks) {
11121 MachineFunction &MF = DAG.getMachineFunction();
11150 if (SplitStack) {
1112211151 MachineRegisterInfo &MRI = MF.getRegInfo();
1112311152
1112411153 if (Is64Bit) {
1579515824 MachineFunction *MF = BB->getParent();
1579615825 const BasicBlock *LLVM_BB = BB->getBasicBlock();
1579715826
15798 assert(getTargetMachine().Options.EnableSegmentedStacks);
15827 assert(MF->shouldSplitStack());
1579915828
1580015829 unsigned TlsReg = Is64Bit ? X86::FS : X86::GS;
1580115830 unsigned TlsOffset = Is64Bit ? 0x70 : 0x30;
None ; RUN: llc < %s -mtriple=arm-linux-unknown-gnueabi -segmented-stacks -verify-machineinstrs -filetype=asm | FileCheck %s -check-prefix=ARM-linux
1 ; RUN: llc < %s -mtriple=arm-linux-unknown-gnueabi -segmented-stacks -filetype=obj
0 ; RUN: llc < %s -mtriple=arm-linux-unknown-gnueabi -verify-machineinstrs -filetype=asm | FileCheck %s -check-prefix=ARM-linux
1 ; RUN: llc < %s -mtriple=arm-linux-unknown-gnueabi -filetype=obj
22
33 !llvm.dbg.cu = !{!0}
44 !llvm.module.flags = !{!9, !10}
55 !llvm.ident = !{!11}
66
7 define void @test_basic() {
7 define void @test_basic() #0 {
88 %mem = alloca i32, i32 10
99 call void @dummy_use (i32* %mem, i32 10)
1010 ret void
7777
7878 ; Just to prevent the alloca from being optimized away
7979 declare void @dummy_use(i32*, i32)
80
81 attributes #0 = { "split-stack" }
None ; RUN: llc < %s -mtriple=arm-linux-androideabi -segmented-stacks -verify-machineinstrs | FileCheck %s -check-prefix=ARM-android
1 ; RUN: llc < %s -mtriple=arm-linux-unknown-gnueabi -segmented-stacks -verify-machineinstrs | FileCheck %s -check-prefix=ARM-linux
2 ; RUN: llc < %s -mtriple=arm-linux-androideabi -segmented-stacks -filetype=obj
3 ; RUN: llc < %s -mtriple=arm-linux-unknown-gnueabi -segmented-stacks -filetype=obj
0 ; RUN: llc < %s -mtriple=arm-linux-androideabi -verify-machineinstrs | FileCheck %s -check-prefix=ARM-android
1 ; RUN: llc < %s -mtriple=arm-linux-unknown-gnueabi -verify-machineinstrs | FileCheck %s -check-prefix=ARM-linux
2 ; RUN: llc < %s -mtriple=arm-linux-androideabi -filetype=obj
3 ; RUN: llc < %s -mtriple=arm-linux-unknown-gnueabi -filetype=obj
44
55 ; Just to prevent the alloca from being optimized away
66 declare void @dummy_use(i32*, i32)
77
8 define i32 @test_basic(i32 %l) {
8 define i32 @test_basic(i32 %l) #0 {
99 %mem = alloca i32, i32 %l
1010 call void @dummy_use (i32* %mem, i32 %l)
1111 %terminate = icmp eq i32 %l, 0
5959 ; ARM-android: pop {r4, r5}
6060
6161 }
62
63 attributes #0 = { "split-stack" }
None ; RUN: llc < %s -mtriple=arm-linux-androideabi -segmented-stacks -verify-machineinstrs | FileCheck %s -check-prefix=ARM-android
1 ; RUN: llc < %s -mtriple=arm-linux-unknown-gnueabi -segmented-stacks -verify-machineinstrs | FileCheck %s -check-prefix=ARM-linux
0 ; RUN: llc < %s -mtriple=arm-linux-androideabi -verify-machineinstrs | FileCheck %s -check-prefix=ARM-android
1 ; RUN: llc < %s -mtriple=arm-linux-unknown-gnueabi -verify-machineinstrs | FileCheck %s -check-prefix=ARM-linux
22
33 ; We used to crash with filetype=obj
4 ; RUN: llc < %s -mtriple=arm-linux-androideabi -segmented-stacks -filetype=obj
5 ; RUN: llc < %s -mtriple=arm-linux-unknown-gnueabi -segmented-stacks -filetype=obj
4 ; RUN: llc < %s -mtriple=arm-linux-androideabi -filetype=obj
5 ; RUN: llc < %s -mtriple=arm-linux-unknown-gnueabi -filetype=obj
66
77
88 ; Just to prevent the alloca from being optimized away
99 declare void @dummy_use(i32*, i32)
1010
11 define void @test_basic() {
11 define void @test_basic() #0 {
1212 %mem = alloca i32, i32 10
1313 call void @dummy_use (i32* %mem, i32 10)
1414 ret void
5353
5454 }
5555
56 define i32 @test_nested(i32 * nest %closure, i32 %other) {
56 define i32 @test_nested(i32 * nest %closure, i32 %other) #0 {
5757 %addend = load i32 * %closure
5858 %result = add i32 %other, %addend
5959 ret i32 %result
9898
9999 }
100100
101 define void @test_large() {
101 define void @test_large() #0 {
102102 %mem = alloca i32, i32 10000
103103 call void @dummy_use (i32* %mem, i32 0)
104104 ret void
143143
144144 }
145145
146 define fastcc void @test_fastcc() {
146 define fastcc void @test_fastcc() #0 {
147147 %mem = alloca i32, i32 10
148148 call void @dummy_use (i32* %mem, i32 10)
149149 ret void
188188
189189 }
190190
191 define fastcc void @test_fastcc_large() {
191 define fastcc void @test_fastcc_large() #0 {
192192 %mem = alloca i32, i32 10000
193193 call void @dummy_use (i32* %mem, i32 0)
194194 ret void
232232 ; ARM-android: pop {r4, r5}
233233
234234 }
235
236 attributes #0 = { "split-stack" }
None ; RUN: llc < %s -mtriple=thumb-linux-unknown-gnueabi -segmented-stacks -verify-machineinstrs | FileCheck %s -check-prefix=Thumb-linux
1 ; RUN: llc < %s -mtriple=thumb-linux-androideabi -segmented-stacks -verify-machineinstrs | FileCheck %s -check-prefix=Thumb-android
2 ; RUN: llc < %s -mtriple=thumb-linux-unknown-gnueabi -segmented-stacks -filetype=obj
3 ; RUN: llc < %s -mtriple=thumb-linux-androideabi -segmented-stacks -filetype=obj
0 ; RUN: llc < %s -mtriple=thumb-linux-unknown-gnueabi -verify-machineinstrs | FileCheck %s -check-prefix=Thumb-linux
1 ; RUN: llc < %s -mtriple=thumb-linux-androideabi -verify-machineinstrs | FileCheck %s -check-prefix=Thumb-android
2 ; RUN: llc < %s -mtriple=thumb-linux-unknown-gnueabi -filetype=obj
3 ; RUN: llc < %s -mtriple=thumb-linux-androideabi -filetype=obj
44
55 ; Just to prevent the alloca from being optimized away
66 declare void @dummy_use(i32*, i32)
77
8 define i32 @test_basic(i32 %l) {
8 define i32 @test_basic(i32 %l) #0 {
99 %mem = alloca i32, i32 %l
1010 call void @dummy_use (i32* %mem, i32 %l)
1111 %terminate = icmp eq i32 %l, 0
6060 ; Thumb-android: pop {r4, r5}
6161
6262 }
63
64 attributes #0 = { "split-stack" }
None ; RUN: llc < %s -mtriple=thumb-linux-androideabi -segmented-stacks -verify-machineinstrs | FileCheck %s -check-prefix=Thumb-android
1 ; RUN: llc < %s -mtriple=thumb-linux-unknown-gnueabi -segmented-stacks -verify-machineinstrs | FileCheck %s -check-prefix=Thumb-linux
2 ; RUN: llc < %s -mtriple=thumb-linux-androideabi -segmented-stacks -filetype=obj
3 ; RUN: llc < %s -mtriple=thumb-linux-unknown-gnueabi -segmented-stacks -filetype=obj
0 ; RUN: llc < %s -mtriple=thumb-linux-androideabi -verify-machineinstrs | FileCheck %s -check-prefix=Thumb-android
1 ; RUN: llc < %s -mtriple=thumb-linux-unknown-gnueabi -verify-machineinstrs | FileCheck %s -check-prefix=Thumb-linux
2 ; RUN: llc < %s -mtriple=thumb-linux-androideabi -filetype=obj
3 ; RUN: llc < %s -mtriple=thumb-linux-unknown-gnueabi -filetype=obj
44
55
66 ; Just to prevent the alloca from being optimized away
77 declare void @dummy_use(i32*, i32)
88
9 define void @test_basic() {
9 define void @test_basic() #0 {
1010 %mem = alloca i32, i32 10
1111 call void @dummy_use (i32* %mem, i32 10)
1212 ret void
5353
5454 }
5555
56 define i32 @test_nested(i32 * nest %closure, i32 %other) {
56 define i32 @test_nested(i32 * nest %closure, i32 %other) #0 {
5757 %addend = load i32 * %closure
5858 %result = add i32 %other, %addend
5959 ret i32 %result
100100
101101 }
102102
103 define void @test_large() {
103 define void @test_large() #0 {
104104 %mem = alloca i32, i32 10000
105105 call void @dummy_use (i32* %mem, i32 0)
106106 ret void
149149
150150 }
151151
152 define fastcc void @test_fastcc() {
152 define fastcc void @test_fastcc() #0 {
153153 %mem = alloca i32, i32 10
154154 call void @dummy_use (i32* %mem, i32 10)
155155 ret void
196196
197197 }
198198
199 define fastcc void @test_fastcc_large() {
199 define fastcc void @test_fastcc_large() #0 {
200200 %mem = alloca i32, i32 10000
201201 call void @dummy_use (i32* %mem, i32 0)
202202 ret void
244244 ; Thumb-linux: pop {r4, r5}
245245
246246 }
247
248 attributes #0 = { "split-stack" }
None ; RUN: llc < %s -mtriple=thumb-linux-androideabi -march=thumb -mcpu=arm1156t2-s -mattr=+thumb2 -segmented-stacks -verify-machineinstrs | FileCheck %s -check-prefix=Thumb-android
1 ; RUN: llc < %s -mtriple=thumb-linux-androideabi -march=thumb -mcpu=arm1156t2-s -mattr=+thumb2 -segmented-stacks -filetype=obj
0 ; RUN: llc < %s -mtriple=thumb-linux-androideabi -march=thumb -mcpu=arm1156t2-s -mattr=+thumb2 -verify-machineinstrs | FileCheck %s -check-prefix=Thumb-android
1 ; RUN: llc < %s -mtriple=thumb-linux-androideabi -march=thumb -mcpu=arm1156t2-s -mattr=+thumb2 -filetype=obj
22
33
44 ; Just to prevent the alloca from being optimized away
55 declare void @dummy_use(i32*, i32)
66
7 define void @test_basic() {
7 define void @test_basic() #0 {
88 %mem = alloca i32, i32 10
99 call void @dummy_use (i32* %mem, i32 10)
1010 ret void
2929 ; Thumb-android: pop {r4, r5}
3030
3131 }
32
33 attributes #0 = { "split-stack" }
None ; RUN: llc < %s -mcpu=generic -mtriple=i686-linux -segmented-stacks -verify-machineinstrs | FileCheck %s -check-prefix=X32
1 ; RUN: llc < %s -mcpu=generic -mtriple=x86_64-linux -segmented-stacks -verify-machineinstrs | FileCheck %s -check-prefix=X64
2 ; RUN: llc < %s -mcpu=generic -mtriple=i686-linux -segmented-stacks -filetype=obj
3 ; RUN: llc < %s -mcpu=generic -mtriple=x86_64-linux -segmented-stacks -filetype=obj
0 ; RUN: llc < %s -mcpu=generic -mtriple=i686-linux -verify-machineinstrs | FileCheck %s -check-prefix=X32
1 ; RUN: llc < %s -mcpu=generic -mtriple=x86_64-linux -verify-machineinstrs | FileCheck %s -check-prefix=X64
2 ; RUN: llc < %s -mcpu=generic -mtriple=i686-linux -filetype=obj
3 ; RUN: llc < %s -mcpu=generic -mtriple=x86_64-linux -filetype=obj
44
55 ; Just to prevent the alloca from being optimized away
66 declare void @dummy_use(i32*, i32)
77
8 define i32 @test_basic(i32 %l) {
8 define i32 @test_basic(i32 %l) #0 {
99 %mem = alloca i32, i32 %l
1010 call void @dummy_use (i32* %mem, i32 %l)
1111 %terminate = icmp eq i32 %l, 0
6161 ; X64: movq %rax, %rdi
6262
6363 }
64
65 attributes #0 = { "split-stack" }
None ; RUN: llc < %s -mcpu=generic -mtriple=i686-linux -segmented-stacks -verify-machineinstrs | FileCheck %s -check-prefix=X32-Linux
1 ; RUN: llc < %s -mcpu=generic -mtriple=x86_64-linux -segmented-stacks -verify-machineinstrs | FileCheck %s -check-prefix=X64-Linux
2 ; RUN: llc < %s -mcpu=generic -mtriple=i686-darwin -segmented-stacks -verify-machineinstrs | FileCheck %s -check-prefix=X32-Darwin
3 ; RUN: llc < %s -mcpu=generic -mtriple=x86_64-darwin -segmented-stacks -verify-machineinstrs | FileCheck %s -check-prefix=X64-Darwin
4 ; RUN: llc < %s -mcpu=generic -mtriple=i686-mingw32 -segmented-stacks -verify-machineinstrs | FileCheck %s -check-prefix=X32-MinGW
5 ; RUN: llc < %s -mcpu=generic -mtriple=x86_64-freebsd -segmented-stacks -verify-machineinstrs | FileCheck %s -check-prefix=X64-FreeBSD
6 ; RUN: llc < %s -mcpu=generic -mtriple=x86_64-mingw32 -segmented-stacks -verify-machineinstrs | FileCheck %s -check-prefix=X64-MinGW
0 ; RUN: llc < %s -mcpu=generic -mtriple=i686-linux -verify-machineinstrs | FileCheck %s -check-prefix=X32-Linux
1 ; RUN: llc < %s -mcpu=generic -mtriple=x86_64-linux -verify-machineinstrs | FileCheck %s -check-prefix=X64-Linux
2 ; RUN: llc < %s -mcpu=generic -mtriple=i686-darwin -verify-machineinstrs | FileCheck %s -check-prefix=X32-Darwin
3 ; RUN: llc < %s -mcpu=generic -mtriple=x86_64-darwin -verify-machineinstrs | FileCheck %s -check-prefix=X64-Darwin
4 ; RUN: llc < %s -mcpu=generic -mtriple=i686-mingw32 -verify-machineinstrs | FileCheck %s -check-prefix=X32-MinGW
5 ; RUN: llc < %s -mcpu=generic -mtriple=x86_64-freebsd -verify-machineinstrs | FileCheck %s -check-prefix=X64-FreeBSD
6 ; RUN: llc < %s -mcpu=generic -mtriple=x86_64-mingw32 -verify-machineinstrs | FileCheck %s -check-prefix=X64-MinGW
77
88 ; We used to crash with filetype=obj
9 ; RUN: llc < %s -mcpu=generic -mtriple=i686-linux -segmented-stacks -filetype=obj
10 ; RUN: llc < %s -mcpu=generic -mtriple=x86_64-linux -segmented-stacks -filetype=obj
11 ; RUN: llc < %s -mcpu=generic -mtriple=i686-darwin -segmented-stacks -filetype=obj
12 ; RUN: llc < %s -mcpu=generic -mtriple=x86_64-darwin -segmented-stacks -filetype=obj
13 ; RUN: llc < %s -mcpu=generic -mtriple=i686-mingw32 -segmented-stacks -filetype=obj
14 ; RUN: llc < %s -mcpu=generic -mtriple=x86_64-freebsd -segmented-stacks -filetype=obj
15 ; RUN: llc < %s -mcpu=generic -mtriple=x86_64-mingw32 -segmented-stacks -filetype=obj
16
17 ; RUN: not llc < %s -mcpu=generic -mtriple=x86_64-solaris -segmented-stacks 2> %t.log
9 ; RUN: llc < %s -mcpu=generic -mtriple=i686-linux -filetype=obj
10 ; RUN: llc < %s -mcpu=generic -mtriple=x86_64-linux -filetype=obj
11 ; RUN: llc < %s -mcpu=generic -mtriple=i686-darwin -filetype=obj
12 ; RUN: llc < %s -mcpu=generic -mtriple=x86_64-darwin -filetype=obj
13 ; RUN: llc < %s -mcpu=generic -mtriple=i686-mingw32 -filetype=obj
14 ; RUN: llc < %s -mcpu=generic -mtriple=x86_64-freebsd -filetype=obj
15 ; RUN: llc < %s -mcpu=generic -mtriple=x86_64-mingw32 -filetype=obj
16
17 ; RUN: not llc < %s -mcpu=generic -mtriple=x86_64-solaris 2> %t.log
1818 ; RUN: FileCheck %s -input-file=%t.log -check-prefix=X64-Solaris
19 ; RUN: not llc < %s -mcpu=generic -mtriple=i686-freebsd -segmented-stacks 2> %t.log
19 ; RUN: not llc < %s -mcpu=generic -mtriple=i686-freebsd 2> %t.log
2020 ; RUN: FileCheck %s -input-file=%t.log -check-prefix=X32-FreeBSD
2121
2222 ; X64-Solaris: Segmented stacks not supported on this platform
2525 ; Just to prevent the alloca from being optimized away
2626 declare void @dummy_use(i32*, i32)
2727
28 define void @test_basic() {
28 define void @test_basic() #0 {
2929 %mem = alloca i32, i32 10
3030 call void @dummy_use (i32* %mem, i32 10)
3131 ret void
103103
104104 }
105105
106 define i32 @test_nested(i32 * nest %closure, i32 %other) {
106 define i32 @test_nested(i32 * nest %closure, i32 %other) #0 {
107107 %addend = load i32 * %closure
108108 %result = add i32 %other, %addend
109109 ret i32 %result
176176
177177 }
178178
179 define void @test_large() {
179 define void @test_large() #0 {
180180 %mem = alloca i32, i32 10000
181181 call void @dummy_use (i32* %mem, i32 0)
182182 ret void
248248
249249 }
250250
251 define fastcc void @test_fastcc() {
251 define fastcc void @test_fastcc() #0 {
252252 %mem = alloca i32, i32 10
253253 call void @dummy_use (i32* %mem, i32 10)
254254 ret void
326326
327327 }
328328
329 define fastcc void @test_fastcc_large() {
329 define fastcc void @test_fastcc_large() #0 {
330330 %mem = alloca i32, i32 10000
331331 call void @dummy_use (i32* %mem, i32 0)
332332 ret void
411411
412412 }
413413
414 define fastcc void @test_fastcc_large_with_ecx_arg(i32 %a) {
414 define fastcc void @test_fastcc_large_with_ecx_arg(i32 %a) #0 {
415415 %mem = alloca i32, i32 10000
416416 call void @dummy_use (i32* %mem, i32 %a)
417417 ret void
433433 ; X32-Darwin-NEXT: ret
434434
435435 }
436
437 attributes #0 = { "split-stack" }