LLVM API Documentation

 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
XCoreFrameLowering.cpp
Go to the documentation of this file.
1 //===-- XCoreFrameLowering.cpp - Frame info for XCore Target --------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file contains XCore frame information that doesn't fit anywhere else
11 // cleanly...
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "XCoreFrameLowering.h"
16 #include "XCore.h"
17 #include "XCoreInstrInfo.h"
25 #include "llvm/IR/DataLayout.h"
26 #include "llvm/IR/Function.h"
29 
30 using namespace llvm;
31 
32 // helper functions. FIXME: Eliminate.
33 static inline bool isImmU6(unsigned val) {
34  return val < (1 << 6);
35 }
36 
37 static inline bool isImmU16(unsigned val) {
38  return val < (1 << 16);
39 }
40 
43  unsigned DstReg, int Offset, DebugLoc dl,
44  const TargetInstrInfo &TII) {
45  assert(Offset%4 == 0 && "Misaligned stack offset");
46  Offset/=4;
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)
52  .addImm(Offset);
53 }
54 
55 
58  unsigned SrcReg, int Offset, DebugLoc dl,
59  const TargetInstrInfo &TII) {
60  assert(Offset%4 == 0 && "Misaligned stack offset");
61  Offset/=4;
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))
67  .addReg(SrcReg)
68  .addImm(Offset);
69 }
70 
71 
72 //===----------------------------------------------------------------------===//
73 // XCoreFrameLowering:
74 //===----------------------------------------------------------------------===//
75 
77  : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, 4, 0) {
78  // Do nothing
79 }
80 
82  return MF.getTarget().Options.DisableFramePointerElim(MF) ||
84 }
85 
87  MachineBasicBlock &MBB = MF.front(); // Prolog goes in entry BB
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());
95  DebugLoc dl = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
96 
97  if (MFI->getMaxAlignment() > getStackAlignment())
98  report_fatal_error("emitPrologue unsupported alignment: "
99  + Twine(MFI->getMaxAlignment()));
100 
101  bool FP = hasFP(MF);
102  const AttributeSet &PAL = MF.getFunction()->getAttributes();
103 
105  loadFromStack(MBB, MBBI, XCore::R11, 0, dl, TII);
106 
107  // Work out frame sizes.
108  int FrameSize = MFI->getStackSize();
109  assert(FrameSize%4 == 0 && "Misaligned frame size");
110  FrameSize/=4;
111 
112  bool isU6 = isImmU6(FrameSize);
113 
114  if (!isU6 && !isImmU16(FrameSize)) {
115  // FIXME could emit multiple instructions.
116  report_fatal_error("emitPrologue Frame size too big: " + Twine(FrameSize));
117  }
118  bool emitFrameMoves = XCoreRegisterInfo::needsFrameMoves(MF);
119 
120  bool saveLR = XFI->getUsesLR();
121  // Do we need to allocate space on the stack?
122  if (FrameSize) {
123  bool LRSavedOnEntry = false;
124  int Opcode;
125  if (saveLR && (MFI->getObjectOffset(XFI->getLRSpillSlot()) == 0)) {
126  Opcode = (isU6) ? XCore::ENTSP_u6 : XCore::ENTSP_lu6;
127  MBB.addLiveIn(XCore::LR);
128  saveLR = false;
129  LRSavedOnEntry = true;
130  } else {
131  Opcode = (isU6) ? XCore::EXTSP_u6 : XCore::EXTSP_lu6;
132  }
133  BuildMI(MBB, MBBI, dl, TII.get(Opcode)).addImm(FrameSize);
134 
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);
140  -FrameSize*4));
141  if (LRSavedOnEntry) {
142  unsigned Reg = MRI->getDwarfRegNum(XCore::LR, true);
143  MMI->addFrameInst(MCCFIInstruction::createOffset(FrameLabel, Reg, 0));
144  }
145  }
146  }
147  if (saveLR) {
148  int LRSpillOffset = MFI->getObjectOffset(XFI->getLRSpillSlot());
149  storeToStack(MBB, MBBI, XCore::LR, LRSpillOffset + FrameSize*4, dl, TII);
150  MBB.addLiveIn(XCore::LR);
151 
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,
157  LRSpillOffset));
158  }
159  }
160 
161  if (FP) {
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,
172  FPSpillOffset));
173  }
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);
183  Reg));
184  }
185  }
186 
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,
197  Offset));
198  }
199  }
200 }
201 
203  MachineBasicBlock &MBB) const {
204  MachineFrameInfo *MFI = MF.getFrameInfo();
206  const XCoreInstrInfo &TII =
207  *static_cast<const XCoreInstrInfo*>(MF.getTarget().getInstrInfo());
209  DebugLoc dl = MBBI->getDebugLoc();
210 
211  bool FP = hasFP(MF);
212  if (FP) {
213  // Restore the stack pointer.
214  unsigned FramePtr = XCore::R10;
215  BuildMI(MBB, MBBI, dl, TII.get(XCore::SETSP_1r))
216  .addReg(FramePtr);
217  }
218 
219  // Work out frame sizes.
220  int FrameSize = MFI->getStackSize();
221 
222  assert(FrameSize%4 == 0 && "Misaligned frame size");
223 
224  FrameSize/=4;
225 
226  bool isU6 = isImmU6(FrameSize);
227 
228  if (!isU6 && !isImmU16(FrameSize)) {
229  // FIXME could emit multiple instructions.
230  report_fatal_error("emitEpilogue Frame size too big: " + Twine(FrameSize));
231  }
232 
233  if (FP) {
234  // Restore R10
235  int FPSpillOffset = MFI->getObjectOffset(XFI->getFPSpillSlot());
236  FPSpillOffset += FrameSize*4;
237  loadFromStack(MBB, MBBI, XCore::R10, FPSpillOffset, dl, TII);
238  }
239 
240  bool restoreLR = XFI->getUsesLR();
241  if (restoreLR &&
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);
246  restoreLR = false;
247  }
248 
249  if (FrameSize) {
250  if (restoreLR) {
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
259  MBB.erase(MBBI);
260  } else {
261  int Opcode = (isU6) ? XCore::LDAWSP_ru6 : XCore::LDAWSP_lru6;
262  BuildMI(MBB, MBBI, dl, TII.get(Opcode), XCore::SP).addImm(FrameSize);
263  }
264  }
265 }
266 
269  const std::vector<CalleeSavedInfo> &CSI,
270  const TargetRegisterInfo *TRI) const {
271  if (CSI.empty())
272  return true;
273 
274  MachineFunction *MF = MBB.getParent();
275  const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo();
276 
278  bool emitFrameMoves = XCoreRegisterInfo::needsFrameMoves(*MF);
279 
280  DebugLoc DL;
281  if (MI != MBB.end()) DL = MI->getDebugLoc();
282 
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());
287 
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));
296  }
297  }
298  return true;
299 }
300 
303  const std::vector<CalleeSavedInfo> &CSI,
304  const TargetRegisterInfo *TRI) const{
305  MachineFunction *MF = MBB.getParent();
306  const TargetInstrInfo &TII = *MF->getTarget().getInstrInfo();
307 
308  bool AtStart = MI == MBB.begin();
310  if (!AtStart)
311  --BeforeI;
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(),
317  RC, TRI);
318  assert(MI != MBB.begin() &&
319  "loadRegFromStackSlot didn't insert any code!");
320  // Insert in reverse order. loadRegFromStackSlot can insert multiple
321  // instructions.
322  if (AtStart)
323  MI = MBB.begin();
324  else {
325  MI = BeforeI;
326  ++MI;
327  }
328  }
329  return true;
330 }
331 
332 // This function eliminates ADJCALLSTACKDOWN,
333 // ADJCALLSTACKUP pseudo instructions
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();
344  if (Amount != 0) {
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;
350 
351  assert(Amount%4 == 0);
352  Amount /= 4;
353 
354  bool isU6 = isImmU6(Amount);
355  if (!isU6 && !isImmU16(Amount)) {
356  // FIX could emit multiple instructions in this case.
357 #ifndef NDEBUG
358  errs() << "eliminateCallFramePseudoInstr size too big: "
359  << Amount << "\n";
360 #endif
361  llvm_unreachable(0);
362  }
363 
364  MachineInstr *New;
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))
368  .addImm(Amount);
369  } else {
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)
373  .addImm(Amount);
374  }
375 
376  // Replace the pseudo instruction with a new instruction...
377  MBB.insert(I, New);
378  }
379  }
380 
381  MBB.erase(I);
382 }
383 
384 void
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;
392  if (LRUsed) {
393  MF.getRegInfo().setPhysRegUnused(XCore::LR);
394 
395  bool isVarArg = MF.getFunction()->isVarArg();
396  int FrameIdx;
397  if (! isVarArg) {
398  // A fixed offset of 0 allows us to save / restore LR using entsp / retsp.
399  FrameIdx = MFI->CreateFixedObject(RC->getSize(), 0, true);
400  } else {
401  FrameIdx = MFI->CreateStackObject(RC->getSize(), RC->getAlignment(),
402  false);
403  }
404  XFI->setUsesLR(FrameIdx);
405  XFI->setLRSpillSlot(FrameIdx);
406  }
407  if (RegInfo->requiresRegisterScavenging(MF)) {
408  // Reserve a slot close to SP or frame pointer.
410  RC->getAlignment(),
411  false));
412  }
413  if (hasFP(MF)) {
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(),
417  RC->getAlignment(),
418  false));
419  }
420 }
unsigned getStackAlignment() const
const MachineFunction * getParent() const
instr_iterator erase(instr_iterator I)
int getDwarfRegNum(unsigned RegNum, bool isEH) const
Map a target register to an equivalent dwarf register number. Returns -1 if there is no equivalent va...
static bool isImmU16(unsigned val)
raw_ostream & errs()
const TargetRegisterClass * getMinimalPhysRegClass(unsigned Reg, EVT VT=MVT::Other) const
XCoreFrameLowering(const XCoreSubtarget &STI)
Nested function static chain.
Definition: Attributes.h:79
static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register, int Offset)
.cfi_offset Previous value of Register is saved at offset Offset from CFA.
Definition: MCDwarf.h:348
void addLiveIn(unsigned Reg)
bool hasFP(const MachineFunction &MF) const
static void storeToStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, unsigned SrcReg, int Offset, DebugLoc dl, const TargetInstrInfo &TII)
const Function * getFunction() const
static MCCFIInstruction createDefCfaOffset(MCSymbol *L, int Offset)
.cfi_def_cfa_offset modifies a rule for computing CFA. Register remains the same, but offset is new...
Definition: MCDwarf.h:335
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const char *reason, bool gen_crash_diag=true)
unsigned getMaxAlignment() const
uint64_t getStackSize() const
MCSymbol * CreateTempSymbol()
Definition: MCContext.cpp:165
const HexagonInstrInfo * TII
static void loadFromStack(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, unsigned DstReg, int Offset, DebugLoc dl, const TargetInstrInfo &TII)
#define llvm_unreachable(msg)
bool DisableFramePointerElim(const MachineFunction &MF) const
Abstract Stack Frame Information.
const MachineInstrBuilder & addImm(int64_t Val) const
bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const std::vector< CalleeSavedInfo > &CSI, const TargetRegisterInfo *TRI) const
const MachineBasicBlock & front() const
static bool needsFrameMoves(const MachineFunction &MF)
Return whether to emit frame moves.
int getOpcode() const
Definition: MachineInstr.h:261
int64_t getImm() const
MCContext & getContext() const
void emitPrologue(MachineFunction &MF) const
virtual bool requiresRegisterScavenging(const MachineFunction &MF) const
bundle_iterator< MachineInstr, instr_iterator > iterator
void eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const
unsigned getAlignment() const
static MCCFIInstruction createDefCfaRegister(MCSymbol *L, unsigned Register)
.cfi_def_cfa_register modifies a rule for computing CFA. From now on Register will be used instead of...
Definition: MCDwarf.h:328
const MachineOperand & getOperand(unsigned i) const
Definition: MachineInstr.h:267
virtual void loadRegFromStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned DestReg, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI) const
MachineInstrBuilder BuildMI(MachineFunction &MF, DebugLoc DL, const MCInstrDesc &MCID)
virtual void storeRegToStackSlot(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned SrcReg, bool isKill, int FrameIndex, const TargetRegisterClass *RC, const TargetRegisterInfo *TRI) const
const MCInstrDesc & get(unsigned Opcode) const
Definition: MCInstrInfo.h:48
virtual bool hasReservedCallFrame(const MachineFunction &MF) const
int64_t getObjectOffset(int ObjectIdx) const
bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const std::vector< CalleeSavedInfo > &CSI, const TargetRegisterInfo *TRI) const
virtual const TargetInstrInfo * getInstrInfo() const
void addOperand(MachineFunction &MF, const MachineOperand &Op)
std::vector< std::pair< MCSymbol *, CalleeSavedInfo > > & getSpillLabels()
const MCContext & getContext() const
void addScavengingFrameIndex(int FI)
Add a scavenging frame index.
void processFunctionBeforeCalleeSavedScan(MachineFunction &MF, RegScavenger *RS=NULL) const
void setPhysRegUnused(unsigned Reg)
MachineFrameInfo * getFrameInfo()
static bool isImmU6(unsigned val)
AttributeSet getAttributes() const
Return the attribute list for this Function.
Definition: Function.h:170
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const
static cl::opt< AlignMode > Align(cl::desc("Load/store alignment support"), cl::Hidden, cl::init(DefaultAlign), cl::values(clEnumValN(DefaultAlign,"arm-default-align","Generate unaligned accesses only on hardware/OS ""combinations that are known to support them"), clEnumValN(StrictAlign,"arm-strict-align","Disallow all unaligned memory accesses"), clEnumValN(NoStrictAlign,"arm-no-strict-align","Allow unaligned memory accesses"), clEnumValEnd))
const MCRegisterInfo * getRegisterInfo() const
Definition: MCContext.h:177
int CreateStackObject(uint64_t Size, unsigned Alignment, bool isSS, bool MayNeedSP=false, const AllocaInst *Alloca=0)
MachineRegisterInfo & getRegInfo()
bool hasAttrSomewhere(Attribute::AttrKind Attr) const
Return true if the specified attribute is set for at least one parameter or for the return value...
Definition: Attributes.cpp:835
#define I(x, y, z)
Definition: MD5.cpp:54
void addFrameInst(const MCCFIInstruction &Inst)
const TargetMachine & getTarget() const
instr_iterator insert(instr_iterator I, MachineInstr *M)
virtual const TargetRegisterInfo * getRegisterInfo() const
bool hasVarSizedObjects() const
bool isPhysRegUsed(unsigned Reg) const
MachineModuleInfo & getMMI() const
const MCRegisterInfo & MRI
int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool Immutable)
bool isVarArg() const
Definition: Function.cpp:175
DebugLoc getDebugLoc() const
Definition: MachineInstr.h:244
unsigned getReg() const