brintos

brintos / llvm-project-archived public Read only

0
0
Text · 15.5 KiB · bc24b32 Raw
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