Skip to content
This repository was archived by the owner on Feb 5, 2019. It is now read-only.

Commit 6abe4fe

Browse files
brsonluqmana
authored andcommitted
Add MIPS segmented stacks
1 parent e1cfed4 commit 6abe4fe

File tree

4 files changed

+187
-0
lines changed

4 files changed

+187
-0
lines changed

lib/Target/Mips/MipsFrameLowering.cpp

Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,3 +132,179 @@ uint64_t MipsFrameLowering::estimateStackSize(const MachineFunction &MF) const {
132132

133133
return RoundUpToAlignment(Offset, getStackAlignment());
134134
}
135+
136+
// The stack limit in the TCB is set to this manyu bytes above the actual
137+
// stack limit.
138+
static const uint64_t kSplitStackAvailable = 256;
139+
140+
// helper function for loading immediate
141+
static void loadImm(MachineBasicBlock *MBB, DebugLoc DL,
142+
const TargetInstrInfo &TII,
143+
unsigned Reg, int64_t Imm) {
144+
if (isInt<16>(Imm)) {
145+
// addiu $Reg, $zero, Imm
146+
BuildMI(MBB, DL, TII.get(Mips::ADDiu), Reg)
147+
.addReg(Mips::ZERO).addImm(Imm);
148+
} else {
149+
// lui $Reg, (Imm >> 16)
150+
BuildMI(MBB, DL, TII.get(Mips::LUi), Reg)
151+
.addImm(Imm >> 16);
152+
// ori $Reg, $Reg, (Imm & 0xffff)
153+
BuildMI(MBB, DL, TII.get(Mips::ORi), Reg)
154+
.addReg(Reg).addImm(Imm & 0xffff);
155+
}
156+
}
157+
158+
// Adjust function prologue to enable split stack.
159+
void
160+
MipsFrameLowering::adjustForSegmentedStacks(MachineFunction &MF) const {
161+
const TargetMachine &TM = MF.getTarget();
162+
const MipsSubtarget *ST = &TM.getSubtarget<MipsSubtarget>();
163+
164+
// Doesn't support vararg function.
165+
if (MF.getFunction()->isVarArg())
166+
report_fatal_error("Segmented stacks do not support vararg functions.");
167+
// Doesn't support other than linux o32 with pic relocation.
168+
if (!ST->isLinux() || !ST->isABI_O32() || TM.getRelocationModel() != Reloc::PIC_)
169+
report_fatal_error("Segmented statks not supported on this platfrom.");
170+
171+
MachineBasicBlock &prologueMBB = MF.front();
172+
MachineFrameInfo* MFI = MF.getFrameInfo();
173+
const TargetInstrInfo &TII = *TM.getInstrInfo();
174+
MipsFunctionInfo* MipsFI = MF.getInfo<MipsFunctionInfo>();
175+
DebugLoc DL;
176+
177+
// Use t6 and t7 as scratch register.
178+
unsigned ScratchReg0 = Mips::T6;
179+
unsigned ScratchReg1 = Mips::T7;
180+
// Use the private field of tcb head.
181+
unsigned TlsOffset = 0x7004;
182+
183+
MachineBasicBlock* allocMBB = MF.CreateMachineBasicBlock();
184+
MachineBasicBlock* checkMBB = MF.CreateMachineBasicBlock();
185+
186+
for (MachineBasicBlock::livein_iterator i = prologueMBB.livein_begin(),
187+
e = prologueMBB.livein_end(); i != e; ++i) {
188+
allocMBB->addLiveIn(*i);
189+
checkMBB->addLiveIn(*i);
190+
}
191+
192+
MF.push_front(allocMBB);
193+
MF.push_front(checkMBB);
194+
195+
uint64_t StackSize = MFI->getStackSize();
196+
197+
// When the frame size is less than 256 we just compare the stack
198+
// boundary directly to the value of the stack pointer, per gcc.
199+
bool CompareStackPointer = StackSize < kSplitStackAvailable;
200+
201+
if (!MipsFI->globalBaseRegSet()) {
202+
// lui $v0, %hi(_gp_disp)
203+
BuildMI(checkMBB, DL, TII.get(Mips::LUi), Mips::V0)
204+
.addExternalSymbol("_gp_disp", MipsII::MO_ABS_HI);
205+
// addiu $v0, $v0, %lo(_gp_disp)
206+
BuildMI(checkMBB, DL, TII.get(Mips::ADDiu), Mips::V0)
207+
.addReg(Mips::V0)
208+
.addExternalSymbol("_gp_disp", MipsII::MO_ABS_LO);
209+
allocMBB->addLiveIn(Mips::V0);
210+
allocMBB->addLiveIn(Mips::T9);
211+
}
212+
213+
if (CompareStackPointer) {
214+
// addu $SR1, $sp, $zero
215+
BuildMI(checkMBB, DL, TII.get(Mips::ADDu), ScratchReg1)
216+
.addReg(Mips::SP).addReg(Mips::ZERO);
217+
} else {
218+
// li $SR1, -StackSize
219+
loadImm(checkMBB, DL, TII, ScratchReg1, -StackSize);
220+
// addu $SR1, $sp, $SR1
221+
BuildMI(checkMBB, DL, TII.get(Mips::ADDu), ScratchReg1)
222+
.addReg(Mips::SP).addReg(ScratchReg1);
223+
}
224+
225+
// rdhwr $v1, $sp
226+
BuildMI(checkMBB, DL, TII.get(Mips::RDHWR), Mips::V1)
227+
.addReg(Mips::HWR29);
228+
229+
// addiu $v1, $v1, -TlsOffset
230+
BuildMI(checkMBB, DL, TII.get(Mips::ADDiu), Mips::V1)
231+
.addReg(Mips::V1).addImm((-TlsOffset) & 0xffff);
232+
233+
// Get stack limit.
234+
// lw $SR0, 0($v1)
235+
BuildMI(checkMBB, DL, TII.get(Mips::LW), ScratchReg0)
236+
.addReg(Mips::V1).addImm(0);
237+
238+
// Compare stack limit with stack size requested.
239+
// sltu $v1, $SR0, $SR1
240+
BuildMI(checkMBB, DL, TII.get(Mips::SLTu), Mips::V1)
241+
.addReg(ScratchReg0).addReg(ScratchReg1);
242+
243+
// This jump is taken if StackLimit < (SP - stack required).
244+
// bne $v1, $zero, $prologueMBB
245+
BuildMI(checkMBB, DL, TII.get(Mips::BNE))
246+
.addReg(Mips::V1).addReg(Mips::ZERO).addMBB(&prologueMBB);
247+
248+
// Calling __morestack(StackSize, Size of stack arguments).
249+
// __morestack knows that the stack size requested is in SR0(t6)
250+
// and amount size of stack arguments is in SR1(t7).
251+
252+
// Pass first argument for the __morestack by Scratch Register #0.
253+
// The amount size of stack required
254+
// li $SR0, StackSize
255+
loadImm(allocMBB, DL, TII, ScratchReg0, StackSize);
256+
257+
// Pass second argument for the __morestack by Scratch Register #1.
258+
// The amount size of stack consumed to save function arguments.
259+
// li $SR1, ArgumentStackSize
260+
loadImm(allocMBB, DL, TII, ScratchReg1, MipsFI->getArgumentStackSize());
261+
262+
// addiu $sp, $sp, -12
263+
BuildMI(allocMBB, DL, TII.get(Mips::ADDiu), Mips::SP)
264+
.addReg(Mips::SP).addImm(-12);
265+
// Save return address of this function.
266+
// sw $ra, 8($sp)
267+
BuildMI(allocMBB, DL, TII.get(Mips::SW))
268+
.addReg(Mips::RA).addReg(Mips::SP).addImm(8);
269+
// Save function address and _gp_disp for PIC.
270+
// sw $t9, 4($sp)
271+
BuildMI(allocMBB, DL, TII.get(Mips::SW))
272+
.addReg(Mips::T9).addReg(Mips::SP).addImm(4);
273+
// sw $v0, 0($sp)
274+
BuildMI(allocMBB, DL, TII.get(Mips::SW))
275+
.addReg(Mips::V0).addReg(Mips::SP).addImm(0);
276+
277+
// addu $gp, $v0, $t9
278+
BuildMI(allocMBB, DL, TII.get(Mips::ADDu), Mips::GP)
279+
.addReg(Mips::V0).addReg(Mips::T9);
280+
// lw $t9, %call16(__morestack)($gp)
281+
BuildMI(allocMBB, DL, TII.get(Mips::LW), Mips::T9)
282+
.addReg(Mips::GP)
283+
.addExternalSymbol("__morestack", MipsII::MO_GOT_CALL);
284+
// jalr $t9
285+
BuildMI(allocMBB, DL, TII.get(Mips::JALR), Mips::RA)
286+
.addReg(Mips::T9);
287+
288+
// Restore return address of this original function.
289+
// lw $ra, 8($sp)
290+
BuildMI(allocMBB, DL, TII.get(Mips::LW), Mips::RA)
291+
.addReg(Mips::SP).addImm(8);
292+
// addiu $sp, $sp, 12
293+
BuildMI(allocMBB, DL, TII.get(Mips::ADDiu), Mips::SP)
294+
.addReg(Mips::SP).addImm(12);
295+
296+
// Return from this function.
297+
// jr $ra
298+
BuildMI(allocMBB, DL, TII.get(Mips::JR))
299+
.addReg(Mips::RA);
300+
301+
// Organizing MBB lists
302+
allocMBB->addSuccessor(&prologueMBB);
303+
304+
checkMBB->addSuccessor(allocMBB);
305+
checkMBB->addSuccessor(&prologueMBB);
306+
307+
#ifdef XDEBUG
308+
MF.verify();
309+
#endif
310+
}

