LLVM 22.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"
23
24using namespace llvm;
25
27 : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, Align(2), -2,
28 Align(2)),
29 STI(STI), TII(*STI.getInstrInfo()), TRI(STI.getRegisterInfo()) {}
30
32 const MachineFrameInfo &MFI = MF.getFrameInfo();
33
34 return (MF.getTarget().Options.DisableFramePointerElim(MF) ||
37}
38
40 return !MF.getFrameInfo().hasVarSizedObjects();
41}
42
45 const DebugLoc &DL,
46 const MCCFIInstruction &CFIInst,
47 MachineInstr::MIFlag Flag) const {
49 unsigned CFIIndex = MF.addFrameInst(CFIInst);
50 BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
51 .addCFIIndex(CFIIndex)
52 .setMIFlag(Flag);
53}
54
57 const DebugLoc &DL, bool IsPrologue) const {
61
62 // Add callee saved registers to move list.
63 const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
64
65 // Calculate offsets.
66 for (const CalleeSavedInfo &I : CSI) {
67 int64_t Offset = MFI.getObjectOffset(I.getFrameIdx());
68 MCRegister Reg = I.getReg();
69 unsigned DwarfReg = MRI->getDwarfRegNum(Reg, true);
70
71 if (IsPrologue) {
73 MCCFIInstruction::createOffset(nullptr, DwarfReg, Offset));
74 } else {
76 MCCFIInstruction::createRestore(nullptr, DwarfReg));
77 }
78 }
79}
80
82 MachineBasicBlock &MBB) const {
83 assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported");
86 const MSP430InstrInfo &TII =
87 *static_cast<const MSP430InstrInfo *>(MF.getSubtarget().getInstrInfo());
88
90 DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
91
92 // Get the number of bytes to allocate from the FrameInfo.
93 uint64_t StackSize = MFI.getStackSize();
94 int stackGrowth = -2;
95
96 uint64_t NumBytes = 0;
97 if (hasFP(MF)) {
98 // Calculate required stack adjustment
99 uint64_t FrameSize = StackSize - 2;
100 NumBytes = FrameSize - MSP430FI->getCalleeSavedFrameSize();
101
102 // Get the offset of the stack slot for the EBP register... which is
103 // guaranteed to be the last slot by processFunctionBeforeFrameFinalized.
104 // Update the frame offset adjustment.
105 MFI.setOffsetAdjustment(-NumBytes);
106
107 // Save FP into the appropriate stack slot...
108 BuildMI(MBB, MBBI, DL, TII.get(MSP430::PUSH16r))
109 .addReg(MSP430::R4, RegState::Kill)
111
112 // Mark the place where FP was saved.
113 // Define the current CFA rule to use the provided offset.
115 MCCFIInstruction::cfiDefCfaOffset(nullptr, -2 * stackGrowth),
117
118 // Change the rule for the FramePtr to be an "offset" rule.
119 unsigned DwarfFramePtr = TRI->getDwarfRegNum(MSP430::R4, true);
120 BuildCFI(
121 MBB, MBBI, DL,
122 MCCFIInstruction::createOffset(nullptr, DwarfFramePtr, 2 * stackGrowth),
124
125 // Update FP with the new base value...
126 BuildMI(MBB, MBBI, DL, TII.get(MSP430::MOV16rr), MSP430::R4)
127 .addReg(MSP430::SP)
129
130 // Mark effective beginning of when frame pointer becomes valid.
131 // Define the current CFA to use the FP register.
133 MCCFIInstruction::createDefCfaRegister(nullptr, DwarfFramePtr),
135
136 // Mark the FramePtr as live-in in every block except the entry.
137 for (MachineBasicBlock &MBBJ : llvm::drop_begin(MF))
138 MBBJ.addLiveIn(MSP430::R4);
139 } else
140 NumBytes = StackSize - MSP430FI->getCalleeSavedFrameSize();
141
142 // Skip the callee-saved push instructions.
143 int StackOffset = 2 * stackGrowth;
144 while (MBBI != MBB.end() && MBBI->getFlag(MachineInstr::FrameSetup) &&
145 (MBBI->getOpcode() == MSP430::PUSH16r)) {
146 ++MBBI;
147
148 if (!hasFP(MF)) {
149 // Mark callee-saved push instruction.
150 // Define the current CFA rule to use the provided offset.
151 assert(StackSize && "Expected stack frame");
155 StackOffset += stackGrowth;
156 }
157 }
158
159 if (MBBI != MBB.end())
160 DL = MBBI->getDebugLoc();
161
162 if (NumBytes) { // adjust stack pointer: SP -= numbytes
163 // If there is an SUB16ri of SP immediately before this instruction, merge
164 // the two.
165 //NumBytes -= mergeSPUpdates(MBB, MBBI, true);
166 // If there is an ADD16ri or SUB16ri of SP immediately after this
167 // instruction, merge the two instructions.
168 // mergeSPUpdatesDown(MBB, MBBI, &NumBytes);
169
170 if (NumBytes) {
172 BuildMI(MBB, MBBI, DL, TII.get(MSP430::SUB16ri), MSP430::SP)
173 .addReg(MSP430::SP)
174 .addImm(NumBytes)
176 // The SRW implicit def is dead.
177 MI->getOperand(3).setIsDead();
178 }
179 if (!hasFP(MF)) {
180 // Adjust the previous CFA value if CFA was not redefined by FP
181 BuildCFI(
182 MBB, MBBI, DL,
183 MCCFIInstruction::cfiDefCfaOffset(nullptr, StackSize - stackGrowth),
185 }
186 }
187
189}
190
192 MachineBasicBlock &MBB) const {
193 const MachineFrameInfo &MFI = MF.getFrameInfo();
195 const MSP430InstrInfo &TII =
196 *static_cast<const MSP430InstrInfo *>(MF.getSubtarget().getInstrInfo());
197
199 unsigned RetOpcode = MBBI->getOpcode();
200 DebugLoc DL = MBBI->getDebugLoc();
201
202 switch (RetOpcode) {
203 case MSP430::RET:
204 case MSP430::RETI: break; // These are ok
205 default:
206 llvm_unreachable("Can only insert epilog into returning blocks");
207 }
208
209 // Get the number of bytes to allocate from the FrameInfo
210 uint64_t StackSize = MFI.getStackSize();
211 unsigned CSSize = MSP430FI->getCalleeSavedFrameSize();
212 uint64_t NumBytes = 0;
213
215 if (hasFP(MF)) {
216 // Calculate required stack adjustment
217 uint64_t FrameSize = StackSize - 2;
218 NumBytes = FrameSize - CSSize;
219
220 // pop FP.
221 BuildMI(MBB, MBBI, DL, TII.get(MSP430::POP16r), MSP430::R4)
223 unsigned DwarfStackPtr = TRI->getDwarfRegNum(MSP430::SP, true);
225 MCCFIInstruction::cfiDefCfa(nullptr, DwarfStackPtr, 2),
227 --MBBI;
228 if (!MBB.succ_empty() && !MBB.isReturnBlock()) {
229 unsigned DwarfFramePtr = TRI->getDwarfRegNum(MSP430::R4, true);
230 BuildCFI(MBB, AfterPop, DL,
231 MCCFIInstruction::createRestore(nullptr, DwarfFramePtr),
233 --MBBI;
234 --AfterPop;
235 }
236 } else
237 NumBytes = StackSize - CSSize;
238
239 // Skip the callee-saved pop instructions.
241 while (MBBI != MBB.begin()) {
242 MachineBasicBlock::iterator PI = std::prev(MBBI);
243 unsigned Opc = PI->getOpcode();
244 if ((Opc != MSP430::POP16r || !PI->getFlag(MachineInstr::FrameDestroy)) &&
245 !PI->isTerminator())
246 break;
247 FirstCSPop = PI;
248 --MBBI;
249 }
250 MBBI = FirstCSPop;
251
252 DL = MBBI->getDebugLoc();
253
254 // If there is an ADD16ri or SUB16ri of SP immediately before this
255 // instruction, merge the two instructions.
256 //if (NumBytes || MFI.hasVarSizedObjects())
257 // mergeSPUpdatesUp(MBB, MBBI, StackPtr, &NumBytes);
258
259 if (MFI.hasVarSizedObjects()) {
260 BuildMI(MBB, MBBI, DL, TII.get(MSP430::MOV16rr), MSP430::SP)
261 .addReg(MSP430::R4)
263 if (CSSize) {
265 BuildMI(MBB, MBBI, DL, TII.get(MSP430::SUB16ri), MSP430::SP)
266 .addReg(MSP430::SP)
267 .addImm(CSSize)
269 // The SRW implicit def is dead.
270 MI->getOperand(3).setIsDead();
271 }
272 } else {
273 // adjust stack pointer back: SP += numbytes
274 if (NumBytes) {
276 BuildMI(MBB, MBBI, DL, TII.get(MSP430::ADD16ri), MSP430::SP)
277 .addReg(MSP430::SP)
278 .addImm(NumBytes)
280 // The SRW implicit def is dead.
281 MI->getOperand(3).setIsDead();
282
283 if (!hasFP(MF)) {
284 // Adjust CFA value if it was defined by SP
286 MCCFIInstruction::cfiDefCfaOffset(nullptr, CSSize + 2),
288 }
289 }
290 }
291
292 if (!hasFP(MF)) {
293 MBBI = FirstCSPop;
294 int64_t Offset = -(int64_t)CSSize - 2;
295 // Mark callee-saved pop instruction.
296 // Define the current CFA rule to use the provided offset.
297 while (MBBI != MBB.end()) {
299 unsigned Opc = PI->getOpcode();
300 ++MBBI;
301 if (Opc == MSP430::POP16r) {
302 Offset += 2;
306 }
307 }
308 }
309 emitCalleeSavedFrameMoves(MBB, AfterPop, DL, false);
310}
311
312// FIXME: Can we eleminate these in favour of generic code?
316 if (CSI.empty())
317 return false;
318
319 DebugLoc DL;
320 if (MI != MBB.end()) DL = MI->getDebugLoc();
321
325 MFI->setCalleeSavedFrameSize(CSI.size() * 2);
326
327 for (const CalleeSavedInfo &I : CSI) {
328 MCRegister Reg = I.getReg();
329 // Add the callee-saved register as live-in. It's killed at the spill.
330 MBB.addLiveIn(Reg);
331 BuildMI(MBB, MI, DL, TII.get(MSP430::PUSH16r))
334 }
335 return true;
336}
337
341 if (CSI.empty())
342 return false;
343
344 DebugLoc DL;
345 if (MI != MBB.end()) DL = MI->getDebugLoc();
346
349
350 for (const CalleeSavedInfo &I : llvm::reverse(CSI))
351 BuildMI(MBB, MI, DL, TII.get(MSP430::POP16r), I.getReg())
353
354 return true;
355}
356
360 const MSP430InstrInfo &TII =
361 *static_cast<const MSP430InstrInfo *>(MF.getSubtarget().getInstrInfo());
362 if (!hasReservedCallFrame(MF)) {
363 // If the stack pointer can be changed after prologue, turn the
364 // adjcallstackup instruction into a 'sub SP, <amt>' and the
365 // adjcallstackdown instruction into 'add SP, <amt>'
366 // TODO: consider using push / pop instead of sub + store / add
367 MachineInstr &Old = *I;
368 uint64_t Amount = TII.getFrameSize(Old);
369 if (Amount != 0) {
370 // We need to keep the stack aligned properly. To do this, we round the
371 // amount of space needed for the outgoing arguments up to the next
372 // alignment boundary.
373 Amount = alignTo(Amount, getStackAlign());
374
375 MachineInstr *New = nullptr;
376 if (Old.getOpcode() == TII.getCallFrameSetupOpcode()) {
377 New =
378 BuildMI(MF, Old.getDebugLoc(), TII.get(MSP430::SUB16ri), MSP430::SP)
379 .addReg(MSP430::SP)
380 .addImm(Amount);
381 } else {
382 assert(Old.getOpcode() == TII.getCallFrameDestroyOpcode());
383 // factor out the amount the callee already popped.
384 Amount -= TII.getFramePoppedByCallee(Old);
385 if (Amount)
386 New = BuildMI(MF, Old.getDebugLoc(), TII.get(MSP430::ADD16ri),
387 MSP430::SP)
388 .addReg(MSP430::SP)
389 .addImm(Amount);
390 }
391
392 if (New) {
393 // The SRW implicit def is dead.
394 New->getOperand(3).setIsDead();
395
396 // Replace the pseudo instruction with a new instruction...
397 MBB.insert(I, New);
398 }
399 }
400 } else if (I->getOpcode() == TII.getCallFrameDestroyOpcode()) {
401 // If we are performing frame pointer elimination and if the callee pops
402 // something off the stack pointer, add it back.
403 if (uint64_t CalleeAmt = TII.getFramePoppedByCallee(*I)) {
404 MachineInstr &Old = *I;
405 MachineInstr *New =
406 BuildMI(MF, Old.getDebugLoc(), TII.get(MSP430::SUB16ri), MSP430::SP)
407 .addReg(MSP430::SP)
408 .addImm(CalleeAmt);
409 if (!hasFP(MF)) {
411 .buildAdjustCFAOffset(CalleeAmt);
412 }
413 // The SRW implicit def is dead.
414 New->getOperand(3).setIsDead();
415
416 MBB.insert(I, New);
417 }
418 }
419
420 return MBB.erase(I);
421}
422
423void
425 RegScavenger *) const {
426 // Create a frame entry for the FP register that must be saved.
427 if (hasFP(MF)) {
428 int FrameIdx = MF.getFrameInfo().CreateFixedObject(2, -4, true);
429 (void)FrameIdx;
430 assert(FrameIdx == MF.getFrameInfo().getObjectIndexBegin() &&
431 "Slot for FP register must be last in order to be found!");
432 }
433}
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
MachineBasicBlock MachineBasicBlock::iterator MBBI
const HexagonInstrInfo * TII
IRTranslator LLVM IR MI
#define I(x, y, z)
Definition: MD5.cpp:58
Register const TargetRegisterInfo * TRI
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:147
bool empty() const
empty - Check if the array is empty.
Definition: ArrayRef.h:142
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:124
static MCCFIInstruction createDefCfaRegister(MCSymbol *L, unsigned Register, SMLoc Loc={})
.cfi_def_cfa_register modifies a rule for computing CFA.
Definition: MCDwarf.h:592
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:666
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:585
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:627
static MCCFIInstruction cfiDefCfaOffset(MCSymbol *L, int64_t Offset, SMLoc Loc={})
.cfi_def_cfa_offset modifies a rule for computing CFA.
Definition: MCDwarf.h:600
const MCRegisterInfo * getRegisterInfo() const
Definition: MCContext.h:414
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
Wrapper class representing physical registers. Should be passed by value.
Definition: MCRegister.h:33
MSP430FrameLowering(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
int64_t getFramePoppedByCallee(const MachineInstr &I) const
MSP430MachineFunctionInfo - This class is derived from MachineFunction and contains private MSP430 ta...
LLVM_ABI instr_iterator insert(instr_iterator I, MachineInstr *M)
Insert MI into the instruction list before I, possibly inside a bundle.
bool isReturnBlock() const
Convenience function that returns true if the block ends in a return instruction.
LLVM_ABI iterator getLastNonDebugInstr(bool SkipPseudoOp=true)
Returns an iterator to the last non-debug instruction in the basic block, or end().
void addLiveIn(MCRegister PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
LLVM_ABI instr_iterator erase(instr_iterator I)
Remove an instruction from the instruction list and delete it.
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
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineBasicBlock & front() const
const TargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
const MachineInstrBuilder & addCFIIndex(unsigned CFIIndex) const
const MachineInstrBuilder & setMIFlag(MachineInstr::MIFlag Flag) const
const MachineInstrBuilder & addImm(int64_t Val) const
Add a new immediate operand.
const MachineInstrBuilder & addReg(Register RegNo, unsigned flags=0, unsigned SubReg=0) const
Add a new virtual register operand.
Representation of each machine instruction.
Definition: MachineInstr.h:72
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:587
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
Definition: MachineInstr.h:511
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
Definition: ArrayRef.h:303
StackOffset holds a fixed and a scalable offset in bytes.
Definition: TypeSize.h:34
Information about stack frame layout on the target.
bool hasFP(const MachineFunction &MF) const
hasFP - Return true if the specified function should have a dedicated frame pointer register.
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.
TargetOptions Options
LLVM_ABI bool DisableFramePointerElim(const MachineFunction &MF) const
DisableFramePointerElim - This returns true if frame pointer elimination optimization should be disab...
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.
@ Kill
The last use of a register.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition: STLExtras.h:338
@ Offset
Definition: DWP.cpp:477
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
auto reverse(ContainerTy &&C)
Definition: STLExtras.h:428
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition: Alignment.h:155
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39