brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.2 KiB · ff13e1b Raw
194 lines · cpp
1//===---- X86ArgumentStackSlotRebase.cpp - rebase argument stack slot -----===//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 pass replace the frame register with a GPR virtual register and set10// the stack offset for each instruction which reference argument from stack.11//12//===----------------------------------------------------------------------===//13 14#include "X86.h"15#include "X86MachineFunctionInfo.h"16#include "X86RegisterInfo.h"17#include "X86Subtarget.h"18#include "llvm/CodeGen/MachineBasicBlock.h"19#include "llvm/CodeGen/MachineFrameInfo.h"20#include "llvm/CodeGen/MachineFunction.h"21#include "llvm/CodeGen/MachineFunctionPass.h"22#include "llvm/CodeGen/MachineInstr.h"23#include "llvm/CodeGen/MachineOperand.h"24#include "llvm/CodeGen/MachineRegisterInfo.h"25#include "llvm/CodeGen/TargetRegisterInfo.h"26#include "llvm/CodeGen/TargetSubtargetInfo.h"27#include "llvm/IR/Attributes.h"28#include "llvm/IR/Function.h"29#include "llvm/Pass.h"30 31using namespace llvm;32 33#define DEBUG_TYPE "x86argumentstackrebase"34 35namespace {36 37class X86ArgumentStackSlotPass : public MachineFunctionPass {38 39public:40  static char ID; // Pass identification, replacement for typeid41 42  explicit X86ArgumentStackSlotPass() : MachineFunctionPass(ID) {}43 44  bool runOnMachineFunction(MachineFunction &MF) override;45 46  void getAnalysisUsage(AnalysisUsage &AU) const override {47    AU.setPreservesCFG();48    MachineFunctionPass::getAnalysisUsage(AU);49  }50};51 52} // end anonymous namespace53 54char X86ArgumentStackSlotPass::ID = 0;55 56INITIALIZE_PASS(X86ArgumentStackSlotPass, DEBUG_TYPE, "Argument Stack Rebase",57                false, false)58 59FunctionPass *llvm::createX86ArgumentStackSlotPass() {60  return new X86ArgumentStackSlotPass();61}62 63static Register getArgBaseReg(MachineFunction &MF) {64  MachineRegisterInfo &MRI = MF.getRegInfo();65  const X86Subtarget &STI = MF.getSubtarget<X86Subtarget>();66  const Function &F = MF.getFunction();67  CallingConv::ID CC = F.getCallingConv();68  Register NoReg;69  const TargetRegisterClass *RC = nullptr;70  switch (CC) {71  // We need a virtual register in case there is inline assembly72  // clobber argument base register.73  case CallingConv::C:74    RC = STI.is64Bit() ? &X86::GR64_ArgRefRegClass : &X86::GR32_ArgRefRegClass;75    break;76  case CallingConv::X86_RegCall:77    // FIXME: For regcall there is no scratch register on 32-bit target.78    // We may use a callee saved register as argument base register and79    // save it before being changed as base pointer. We need DW_CFA to80    // indicate where the callee saved register is saved, so that it can81    // be correctly unwind.82    // push      ebx83    // mov       ebx, esp84    // and       esp, -12885    // ...86    // pop       ebx87    // ret88    RC = STI.is64Bit() ? &X86::GR64_ArgRefRegClass : nullptr;89    break;90  // TODO: Refine register class for each calling convention.91  default:92    break;93  }94  if (RC)95    return MRI.createVirtualRegister(RC);96  else97    return NoReg;98}99 100bool X86ArgumentStackSlotPass::runOnMachineFunction(MachineFunction &MF) {101  const Function &F = MF.getFunction();102  MachineFrameInfo &MFI = MF.getFrameInfo();103  const X86Subtarget &STI = MF.getSubtarget<X86Subtarget>();104  const X86RegisterInfo *TRI = STI.getRegisterInfo();105  const X86InstrInfo *TII = STI.getInstrInfo();106  X86MachineFunctionInfo *X86FI = MF.getInfo<X86MachineFunctionInfo>();107  bool Changed = false;108 109  if (F.hasFnAttribute(Attribute::Naked))110    return false;111  // Only support Linux and ELF.112  if (!STI.isTargetLinux() && !STI.isTargetELF())113    return false;114  if (!TRI->hasBasePointer(MF))115    return false;116  // Don't support X32117  if (STI.isTarget64BitILP32())118    return false;119 120  Register BasePtr = TRI->getBaseRegister();121  auto IsBaseRegisterClobbered = [&]() {122    for (MachineBasicBlock &MBB : MF) {123      for (MachineInstr &MI : MBB) {124        if (!MI.isInlineAsm())125          continue;126        for (MachineOperand &MO : MI.operands()) {127          if (!MO.isReg())128            continue;129          Register Reg = MO.getReg();130          if (!Reg.isPhysical())131            continue;132          if (TRI->isSuperOrSubRegisterEq(BasePtr, Reg))133            return true;134        }135      }136    }137    return false;138  };139  if (!IsBaseRegisterClobbered())140    return false;141 142  Register ArgBaseReg = getArgBaseReg(MF);143  if (!ArgBaseReg.isValid())144    return false;145  // leal    4(%esp), %reg146  MachineBasicBlock &MBB = MF.front();147  MachineBasicBlock::iterator MBBI = MBB.begin();148  DebugLoc DL;149  // Emit instruction to copy get stack pointer to a virtual register150  // and save the instruction to x86 machine functon info. We can get151  // physical register of ArgBaseReg after register allocation. The152  // stack slot is used to save/restore argument base pointer. We can153  // get the index from the instruction.154  unsigned SlotSize = TRI->getSlotSize();155  int FI = MFI.CreateSpillStackObject(SlotSize, Align(SlotSize));156  // Use pseudo LEA to prevent the instruction from being eliminated.157  // TODO: if it is duplicated we can expand it to lea.158  MachineInstr *LEA =159      BuildMI(MBB, MBBI, DL,160              TII->get(STI.is64Bit() ? X86::PLEA64r : X86::PLEA32r), ArgBaseReg)161          .addFrameIndex(FI)162          .addImm(1)163          .addUse(X86::NoRegister)164          .addImm(SlotSize)165          .addUse(X86::NoRegister)166          .setMIFlag(MachineInstr::FrameSetup);167  X86FI->setStackPtrSaveMI(LEA);168 169  for (MachineBasicBlock &MBB : MF) {170    for (MachineInstr &MI : MBB) {171      int I = 0;172      for (MachineOperand &MO : MI.operands()) {173        if (MO.isFI()) {174          int Idx = MO.getIndex();175          if (!MFI.isFixedObjectIndex(Idx))176            continue;177          int64_t Offset = MFI.getObjectOffset(Idx);178          if (Offset < 0)179            continue;180          // TODO replace register for debug instruction181          if (MI.isDebugInstr())182            continue;183          // Replace frame register with argument base pointer and its offset.184          TRI->eliminateFrameIndex(MI.getIterator(), I, ArgBaseReg, Offset);185          Changed = true;186        }187        ++I;188      }189    }190  }191 192  return Changed;193}194