brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.5 KiB · ebf6d1a Raw
219 lines · cpp
1//===- TargetFrameLoweringImpl.cpp - Implement target frame interface ------==//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// Implements the layout of a stack frame on the target machine.10//11//===----------------------------------------------------------------------===//12 13#include "llvm/ADT/BitVector.h"14#include "llvm/CodeGen/MachineFrameInfo.h"15#include "llvm/CodeGen/MachineFunction.h"16#include "llvm/CodeGen/MachineRegisterInfo.h"17#include "llvm/CodeGen/TargetFrameLowering.h"18#include "llvm/CodeGen/TargetInstrInfo.h"19#include "llvm/CodeGen/TargetSubtargetInfo.h"20#include "llvm/IR/Attributes.h"21#include "llvm/IR/Function.h"22#include "llvm/IR/InstrTypes.h"23#include "llvm/MC/MCAsmInfo.h"24#include "llvm/Support/Compiler.h"25#include "llvm/Target/TargetMachine.h"26#include "llvm/Target/TargetOptions.h"27 28using namespace llvm;29 30TargetFrameLowering::~TargetFrameLowering() = default;31 32bool TargetFrameLowering::enableCalleeSaveSkip(const MachineFunction &MF) const {33  assert(MF.getFunction().hasFnAttribute(Attribute::NoReturn) &&34         MF.getFunction().hasFnAttribute(Attribute::NoUnwind) &&35         !MF.getFunction().hasFnAttribute(Attribute::UWTable));36  return false;37}38 39bool TargetFrameLowering::enableCFIFixup(const MachineFunction &MF) const {40  return MF.needsFrameMoves() &&41         !MF.getTarget().getMCAsmInfo()->usesWindowsCFI();42}43 44/// Returns the displacement from the frame register to the stack45/// frame of the specified index, along with the frame register used46/// (in output arg FrameReg). This is the default implementation which47/// is overridden for some targets.48StackOffset49TargetFrameLowering::getFrameIndexReference(const MachineFunction &MF, int FI,50                                            Register &FrameReg) const {51  const MachineFrameInfo &MFI = MF.getFrameInfo();52  const TargetRegisterInfo *RI = MF.getSubtarget().getRegisterInfo();53 54  // By default, assume all frame indices are referenced via whatever55  // getFrameRegister() says. The target can override this if it's doing56  // something different.57  FrameReg = RI->getFrameRegister(MF);58 59  return StackOffset::getFixed(MFI.getObjectOffset(FI) + MFI.getStackSize() -60                               getOffsetOfLocalArea() +61                               MFI.getOffsetAdjustment());62}63 64/// Returns the offset from the stack pointer to the slot of the specified65/// index. This function serves to provide a comparable offset from a single66/// reference point (the value of the stack-pointer at function entry) that can67/// be used for analysis. This is the default implementation using68/// MachineFrameInfo offsets.69StackOffset70TargetFrameLowering::getFrameIndexReferenceFromSP(const MachineFunction &MF,71                                                  int FI) const {72  // To display the true offset from SP, we need to subtract the offset to the73  // local area from MFI's ObjectOffset.74  return StackOffset::getFixed(MF.getFrameInfo().getObjectOffset(FI) -75                               getOffsetOfLocalArea());76}77 78bool TargetFrameLowering::needsFrameIndexResolution(79    const MachineFunction &MF) const {80  return MF.getFrameInfo().hasStackObjects();81}82 83void TargetFrameLowering::getCalleeSaves(const MachineFunction &MF,84                                         BitVector &CalleeSaves) const {85  const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();86  CalleeSaves.resize(TRI.getNumRegs());87 88  const MachineFrameInfo &MFI = MF.getFrameInfo();89  if (!MFI.isCalleeSavedInfoValid())90    return;91 92  for (const CalleeSavedInfo &Info : MFI.getCalleeSavedInfo())93    CalleeSaves.set(Info.getReg());94}95 96void TargetFrameLowering::determineCalleeSaves(MachineFunction &MF,97                                               BitVector &SavedRegs,98                                               RegScavenger *RS) const {99  const TargetRegisterInfo &TRI = *MF.getSubtarget().getRegisterInfo();100 101  // Resize before the early returns. Some backends expect that102  // SavedRegs.size() == TRI.getNumRegs() after this call even if there are no103  // saved registers.104  SavedRegs.resize(TRI.getNumRegs());105 106  // Get the callee saved register list...107  const MCPhysReg *CSRegs = nullptr;108 109  // When interprocedural register allocation is enabled, callee saved register110  // list should be empty, since caller saved registers are preferred over111  // callee saved registers. Unless it has some risked CSR to be optimized out.112  if (MF.getTarget().Options.EnableIPRA &&113      isSafeForNoCSROpt(MF.getFunction()) &&114      isProfitableForNoCSROpt(MF.getFunction()))115    CSRegs = TRI.getIPRACSRegs(&MF);116  else117    CSRegs = MF.getRegInfo().getCalleeSavedRegs();118 119  // Early exit if there are no callee saved registers.120  if (!CSRegs || CSRegs[0] == 0)121    return;122 123  // In Naked functions we aren't going to save any registers.124  if (MF.getFunction().hasFnAttribute(Attribute::Naked))125    return;126 127  // Noreturn+nounwind functions never restore CSR, so no saves are needed.128  // Purely noreturn functions may still return through throws, so those must129  // save CSR for caller exception handlers.130  //131  // If the function uses longjmp to break out of its current path of132  // execution we do not need the CSR spills either: setjmp stores all CSRs133  // it was called with into the jmp_buf, which longjmp then restores.134  if (MF.getFunction().hasFnAttribute(Attribute::NoReturn) &&135        MF.getFunction().hasFnAttribute(Attribute::NoUnwind) &&136        !MF.getFunction().hasFnAttribute(Attribute::UWTable) &&137        enableCalleeSaveSkip(MF))138    return;139 140  // Functions which call __builtin_unwind_init get all their registers saved.141  bool CallsUnwindInit = MF.callsUnwindInit();142  const MachineRegisterInfo &MRI = MF.getRegInfo();143  for (unsigned i = 0; CSRegs[i]; ++i) {144    unsigned Reg = CSRegs[i];145    if (CallsUnwindInit || MRI.isPhysRegModified(Reg))146      SavedRegs.set(Reg);147  }148}149 150bool TargetFrameLowering::allocateScavengingFrameIndexesNearIncomingSP(151  const MachineFunction &MF) const {152  if (!hasFP(MF))153    return false;154 155  const TargetRegisterInfo *RegInfo = MF.getSubtarget().getRegisterInfo();156  return RegInfo->useFPForScavengingIndex(MF) &&157         !RegInfo->hasStackRealignment(MF);158}159 160bool TargetFrameLowering::isSafeForNoCSROpt(const Function &F) {161  if (!F.hasLocalLinkage() || F.hasAddressTaken() ||162      !F.hasFnAttribute(Attribute::NoRecurse))163    return false;164  // Function should not be optimized as tail call.165  for (const User *U : F.users())166    if (auto *CB = dyn_cast<CallBase>(U))167      if (CB->isTailCall())168        return false;169  return true;170}171 172int TargetFrameLowering::getInitialCFAOffset(const MachineFunction &MF) const {173  llvm_unreachable("getInitialCFAOffset() not implemented!");174}175 176Register177TargetFrameLowering::getInitialCFARegister(const MachineFunction &MF) const {178  llvm_unreachable("getInitialCFARegister() not implemented!");179}180 181TargetFrameLowering::DwarfFrameBase182TargetFrameLowering::getDwarfFrameBase(const MachineFunction &MF) const {183  const TargetRegisterInfo *RI = MF.getSubtarget().getRegisterInfo();184  return DwarfFrameBase{DwarfFrameBase::Register, {RI->getFrameRegister(MF).id()}};185}186 187void TargetFrameLowering::spillCalleeSavedRegister(188    MachineBasicBlock &SaveBlock, MachineBasicBlock::iterator MI,189    const CalleeSavedInfo &CS, const TargetInstrInfo *TII,190    const TargetRegisterInfo *TRI) const {191  // Insert the spill to the stack frame.192  MCRegister Reg = CS.getReg();193 194  if (CS.isSpilledToReg()) {195    BuildMI(SaveBlock, MI, DebugLoc(), TII->get(TargetOpcode::COPY),196            CS.getDstReg())197        .addReg(Reg, getKillRegState(true));198  } else {199    const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);200    TII->storeRegToStackSlot(SaveBlock, MI, Reg, true, CS.getFrameIdx(), RC,201                             Register());202  }203}204 205void TargetFrameLowering::restoreCalleeSavedRegister(206    MachineBasicBlock &MBB, MachineBasicBlock::iterator MI,207    const CalleeSavedInfo &CS, const TargetInstrInfo *TII,208    const TargetRegisterInfo *TRI) const {209  MCRegister Reg = CS.getReg();210  if (CS.isSpilledToReg()) {211    BuildMI(MBB, MI, DebugLoc(), TII->get(TargetOpcode::COPY), Reg)212        .addReg(CS.getDstReg(), getKillRegState(true));213  } else {214    const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);215    TII->loadRegFromStackSlot(MBB, MI, Reg, CS.getFrameIdx(), RC, Register());216    assert(MI != MBB.begin() && "loadRegFromStackSlot didn't insert any code!");217  }218}219