lib/Target/Mips/MipsFrameLowering.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ class MipsFrameLowering : public TargetFrameLowering {
3434

3535
bool hasFP(const MachineFunction &MF) const;
3636

37+
void adjustForSegmentedStacks(MachineFunction &MF) const;
38+
3739
protected:
3840
uint64_t estimateStackSize(const MachineFunction &MF) const;
3941
};

lib/Target/Mips/MipsISelLowering.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2732,6 +2732,8 @@ MipsTargetLowering::LowerFormalArguments(SDValue Chain,
27322732
&OutChains[0], OutChains.size());
27332733
}
27342734

2735+
MipsFI->setArgumentStackSize(CCInfo.getNextStackOffset());
2736+
27352737
return Chain;
27362738
}
27372739

lib/Target/Mips/MipsMachineFunction.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,9 @@ class MipsFunctionInfo : public MachineFunctionInfo {
6969
int getVarArgsFrameIndex() const { return VarArgsFrameIndex; }
7070
void setVarArgsFrameIndex(int Index) { VarArgsFrameIndex = Index; }
7171

72+
unsigned getArgumentStackSize() const { return ArgumentStackSize; }
73+
void setArgumentStackSize(unsigned size) { ArgumentStackSize = size; }
74+
7275
bool hasByvalArg() const { return HasByvalArg; }
7376
void setFormalArgInfo(unsigned Size, bool HasByval) {
7477
IncomingArgSize = Size;
@@ -126,6 +129,10 @@ class MipsFunctionInfo : public MachineFunctionInfo {
126129
/// Frame objects for spilling eh data registers.
127130
int EhDataRegFI[4];
128131

132+
/// ArgumentStackSize - amount of bytes on stack consumed by the arguments
133+
/// being passed on the stack
134+
unsigned ArgumentStackSize;
135+
129136
/// MipsCallEntry maps.
130137
StringMap<const MipsCallEntry *> ExternalCallEntries;
131138
ValueMap<const GlobalValue *, const MipsCallEntry *> GlobalCallEntries;

0 commit comments

Comments
 (0)