LLVM 19.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#include "llvm/IR/DataLayout.h"
23#include "llvm/IR/Function.h"
25
26using namespace llvm;
27
29 : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, Align(2), -2,
30 Align(2)),
31 STI(STI), TII(*STI.getInstrInfo()), TRI(STI.getRegisterInfo()) {}
32
34 const MachineFrameInfo &MFI = MF.getFrameInfo();
35
36 return (MF.getTarget().Options.DisableFramePointerElim(MF) ||
39}
40
42 return !MF.getFrameInfo().hasVarSizedObjects();
43}
44
47 const DebugLoc &DL,
48 const MCCFIInstruction &CFIInst,
49 MachineInstr::MIFlag Flag) const {
51 unsigned CFIIndex = MF.addFrameInst(CFIInst);
52 BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))
53 .addCFIIndex(CFIIndex)
54 .setMIFlag(Flag);
55}
56
59 const DebugLoc &DL, bool IsPrologue) const {
62 MachineModuleInfo &MMI = MF.getMMI();
64
65 // Add callee saved registers to move list.
66 const std::vector<CalleeSavedInfo> &CSI = MFI.getCalleeSavedInfo();
67
68 // Calculate offsets.
69 for (const CalleeSavedInfo &I : CSI) {
70 int64_t Offset = MFI.getObjectOffset(I.getFrameIdx());
71 Register Reg = I.getReg();
72 unsigned DwarfReg = MRI->getDwarfRegNum(Reg, true);
73
74 if (IsPrologue) {
76 MCCFIInstruction::createOffset(nullptr, DwarfReg, Offset));
77 } else {
79 MCCFIInstruction::createRestore(nullptr, DwarfReg));
80 }
81 }
82}
83
85 MachineBasicBlock &MBB) const {
86 assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported");
89 const MSP430InstrInfo &TII =
90 *static_cast<const MSP430InstrInfo *>(MF.getSubtarget().getInstrInfo());
91
93 DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc();
94
95 // Get the number of bytes to allocate from the FrameInfo.
96 uint64_t StackSize = MFI.getStackSize();
97 int stackGrowth = -2;
98
99 uint64_t NumBytes = 0;
100 if (hasFP(MF)) {
101 // Calculate required stack adjustment
102 uint64_t FrameSize = StackSize - 2;
103 NumBytes = FrameSize - MSP430FI->getCalleeSavedFrameSize();
104
105 // Get the offset of the stack slot for the EBP register... which is
106 // guaranteed to be the last slot by processFunctionBeforeFrameFinalized.
107 // Update the frame offset adjustment.
108 MFI.setOffsetAdjustment(-NumBytes);
109
110 // Save FP into the appropriate stack slot...
111 BuildMI(MBB, MBBI, DL, TII.get(MSP430::PUSH16r))
112 .addReg(MSP430::R4, RegState::Kill)
114
115 // Mark the place where FP was saved.
116 // Define the current CFA rule to use the provided offset.
118 MCCFIInstruction::cfiDefCfaOffset(nullptr, -2 * stackGrowth),
120
121 // Change the rule for the FramePtr to be an "offset" rule.
122 unsigned DwarfFramePtr = TRI->getDwarfRegNum(MSP430::R4, true);
123 BuildCFI(
124 MBB, MBBI, DL,
125 MCCFIInstruction::createOffset(nullptr, DwarfFramePtr, 2 * stackGrowth),
127
128 // Update FP with the new base value...
129 BuildMI(MBB, MBBI, DL, TII.get(MSP430::MOV16rr), MSP430::R4)
130 .addReg(MSP430::SP)
132
133 // Mark effective beginning of when frame pointer becomes valid.
134 // Define the current CFA to use the FP register.
136 MCCFIInstruction::createDefCfaRegister(nullptr, DwarfFramePtr),
138
139 // Mark the FramePtr as live-in in every block except the entry.
140 for (MachineBasicBlock &MBBJ : llvm::drop_begin(MF))
141 MBBJ.addLiveIn(MSP430::R4);
142 } else
143 NumBytes = StackSize - MSP430FI->getCalleeSavedFrameSize();
144
145 // Skip the callee-saved push instructions.
146 int StackOffset = 2 * stackGrowth;
147 while (MBBI != MBB.end() && MBBI->getFlag(MachineInstr::FrameSetup) &&
148 (MBBI->getOpcode() == MSP430::PUSH16r)) {
149 ++MBBI;
150
151 if (!hasFP(MF)) {
152 // Mark callee-saved push instruction.
153 // Define the current CFA rule to use the provided offset.
154 assert(StackSize && "Expected stack frame");
158 StackOffset += stackGrowth;
159 }
160 }
161
162 if (MBBI != MBB.end())
163 DL = MBBI->getDebugLoc();
164
165 if (NumBytes) { // adjust stack pointer: SP -= numbytes
166 // If there is an SUB16ri of SP immediately before this instruction, merge
167 // the two.
168 //NumBytes -= mergeSPUpdates(MBB, MBBI, true);
169 // If there is an ADD16ri or SUB16ri of SP immediately after this
170 // instruction, merge the two instructions.
171 // mergeSPUpdatesDown(MBB, MBBI, &NumBytes);
172
173 if (NumBytes) {
175 BuildMI(MBB, MBBI, DL, TII.get(MSP430::SUB16ri), MSP430::SP)
176 .addReg(MSP430::SP)
177 .addImm(NumBytes)
179 // The SRW implicit def is dead.
180 MI->getOperand(3).setIsDead();
181 }
182 if (!hasFP(MF)) {
183 // Adjust the previous CFA value if CFA was not redefined by FP
184 BuildCFI(
185 MBB, MBBI, DL,
186 MCCFIInstruction::cfiDefCfaOffset(nullptr, StackSize - stackGrowth),
188 }
189 }
190
192}
193
195 MachineBasicBlock &MBB) const {
196 const MachineFrameInfo &MFI = MF.getFrameInfo();
198 const MSP430InstrInfo &TII =
199 *static_cast<const MSP430InstrInfo *>(MF.getSubtarget().getInstrInfo());
200
202 unsigned RetOpcode = MBBI->getOpcode();
203 DebugLoc DL = MBBI->getDebugLoc();
204
205 switch (RetOpcode) {
206 case MSP430::RET:
207 case MSP430::RETI: break; // These are ok
208 default:
209 llvm_unreachable("Can only insert epilog into returning blocks");
210 }
211
212 // Get the number of bytes to allocate from the FrameInfo
213 uint64_t StackSize = MFI.getStackSize();
214 unsigned CSSize = MSP430FI->getCalleeSavedFrameSize();
215 uint64_t NumBytes = 0;
216
218 if (hasFP(MF)) {
219 // Calculate required stack adjustment
220 uint64_t FrameSize = StackSize - 2;
221 NumBytes = FrameSize - CSSize;
222
223 // pop FP.
224 BuildMI(MBB, MBBI, DL, TII.get(MSP430::POP16r), MSP430::R4)
226 unsigned DwarfStackPtr = TRI->getDwarfRegNum(MSP430::SP, true);
228 MCCFIInstruction::cfiDefCfa(nullptr, DwarfStackPtr, 2),
230 --MBBI;
231 if (!MBB.succ_empty() && !MBB.isReturnBlock()) {
232 unsigned DwarfFramePtr = TRI->getDwarfRegNum(MSP430::R4, true);
233 BuildCFI(MBB, AfterPop, DL,
234 MCCFIInstruction::createRestore(nullptr, DwarfFramePtr),
236 --MBBI;
237 --AfterPop;
238 }
239 } else
240 NumBytes = StackSize - CSSize;
241
242 // Skip the callee-saved pop instructions.
244 while (MBBI != MBB.begin()) {
245 MachineBasicBlock::iterator PI = std::prev(MBBI);
246 unsigned Opc = PI->getOpcode();
247 if ((Opc != MSP430::POP16r || !PI->getFlag(MachineInstr::FrameDestroy)) &&
248 !PI->isTerminator())
249 break;
250 FirstCSPop = PI;
251 --MBBI;
252 }
253 MBBI = FirstCSPop;
254
255 DL = MBBI->getDebugLoc();
256
257 // If there is an ADD16ri or SUB16ri of SP immediately before this
258 // instruction, merge the two instructions.
259 //if (NumBytes || MFI.hasVarSizedObjects())
260 // mergeSPUpdatesUp(MBB, MBBI, StackPtr, &NumBytes);
261
262 if (MFI.hasVarSizedObjects()) {
263 BuildMI(MBB, MBBI, DL, TII.get(MSP430::MOV16rr), MSP430::SP)
264 .addReg(MSP430::R4)
266 if (CSSize) {
268 BuildMI(MBB, MBBI, DL, TII.get(MSP430::SUB16ri), MSP430::SP)
269 .addReg(MSP430::SP)
270 .addImm(CSSize)
272 // The SRW implicit def is dead.
273 MI->getOperand(3).setIsDead();
274 }
275 } else {
276 // adjust stack pointer back: SP += numbytes
277 if (NumBytes) {
279 BuildMI(MBB, MBBI, DL, TII.get(MSP430::ADD16ri), MSP430::SP)
280 .addReg(MSP430::SP)
281 .addImm(NumBytes)
283 // The SRW implicit def is dead.
284 MI->getOperand(3).setIsDead();
285
286 if (!hasFP(MF)) {
287 // Adjust CFA value if it was defined by SP
289 MCCFIInstruction::cfiDefCfaOffset(nullptr, CSSize + 2),
291 }
292 }
293 }
294
295 if (!hasFP(MF)) {
296 MBBI = FirstCSPop;
297 int64_t Offset = -CSSize - 2;
298 // Mark callee-saved pop instruction.
299 // Define the current CFA rule to use the provided offset.
300 while (MBBI != MBB.end()) {
302 unsigned Opc = PI->getOpcode();
303 ++MBBI;
304 if (Opc == MSP430::POP16r) {
305 Offset += 2;
309 }
310 }
311 }
312 emitCalleeSavedFrameMoves(MBB, AfterPop, DL, false);
313}
314
315// FIXME: Can we eleminate these in favour of generic code?
319 if (CSI.empty())
320 return false;
321
322 DebugLoc DL;
323 if (MI != MBB.end()) DL = MI->getDebugLoc();
324
328 MFI->setCalleeSavedFrameSize(CSI.size() * 2);
329
330 for (const CalleeSavedInfo &I : CSI) {
331 Register Reg = I.getReg();
332 // Add the callee-saved register as live-in. It's killed at the spill.
333 MBB.addLiveIn(Reg);
334 BuildMI(MBB, MI, DL, TII.get(MSP430::PUSH16r))
337 }
338 return true;
339}
340
344 if (CSI.empty())
345 return false;
346
347 DebugLoc DL;
348 if (MI != MBB.end()) DL = MI->getDebugLoc();
349
352
353 for (const CalleeSavedInfo &I : llvm::reverse(CSI))
354 BuildMI(MBB, MI, DL, TII.get(MSP430::POP16r), I.getReg())
356
357 return true;
358}
359
363 const MSP430InstrInfo &TII =
364 *static_cast<const MSP430InstrInfo *>(MF.getSubtarget().getInstrInfo());
365 if (!hasReservedCallFrame(MF)) {
366 // If the stack pointer can be changed after prologue, turn the
367 // adjcallstackup instruction into a 'sub SP, <amt>' and the
368 // adjcallstackdown instruction into 'add SP, <amt>'
369 // TODO: consider using push / pop instead of sub + store / add
370 MachineInstr &Old = *I;
371 uint64_t Amount = TII.getFrameSize(Old);
372 if (Amount != 0) {
373 // We need to keep the stack aligned properly. To do this, we round the
374 // amount of space needed for the outgoing arguments up to the next
375 // alignment boundary.
376 Amount = alignTo(Amount, getStackAlign());
377
378 MachineInstr *New = nullptr;
379 if (Old.getOpcode() == TII.getCallFrameSetupOpcode()) {
380 New =
381 BuildMI(MF, Old.getDebugLoc(), TII.get(MSP430::SUB16ri), MSP430::SP)
382 .addReg(MSP430::SP)
383 .addImm(Amount);
384 } else {
385 assert(Old.getOpcode() == TII.getCallFrameDestroyOpcode());
386 // factor out the amount the callee already popped.
387 Amount -= TII.getFramePoppedByCallee(Old);
388 if (Amount)
389 New = BuildMI(MF, Old.getDebugLoc(), TII.get(MSP430::ADD16ri),
390 MSP430::SP)
391 .addReg(MSP430::SP)
392 .addImm(Amount);
393 }
394
395 if (New) {
396 // The SRW implicit def is dead.
397 New->getOperand(3).setIsDead();
398
399 // Replace the pseudo instruction with a new instruction...
400 MBB.insert(I, New);
401 }
402 }
403 } else if (I->getOpcode() == TII.getCallFrameDestroyOpcode()) {
404 // If we are performing frame pointer elimination and if the callee pops
405 // something off the stack pointer, add it back.
406 if (uint64_t CalleeAmt = TII.getFramePoppedByCallee(*I)) {
407 MachineInstr &Old = *I;
408 MachineInstr *New =
409 BuildMI(MF, Old.getDebugLoc(), TII.get(MSP430::SUB16ri), MSP430::SP)
410 .addReg(MSP430::SP)
411 .addImm(CalleeAmt);
412 if (!hasFP(MF)) {
413 DebugLoc DL = I->getDebugLoc();
414 BuildCFI(MBB, I, DL,
415 MCCFIInstruction::createAdjustCfaOffset(nullptr, CalleeAmt));
416 }
417 // The SRW implicit def is dead.
418 New->getOperand(3).setIsDead();
419
420 MBB.insert(I, New);
421 }
422 }
423
424 return MBB.erase(I);
425}
426
427void
429 RegScavenger *) const {
430 // Create a frame entry for the FP register that must be saved.
431 if (hasFP(MF)) {
432 int FrameIdx = MF.getFrameInfo().CreateFixedObject(2, -4, true);
433 (void)FrameIdx;
434 assert(FrameIdx == MF.getFrameInfo().getObjectIndexBegin() &&
435 "Slot for FP register must be last in order to be found!");
436 }
437}
unsigned const MachineRegisterInfo * MRI
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
unsigned const TargetRegisterInfo * TRI
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
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:165
bool empty() const
empty - Check if the array is empty.
Definition: ArrayRef.h:160
The CalleeSavedInfo class tracks the information need to locate where a callee saved register is in t...
A debug info location.
Definition: DebugLoc.h:33
static MCCFIInstruction createDefCfaRegister(MCSymbol *L, unsigned Register, SMLoc Loc={})
.cfi_def_cfa_register modifies a rule for computing CFA.
Definition: MCDwarf.h:548
static MCCFIInstruction createOffset(MCSymbol *L, unsigned Register, int Offset, SMLoc Loc={})
.cfi_offset Previous value of Register is saved at offset Offset from CFA.
Definition: MCDwarf.h:583
static MCCFIInstruction cfiDefCfaOffset(MCSymbol *L, int Offset, SMLoc Loc={})
.cfi_def_cfa_offset modifies a rule for computing CFA.
Definition: MCDwarf.h:556
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:616
static MCCFIInstruction cfiDefCfa(MCSymbol *L, unsigned Register, int 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:541
static MCCFIInstruction createAdjustCfaOffset(MCSymbol *L, int Adjustment, SMLoc Loc={})
.cfi_adjust_cfa_offset Same as .cfi_def_cfa_offset, but Offset is a relative value that is added/subt...
Definition: MCDwarf.h:564
const MCRegisterInfo * getRegisterInfo() const
Definition: MCContext.h:448
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
MSP430FrameLowering(const MSP430Subtarget &STI)
bool hasFP(const MachineFunction &MF) const override
hasFP - Return true if the specified function should have a dedicated frame pointer register.
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...
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.
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.
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.
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...
void setOffsetAdjustment(int Adj)
Set the correction for frame offsets.
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.
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.
const LLVMTargetMachine & getTarget() const
getTarget - Return the target machine this machine code is compiled with
MachineModuleInfo & getMMI() 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 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:69
unsigned getOpcode() const
Returns the opcode of this MachineInstr.
Definition: MachineInstr.h:546
const DebugLoc & getDebugLoc() const
Returns the debug location id of this MachineInstr.
Definition: MachineInstr.h:475
This class contains meta information specific to a module.
const MCContext & getContext() const
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
Definition: ArrayRef.h:307
Wrapper class representing virtual and physical registers.
Definition: Register.h:19
StackOffset holds a fixed and a scalable offset in bytes.
Definition: TypeSize.h:33
Information about stack frame layout on the target.
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
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:329
@ Offset
Definition: DWP.cpp:456
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