LLVM 24.0.0git
MSP430FrameLowering.cpp
Go to the documentation of this file.
1//===-- MSP430FrameLowering.cpp - MSP430 Frame Information ----------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains the MSP430 implementation of TargetFrameLowering class.
10//
11//===----------------------------------------------------------------------===//
12
13#include "MSP430FrameLowering.h"
14#include "MSP430InstrInfo.h"
16#include "MSP430Subtarget.h"
22
23using namespace llvm;
24
29
31 const MachineFrameInfo &MFI = MF.getFrameInfo();
32
33 return (MF.disableFramePointerElim() ||
35}
36
40
43 const DebugLoc &DL,
44 const MCCFIInstruction &CFIInst,
45 MachineInstr::MIFlag Flag) const {
46 MachineFunction &MF = *MBB.getParent();
47 unsigned CFIIndex = MF.addFrameInst(CFIInst);
48 BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
49 .addCFIIndex(CFIIndex)
50 .setMIFlag(Flag);
51}
52
55 const DebugLoc &DL, bool IsPrologue) const {
56 MachineFunction &MF = *MBB.getParent();
58 const MCRegisterInfo *MRI = MF.getContext().getRegisterInfo();
59
60 // Add callee saved registers to move list.
61 const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
62
63 // Calculate offsets.
64 for (const CalleeSavedInfo &I : CSI) {
65 int64_t Offset = MFI.getObjectOffset(I.getFrameIdx());
66 MCRegister Reg = I.getReg();
67 unsigned DwarfReg = MRI->getDwarfRegNum(Reg, true);
68
69 if (IsPrologue) {
71 MCCFIInstruction::createOffset(nullptr, DwarfReg, Offset));
72 } else {
74 MCCFIInstruction::createRestore(nullptr, DwarfReg));
75 }
76 }
77}
78
80 MachineBasicBlock &MBB) const {
81 assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported");
84 const MSP430InstrInfo &TII =
85 *static_cast<const MSP430InstrInfo *>(MF.getSubtarget().getInstrInfo());
86
88 DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
89
90 // Get the number of bytes to allocate from the FrameInfo.
91 uint64_t StackSize = MFI.getStackSize();
92 int stackGrowth = -2;
93
94 uint64_t NumBytes = 0;
95 if (hasFP(MF)) {
96 // Calculate required stack adjustment
97 uint64_t FrameSize = StackSize - 2;
98 NumBytes = FrameSize - MSP430FI->getCalleeSavedFrameSize();
99
100 // Get the offset of the stack slot for the EBP register... which is
101 // guaranteed to be the last slot by processFunctionBeforeFrameFinalized.
102 // Update the frame offset adjustment.
103 MFI.setOffsetAdjustment(-NumBytes);
104
105 // Save FP into the appropriate stack slot...
106 BuildMI(MBB, MBBI, DL, TII.get(MSP430::PUSH16r))
107 .addReg(MSP430::R4, RegState::Kill)
109
110 // Mark the place where FP was saved.
111 // Define the current CFA rule to use the provided offset.
113 MCCFIInstruction::cfiDefCfaOffset(nullptr, -2 * stackGrowth),
115
116 // Change the rule for the FramePtr to be an "offset" rule.
117 unsigned DwarfFramePtr = TRI->getDwarfRegNum(MSP430::R4, true);
118 BuildCFI(
119 MBB, MBBI, DL,
120 MCCFIInstruction::createOffset(nullptr, DwarfFramePtr, 2 * stackGrowth),
122
123 // Update FP with the new base value...
124 BuildMI(MBB, MBBI, DL, TII.get(MSP430::MOV16rr), MSP430::R4)
125 .addReg(MSP430::SP)
127
128 // Mark effective beginning of when frame pointer becomes valid.
129 // Define the current CFA to use the FP register.
131 MCCFIInstruction::createDefCfaRegister(nullptr, DwarfFramePtr),
133
134 // Mark the FramePtr as live-in in every block except the entry.
135 for (MachineBasicBlock &MBBJ : llvm::drop_begin(MF))
136 MBBJ.addLiveIn(MSP430::R4);
137 } else
138 NumBytes = StackSize - MSP430FI->getCalleeSavedFrameSize();
139
140 // Skip the callee-saved push instructions.
141 int StackOffset = 2 * stackGrowth;
142 while (MBBI != MBB.end() && MBBI->getFlag(MachineInstr::FrameSetup) &&
143 (MBBI->getOpcode() == MSP430::PUSH16r)) {
144 ++MBBI;
145
146 if (!hasFP(MF)) {
147 // Mark callee-saved push instruction.
148 // Define the current CFA rule to use the provided offset.
149 assert(StackSize && "Expected stack frame");
153 StackOffset += stackGrowth;
154 }
155 }
156
157 if (MBBI != MBB.end())
158 DL = MBBI->getDebugLoc();
159
160 if (NumBytes) { // adjust stack pointer: SP -= numbytes
161 // If there is an SUB16ri of SP immediately before this instruction, merge
162 // the two.
163 //NumBytes -= mergeSPUpdates(MBB, MBBI, true);
164 // If there is an ADD16ri or SUB16ri of SP immediately after this
165 // instruction, merge the two instructions.
166 // mergeSPUpdatesDown(MBB, MBBI, &NumBytes);
167
168 if (NumBytes) {
170 BuildMI(MBB, MBBI, DL, TII.get(MSP430::SUB16ri), MSP430::SP)
171 .addReg(MSP430::SP)
172 .addImm(NumBytes)
174 // The SRW implicit def is dead.
175 MI->getOperand(3).setIsDead();
176 }
177 if (!hasFP(MF)) {
178 // Adjust the previous CFA value if CFA was not redefined by FP
179 BuildCFI(
180 MBB, MBBI, DL,
181 MCCFIInstruction::cfiDefCfaOffset(nullptr, StackSize - stackGrowth),
183 }
184 }
185
187}
188
190 MachineBasicBlock &MBB) const {
191 const MachineFrameInfo &MFI = MF.getFrameInfo();
193 const MSP430InstrInfo &TII =
194 *static_cast<const MSP430InstrInfo *>(MF.getSubtarget().getInstrInfo());
195
196 MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();
197 unsigned RetOpcode = MBBI->getOpcode();
198 DebugLoc DL = MBBI->getDebugLoc();
199
200 switch (RetOpcode) {
201 case MSP430::RET:
202 case MSP430::RETI: break; // These are ok
203 default:
204 llvm_unreachable("Can only insert epilog into returning blocks");
205 }
206
207 // Get the number of bytes to allocate from the FrameInfo
208 uint64_t StackSize = MFI.getStackSize();
209 unsigned CSSize = MSP430FI->getCalleeSavedFrameSize();
210 uint64_t NumBytes = 0;
211
213 if (hasFP(MF)) {
214 // Calculate required stack adjustment
215 uint64_t FrameSize = StackSize - 2;
216 NumBytes = FrameSize - CSSize;
217
218 // pop FP.
219 BuildMI(MBB, MBBI, DL, TII.get(MSP430::POP16r), MSP430::R4)
221 unsigned DwarfStackPtr = TRI->getDwarfRegNum(MSP430::SP, true);
223 MCCFIInstruction::cfiDefCfa(nullptr, DwarfStackPtr, 2),
225 --MBBI;
226 if (!MBB.succ_empty() && !MBB.isReturnBlock()) {
227 unsigned DwarfFramePtr = TRI->getDwarfRegNum(MSP430::R4, true);
228 BuildCFI(MBB, AfterPop, DL,
229 MCCFIInstruction::createRestore(nullptr, DwarfFramePtr),
231 --MBBI;
232 --AfterPop;
233 }
234 } else
235 NumBytes = StackSize - CSSize;
236
237 // Skip the callee-saved pop instructions.
239 while (MBBI != MBB.begin()) {
240 MachineBasicBlock::iterator PI = std::prev(MBBI);
241 unsigned Opc = PI->getOpcode();
242 if ((Opc != MSP430::POP16r || !PI->getFlag(MachineInstr::FrameDestroy)) &&
243 !PI->isTerminator())
244 break;
245 FirstCSPop = PI;
246 --MBBI;
247 }
248 MBBI = FirstCSPop;
249
250 DL = MBBI->getDebugLoc();
251
252 // If there is an ADD16ri or SUB16ri of SP immediately before this
253 // instruction, merge the two instructions.
254 //if (NumBytes || MFI.hasVarSizedObjects())
255 // mergeSPUpdatesUp(MBB, MBBI, StackPtr, &NumBytes);
256
257 if (MFI.hasVarSizedObjects()) {
258 BuildMI(MBB, MBBI, DL, TII.get(MSP430::MOV16rr), MSP430::SP)
259 .addReg(MSP430::R4)
261 if (CSSize) {
263 BuildMI(MBB, MBBI, DL, TII.get(MSP430::SUB16ri), MSP430::SP)
264 .addReg(MSP430::SP)
265 .addImm(CSSize)
267 // The SRW implicit def is dead.
268 MI->getOperand(3).setIsDead();
269 }
270 } else {
271 // adjust stack pointer back: SP += numbytes
272 if (NumBytes) {
274 BuildMI(MBB, MBBI, DL, TII.get(MSP430::ADD16ri), MSP430::SP)
275 .addReg(MSP430::SP)
276 .addImm(NumBytes)
278 // The SRW implicit def is dead.
279 MI->getOperand(3).setIsDead();
280
281 if (!hasFP(MF)) {
282 // Adjust CFA value if it was defined by SP
284 MCCFIInstruction::cfiDefCfaOffset(nullptr, CSSize + 2),
286 }
287 }
288 }
289
290 if (!hasFP(MF)) {
291 MBBI = FirstCSPop;
292 int64_t Offset = -(int64_t)CSSize - 2;
293 // Mark callee-saved pop instruction.
294 // Define the current CFA rule to use the provided offset.
295 while (MBBI != MBB.end()) {
297 unsigned Opc = PI->getOpcode();
298 ++MBBI;
299 if (Opc == MSP430::POP16r) {
300 Offset += 2;
304 }
305 }
306 }
307 emitCalleeSavedFrameMoves(MBB, AfterPop, DL, false);
308}
309
310// FIXME: Can we eleminate these in favour of generic code?
314 if (CSI.empty())
315 return false;
316
317 DebugLoc DL;
318 if (MI != MBB.end()) DL = MI->getDebugLoc();
319
320 MachineFunction &MF = *MBB.getParent();
323 MFI->setCalleeSavedFrameSize(CSI.size() * 2);
324
325 for (const CalleeSavedInfo &I : CSI) {
326 MCRegister Reg = I.getReg();
327 // Add the callee-saved register as live-in. It's killed at the spill.
328 MBB.addLiveIn(Reg);
329 BuildMI(MBB, MI, DL, TII.get(MSP430::PUSH16r))
332 }
333 return true;
334}
335
339 if (CSI.empty())
340 return false;
341
342 DebugLoc DL;
343 if (MI != MBB.end()) DL = MI->getDebugLoc();
344
345 MachineFunction &MF = *MBB.getParent();
347
348 for (const CalleeSavedInfo &I : llvm::reverse(CSI))
349 BuildMI(MBB, MI, DL, TII.get(MSP430::POP16r), I.getReg())
351
352 return true;
353}
354
358 const MSP430InstrInfo &TII =
359 *static_cast<const MSP430InstrInfo *>(MF.getSubtarget().getInstrInfo());
360 if (!hasReservedCallFrame(MF)) {
361 // If the stack pointer can be changed after prologue, turn the
362 // adjcallstackup instruction into a 'sub SP, <amt>' and the
363 // adjcallstackdown instruction into 'add SP, <amt>'
364 // TODO: consider using push / pop instead of sub + store / add
365 MachineInstr &Old = *I;
366 uint64_t Amount = TII.getFrameSize(Old);
367 if (Amount != 0) {
368 // We need to keep the stack aligned properly. To do this, we round the
369 // amount of space needed for the outgoing arguments up to the next
370 // alignment boundary.
371 Amount = alignTo(Amount, getStackAlign());
372
373 MachineInstr *New = nullptr;
374 if (Old.getOpcode() == TII.getCallFrameSetupOpcode()) {
375 New =
376 BuildMI(MF, Old.getDebugLoc(), TII.get(MSP430::SUB16ri), MSP430::SP)
377 .addReg(MSP430::SP)
378 .addImm(Amount);
379 } else {
380 assert(Old.getOpcode() == TII.getCallFrameDestroyOpcode());
381 // factor out the amount the callee already popped.
382 Amount -= TII.getFramePoppedByCallee(Old);
383 if (Amount)
384 New = BuildMI(MF, Old.getDebugLoc(), TII.get(MSP430::ADD16ri),
385 MSP430::SP)
386 .addReg(MSP430::SP)
387 .addImm(Amount);
388 }
389
390 if (New) {
391 // The SRW implicit def is dead.
392 New->getOperand(3).setIsDead();
393
394 // Replace the pseudo instruction with a new instruction...
395 MBB.insert(I, New);
396 }
397 }
398 } else if (I->getOpcode() == TII.getCallFrameDestroyOpcode()) {
399 // If we are performing frame pointer elimination and if the callee pops
400 // something off the stack pointer, add it back.
401 if (uint64_t CalleeAmt = TII.getFramePoppedByCallee(*I)) {
402 MachineInstr &Old = *I;
403 MachineInstr *New =
404 BuildMI(MF, Old.getDebugLoc(), TII.get(MSP430::SUB16ri), MSP430::SP)
405 .addReg(MSP430::SP)
406 .addImm(CalleeAmt);
407 if (!hasFP(MF)) {
409 .buildAdjustCFAOffset(CalleeAmt);
410 }
411 // The SRW implicit def is dead.
412 New->getOperand(3).setIsDead();
413
414 MBB.insert(I, New);
415 }
416 }
417
418 return MBB.erase(I);
419}
420
421void
423 RegScavenger *) const {
424 // Create a frame entry for the FP register that must be saved.
425 if (hasFP(MF)) {
426 int FrameIdx = MF.getFrameInfo().CreateFixedObject(2, -4, true);
427 (void)FrameIdx;
428 assert(FrameIdx == MF.getFrameInfo().getObjectIndexBegin() &&
429 "Slot for FP register must be last in order to be found!");
430 }
431}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition MD5.cpp:57
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
size_t size() const
Get the array size.
Definition ArrayRef.h:141
bool empty() const
Check if the array is empty.
Definition ArrayRef.h:136
Helper class for creating CFI instructions and inserting them into MIR.
void buildAdjustCFAOffset(int64_t Adjustment) const
The CalleeSavedInfo class tracks the information need to locate where a callee saved register is in t...
A debug info location.
Definition DebugLoc.h:126
static MCCFIInstruction createDefCfaRegister(MCSymbol *L, unsigned Register, SMLoc Loc={})
.cfi_def_cfa_register modifies a rule for computing CFA.
Definition MCDwarf.h:635
static MCCFIInstruction createRestore(MCSymbol *L, unsigned Register, SMLoc Loc={})
.cfi_restore says that the rule for Register is now the same as it was at the beginning of the functi...
Definition MCDwarf.h:725
static MCCFIInstruction cfiDefCfa(MCSymbol *L, unsigned Register, int64_t Offset, SMLoc Loc={})
.cfi_def_cfa defines a rule for computing CFA as: take address from Register and add Offset to it.
Definition MCDwarf.h:628
static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register, int64_t Offset, SMLoc Loc={})
.cfi_offset Previous value of Register is saved at offset Offset from CFA.
Definition MCDwarf.h:670
static MCCFIInstruction cfiDefCfaOffset(MCSymbol *L, int64_t Offset, SMLoc Loc={})
.cfi_def_cfa_offset modifies a rule for computing CFA.
Definition MCDwarf.h:643
const MCRegisterInfo * getRegisterInfo() const
Definition MCContext.h:411
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
virtual int64_t getDwarfRegNum(MCRegister Reg, bool isEH) const
Map a target register to an equivalent dwarf register number.
Wrapper class representing physical registers. Should be passed by value.
Definition MCRegister.h:41
MSP430FrameLowering(const MSP430Subtarget &STI)
const MSP430Subtarget & STI
bool hasFPImpl(const MachineFunction &MF) const override
void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override
bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, ArrayRef< CalleeSavedInfo > CSI, const TargetRegisterInfo *TRI) const override
spillCalleeSavedRegisters - Issues instruction(s) to spill all callee saved registers and returns tru...
void emitCalleeSavedFrameMoves(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, bool IsPrologue) const
void emitPrologue(MachineFunction &MF, MachineBasicBlock &MBB) const override
emitProlog/emitEpilog - These methods insert prolog and epilog code into the function.
MachineBasicBlock::iterator eliminateCallFramePseudoInstr(MachineFunction &MF, MachineBasicBlock &MBB, MachineBasicBlock::iterator I) const override
This method is called during prolog/epilog code insertion to eliminate call frame setup and destroy p...
bool hasReservedCallFrame(const MachineFunction &MF) const override
hasReservedCallFrame - Under normal circumstances, when a frame pointer is not required,...
const MSP430RegisterInfo * TRI
void processFunctionBeforeFrameFinalized(MachineFunction &MF, RegScavenger *RS=nullptr) const override
processFunctionBeforeFrameFinalized - This method is called immediately before the specified function...
bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, MutableArrayRef< CalleeSavedInfo > CSI, const TargetRegisterInfo *TRI) const override
restoreCalleeSavedRegisters - Issues instruction(s) to restore all callee saved registers and returns...
void BuildCFI(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, const DebugLoc &DL, const MCCFIInstruction &CFIInst, MachineInstr::MIFlag Flag=MachineInstr::NoFlags) const
Wraps up getting a CFI index and building a MachineInstr for it.
const MSP430InstrInfo & TII
MSP430MachineFunctionInfo - This class is derived from MachineFunction and contains private MSP430 ta...
MachineInstrBundleIterator< MachineInstr > iterator
The MachineFrameInfo class represents an abstract stack frame until prolog/epilog code is inserted.
LLVM_ABI int CreateFixedObject(uint64_t Size, int64_t SPOffset, bool IsImmutable, bool isAliased=false)
Create a new object at a fixed location on the stack.
bool hasVarSizedObjects() const
This method may be called any time after instruction selection is complete to determine if the stack ...
uint64_t getStackSize() const
Return the number of bytes that must be allocated to hold all of the fixed size frame objects.
bool isFrameAddressTaken() const
This method may be called any time after instruction selection is complete to determine if there is a...
const std::vector< CalleeSavedInfo > & getCalleeSavedInfo() const
Returns a reference to call saved info vector for the current function.
int64_t getObjectOffset(int ObjectIdx) const
Return the assigned stack offset of the specified object from the incoming stack pointer.
int getObjectIndexBegin() const
Return the minimum frame object index.
void setOffsetAdjustment(int64_t Adj)
Set the correction for frame offsets.
unsigned addFrameInst(const MCCFIInstruction &Inst)
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MCContext & getContext() const
LLVM_ABI bool disableFramePointerElim() const
Returns true if frame pointer elimination should be disabled for this function.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineBasicBlock & front() const
const MachineInstrBuilder & addCFIIndex(unsigned CFIIndex) const
const MachineInstrBuilder & addReg(Register RegNo, RegState Flags={}, unsigned SubReg=0) const
Add a new virtual register operand.
const MachineInstrBuilder & setMIFlag(MachineInstr::MIFlag Flag) const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
Representation of each machine instruction.
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:294
StackOffset holds a fixed and a scalable offset in bytes.
Definition TypeSize.h:30
bool hasFP(const MachineFunction &MF) const
hasFP - Return true if the specified function should have a dedicated frame pointer register.
TargetFrameLowering(StackDirection D, Align StackAl, int LAO, Align TransAl=Align(1), bool StackReal=true)
Align getStackAlign() const
getStackAlignment - This method returns the number of bytes to which the stack pointer must be aligne...
TargetInstrInfo - Interface to description of machine instruction set.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetInstrInfo * getInstrInfo() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
This is an optimization pass for GlobalISel generic memory operations.
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition STLExtras.h:315
@ Offset
Definition DWP.cpp:577
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
@ Kill
The last use of a register.
auto reverse(ContainerTy &&C)
Definition STLExtras.h:407
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition Alignment.h:144
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39