1 //===-- XCoreFrameLowering.cpp - Frame info for XCore Target -----*- C++ -*-==//
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 //===----------------------------------------------------------------------===//
16 #include "XCoreFrameLowering.h"
17 #include "XCoreInstrInfo.h"
18 #include "XCoreMachineFunctionInfo.h"
19 #include "llvm/Function.h"
20 #include "llvm/CodeGen/MachineFrameInfo.h"
21 #include "llvm/CodeGen/MachineFunction.h"
22 #include "llvm/CodeGen/MachineInstrBuilder.h"
23 #include "llvm/CodeGen/MachineModuleInfo.h"
24 #include "llvm/CodeGen/MachineRegisterInfo.h"
25 #include "llvm/CodeGen/RegisterScavenging.h"
26 #include "llvm/Target/TargetData.h"
27 #include "llvm/Target/TargetOptions.h"
28 #include "llvm/Support/ErrorHandling.h"
32 // helper functions. FIXME: Eliminate.
33 static inline bool isImmUs(unsigned val
) {
37 static inline bool isImmU6(unsigned val
) {
38 return val
< (1 << 6);
41 static inline bool isImmU16(unsigned val
) {
42 return val
< (1 << 16);
45 static void loadFromStack(MachineBasicBlock
&MBB
,
46 MachineBasicBlock::iterator I
,
47 unsigned DstReg
, int Offset
, DebugLoc dl
,
48 const TargetInstrInfo
&TII
) {
49 assert(Offset
%4 == 0 && "Misaligned stack offset");
51 bool isU6
= isImmU6(Offset
);
52 if (!isU6
&& !isImmU16(Offset
))
53 report_fatal_error("loadFromStack offset too big " + Twine(Offset
));
54 int Opcode
= isU6
? XCore::LDWSP_ru6
: XCore::LDWSP_lru6
;
55 BuildMI(MBB
, I
, dl
, TII
.get(Opcode
), DstReg
)
60 static void storeToStack(MachineBasicBlock
&MBB
,
61 MachineBasicBlock::iterator I
,
62 unsigned SrcReg
, int Offset
, DebugLoc dl
,
63 const TargetInstrInfo
&TII
) {
64 assert(Offset
%4 == 0 && "Misaligned stack offset");
66 bool isU6
= isImmU6(Offset
);
67 if (!isU6
&& !isImmU16(Offset
))
68 report_fatal_error("storeToStack offset too big " + Twine(Offset
));
69 int Opcode
= isU6
? XCore::STWSP_ru6
: XCore::STWSP_lru6
;
70 BuildMI(MBB
, I
, dl
, TII
.get(Opcode
))
76 //===----------------------------------------------------------------------===//
77 // XCoreFrameLowering:
78 //===----------------------------------------------------------------------===//
80 XCoreFrameLowering::XCoreFrameLowering(const XCoreSubtarget
&sti
)
81 : TargetFrameLowering(TargetFrameLowering::StackGrowsDown
, 4, 0),
86 bool XCoreFrameLowering::hasFP(const MachineFunction
&MF
) const {
87 return DisableFramePointerElim(MF
) || MF
.getFrameInfo()->hasVarSizedObjects();
90 void XCoreFrameLowering::emitPrologue(MachineFunction
&MF
) const {
91 MachineBasicBlock
&MBB
= MF
.front(); // Prolog goes in entry BB
92 MachineBasicBlock::iterator MBBI
= MBB
.begin();
93 MachineFrameInfo
*MFI
= MF
.getFrameInfo();
94 MachineModuleInfo
*MMI
= &MF
.getMMI();
95 const XCoreRegisterInfo
*RegInfo
=
96 static_cast<const XCoreRegisterInfo
*>(MF
.getTarget().getRegisterInfo());
97 const XCoreInstrInfo
&TII
=
98 *static_cast<const XCoreInstrInfo
*>(MF
.getTarget().getInstrInfo());
99 XCoreFunctionInfo
*XFI
= MF
.getInfo
<XCoreFunctionInfo
>();
100 DebugLoc dl
= MBBI
!= MBB
.end() ? MBBI
->getDebugLoc() : DebugLoc();
103 bool Nested
= MF
.getFunction()->getAttributes().hasAttrSomewhere(Attribute::Nest
);
106 loadFromStack(MBB
, MBBI
, XCore::R11
, 0, dl
, TII
);
109 // Work out frame sizes.
110 int FrameSize
= MFI
->getStackSize();
111 assert(FrameSize
%4 == 0 && "Misaligned frame size");
114 bool isU6
= isImmU6(FrameSize
);
116 if (!isU6
&& !isImmU16(FrameSize
)) {
117 // FIXME could emit multiple instructions.
118 report_fatal_error("emitPrologue Frame size too big: " + Twine(FrameSize
));
120 bool emitFrameMoves
= RegInfo
->needsFrameMoves(MF
);
122 // Do we need to allocate space on the stack?
124 bool saveLR
= XFI
->getUsesLR();
125 bool LRSavedOnEntry
= false;
127 if (saveLR
&& (MFI
->getObjectOffset(XFI
->getLRSpillSlot()) == 0)) {
128 Opcode
= (isU6
) ? XCore::ENTSP_u6
: XCore::ENTSP_lu6
;
129 MBB
.addLiveIn(XCore::LR
);
131 LRSavedOnEntry
= true;
133 Opcode
= (isU6
) ? XCore::EXTSP_u6
: XCore::EXTSP_lu6
;
135 BuildMI(MBB
, MBBI
, dl
, TII
.get(Opcode
)).addImm(FrameSize
);
137 if (emitFrameMoves
) {
138 std::vector
<MachineMove
> &Moves
= MMI
->getFrameMoves();
140 // Show update of SP.
141 MCSymbol
*FrameLabel
= MMI
->getContext().CreateTempSymbol();
142 BuildMI(MBB
, MBBI
, dl
, TII
.get(XCore::PROLOG_LABEL
)).addSym(FrameLabel
);
144 MachineLocation
SPDst(MachineLocation::VirtualFP
);
145 MachineLocation
SPSrc(MachineLocation::VirtualFP
, -FrameSize
* 4);
146 Moves
.push_back(MachineMove(FrameLabel
, SPDst
, SPSrc
));
148 if (LRSavedOnEntry
) {
149 MachineLocation
CSDst(MachineLocation::VirtualFP
, 0);
150 MachineLocation
CSSrc(XCore::LR
);
151 Moves
.push_back(MachineMove(FrameLabel
, CSDst
, CSSrc
));
155 int LRSpillOffset
= MFI
->getObjectOffset(XFI
->getLRSpillSlot());
156 storeToStack(MBB
, MBBI
, XCore::LR
, LRSpillOffset
+ FrameSize
*4, dl
, TII
);
157 MBB
.addLiveIn(XCore::LR
);
159 if (emitFrameMoves
) {
160 MCSymbol
*SaveLRLabel
= MMI
->getContext().CreateTempSymbol();
161 BuildMI(MBB
, MBBI
, dl
, TII
.get(XCore::PROLOG_LABEL
)).addSym(SaveLRLabel
);
162 MachineLocation
CSDst(MachineLocation::VirtualFP
, LRSpillOffset
);
163 MachineLocation
CSSrc(XCore::LR
);
164 MMI
->getFrameMoves().push_back(MachineMove(SaveLRLabel
, CSDst
, CSSrc
));
170 // Save R10 to the stack.
171 int FPSpillOffset
= MFI
->getObjectOffset(XFI
->getFPSpillSlot());
172 storeToStack(MBB
, MBBI
, XCore::R10
, FPSpillOffset
+ FrameSize
*4, dl
, TII
);
173 // R10 is live-in. It is killed at the spill.
174 MBB
.addLiveIn(XCore::R10
);
175 if (emitFrameMoves
) {
176 MCSymbol
*SaveR10Label
= MMI
->getContext().CreateTempSymbol();
177 BuildMI(MBB
, MBBI
, dl
, TII
.get(XCore::PROLOG_LABEL
)).addSym(SaveR10Label
);
178 MachineLocation
CSDst(MachineLocation::VirtualFP
, FPSpillOffset
);
179 MachineLocation
CSSrc(XCore::R10
);
180 MMI
->getFrameMoves().push_back(MachineMove(SaveR10Label
, CSDst
, CSSrc
));
182 // Set the FP from the SP.
183 unsigned FramePtr
= XCore::R10
;
184 BuildMI(MBB
, MBBI
, dl
, TII
.get(XCore::LDAWSP_ru6
), FramePtr
)
186 if (emitFrameMoves
) {
187 // Show FP is now valid.
188 MCSymbol
*FrameLabel
= MMI
->getContext().CreateTempSymbol();
189 BuildMI(MBB
, MBBI
, dl
, TII
.get(XCore::PROLOG_LABEL
)).addSym(FrameLabel
);
190 MachineLocation
SPDst(FramePtr
);
191 MachineLocation
SPSrc(MachineLocation::VirtualFP
);
192 MMI
->getFrameMoves().push_back(MachineMove(FrameLabel
, SPDst
, SPSrc
));
196 if (emitFrameMoves
) {
197 // Frame moves for callee saved.
198 std::vector
<MachineMove
> &Moves
= MMI
->getFrameMoves();
199 std::vector
<std::pair
<MCSymbol
*, CalleeSavedInfo
> >&SpillLabels
=
200 XFI
->getSpillLabels();
201 for (unsigned I
= 0, E
= SpillLabels
.size(); I
!= E
; ++I
) {
202 MCSymbol
*SpillLabel
= SpillLabels
[I
].first
;
203 CalleeSavedInfo
&CSI
= SpillLabels
[I
].second
;
204 int Offset
= MFI
->getObjectOffset(CSI
.getFrameIdx());
205 unsigned Reg
= CSI
.getReg();
206 MachineLocation
CSDst(MachineLocation::VirtualFP
, Offset
);
207 MachineLocation
CSSrc(Reg
);
208 Moves
.push_back(MachineMove(SpillLabel
, CSDst
, CSSrc
));
213 void XCoreFrameLowering::emitEpilogue(MachineFunction
&MF
,
214 MachineBasicBlock
&MBB
) const {
215 MachineFrameInfo
*MFI
= MF
.getFrameInfo();
216 MachineBasicBlock::iterator MBBI
= MBB
.getLastNonDebugInstr();
217 const XCoreInstrInfo
&TII
=
218 *static_cast<const XCoreInstrInfo
*>(MF
.getTarget().getInstrInfo());
219 DebugLoc dl
= MBBI
->getDebugLoc();
223 // Restore the stack pointer.
224 unsigned FramePtr
= XCore::R10
;
225 BuildMI(MBB
, MBBI
, dl
, TII
.get(XCore::SETSP_1r
))
229 // Work out frame sizes.
230 int FrameSize
= MFI
->getStackSize();
232 assert(FrameSize
%4 == 0 && "Misaligned frame size");
236 bool isU6
= isImmU6(FrameSize
);
238 if (!isU6
&& !isImmU16(FrameSize
)) {
239 // FIXME could emit multiple instructions.
240 report_fatal_error("emitEpilogue Frame size too big: " + Twine(FrameSize
));
244 XCoreFunctionInfo
*XFI
= MF
.getInfo
<XCoreFunctionInfo
>();
248 int FPSpillOffset
= MFI
->getObjectOffset(XFI
->getFPSpillSlot());
249 FPSpillOffset
+= FrameSize
*4;
250 loadFromStack(MBB
, MBBI
, XCore::R10
, FPSpillOffset
, dl
, TII
);
252 bool restoreLR
= XFI
->getUsesLR();
253 if (restoreLR
&& MFI
->getObjectOffset(XFI
->getLRSpillSlot()) != 0) {
254 int LRSpillOffset
= MFI
->getObjectOffset(XFI
->getLRSpillSlot());
255 LRSpillOffset
+= FrameSize
*4;
256 loadFromStack(MBB
, MBBI
, XCore::LR
, LRSpillOffset
, dl
, TII
);
260 // Fold prologue into return instruction
261 assert(MBBI
->getOpcode() == XCore::RETSP_u6
262 || MBBI
->getOpcode() == XCore::RETSP_lu6
);
263 int Opcode
= (isU6
) ? XCore::RETSP_u6
: XCore::RETSP_lu6
;
264 BuildMI(MBB
, MBBI
, dl
, TII
.get(Opcode
)).addImm(FrameSize
);
267 int Opcode
= (isU6
) ? XCore::LDAWSP_ru6_RRegs
: XCore::LDAWSP_lru6_RRegs
;
268 BuildMI(MBB
, MBBI
, dl
, TII
.get(Opcode
), XCore::SP
).addImm(FrameSize
);
273 void XCoreFrameLowering::getInitialFrameState(std::vector
<MachineMove
> &Moves
)
275 // Initial state of the frame pointer is SP.
276 MachineLocation
Dst(MachineLocation::VirtualFP
);
277 MachineLocation
Src(XCore::SP
, 0);
278 Moves
.push_back(MachineMove(0, Dst
, Src
));
281 bool XCoreFrameLowering::spillCalleeSavedRegisters(MachineBasicBlock
&MBB
,
282 MachineBasicBlock::iterator MI
,
283 const std::vector
<CalleeSavedInfo
> &CSI
,
284 const TargetRegisterInfo
*TRI
) const {
288 MachineFunction
*MF
= MBB
.getParent();
289 const TargetInstrInfo
&TII
= *MF
->getTarget().getInstrInfo();
291 XCoreFunctionInfo
*XFI
= MF
->getInfo
<XCoreFunctionInfo
>();
292 bool emitFrameMoves
= XCoreRegisterInfo::needsFrameMoves(*MF
);
295 if (MI
!= MBB
.end()) DL
= MI
->getDebugLoc();
297 for (std::vector
<CalleeSavedInfo
>::const_iterator it
= CSI
.begin();
298 it
!= CSI
.end(); ++it
) {
299 // Add the callee-saved register as live-in. It's killed at the spill.
300 MBB
.addLiveIn(it
->getReg());
302 unsigned Reg
= it
->getReg();
303 const TargetRegisterClass
*RC
= TRI
->getMinimalPhysRegClass(Reg
);
304 TII
.storeRegToStackSlot(MBB
, MI
, Reg
, true,
305 it
->getFrameIdx(), RC
, TRI
);
306 if (emitFrameMoves
) {
307 MCSymbol
*SaveLabel
= MF
->getContext().CreateTempSymbol();
308 BuildMI(MBB
, MI
, DL
, TII
.get(XCore::PROLOG_LABEL
)).addSym(SaveLabel
);
309 XFI
->getSpillLabels().push_back(std::make_pair(SaveLabel
, *it
));
315 bool XCoreFrameLowering::restoreCalleeSavedRegisters(MachineBasicBlock
&MBB
,
316 MachineBasicBlock::iterator MI
,
317 const std::vector
<CalleeSavedInfo
> &CSI
,
318 const TargetRegisterInfo
*TRI
) const{
319 MachineFunction
*MF
= MBB
.getParent();
320 const TargetInstrInfo
&TII
= *MF
->getTarget().getInstrInfo();
322 bool AtStart
= MI
== MBB
.begin();
323 MachineBasicBlock::iterator BeforeI
= MI
;
326 for (std::vector
<CalleeSavedInfo
>::const_iterator it
= CSI
.begin();
327 it
!= CSI
.end(); ++it
) {
328 unsigned Reg
= it
->getReg();
329 const TargetRegisterClass
*RC
= TRI
->getMinimalPhysRegClass(Reg
);
330 TII
.loadRegFromStackSlot(MBB
, MI
, it
->getReg(), it
->getFrameIdx(),
332 assert(MI
!= MBB
.begin() &&
333 "loadRegFromStackSlot didn't insert any code!");
334 // Insert in reverse order. loadRegFromStackSlot can insert multiple
347 XCoreFrameLowering::processFunctionBeforeCalleeSavedScan(MachineFunction
&MF
,
348 RegScavenger
*RS
) const {
349 MachineFrameInfo
*MFI
= MF
.getFrameInfo();
350 const TargetRegisterInfo
*RegInfo
= MF
.getTarget().getRegisterInfo();
351 bool LRUsed
= MF
.getRegInfo().isPhysRegUsed(XCore::LR
);
352 const TargetRegisterClass
*RC
= XCore::GRRegsRegisterClass
;
353 XCoreFunctionInfo
*XFI
= MF
.getInfo
<XCoreFunctionInfo
>();
355 MF
.getRegInfo().setPhysRegUnused(XCore::LR
);
357 bool isVarArg
= MF
.getFunction()->isVarArg();
360 // A fixed offset of 0 allows us to save / restore LR using entsp / retsp.
361 FrameIdx
= MFI
->CreateFixedObject(RC
->getSize(), 0, true);
363 FrameIdx
= MFI
->CreateStackObject(RC
->getSize(), RC
->getAlignment(),
366 XFI
->setUsesLR(FrameIdx
);
367 XFI
->setLRSpillSlot(FrameIdx
);
369 if (RegInfo
->requiresRegisterScavenging(MF
)) {
370 // Reserve a slot close to SP or frame pointer.
371 RS
->setScavengingFrameIndex(MFI
->CreateStackObject(RC
->getSize(),
376 // A callee save register is used to hold the FP.
377 // This needs saving / restoring in the epilogue / prologue.
378 XFI
->setFPSpillSlot(MFI
->CreateStackObject(RC
->getSize(),
384 void XCoreFrameLowering::
385 processFunctionBeforeFrameFinalized(MachineFunction
&MF
) const {