434 lines · cpp
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-exception6//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/CFIInstBuilder.h"18#include "llvm/CodeGen/MachineFrameInfo.h"19#include "llvm/CodeGen/MachineFunction.h"20#include "llvm/CodeGen/MachineInstrBuilder.h"21#include "llvm/CodeGen/MachineModuleInfo.h"22#include "llvm/Target/TargetOptions.h"23 24using namespace llvm;25 26MSP430FrameLowering::MSP430FrameLowering(const MSP430Subtarget &STI)27 : TargetFrameLowering(TargetFrameLowering::StackGrowsDown, Align(2), -2,28 Align(2)),29 STI(STI), TII(*STI.getInstrInfo()), TRI(STI.getRegisterInfo()) {}30 31bool MSP430FrameLowering::hasFPImpl(const MachineFunction &MF) const {32 const MachineFrameInfo &MFI = MF.getFrameInfo();33 34 return (MF.getTarget().Options.DisableFramePointerElim(MF) ||35 MF.getFrameInfo().hasVarSizedObjects() ||36 MFI.isFrameAddressTaken());37}38 39bool MSP430FrameLowering::hasReservedCallFrame(const MachineFunction &MF) const {40 return !MF.getFrameInfo().hasVarSizedObjects();41}42 43void MSP430FrameLowering::BuildCFI(MachineBasicBlock &MBB,44 MachineBasicBlock::iterator MBBI,45 const DebugLoc &DL,46 const MCCFIInstruction &CFIInst,47 MachineInstr::MIFlag Flag) const {48 MachineFunction &MF = *MBB.getParent();49 unsigned CFIIndex = MF.addFrameInst(CFIInst);50 BuildMI(MBB, MBBI, DL, TII.get(TargetOpcode::CFI_INSTRUCTION))51 .addCFIIndex(CFIIndex)52 .setMIFlag(Flag);53}54 55void MSP430FrameLowering::emitCalleeSavedFrameMoves(56 MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,57 const DebugLoc &DL, bool IsPrologue) const {58 MachineFunction &MF = *MBB.getParent();59 MachineFrameInfo &MFI = MF.getFrameInfo();60 const MCRegisterInfo *MRI = MF.getContext().getRegisterInfo();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) {72 BuildCFI(MBB, MBBI, DL,73 MCCFIInstruction::createOffset(nullptr, DwarfReg, Offset));74 } else {75 BuildCFI(MBB, MBBI, DL,76 MCCFIInstruction::createRestore(nullptr, DwarfReg));77 }78 }79}80 81void MSP430FrameLowering::emitPrologue(MachineFunction &MF,82 MachineBasicBlock &MBB) const {83 assert(&MF.front() == &MBB && "Shrink-wrapping not yet supported");84 MachineFrameInfo &MFI = MF.getFrameInfo();85 MSP430MachineFunctionInfo *MSP430FI = MF.getInfo<MSP430MachineFunctionInfo>();86 const MSP430InstrInfo &TII =87 *static_cast<const MSP430InstrInfo *>(MF.getSubtarget().getInstrInfo());88 89 MachineBasicBlock::iterator MBBI = MBB.begin();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 adjustment99 uint64_t FrameSize = StackSize - 2;100 NumBytes = FrameSize - MSP430FI->getCalleeSavedFrameSize();101 102 // Get the offset of the stack slot for the EBP register... which is103 // 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)110 .setMIFlag(MachineInstr::FrameSetup);111 112 // Mark the place where FP was saved.113 // Define the current CFA rule to use the provided offset.114 BuildCFI(MBB, MBBI, DL,115 MCCFIInstruction::cfiDefCfaOffset(nullptr, -2 * stackGrowth),116 MachineInstr::FrameSetup);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),123 MachineInstr::FrameSetup);124 125 // Update FP with the new base value...126 BuildMI(MBB, MBBI, DL, TII.get(MSP430::MOV16rr), MSP430::R4)127 .addReg(MSP430::SP)128 .setMIFlag(MachineInstr::FrameSetup);129 130 // Mark effective beginning of when frame pointer becomes valid.131 // Define the current CFA to use the FP register.132 BuildCFI(MBB, MBBI, DL,133 MCCFIInstruction::createDefCfaRegister(nullptr, DwarfFramePtr),134 MachineInstr::FrameSetup);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 } else140 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");152 BuildCFI(MBB, MBBI, DL,153 MCCFIInstruction::cfiDefCfaOffset(nullptr, -StackOffset),154 MachineInstr::FrameSetup);155 StackOffset += stackGrowth;156 }157 }158 159 if (MBBI != MBB.end())160 DL = MBBI->getDebugLoc();161 162 if (NumBytes) { // adjust stack pointer: SP -= numbytes163 // If there is an SUB16ri of SP immediately before this instruction, merge164 // the two.165 //NumBytes -= mergeSPUpdates(MBB, MBBI, true);166 // If there is an ADD16ri or SUB16ri of SP immediately after this167 // instruction, merge the two instructions.168 // mergeSPUpdatesDown(MBB, MBBI, &NumBytes);169 170 if (NumBytes) {171 MachineInstr *MI =172 BuildMI(MBB, MBBI, DL, TII.get(MSP430::SUB16ri), MSP430::SP)173 .addReg(MSP430::SP)174 .addImm(NumBytes)175 .setMIFlag(MachineInstr::FrameSetup);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 FP181 BuildCFI(182 MBB, MBBI, DL,183 MCCFIInstruction::cfiDefCfaOffset(nullptr, StackSize - stackGrowth),184 MachineInstr::FrameSetup);185 }186 }187 188 emitCalleeSavedFrameMoves(MBB, MBBI, DL, true);189}190 191void MSP430FrameLowering::emitEpilogue(MachineFunction &MF,192 MachineBasicBlock &MBB) const {193 const MachineFrameInfo &MFI = MF.getFrameInfo();194 MSP430MachineFunctionInfo *MSP430FI = MF.getInfo<MSP430MachineFunctionInfo>();195 const MSP430InstrInfo &TII =196 *static_cast<const MSP430InstrInfo *>(MF.getSubtarget().getInstrInfo());197 198 MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr();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 ok205 default:206 llvm_unreachable("Can only insert epilog into returning blocks");207 }208 209 // Get the number of bytes to allocate from the FrameInfo210 uint64_t StackSize = MFI.getStackSize();211 unsigned CSSize = MSP430FI->getCalleeSavedFrameSize();212 uint64_t NumBytes = 0;213 214 MachineBasicBlock::iterator AfterPop = MBBI;215 if (hasFP(MF)) {216 // Calculate required stack adjustment217 uint64_t FrameSize = StackSize - 2;218 NumBytes = FrameSize - CSSize;219 220 // pop FP.221 BuildMI(MBB, MBBI, DL, TII.get(MSP430::POP16r), MSP430::R4)222 .setMIFlag(MachineInstr::FrameDestroy);223 unsigned DwarfStackPtr = TRI->getDwarfRegNum(MSP430::SP, true);224 BuildCFI(MBB, MBBI, DL,225 MCCFIInstruction::cfiDefCfa(nullptr, DwarfStackPtr, 2),226 MachineInstr::FrameDestroy);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),232 MachineInstr::FrameDestroy);233 --MBBI;234 --AfterPop;235 }236 } else237 NumBytes = StackSize - CSSize;238 239 // Skip the callee-saved pop instructions.240 MachineBasicBlock::iterator FirstCSPop = MBBI;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 this255 // 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)262 .setMIFlag(MachineInstr::FrameDestroy);263 if (CSSize) {264 MachineInstr *MI =265 BuildMI(MBB, MBBI, DL, TII.get(MSP430::SUB16ri), MSP430::SP)266 .addReg(MSP430::SP)267 .addImm(CSSize)268 .setMIFlag(MachineInstr::FrameDestroy);269 // The SRW implicit def is dead.270 MI->getOperand(3).setIsDead();271 }272 } else {273 // adjust stack pointer back: SP += numbytes274 if (NumBytes) {275 MachineInstr *MI =276 BuildMI(MBB, MBBI, DL, TII.get(MSP430::ADD16ri), MSP430::SP)277 .addReg(MSP430::SP)278 .addImm(NumBytes)279 .setMIFlag(MachineInstr::FrameDestroy);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 SP285 BuildCFI(MBB, MBBI, DL,286 MCCFIInstruction::cfiDefCfaOffset(nullptr, CSSize + 2),287 MachineInstr::FrameDestroy);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()) {298 MachineBasicBlock::iterator PI = MBBI;299 unsigned Opc = PI->getOpcode();300 ++MBBI;301 if (Opc == MSP430::POP16r) {302 Offset += 2;303 BuildCFI(MBB, MBBI, DL,304 MCCFIInstruction::cfiDefCfaOffset(nullptr, -Offset),305 MachineInstr::FrameDestroy);306 }307 }308 }309 emitCalleeSavedFrameMoves(MBB, AfterPop, DL, false);310}311 312// FIXME: Can we eleminate these in favour of generic code?313bool MSP430FrameLowering::spillCalleeSavedRegisters(314 MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,315 ArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {316 if (CSI.empty())317 return false;318 319 DebugLoc DL;320 if (MI != MBB.end()) DL = MI->getDebugLoc();321 322 MachineFunction &MF = *MBB.getParent();323 const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();324 MSP430MachineFunctionInfo *MFI = MF.getInfo<MSP430MachineFunctionInfo>();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))332 .addReg(Reg, RegState::Kill)333 .setMIFlag(MachineInstr::FrameSetup);334 }335 return true;336}337 338bool MSP430FrameLowering::restoreCalleeSavedRegisters(339 MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,340 MutableArrayRef<CalleeSavedInfo> CSI, const TargetRegisterInfo *TRI) const {341 if (CSI.empty())342 return false;343 344 DebugLoc DL;345 if (MI != MBB.end()) DL = MI->getDebugLoc();346 347 MachineFunction &MF = *MBB.getParent();348 const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo();349 350 for (const CalleeSavedInfo &I : llvm::reverse(CSI))351 BuildMI(MBB, MI, DL, TII.get(MSP430::POP16r), I.getReg())352 .setMIFlag(MachineInstr::FrameDestroy);353 354 return true;355}356 357MachineBasicBlock::iterator MSP430FrameLowering::eliminateCallFramePseudoInstr(358 MachineFunction &MF, MachineBasicBlock &MBB,359 MachineBasicBlock::iterator I) const {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 the364 // adjcallstackup instruction into a 'sub SP, <amt>' and the365 // adjcallstackdown instruction into 'add SP, <amt>'366 // TODO: consider using push / pop instead of sub + store / add367 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 the371 // amount of space needed for the outgoing arguments up to the next372 // 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 pops402 // 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)) {410 CFIInstBuilder(MBB, I, MachineInstr::NoFlags)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 423void424MSP430FrameLowering::processFunctionBeforeFrameFinalized(MachineFunction &MF,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}434