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" 15 #include "MSP430MachineFunctionInfo.h" 16 #include "MSP430Subtarget.h" 17 #include "llvm/CodeGen/MachineFrameInfo.h" 18 #include "llvm/CodeGen/MachineFunction.h" 19 #include "llvm/CodeGen/MachineInstrBuilder.h" 20 #include "llvm/CodeGen/MachineModuleInfo.h" 21 #include "llvm/CodeGen/MachineRegisterInfo.h" 22 #include "llvm/IR/DataLayout.h" 23 #include "llvm/IR/Function.h" 24 #include "llvm/Target/TargetOptions.h" 25 26 using namespace llvm; 27 28 bool MSP430FrameLowering::hasFP(const MachineFunction &MF) const { 29 const MachineFrameInfo &MFI = MF.getFrameInfo(); 30 31 return (MF.getTarget().Options.DisableFramePointerElim(MF) || 32 MF.getFrameInfo().hasVarSizedObjects() || 33 MFI.isFrameAddressTaken()); 34 } 35 36 bool MSP430FrameLowering::hasReservedCallFrame(const MachineFunction &MF) const { 37 return !MF.getFrameInfo().hasVarSizedObjects(); 38 } 39 40 void MSP430FrameLowering::emitPrologue(MachineFunction &MF, 41 MachineBasicBlock &MBB) const { 42 assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported"); 43 MachineFrameInfo &MFI = MF.getFrameInfo(); 44 MSP430MachineFunctionInfo *MSP430FI = MF.getInfo<MSP430MachineFunctionInfo>(); 45 const MSP430InstrInfo &TII = 46 *static_cast<const MSP430InstrInfo *>(MF.getSubtarget().getInstrInfo()); 47 48 MachineBasicBlock::iterator MBBI = MBB.begin(); 49 DebugLoc DL = MBBI != MBB.end() ? MBBI->getDebugLoc() : DebugLoc(); 50 51 // Get the number of bytes to allocate from the FrameInfo. 52 uint64_t StackSize = MFI.getStackSize(); 53 54 uint64_t NumBytes = 0; 55 if (hasFP(MF)) { 56 // Calculate required stack adjustment 57 uint64_t FrameSize = StackSize - 2; 58 NumBytes = FrameSize - MSP430FI->getCalleeSavedFrameSize(); 59 60 // Get the offset of the stack slot for the EBP register... which is 61 // guaranteed to be the last slot by processFunctionBeforeFrameFinalized. 62 // Update the frame offset adjustment. 63 MFI.setOffsetAdjustment(-NumBytes); 64 65 // Save FP into the appropriate stack slot... 66 BuildMI(MBB, MBBI, DL, TII.get(MSP430::PUSH16r)) 67 .addReg(MSP430::R4, RegState::Kill); 68 69 // Update FP with the new base value... 70 BuildMI(MBB, MBBI, DL, TII.get(MSP430::MOV16rr), MSP430::R4) 71 .addReg(MSP430::SP); 72 73 // Mark the FramePtr as live-in in every block except the entry. 74 for (MachineFunction::iterator I = std::next(MF.begin()), E = MF.end(); 75 I != E; ++I) 76 I->addLiveIn(MSP430::R4); 77 78 } else 79 NumBytes = StackSize - MSP430FI->getCalleeSavedFrameSize(); 80 81 // Skip the callee-saved push instructions. 82 while (MBBI != MBB.end() && (MBBI->getOpcode() == MSP430::PUSH16r)) 83 ++MBBI; 84 85 if (MBBI != MBB.end()) 86 DL = MBBI->getDebugLoc(); 87 88 if (NumBytes) { // adjust stack pointer: SP -= numbytes 89 // If there is an SUB16ri of SP immediately before this instruction, merge 90 // the two. 91 //NumBytes -= mergeSPUpdates(MBB, MBBI, true); 92 // If there is an ADD16ri or SUB16ri of SP immediately after this 93 // instruction, merge the two instructions. 94 // mergeSPUpdatesDown(MBB, MBBI, &NumBytes); 95 96 if (NumBytes) { 97 MachineInstr *MI = 98 BuildMI(MBB, MBBI, DL, TII.get(MSP430::SUB16ri), MSP430::SP) 99 .addReg(MSP430::SP).addImm(NumBytes); 100 // The SRW implicit def is dead. 101 MI->getOperand(3).setIsDead(); 102 } 103 } 104 } 105 106 void MSP430FrameLowering::emitEpilogue(MachineFunction &MF, 107 MachineBasicBlock &MBB) const { 108 const MachineFrameInfo &MFI = MF.getFrameInfo(); 109 MSP430MachineFunctionInfo *MSP430FI = MF.getInfo<MSP430MachineFunctionInfo>(); 110 const MSP430InstrInfo &TII = 111 *static_cast<const MSP430InstrInfo *>(MF.getSubtarget().getInstrInfo()); 112 113 MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); 114 unsigned RetOpcode = MBBI->getOpcode(); 115 DebugLoc DL = MBBI->getDebugLoc(); 116 117 switch (RetOpcode) { 118 case MSP430::RET: 119 case MSP430::RETI: break; // These are ok 120 default: 121 llvm_unreachable("Can only insert epilog into returning blocks"); 122 } 123 124 // Get the number of bytes to allocate from the FrameInfo 125 uint64_t StackSize = MFI.getStackSize(); 126 unsigned CSSize = MSP430FI->getCalleeSavedFrameSize(); 127 uint64_t NumBytes = 0; 128 129 if (hasFP(MF)) { 130 // Calculate required stack adjustment 131 uint64_t FrameSize = StackSize - 2; 132 NumBytes = FrameSize - CSSize; 133 134 // pop FP. 135 BuildMI(MBB, MBBI, DL, TII.get(MSP430::POP16r), MSP430::R4); 136 } else 137 NumBytes = StackSize - CSSize; 138 139 // Skip the callee-saved pop instructions. 140 while (MBBI != MBB.begin()) { 141 MachineBasicBlock::iterator PI = std::prev(MBBI); 142 unsigned Opc = PI->getOpcode(); 143 if (Opc != MSP430::POP16r && !PI->isTerminator()) 144 break; 145 --MBBI; 146 } 147 148 DL = MBBI->getDebugLoc(); 149 150 // If there is an ADD16ri or SUB16ri of SP immediately before this 151 // instruction, merge the two instructions. 152 //if (NumBytes || MFI.hasVarSizedObjects()) 153 // mergeSPUpdatesUp(MBB, MBBI, StackPtr, &NumBytes); 154 155 if (MFI.hasVarSizedObjects()) { 156 BuildMI(MBB, MBBI, DL, 157 TII.get(MSP430::MOV16rr), MSP430::SP).addReg(MSP430::R4); 158 if (CSSize) { 159 MachineInstr *MI = 160 BuildMI(MBB, MBBI, DL, 161 TII.get(MSP430::SUB16ri), MSP430::SP) 162 .addReg(MSP430::SP).addImm(CSSize); 163 // The SRW implicit def is dead. 164 MI->getOperand(3).setIsDead(); 165 } 166 } else { 167 // adjust stack pointer back: SP += numbytes 168 if (NumBytes) { 169 MachineInstr *MI = 170 BuildMI(MBB, MBBI, DL, TII.get(MSP430::ADD16ri), MSP430::SP) 171 .addReg(MSP430::SP).addImm(NumBytes); 172 // The SRW implicit def is dead. 173 MI->getOperand(3).setIsDead(); 174 } 175 } 176 } 177 178 // FIXME: Can we eleminate these in favour of generic code? 179 bool MSP430FrameLowering::spillCalleeSavedRegisters( 180 MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, 181 ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const { 182 if (CSI.empty()) 183 return false; 184 185 DebugLoc DL; 186 if (MI != MBB.end()) DL = MI->getDebugLoc(); 187 188 MachineFunction &MF = *MBB.getParent(); 189 const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); 190 MSP430MachineFunctionInfo *MFI = MF.getInfo<MSP430MachineFunctionInfo>(); 191 MFI->setCalleeSavedFrameSize(CSI.size() * 2); 192 193 for (unsigned i = CSI.size(); i != 0; --i) { 194 unsigned Reg = CSI[i-1].getReg(); 195 // Add the callee-saved register as live-in. It's killed at the spill. 196 MBB.addLiveIn(Reg); 197 BuildMI(MBB, MI, DL, TII.get(MSP430::PUSH16r)) 198 .addReg(Reg, RegState::Kill); 199 } 200 return true; 201 } 202 203 bool MSP430FrameLowering::restoreCalleeSavedRegisters( 204 MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, 205 MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const { 206 if (CSI.empty()) 207 return false; 208 209 DebugLoc DL; 210 if (MI != MBB.end()) DL = MI->getDebugLoc(); 211 212 MachineFunction &MF = *MBB.getParent(); 213 const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); 214 215 for (unsigned i = 0, e = CSI.size(); i != e; ++i) 216 BuildMI(MBB, MI, DL, TII.get(MSP430::POP16r), CSI[i].getReg()); 217 218 return true; 219 } 220 221 MachineBasicBlock::iterator MSP430FrameLowering::eliminateCallFramePseudoInstr( 222 MachineFunction &MF, MachineBasicBlock &MBB, 223 MachineBasicBlock::iterator I) const { 224 const MSP430InstrInfo &TII = 225 *static_cast<const MSP430InstrInfo *>(MF.getSubtarget().getInstrInfo()); 226 if (!hasReservedCallFrame(MF)) { 227 // If the stack pointer can be changed after prologue, turn the 228 // adjcallstackup instruction into a 'sub SP, <amt>' and the 229 // adjcallstackdown instruction into 'add SP, <amt>' 230 // TODO: consider using push / pop instead of sub + store / add 231 MachineInstr &Old = *I; 232 uint64_t Amount = TII.getFrameSize(Old); 233 if (Amount != 0) { 234 // We need to keep the stack aligned properly. To do this, we round the 235 // amount of space needed for the outgoing arguments up to the next 236 // alignment boundary. 237 Amount = alignTo(Amount, getStackAlign()); 238 239 MachineInstr *New = nullptr; 240 if (Old.getOpcode() == TII.getCallFrameSetupOpcode()) { 241 New = 242 BuildMI(MF, Old.getDebugLoc(), TII.get(MSP430::SUB16ri), MSP430::SP) 243 .addReg(MSP430::SP) 244 .addImm(Amount); 245 } else { 246 assert(Old.getOpcode() == TII.getCallFrameDestroyOpcode()); 247 // factor out the amount the callee already popped. 248 Amount -= TII.getFramePoppedByCallee(Old); 249 if (Amount) 250 New = BuildMI(MF, Old.getDebugLoc(), TII.get(MSP430::ADD16ri), 251 MSP430::SP) 252 .addReg(MSP430::SP) 253 .addImm(Amount); 254 } 255 256 if (New) { 257 // The SRW implicit def is dead. 258 New->getOperand(3).setIsDead(); 259 260 // Replace the pseudo instruction with a new instruction... 261 MBB.insert(I, New); 262 } 263 } 264 } else if (I->getOpcode() == TII.getCallFrameDestroyOpcode()) { 265 // If we are performing frame pointer elimination and if the callee pops 266 // something off the stack pointer, add it back. 267 if (uint64_t CalleeAmt = TII.getFramePoppedByCallee(*I)) { 268 MachineInstr &Old = *I; 269 MachineInstr *New = 270 BuildMI(MF, Old.getDebugLoc(), TII.get(MSP430::SUB16ri), MSP430::SP) 271 .addReg(MSP430::SP) 272 .addImm(CalleeAmt); 273 // The SRW implicit def is dead. 274 New->getOperand(3).setIsDead(); 275 276 MBB.insert(I, New); 277 } 278 } 279 280 return MBB.erase(I); 281 } 282 283 void 284 MSP430FrameLowering::processFunctionBeforeFrameFinalized(MachineFunction &MF, 285 RegScavenger *) const { 286 // Create a frame entry for the FP register that must be saved. 287 if (hasFP(MF)) { 288 int FrameIdx = MF.getFrameInfo().CreateFixedObject(2, -4, true); 289 (void)FrameIdx; 290 assert(FrameIdx == MF.getFrameInfo().getObjectIndexBegin() && 291 "Slot for FP register must be last in order to be found!"); 292 } 293 } 294