llvm.org GIT mirror llvm / 76927d7
Emit segmented-stack specific code into function prologues for X86. Modify the pass added in the previous patch to call this new code. This new prologues generated will call a libgcc routine (__morestack) to allocate more stack space from the heap when required Patch by Sanjoy Das. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@138812 91177308-0d34-0410-b5e6-96231b3b80d8 Rafael Espindola 9 years ago
6 changed file(s) with 186 addition(s) and 3 deletion(s). Raw diff Collapse all Expand all
113113 virtual void emitEpilogue(MachineFunction &MF,
114114 MachineBasicBlock &MBB) const = 0;
115115
116 /// Adjust the prologue to have the function use segmented stacks. This works
117 /// by adding a check even before the "normal" function prologue.
118 virtual void adjustForSegmentedStacks(MachineFunction &MF) const { }
119
116120 /// spillCalleeSavedRegisters - Issues instruction(s) to spill all callee
117121 /// saved registers and returns true if it isn't possible / profitable to do
118122 /// so by issuing a series of store instructions via
2828 #include "llvm/CodeGen/MachineRegisterInfo.h"
2929 #include "llvm/CodeGen/RegisterScavenging.h"
3030 #include "llvm/Target/TargetMachine.h"
31 #include "llvm/Target/TargetOptions.h"
3132 #include "llvm/Target/TargetRegisterInfo.h"
3233 #include "llvm/Target/TargetFrameLowering.h"
3334 #include "llvm/Target/TargetInstrInfo.h"
698699 if (!I->empty() && I->back().getDesc().isReturn())
699700 TFI.emitEpilogue(Fn, *I);
700701 }
702
703 // Emit additional code that is required support segmented stacks, if we've
704 // been asked for it. This, when linked with a runtime with support for
705 // segmented stacks (libgcc is one), will result allocating stack space in
706 // small chunks instead of one large contiguous block.
707 if (EnableSegmentedStacks)
708 TFI.adjustForSegmentedStacks(Fn);
701709 }
702710
703711 /// replaceFrameIndices - Replace all MO_FrameIndex operands with physical
1414 #include "X86InstrBuilder.h"
1515 #include "X86InstrInfo.h"
1616 #include "X86MachineFunctionInfo.h"
17 #include "X86Subtarget.h"
1718 #include "X86TargetMachine.h"
1819 #include "llvm/Function.h"
1920 #include "llvm/CodeGen/MachineFrameInfo.h"
644645 !RegInfo->needsStackRealignment(MF) &&
645646 !MFI->hasVarSizedObjects() && // No dynamic alloca.
646647 !MFI->adjustsStack() && // No calls.
647 !IsWin64) { // Win64 has no Red Zone
648 !IsWin64 && // Win64 has no Red Zone
649 !EnableSegmentedStacks) { // Regular stack
648650 uint64_t MinSize = X86FI->getCalleeSavedFrameSize();
649651 if (HasFP) MinSize += SlotSize;
650652 StackSize = std::max(MinSize, StackSize > 128 ? StackSize - 128 : 0);
12741276 FrameIdx = 0;
12751277 }
12761278 }
1279
1280 static bool
1281 HasNestArgument(const MachineFunction *MF) {
1282 const Function *F = MF->getFunction();
1283 for (Function::const_arg_iterator I = F->arg_begin(), E = F->arg_end();
1284 I != E; I++) {
1285 if (I->hasNestAttr())
1286 return true;
1287 }
1288 return false;
1289 }
1290
1291 static unsigned
1292 GetScratchRegister(bool Is64Bit, const MachineFunction &MF) {
1293 if (Is64Bit) {
1294 return X86::R11;
1295 } else {
1296 CallingConv::ID CallingConvention = MF.getFunction()->getCallingConv();
1297 bool IsNested = HasNestArgument(&MF);
1298
1299 if (CallingConvention == CallingConv::X86_FastCall) {
1300 if (IsNested) {
1301 report_fatal_error("Segmented stacks does not supprot fastcall with "
1302 "nested fucntion.");
1303 return -1;
1304 } else {
1305 return X86::EAX;
1306 }
1307 } else {
1308 if (IsNested)
1309 return X86::EDX;
1310 else
1311 return X86::ECX;
1312 }
1313 }
1314 }
1315
1316 void
1317 X86FrameLowering::adjustForSegmentedStacks(MachineFunction &MF) const {
1318 MachineBasicBlock &prologueMBB = MF.front();
1319 MachineFrameInfo *MFI = MF.getFrameInfo();
1320 const X86InstrInfo &TII = *TM.getInstrInfo();
1321 uint64_t StackSize;
1322 bool Is64Bit = STI.is64Bit();
1323 unsigned TlsReg, TlsOffset;
1324 DebugLoc DL;
1325 const X86Subtarget *ST = &MF.getTarget().getSubtarget();
1326
1327 unsigned ScratchReg = GetScratchRegister(Is64Bit, MF);
1328 assert(!MF.getRegInfo().isLiveIn(ScratchReg) &&
1329 "Scratch register is live-in");
1330
1331 if (MF.getFunction()->isVarArg())
1332 report_fatal_error("Segmented stacks do not support vararg functions.");
1333 if (!ST->isTargetLinux())
1334 report_fatal_error("Segmented stacks supported only on linux.");
1335
1336 MachineBasicBlock *allocMBB = MF.CreateMachineBasicBlock();
1337 MachineBasicBlock *checkMBB = MF.CreateMachineBasicBlock();
1338 X86MachineFunctionInfo *X86FI = MF.getInfo();
1339 bool IsNested = false;
1340
1341 // We need to know if the function has a nest argument only in 64 bit mode.
1342 if (Is64Bit)
1343 IsNested = HasNestArgument(&MF);
1344
1345 for (MachineBasicBlock::livein_iterator i = prologueMBB.livein_begin(),
1346 e = prologueMBB.livein_end(); i != e; i++) {
1347 allocMBB->addLiveIn(*i);
1348 checkMBB->addLiveIn(*i);
1349 }
1350
1351 if (IsNested)
1352 allocMBB->addLiveIn(X86::R10);
1353
1354 MF.push_front(allocMBB);
1355 MF.push_front(checkMBB);
1356
1357 // Eventually StackSize will be calculated by a link-time pass; which will
1358 // also decide whether checking code needs to be injected into this particular
1359 // prologue.
1360 StackSize = MFI->getStackSize();
1361
1362 // Read the limit off the current stacklet off the stack_guard location.
1363 if (Is64Bit) {
1364 TlsReg = X86::FS;
1365 TlsOffset = 0x70;
1366
1367 BuildMI(checkMBB, DL, TII.get(X86::LEA64r), ScratchReg).addReg(X86::RSP)
1368 .addImm(0).addReg(0).addImm(-StackSize).addReg(0);
1369 BuildMI(checkMBB, DL, TII.get(X86::CMP64rm)).addReg(ScratchReg)
1370 .addReg(0).addImm(0).addReg(0).addImm(TlsOffset).addReg(TlsReg);
1371 } else {
1372 TlsReg = X86::GS;
1373 TlsOffset = 0x30;
1374
1375 BuildMI(checkMBB, DL, TII.get(X86::LEA32r), ScratchReg).addReg(X86::ESP)
1376 .addImm(0).addReg(0).addImm(-StackSize).addReg(0);
1377 BuildMI(checkMBB, DL, TII.get(X86::CMP32rm)).addReg(ScratchReg)
1378 .addReg(0).addImm(0).addReg(0).addImm(TlsOffset).addReg(TlsReg);
1379 }
1380
1381 // This jump is taken if SP >= (Stacklet Limit + Stack Space required).
1382 // It jumps to normal execution of the function body.
1383 BuildMI(checkMBB, DL, TII.get(X86::JG_4)).addMBB(&prologueMBB);
1384
1385 // On 32 bit we first push the arguments size and then the frame size. On 64
1386 // bit, we pass the stack frame size in r10 and the argument size in r11.
1387 if (Is64Bit) {
1388 // Functions with nested arguments use R10, so it needs to be saved across
1389 // the call to _morestack
1390
1391 if (IsNested)
1392 BuildMI(allocMBB, DL, TII.get(X86::MOV64rr), X86::RAX).addReg(X86::R10);
1393
1394 BuildMI(allocMBB, DL, TII.get(X86::MOV64ri), X86::R10)
1395 .addImm(StackSize);
1396 BuildMI(allocMBB, DL, TII.get(X86::MOV64ri), X86::R11)
1397 .addImm(X86FI->getArgumentStackSize());
1398 MF.getRegInfo().setPhysRegUsed(X86::R10);
1399 MF.getRegInfo().setPhysRegUsed(X86::R11);
1400 } else {
1401 // Since we'll call __morestack, stack alignment needs to be preserved.
1402 BuildMI(allocMBB, DL, TII.get(X86::SUB32ri), X86::ESP).addReg(X86::ESP)
1403 .addImm(8);
1404 BuildMI(allocMBB, DL, TII.get(X86::PUSHi32))
1405 .addImm(X86FI->getArgumentStackSize());
1406 BuildMI(allocMBB, DL, TII.get(X86::PUSHi32))
1407 .addImm(StackSize);
1408 }
1409
1410 // __morestack is in libgcc
1411 if (Is64Bit)
1412 BuildMI(allocMBB, DL, TII.get(X86::CALL64pcrel32))
1413 .addExternalSymbol("__morestack");
1414 else
1415 BuildMI(allocMBB, DL, TII.get(X86::CALLpcrel32))
1416 .addExternalSymbol("__morestack");
1417
1418 // __morestack only seems to remove 8 bytes off the stack. Add back the
1419 // additional 8 bytes we added before pushing the arguments.
1420 if (!Is64Bit)
1421 BuildMI(allocMBB, DL, TII.get(X86::ADD32ri), X86::ESP).addReg(X86::ESP)
1422 .addImm(8);
1423 BuildMI(allocMBB, DL, TII.get(X86::RET));
1424
1425 if (Is64Bit && IsNested)
1426 BuildMI(allocMBB, DL, TII.get(X86::MOV64rr), X86::R10).addReg(X86::RAX);
1427
1428 allocMBB->addSuccessor(&prologueMBB);
1429 checkMBB->addSuccessor(allocMBB);
1430 checkMBB->addSuccessor(&prologueMBB);
1431
1432 #ifndef NDEBUG
1433 MF.verify();
1434 #endif
1435 }
4040 void emitPrologue(MachineFunction &MF) const;
4141 void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const;
4242
43 void adjustForSegmentedStacks(MachineFunction &MF) const;
44
4345 void processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
4446 RegScavenger *RS = NULL) const;
4547
19291929 // fastcc functions can't have varargs.
19301930 FuncInfo->setVarArgsFrameIndex(0xAAAAAAA);
19311931 }
1932
1933 FuncInfo->setArgumentStackSize(StackSize);
19321934
19331935 return Chain;
19341936 }
6464 unsigned VarArgsGPOffset;
6565 /// VarArgsFPOffset - X86-64 vararg func fp reg offset.
6666 unsigned VarArgsFPOffset;
67 /// ArgumentStackSize - The number of bytes on stack consumed by the arguments
68 /// being passed on the stack.
69 unsigned ArgumentStackSize;
6770
6871 public:
6972 X86MachineFunctionInfo() : ForceFramePointer(false),
7679 VarArgsFrameIndex(0),
7780 RegSaveFrameIndex(0),
7881 VarArgsGPOffset(0),
79 VarArgsFPOffset(0) {}
82 VarArgsFPOffset(0),
83 ArgumentStackSize(0) {}
8084
8185 explicit X86MachineFunctionInfo(MachineFunction &MF)
8286 : ForceFramePointer(false),
9094 VarArgsFrameIndex(0),
9195 RegSaveFrameIndex(0),
9296 VarArgsGPOffset(0),
93 VarArgsFPOffset(0) {}
97 VarArgsFPOffset(0),
98 ArgumentStackSize(0) {}
9499
95100 bool getForceFramePointer() const { return ForceFramePointer;}
96101 void setForceFramePointer(bool forceFP) { ForceFramePointer = forceFP; }
127132
128133 unsigned getVarArgsFPOffset() const { return VarArgsFPOffset; }
129134 void setVarArgsFPOffset(unsigned Offset) { VarArgsFPOffset = Offset; }
135
136 unsigned getArgumentStackSize() const { return ArgumentStackSize; }
137 void setArgumentStackSize(unsigned size) { ArgumentStackSize = size; }
130138 };
131139
132140 } // End llvm namespace