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
34using namespace llvm;
35
36#define DEBUG_TYPE "x86argumentstackrebase"
37
38namespace {
39
40class X86ArgumentStackSlotPass : public MachineFunctionPass {
41
42public:
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
59char X86ArgumentStackSlotPass::ID = 0;
60
61INITIALIZE_PASS(X86ArgumentStackSlotPass, DEBUG_TYPE, "Argument Stack Rebase",
62 false, false)
63
64FunctionPass *llvm::createX86ArgumentStackSlotPass() {
65 return new X86ArgumentStackSlotPass();
66}
67
68static 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(RegClass: RC);
101 else
102 return NoReg;
103}
104
105bool 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(Kind: 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(RegA: BasePtr, RegB: 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(Size: SlotSize, Alignment: 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(BB&: MBB, I: MBBI, MIMD: DL,
165 MCID: TII->get(Opcode: STI.is64Bit() ? X86::PLEA64r : X86::PLEA32r), DestReg: ArgBaseReg)
166 .addFrameIndex(Idx: FI)
167 .addImm(Val: 1)
168 .addUse(RegNo: X86::NoRegister)
169 .addImm(Val: SlotSize)
170 .addUse(RegNo: 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(ObjectIdx: Idx))
181 continue;
182 int64_t Offset = MFI.getObjectOffset(ObjectIdx: 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(II: MI.getIterator(), FIOperandNum: I, BaseReg: ArgBaseReg, FIOffset: Offset);
190 Changed = true;
191 }
192 ++I;
193 }
194 }
195 }
196
197 return Changed;
198}
199