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