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