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