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/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 typeid
41
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 namespace
53
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 assembly
72 // 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 and
79 // save it before being changed as base pointer. We need DW_CFA to
80 // indicate where the callee saved register is saved, so that it can
81 // be correctly unwind.
82 // push ebx
83 // mov ebx, esp
84 // and esp, -128
85 // ...
86 // pop ebx
87 // ret
88 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(RegClass: RC);
96 else
97 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(Kind: 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 X32
117 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(RegA: BasePtr, RegB: 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), %reg
146 MachineBasicBlock &MBB = MF.front();
147 MachineBasicBlock::iterator MBBI = MBB.begin();
148 DebugLoc DL;
149 // Emit instruction to copy get stack pointer to a virtual register
150 // and save the instruction to x86 machine functon info. We can get
151 // physical register of ArgBaseReg after register allocation. The
152 // stack slot is used to save/restore argument base pointer. We can
153 // get the index from the instruction.
154 unsigned SlotSize = TRI->getSlotSize();
155 int FI = MFI.CreateSpillStackObject(Size: SlotSize, Alignment: 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(BB&: MBB, I: MBBI, MIMD: DL,
160 MCID: TII->get(Opcode: STI.is64Bit() ? X86::PLEA64r : X86::PLEA32r), DestReg: ArgBaseReg)
161 .addFrameIndex(Idx: FI)
162 .addImm(Val: 1)
163 .addUse(RegNo: X86::NoRegister)
164 .addImm(Val: SlotSize)
165 .addUse(RegNo: 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(ObjectIdx: Idx))
176 continue;
177 int64_t Offset = MFI.getObjectOffset(ObjectIdx: Idx);
178 if (Offset < 0)
179 continue;
180 // TODO replace register for debug instruction
181 if (MI.isDebugInstr())
182 continue;
183 // Replace frame register with argument base pointer and its offset.
184 TRI->eliminateFrameIndex(II: MI.getIterator(), FIOperandNum: I, BaseReg: ArgBaseReg, FIOffset: Offset);
185 Changed = true;
186 }
187 ++I;
188 }
189 }
190 }
191
192 return Changed;
193}
194