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