1 //===-- XCoreFrameLowering.cpp - Frame info for XCore Target --------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file contains XCore frame information that doesn't fit anywhere else
13 //===----------------------------------------------------------------------===//
15 #include "XCoreFrameLowering.h"
17 #include "XCoreInstrInfo.h"
18 #include "XCoreMachineFunctionInfo.h"
19 #include "llvm/CodeGen/MachineFrameInfo.h"
20 #include "llvm/CodeGen/MachineFunction.h"
21 #include "llvm/CodeGen/MachineInstrBuilder.h"
22 #include "llvm/CodeGen/MachineModuleInfo.h"
23 #include "llvm/CodeGen/MachineRegisterInfo.h"
24 #include "llvm/CodeGen/RegisterScavenging.h"
25 #include "llvm/IR/DataLayout.h"
26 #include "llvm/IR/Function.h"
27 #include "llvm/Support/ErrorHandling.h"
28 #include "llvm/Target/TargetOptions.h"
32 // helper functions. FIXME: Eliminate.
33 static inline bool isImmU6(unsigned val) {
34 return val < (1 << 6);
37 static inline bool isImmU16(unsigned val) {
38 return val < (1 << 16);
41 static void loadFromStack(MachineBasicBlock &MBB,
42 MachineBasicBlock::iterator I,
43 unsigned DstReg, int Offset, DebugLoc dl,
44 const TargetInstrInfo &TII) {
45 assert(Offset%4 == 0 && "Misaligned stack offset");
47 bool isU6 = isImmU6(Offset);
48 if (!isU6 && !isImmU16(Offset))
49 report_fatal_error("loadFromStack offset too big " + Twine(Offset));
50 int Opcode = isU6 ? XCore::LDWSP_ru6 : XCore::LDWSP_lru6;
51 BuildMI(MBB, I, dl, TII.get(Opcode), DstReg)
56 static void storeToStack(MachineBasicBlock &MBB,
57 MachineBasicBlock::iterator I,
58 unsigned SrcReg, int Offset, DebugLoc dl,
59 const TargetInstrInfo &TII) {
60 assert(Offset%4 == 0 && "Misaligned stack offset");
62 bool isU6 = isImmU6(Offset);
63 if (!isU6 && !isImmU16(Offset))
64 report_fatal_error("storeToStack offset too big " + Twine(Offset));
65 int Opcode = isU6 ? XCore::STWSP_ru6 : XCore::STWSP_lru6;
66 BuildMI(MBB, I, dl, TII.get(Opcode))
72 //===----------------------------------------------------------------------===//
73 // XCoreFrameLowering:
74 //===----------------------------------------------------------------------===//
76 XCoreFrameLowering::XCoreFrameLowering(const XCoreSubtarget &sti)
77 : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, 4, 0) {
81 bool XCoreFrameLowering::hasFP(const MachineFunction &MF) const {
82 return MF.getTarget().Options.DisableFramePointerElim(MF) ||
83 MF.getFrameInfo()->hasVarSizedObjects();
86 void XCoreFrameLowering::emitPrologue(MachineFunction &MF) const {
87 MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB
88 MachineBasicBlock::iterator MBBI = MBB.begin();
89 MachineFrameInfo *MFI = MF.getFrameInfo();
90 MachineModuleInfo *MMI = &MF.getMMI();
91 const MCRegisterInfo *MRI = MMI->getContext().getRegisterInfo();
92 const XCoreInstrInfo &TII =
93 *static_cast<const XCoreInstrInfo*>(MF.getTarget().getInstrInfo());
94 XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>();
95 DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
97 if (MFI->getMaxAlignment() > getStackAlignment())
98 report_fatal_error("emitPrologue unsupported alignment: "
99 + Twine(MFI->getMaxAlignment()));
102 const AttributeSet &PAL = MF.getFunction()->getAttributes();
104 if (PAL.hasAttrSomewhere(Attribute::Nest))
105 loadFromStack(MBB, MBBI, XCore::R11, 0, dl, TII);
107 // Work out frame sizes.
108 int FrameSize = MFI->getStackSize();
109 assert(FrameSize%4 == 0 && "Misaligned frame size");
112 bool isU6 = isImmU6(FrameSize);
114 if (!isU6 && !isImmU16(FrameSize)) {
115 // FIXME could emit multiple instructions.
116 report_fatal_error("emitPrologue Frame size too big: " + Twine(FrameSize));
118 bool emitFrameMoves = XCoreRegisterInfo::needsFrameMoves(MF);
120 bool saveLR = XFI->getUsesLR();
121 // Do we need to allocate space on the stack?
123 bool LRSavedOnEntry = false;
125 if (saveLR && (MFI->getObjectOffset(XFI->getLRSpillSlot()) == 0)) {
126 Opcode = (isU6) ? XCore::ENTSP_u6 : XCore::ENTSP_lu6;
127 MBB.addLiveIn(XCore::LR);
129 LRSavedOnEntry = true;
131 Opcode = (isU6) ? XCore::EXTSP_u6 : XCore::EXTSP_lu6;
133 BuildMI(MBB, MBBI, dl, TII.get(Opcode)).addImm(FrameSize);
135 if (emitFrameMoves) {
136 // Show update of SP.
137 MCSymbol *FrameLabel = MMI->getContext().CreateTempSymbol();
138 BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(FrameLabel);
139 MMI->addFrameInst(MCCFIInstruction::createDefCfaOffset(FrameLabel,
141 if (LRSavedOnEntry) {
142 unsigned Reg = MRI->getDwarfRegNum(XCore::LR, true);
143 MMI->addFrameInst(MCCFIInstruction::createOffset(FrameLabel, Reg, 0));
148 int LRSpillOffset = MFI->getObjectOffset(XFI->getLRSpillSlot());
149 storeToStack(MBB, MBBI, XCore::LR, LRSpillOffset + FrameSize*4, dl, TII);
150 MBB.addLiveIn(XCore::LR);
152 if (emitFrameMoves) {
153 MCSymbol *SaveLRLabel = MMI->getContext().CreateTempSymbol();
154 BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(SaveLRLabel);
155 unsigned Reg = MRI->getDwarfRegNum(XCore::LR, true);
156 MMI->addFrameInst(MCCFIInstruction::createOffset(SaveLRLabel, Reg,
162 // Save R10 to the stack.
163 int FPSpillOffset = MFI->getObjectOffset(XFI->getFPSpillSlot());
164 storeToStack(MBB, MBBI, XCore::R10, FPSpillOffset + FrameSize*4, dl, TII);
165 // R10 is live-in. It is killed at the spill.
166 MBB.addLiveIn(XCore::R10);
167 if (emitFrameMoves) {
168 MCSymbol *SaveR10Label = MMI->getContext().CreateTempSymbol();
169 BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(SaveR10Label);
170 unsigned Reg = MRI->getDwarfRegNum(XCore::R10, true);
171 MMI->addFrameInst(MCCFIInstruction::createOffset(SaveR10Label, Reg,
174 // Set the FP from the SP.
175 unsigned FramePtr = XCore::R10;
176 BuildMI(MBB, MBBI, dl, TII.get(XCore::LDAWSP_ru6), FramePtr).addImm(0);
177 if (emitFrameMoves) {
178 // Show FP is now valid.
179 MCSymbol *FrameLabel = MMI->getContext().CreateTempSymbol();
180 BuildMI(MBB, MBBI, dl, TII.get(XCore::PROLOG_LABEL)).addSym(FrameLabel);
181 unsigned Reg = MRI->getDwarfRegNum(FramePtr, true);
182 MMI->addFrameInst(MCCFIInstruction::createDefCfaRegister(FrameLabel,
187 if (emitFrameMoves) {
188 // Frame moves for callee saved.
189 std::vector<std::pair<MCSymbol*, CalleeSavedInfo> >&SpillLabels =
190 XFI->getSpillLabels();
191 for (unsigned I = 0, E = SpillLabels.size(); I != E; ++I) {
192 MCSymbol *SpillLabel = SpillLabels[I].first;
193 CalleeSavedInfo &CSI = SpillLabels[I].second;
194 int Offset = MFI->getObjectOffset(CSI.getFrameIdx());
195 unsigned Reg = MRI->getDwarfRegNum(CSI.getReg(), true);
196 MMI->addFrameInst(MCCFIInstruction::createOffset(SpillLabel, Reg,
202 void XCoreFrameLowering::emitEpilogue(MachineFunction &MF,
203 MachineBasicBlock &MBB) const {
204 MachineFrameInfo *MFI = MF.getFrameInfo();
205 MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
206 const XCoreInstrInfo &TII =
207 *static_cast<const XCoreInstrInfo*>(MF.getTarget().getInstrInfo());
208 XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>();
209 DebugLoc dl = MBBI->getDebugLoc();
213 // Restore the stack pointer.
214 unsigned FramePtr = XCore::R10;
215 BuildMI(MBB, MBBI, dl, TII.get(XCore::SETSP_1r))
219 // Work out frame sizes.
220 int FrameSize = MFI->getStackSize();
222 assert(FrameSize%4 == 0 && "Misaligned frame size");
226 bool isU6 = isImmU6(FrameSize);
228 if (!isU6 && !isImmU16(FrameSize)) {
229 // FIXME could emit multiple instructions.
230 report_fatal_error("emitEpilogue Frame size too big: " + Twine(FrameSize));
235 int FPSpillOffset = MFI->getObjectOffset(XFI->getFPSpillSlot());
236 FPSpillOffset += FrameSize*4;
237 loadFromStack(MBB, MBBI, XCore::R10, FPSpillOffset, dl, TII);
240 bool restoreLR = XFI->getUsesLR();
242 (FrameSize == 0 || MFI->getObjectOffset(XFI->getLRSpillSlot()) != 0)) {
243 int LRSpillOffset = MFI->getObjectOffset(XFI->getLRSpillSlot());
244 LRSpillOffset += FrameSize*4;
245 loadFromStack(MBB, MBBI, XCore::LR, LRSpillOffset, dl, TII);
251 // Fold prologue into return instruction
252 assert(MFI->getObjectOffset(XFI->getLRSpillSlot()) == 0);
253 assert(MBBI->getOpcode() == XCore::RETSP_u6
254 || MBBI->getOpcode() == XCore::RETSP_lu6);
255 int Opcode = (isU6) ? XCore::RETSP_u6 : XCore::RETSP_lu6;
256 MachineInstrBuilder MIB = BuildMI(MBB, MBBI, dl, TII.get(Opcode)).addImm(FrameSize);
257 for (unsigned i = 3, e = MBBI->getNumOperands(); i < e; ++i)
258 MIB->addOperand(MBBI->getOperand(i)); // copy any variadic operands
261 int Opcode = (isU6) ? XCore::LDAWSP_ru6 : XCore::LDAWSP_lru6;
262 BuildMI(MBB, MBBI, dl, TII.get(Opcode), XCore::SP).addImm(FrameSize);
267 bool XCoreFrameLowering::spillCalleeSavedRegisters(MachineBasicBlock &MBB,
268 MachineBasicBlock::iterator MI,
269 const std::vector<CalleeSavedInfo> &CSI,
270 const TargetRegisterInfo *TRI) const {
274 MachineFunction *MF = MBB.getParent();
275 const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo();
277 XCoreFunctionInfo *XFI = MF->getInfo<XCoreFunctionInfo>();
278 bool emitFrameMoves = XCoreRegisterInfo::needsFrameMoves(*MF);
281 if (MI != MBB.end()) DL = MI->getDebugLoc();
283 for (std::vector<CalleeSavedInfo>::const_iterator it = CSI.begin();
284 it != CSI.end(); ++it) {
285 // Add the callee-saved register as live-in. It's killed at the spill.
286 MBB.addLiveIn(it->getReg());
288 unsigned Reg = it->getReg();
289 const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
290 TII.storeRegToStackSlot(MBB, MI, Reg, true,
291 it->getFrameIdx(), RC, TRI);
292 if (emitFrameMoves) {
293 MCSymbol *SaveLabel = MF->getContext().CreateTempSymbol();
294 BuildMI(MBB, MI, DL, TII.get(XCore::PROLOG_LABEL)).addSym(SaveLabel);
295 XFI->getSpillLabels().push_back(std::make_pair(SaveLabel, *it));
301 bool XCoreFrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock &MBB,
302 MachineBasicBlock::iterator MI,
303 const std::vector<CalleeSavedInfo> &CSI,
304 const TargetRegisterInfo *TRI) const{
305 MachineFunction *MF = MBB.getParent();
306 const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo();
308 bool AtStart = MI == MBB.begin();
309 MachineBasicBlock::iterator BeforeI = MI;
312 for (std::vector<CalleeSavedInfo>::const_iterator it = CSI.begin();
313 it != CSI.end(); ++it) {
314 unsigned Reg = it->getReg();
315 const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
316 TII.loadRegFromStackSlot(MBB, MI, it->getReg(), it->getFrameIdx(),
318 assert(MI != MBB.begin() &&
319 "loadRegFromStackSlot didn't insert any code!");
320 // Insert in reverse order. loadRegFromStackSlot can insert multiple
332 // This function eliminates ADJCALLSTACKDOWN,
333 // ADJCALLSTACKUP pseudo instructions
334 void XCoreFrameLowering::
335 eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB,
336 MachineBasicBlock::iterator I) const {
337 const XCoreInstrInfo &TII =
338 *static_cast<const XCoreInstrInfo*>(MF.getTarget().getInstrInfo());
339 if (!hasReservedCallFrame(MF)) {
340 // Turn the adjcallstackdown instruction into 'extsp <amt>' and the
341 // adjcallstackup instruction into 'ldaw sp, sp[<amt>]'
342 MachineInstr *Old = I;
343 uint64_t Amount = Old->getOperand(0).getImm();
345 // We need to keep the stack aligned properly. To do this, we round the
346 // amount of space needed for the outgoing arguments up to the next
347 // alignment boundary.
348 unsigned Align = getStackAlignment();
349 Amount = (Amount+Align-1)/Align*Align;
351 assert(Amount%4 == 0);
354 bool isU6 = isImmU6(Amount);
355 if (!isU6 && !isImmU16(Amount)) {
356 // FIX could emit multiple instructions in this case.
358 errs() << "eliminateCallFramePseudoInstr size too big: "
365 if (Old->getOpcode() == XCore::ADJCALLSTACKDOWN) {
366 int Opcode = isU6 ? XCore::EXTSP_u6 : XCore::EXTSP_lu6;
367 New=BuildMI(MF, Old->getDebugLoc(), TII.get(Opcode))
370 assert(Old->getOpcode() == XCore::ADJCALLSTACKUP);
371 int Opcode = isU6 ? XCore::LDAWSP_ru6 : XCore::LDAWSP_lru6;
372 New=BuildMI(MF, Old->getDebugLoc(), TII.get(Opcode), XCore::SP)
376 // Replace the pseudo instruction with a new instruction...
385 XCoreFrameLowering::processFunctionBeforeCalleeSavedScan(MachineFunction &MF,
386 RegScavenger *RS) const {
387 MachineFrameInfo *MFI = MF.getFrameInfo();
388 const TargetRegisterInfo *RegInfo = MF.getTarget().getRegisterInfo();
389 bool LRUsed = MF.getRegInfo().isPhysRegUsed(XCore::LR);
390 const TargetRegisterClass *RC = &XCore::GRRegsRegClass;
391 XCoreFunctionInfo *XFI = MF.getInfo<XCoreFunctionInfo>();
393 MF.getRegInfo().setPhysRegUnused(XCore::LR);
395 bool isVarArg = MF.getFunction()->isVarArg();
398 // A fixed offset of 0 allows us to save / restore LR using entsp / retsp.
399 FrameIdx = MFI->CreateFixedObject(RC->getSize(), 0, true);
401 FrameIdx = MFI->CreateStackObject(RC->getSize(), RC->getAlignment(),
404 XFI->setUsesLR(FrameIdx);
405 XFI->setLRSpillSlot(FrameIdx);
407 if (RegInfo->requiresRegisterScavenging(MF)) {
408 // Reserve a slot close to SP or frame pointer.
409 RS->addScavengingFrameIndex(MFI->CreateStackObject(RC->getSize(),
414 // A callee save register is used to hold the FP.
415 // This needs saving / restoring in the epilogue / prologue.
416 XFI->setFPSpillSlot(MFI->CreateStackObject(RC->getSize(),