@@ -132,3 +132,179 @@ uint64_t MipsFrameLowering::estimateStackSize(const MachineFunction &MF) const {
132
132
133
133
return RoundUpToAlignment (Offset, getStackAlignment ());
134
134
}
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
+ }
0 commit comments