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