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