xref: /freebsd/contrib/llvm-project/llvm/lib/Target/X86/X86ArgumentStackSlotRebase.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
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 
31 using namespace llvm;
32 
33 #define DEBUG_TYPE "x86argumentstackrebase"
34 
35 namespace {
36 
37 class X86ArgumentStackSlotPass : public MachineFunctionPass {
38 
39 public:
40   static char ID; // Pass identification, replacement for typeid
41 
X86ArgumentStackSlotPass()42   explicit X86ArgumentStackSlotPass() : MachineFunctionPass(ID) {}
43 
44   bool runOnMachineFunction(MachineFunction &MF) override;
45 
getAnalysisUsage(AnalysisUsage & AU) const46   void getAnalysisUsage(AnalysisUsage &AU) const override {
47     AU.setPreservesCFG();
48     MachineFunctionPass::getAnalysisUsage(AU);
49   }
50 };
51 
52 } // end anonymous namespace
53 
54 char X86ArgumentStackSlotPass::ID = 0;
55 
56 INITIALIZE_PASS(X86ArgumentStackSlotPass, DEBUG_TYPE, "Argument Stack Rebase",
57                 false, false)
58 
createX86ArgumentStackSlotPass()59 FunctionPass *llvm::createX86ArgumentStackSlotPass() {
60   return new X86ArgumentStackSlotPass();
61 }
62 
getArgBaseReg(MachineFunction & MF)63 static 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(RC);
96   else
97     return NoReg;
98 }
99 
runOnMachineFunction(MachineFunction & MF)100 bool 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(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(BasePtr, 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(SlotSize, 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(MBB, MBBI, DL,
160               TII->get(STI.is64Bit() ? X86::PLEA64r : X86::PLEA32r), ArgBaseReg)
161           .addFrameIndex(FI)
162           .addImm(1)
163           .addUse(X86::NoRegister)
164           .addImm(SlotSize)
165           .addUse(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(Idx))
176             continue;
177           int64_t Offset = MFI.getObjectOffset(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(MI.getIterator(), I, ArgBaseReg, Offset);
185           Changed = true;
186         }
187         ++I;
188       }
189     }
190   }
191 
192   return Changed;
193 }
194