xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/X86/X86IndirectThunks.cpp (revision 0946e70a3b60dec23922cf3e0c313cb0917fee0a)
1*0946e70aSDimitry Andric //==- X86IndirectThunks.cpp - Construct indirect call/jump thunks for x86  --=//
2*0946e70aSDimitry Andric //
3*0946e70aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*0946e70aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*0946e70aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*0946e70aSDimitry Andric //
7*0946e70aSDimitry Andric //===----------------------------------------------------------------------===//
8*0946e70aSDimitry Andric /// \file
9*0946e70aSDimitry Andric ///
10*0946e70aSDimitry Andric /// Pass that injects an MI thunk that is used to lower indirect calls in a way
11*0946e70aSDimitry Andric /// that prevents speculation on some x86 processors and can be used to mitigate
12*0946e70aSDimitry Andric /// security vulnerabilities due to targeted speculative execution and side
13*0946e70aSDimitry Andric /// channels such as CVE-2017-5715.
14*0946e70aSDimitry Andric ///
15*0946e70aSDimitry Andric /// Currently supported thunks include:
16*0946e70aSDimitry Andric /// - Retpoline -- A RET-implemented trampoline that lowers indirect calls
17*0946e70aSDimitry Andric /// - LVI Thunk -- A CALL/JMP-implemented thunk that forces load serialization
18*0946e70aSDimitry Andric ///   before making an indirect call/jump
19*0946e70aSDimitry Andric ///
20*0946e70aSDimitry Andric /// Note that the reason that this is implemented as a MachineFunctionPass and
21*0946e70aSDimitry Andric /// not a ModulePass is that ModulePasses at this point in the LLVM X86 pipeline
22*0946e70aSDimitry Andric /// serialize all transformations, which can consume lots of memory.
23*0946e70aSDimitry Andric ///
24*0946e70aSDimitry Andric /// TODO(chandlerc): All of this code could use better comments and
25*0946e70aSDimitry Andric /// documentation.
26*0946e70aSDimitry Andric ///
27*0946e70aSDimitry Andric //===----------------------------------------------------------------------===//
28*0946e70aSDimitry Andric 
29*0946e70aSDimitry Andric #include "X86.h"
30*0946e70aSDimitry Andric #include "X86InstrBuilder.h"
31*0946e70aSDimitry Andric #include "X86Subtarget.h"
32*0946e70aSDimitry Andric #include "llvm/CodeGen/MachineFunction.h"
33*0946e70aSDimitry Andric #include "llvm/CodeGen/MachineInstrBuilder.h"
34*0946e70aSDimitry Andric #include "llvm/CodeGen/MachineModuleInfo.h"
35*0946e70aSDimitry Andric #include "llvm/CodeGen/Passes.h"
36*0946e70aSDimitry Andric #include "llvm/CodeGen/TargetPassConfig.h"
37*0946e70aSDimitry Andric #include "llvm/IR/IRBuilder.h"
38*0946e70aSDimitry Andric #include "llvm/IR/Instructions.h"
39*0946e70aSDimitry Andric #include "llvm/IR/Module.h"
40*0946e70aSDimitry Andric #include "llvm/Support/CommandLine.h"
41*0946e70aSDimitry Andric #include "llvm/Support/Debug.h"
42*0946e70aSDimitry Andric #include "llvm/Support/raw_ostream.h"
43*0946e70aSDimitry Andric 
44*0946e70aSDimitry Andric using namespace llvm;
45*0946e70aSDimitry Andric 
46*0946e70aSDimitry Andric #define DEBUG_TYPE "x86-retpoline-thunks"
47*0946e70aSDimitry Andric 
48*0946e70aSDimitry Andric static const char RetpolineNamePrefix[] = "__llvm_retpoline_";
49*0946e70aSDimitry Andric static const char R11RetpolineName[] = "__llvm_retpoline_r11";
50*0946e70aSDimitry Andric static const char EAXRetpolineName[] = "__llvm_retpoline_eax";
51*0946e70aSDimitry Andric static const char ECXRetpolineName[] = "__llvm_retpoline_ecx";
52*0946e70aSDimitry Andric static const char EDXRetpolineName[] = "__llvm_retpoline_edx";
53*0946e70aSDimitry Andric static const char EDIRetpolineName[] = "__llvm_retpoline_edi";
54*0946e70aSDimitry Andric 
55*0946e70aSDimitry Andric static const char LVIThunkNamePrefix[] = "__llvm_lvi_thunk_";
56*0946e70aSDimitry Andric static const char R11LVIThunkName[] = "__llvm_lvi_thunk_r11";
57*0946e70aSDimitry Andric 
58*0946e70aSDimitry Andric namespace {
59*0946e70aSDimitry Andric template <typename Derived> class ThunkInserter {
60*0946e70aSDimitry Andric   Derived &getDerived() { return *static_cast<Derived *>(this); }
61*0946e70aSDimitry Andric 
62*0946e70aSDimitry Andric protected:
63*0946e70aSDimitry Andric   bool InsertedThunks;
64*0946e70aSDimitry Andric   void doInitialization(Module &M) {}
65*0946e70aSDimitry Andric   void createThunkFunction(MachineModuleInfo &MMI, StringRef Name);
66*0946e70aSDimitry Andric 
67*0946e70aSDimitry Andric public:
68*0946e70aSDimitry Andric   void init(Module &M) {
69*0946e70aSDimitry Andric     InsertedThunks = false;
70*0946e70aSDimitry Andric     getDerived().doInitialization(M);
71*0946e70aSDimitry Andric   }
72*0946e70aSDimitry Andric   // return `true` if `MMI` or `MF` was modified
73*0946e70aSDimitry Andric   bool run(MachineModuleInfo &MMI, MachineFunction &MF);
74*0946e70aSDimitry Andric };
75*0946e70aSDimitry Andric 
76*0946e70aSDimitry Andric struct RetpolineThunkInserter : ThunkInserter<RetpolineThunkInserter> {
77*0946e70aSDimitry Andric   const char *getThunkPrefix() { return RetpolineNamePrefix; }
78*0946e70aSDimitry Andric   bool mayUseThunk(const MachineFunction &MF) {
79*0946e70aSDimitry Andric     const auto &STI = MF.getSubtarget<X86Subtarget>();
80*0946e70aSDimitry Andric     return (STI.useRetpolineIndirectCalls() ||
81*0946e70aSDimitry Andric             STI.useRetpolineIndirectBranches()) &&
82*0946e70aSDimitry Andric            !STI.useRetpolineExternalThunk();
83*0946e70aSDimitry Andric   }
84*0946e70aSDimitry Andric   void insertThunks(MachineModuleInfo &MMI);
85*0946e70aSDimitry Andric   void populateThunk(MachineFunction &MF);
86*0946e70aSDimitry Andric };
87*0946e70aSDimitry Andric 
88*0946e70aSDimitry Andric struct LVIThunkInserter : ThunkInserter<LVIThunkInserter> {
89*0946e70aSDimitry Andric   const char *getThunkPrefix() { return LVIThunkNamePrefix; }
90*0946e70aSDimitry Andric   bool mayUseThunk(const MachineFunction &MF) {
91*0946e70aSDimitry Andric     return MF.getSubtarget<X86Subtarget>().useLVIControlFlowIntegrity();
92*0946e70aSDimitry Andric   }
93*0946e70aSDimitry Andric   void insertThunks(MachineModuleInfo &MMI) {
94*0946e70aSDimitry Andric     createThunkFunction(MMI, R11LVIThunkName);
95*0946e70aSDimitry Andric   }
96*0946e70aSDimitry Andric   void populateThunk(MachineFunction &MF) {
97*0946e70aSDimitry Andric     // Grab the entry MBB and erase any other blocks. O0 codegen appears to
98*0946e70aSDimitry Andric     // generate two bbs for the entry block.
99*0946e70aSDimitry Andric     MachineBasicBlock *Entry = &MF.front();
100*0946e70aSDimitry Andric     Entry->clear();
101*0946e70aSDimitry Andric     while (MF.size() > 1)
102*0946e70aSDimitry Andric       MF.erase(std::next(MF.begin()));
103*0946e70aSDimitry Andric 
104*0946e70aSDimitry Andric     // This code mitigates LVI by replacing each indirect call/jump with a
105*0946e70aSDimitry Andric     // direct call/jump to a thunk that looks like:
106*0946e70aSDimitry Andric     // ```
107*0946e70aSDimitry Andric     // lfence
108*0946e70aSDimitry Andric     // jmpq *%r11
109*0946e70aSDimitry Andric     // ```
110*0946e70aSDimitry Andric     // This ensures that if the value in register %r11 was loaded from memory,
111*0946e70aSDimitry Andric     // then the value in %r11 is (architecturally) correct prior to the jump.
112*0946e70aSDimitry Andric     const TargetInstrInfo *TII = MF.getSubtarget<X86Subtarget>().getInstrInfo();
113*0946e70aSDimitry Andric     BuildMI(&MF.front(), DebugLoc(), TII->get(X86::LFENCE));
114*0946e70aSDimitry Andric     BuildMI(&MF.front(), DebugLoc(), TII->get(X86::JMP64r)).addReg(X86::R11);
115*0946e70aSDimitry Andric     MF.front().addLiveIn(X86::R11);
116*0946e70aSDimitry Andric     return;
117*0946e70aSDimitry Andric   }
118*0946e70aSDimitry Andric };
119*0946e70aSDimitry Andric 
120*0946e70aSDimitry Andric class X86IndirectThunks : public MachineFunctionPass {
121*0946e70aSDimitry Andric public:
122*0946e70aSDimitry Andric   static char ID;
123*0946e70aSDimitry Andric 
124*0946e70aSDimitry Andric   X86IndirectThunks() : MachineFunctionPass(ID) {}
125*0946e70aSDimitry Andric 
126*0946e70aSDimitry Andric   StringRef getPassName() const override { return "X86 Indirect Thunks"; }
127*0946e70aSDimitry Andric 
128*0946e70aSDimitry Andric   bool doInitialization(Module &M) override;
129*0946e70aSDimitry Andric   bool runOnMachineFunction(MachineFunction &MF) override;
130*0946e70aSDimitry Andric 
131*0946e70aSDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
132*0946e70aSDimitry Andric     MachineFunctionPass::getAnalysisUsage(AU);
133*0946e70aSDimitry Andric     AU.addRequired<MachineModuleInfoWrapperPass>();
134*0946e70aSDimitry Andric     AU.addPreserved<MachineModuleInfoWrapperPass>();
135*0946e70aSDimitry Andric   }
136*0946e70aSDimitry Andric 
137*0946e70aSDimitry Andric private:
138*0946e70aSDimitry Andric   std::tuple<RetpolineThunkInserter, LVIThunkInserter> TIs;
139*0946e70aSDimitry Andric 
140*0946e70aSDimitry Andric   // FIXME: When LLVM moves to C++17, these can become folds
141*0946e70aSDimitry Andric   template <typename... ThunkInserterT>
142*0946e70aSDimitry Andric   static void initTIs(Module &M,
143*0946e70aSDimitry Andric                       std::tuple<ThunkInserterT...> &ThunkInserters) {
144*0946e70aSDimitry Andric     (void)std::initializer_list<int>{
145*0946e70aSDimitry Andric         (std::get<ThunkInserterT>(ThunkInserters).init(M), 0)...};
146*0946e70aSDimitry Andric   }
147*0946e70aSDimitry Andric   template <typename... ThunkInserterT>
148*0946e70aSDimitry Andric   static bool runTIs(MachineModuleInfo &MMI, MachineFunction &MF,
149*0946e70aSDimitry Andric                      std::tuple<ThunkInserterT...> &ThunkInserters) {
150*0946e70aSDimitry Andric     bool Modified = false;
151*0946e70aSDimitry Andric     (void)std::initializer_list<int>{
152*0946e70aSDimitry Andric         Modified |= std::get<ThunkInserterT>(ThunkInserters).run(MMI, MF)...};
153*0946e70aSDimitry Andric     return Modified;
154*0946e70aSDimitry Andric   }
155*0946e70aSDimitry Andric };
156*0946e70aSDimitry Andric 
157*0946e70aSDimitry Andric } // end anonymous namespace
158*0946e70aSDimitry Andric 
159*0946e70aSDimitry Andric void RetpolineThunkInserter::insertThunks(MachineModuleInfo &MMI) {
160*0946e70aSDimitry Andric   if (MMI.getTarget().getTargetTriple().getArch() == Triple::x86_64)
161*0946e70aSDimitry Andric     createThunkFunction(MMI, R11RetpolineName);
162*0946e70aSDimitry Andric   else
163*0946e70aSDimitry Andric     for (StringRef Name : {EAXRetpolineName, ECXRetpolineName, EDXRetpolineName,
164*0946e70aSDimitry Andric                            EDIRetpolineName})
165*0946e70aSDimitry Andric       createThunkFunction(MMI, Name);
166*0946e70aSDimitry Andric }
167*0946e70aSDimitry Andric 
168*0946e70aSDimitry Andric void RetpolineThunkInserter::populateThunk(MachineFunction &MF) {
169*0946e70aSDimitry Andric   bool Is64Bit = MF.getTarget().getTargetTriple().getArch() == Triple::x86_64;
170*0946e70aSDimitry Andric   Register ThunkReg;
171*0946e70aSDimitry Andric   if (Is64Bit) {
172*0946e70aSDimitry Andric     assert(MF.getName() == "__llvm_retpoline_r11" &&
173*0946e70aSDimitry Andric            "Should only have an r11 thunk on 64-bit targets");
174*0946e70aSDimitry Andric 
175*0946e70aSDimitry Andric     // __llvm_retpoline_r11:
176*0946e70aSDimitry Andric     //   callq .Lr11_call_target
177*0946e70aSDimitry Andric     // .Lr11_capture_spec:
178*0946e70aSDimitry Andric     //   pause
179*0946e70aSDimitry Andric     //   lfence
180*0946e70aSDimitry Andric     //   jmp .Lr11_capture_spec
181*0946e70aSDimitry Andric     // .align 16
182*0946e70aSDimitry Andric     // .Lr11_call_target:
183*0946e70aSDimitry Andric     //   movq %r11, (%rsp)
184*0946e70aSDimitry Andric     //   retq
185*0946e70aSDimitry Andric     ThunkReg = X86::R11;
186*0946e70aSDimitry Andric   } else {
187*0946e70aSDimitry Andric     // For 32-bit targets we need to emit a collection of thunks for various
188*0946e70aSDimitry Andric     // possible scratch registers as well as a fallback that uses EDI, which is
189*0946e70aSDimitry Andric     // normally callee saved.
190*0946e70aSDimitry Andric     //   __llvm_retpoline_eax:
191*0946e70aSDimitry Andric     //         calll .Leax_call_target
192*0946e70aSDimitry Andric     //   .Leax_capture_spec:
193*0946e70aSDimitry Andric     //         pause
194*0946e70aSDimitry Andric     //         jmp .Leax_capture_spec
195*0946e70aSDimitry Andric     //   .align 16
196*0946e70aSDimitry Andric     //   .Leax_call_target:
197*0946e70aSDimitry Andric     //         movl %eax, (%esp)  # Clobber return addr
198*0946e70aSDimitry Andric     //         retl
199*0946e70aSDimitry Andric     //
200*0946e70aSDimitry Andric     //   __llvm_retpoline_ecx:
201*0946e70aSDimitry Andric     //   ... # Same setup
202*0946e70aSDimitry Andric     //         movl %ecx, (%esp)
203*0946e70aSDimitry Andric     //         retl
204*0946e70aSDimitry Andric     //
205*0946e70aSDimitry Andric     //   __llvm_retpoline_edx:
206*0946e70aSDimitry Andric     //   ... # Same setup
207*0946e70aSDimitry Andric     //         movl %edx, (%esp)
208*0946e70aSDimitry Andric     //         retl
209*0946e70aSDimitry Andric     //
210*0946e70aSDimitry Andric     //   __llvm_retpoline_edi:
211*0946e70aSDimitry Andric     //   ... # Same setup
212*0946e70aSDimitry Andric     //         movl %edi, (%esp)
213*0946e70aSDimitry Andric     //         retl
214*0946e70aSDimitry Andric     if (MF.getName() == EAXRetpolineName)
215*0946e70aSDimitry Andric       ThunkReg = X86::EAX;
216*0946e70aSDimitry Andric     else if (MF.getName() == ECXRetpolineName)
217*0946e70aSDimitry Andric       ThunkReg = X86::ECX;
218*0946e70aSDimitry Andric     else if (MF.getName() == EDXRetpolineName)
219*0946e70aSDimitry Andric       ThunkReg = X86::EDX;
220*0946e70aSDimitry Andric     else if (MF.getName() == EDIRetpolineName)
221*0946e70aSDimitry Andric       ThunkReg = X86::EDI;
222*0946e70aSDimitry Andric     else
223*0946e70aSDimitry Andric       llvm_unreachable("Invalid thunk name on x86-32!");
224*0946e70aSDimitry Andric   }
225*0946e70aSDimitry Andric 
226*0946e70aSDimitry Andric   const TargetInstrInfo *TII = MF.getSubtarget<X86Subtarget>().getInstrInfo();
227*0946e70aSDimitry Andric   // Grab the entry MBB and erase any other blocks. O0 codegen appears to
228*0946e70aSDimitry Andric   // generate two bbs for the entry block.
229*0946e70aSDimitry Andric   MachineBasicBlock *Entry = &MF.front();
230*0946e70aSDimitry Andric   Entry->clear();
231*0946e70aSDimitry Andric   while (MF.size() > 1)
232*0946e70aSDimitry Andric     MF.erase(std::next(MF.begin()));
233*0946e70aSDimitry Andric 
234*0946e70aSDimitry Andric   MachineBasicBlock *CaptureSpec =
235*0946e70aSDimitry Andric       MF.CreateMachineBasicBlock(Entry->getBasicBlock());
236*0946e70aSDimitry Andric   MachineBasicBlock *CallTarget =
237*0946e70aSDimitry Andric       MF.CreateMachineBasicBlock(Entry->getBasicBlock());
238*0946e70aSDimitry Andric   MCSymbol *TargetSym = MF.getContext().createTempSymbol();
239*0946e70aSDimitry Andric   MF.push_back(CaptureSpec);
240*0946e70aSDimitry Andric   MF.push_back(CallTarget);
241*0946e70aSDimitry Andric 
242*0946e70aSDimitry Andric   const unsigned CallOpc = Is64Bit ? X86::CALL64pcrel32 : X86::CALLpcrel32;
243*0946e70aSDimitry Andric   const unsigned RetOpc = Is64Bit ? X86::RETQ : X86::RETL;
244*0946e70aSDimitry Andric 
245*0946e70aSDimitry Andric   Entry->addLiveIn(ThunkReg);
246*0946e70aSDimitry Andric   BuildMI(Entry, DebugLoc(), TII->get(CallOpc)).addSym(TargetSym);
247*0946e70aSDimitry Andric 
248*0946e70aSDimitry Andric   // The MIR verifier thinks that the CALL in the entry block will fall through
249*0946e70aSDimitry Andric   // to CaptureSpec, so mark it as the successor. Technically, CaptureTarget is
250*0946e70aSDimitry Andric   // the successor, but the MIR verifier doesn't know how to cope with that.
251*0946e70aSDimitry Andric   Entry->addSuccessor(CaptureSpec);
252*0946e70aSDimitry Andric 
253*0946e70aSDimitry Andric   // In the capture loop for speculation, we want to stop the processor from
254*0946e70aSDimitry Andric   // speculating as fast as possible. On Intel processors, the PAUSE instruction
255*0946e70aSDimitry Andric   // will block speculation without consuming any execution resources. On AMD
256*0946e70aSDimitry Andric   // processors, the PAUSE instruction is (essentially) a nop, so we also use an
257*0946e70aSDimitry Andric   // LFENCE instruction which they have advised will stop speculation as well
258*0946e70aSDimitry Andric   // with minimal resource utilization. We still end the capture with a jump to
259*0946e70aSDimitry Andric   // form an infinite loop to fully guarantee that no matter what implementation
260*0946e70aSDimitry Andric   // of the x86 ISA, speculating this code path never escapes.
261*0946e70aSDimitry Andric   BuildMI(CaptureSpec, DebugLoc(), TII->get(X86::PAUSE));
262*0946e70aSDimitry Andric   BuildMI(CaptureSpec, DebugLoc(), TII->get(X86::LFENCE));
263*0946e70aSDimitry Andric   BuildMI(CaptureSpec, DebugLoc(), TII->get(X86::JMP_1)).addMBB(CaptureSpec);
264*0946e70aSDimitry Andric   CaptureSpec->setHasAddressTaken();
265*0946e70aSDimitry Andric   CaptureSpec->addSuccessor(CaptureSpec);
266*0946e70aSDimitry Andric 
267*0946e70aSDimitry Andric   CallTarget->addLiveIn(ThunkReg);
268*0946e70aSDimitry Andric   CallTarget->setHasAddressTaken();
269*0946e70aSDimitry Andric   CallTarget->setAlignment(Align(16));
270*0946e70aSDimitry Andric 
271*0946e70aSDimitry Andric   // Insert return address clobber
272*0946e70aSDimitry Andric   const unsigned MovOpc = Is64Bit ? X86::MOV64mr : X86::MOV32mr;
273*0946e70aSDimitry Andric   const Register SPReg = Is64Bit ? X86::RSP : X86::ESP;
274*0946e70aSDimitry Andric   addRegOffset(BuildMI(CallTarget, DebugLoc(), TII->get(MovOpc)), SPReg, false,
275*0946e70aSDimitry Andric                0)
276*0946e70aSDimitry Andric       .addReg(ThunkReg);
277*0946e70aSDimitry Andric 
278*0946e70aSDimitry Andric   CallTarget->back().setPreInstrSymbol(MF, TargetSym);
279*0946e70aSDimitry Andric   BuildMI(CallTarget, DebugLoc(), TII->get(RetOpc));
280*0946e70aSDimitry Andric }
281*0946e70aSDimitry Andric 
282*0946e70aSDimitry Andric template <typename Derived>
283*0946e70aSDimitry Andric void ThunkInserter<Derived>::createThunkFunction(MachineModuleInfo &MMI,
284*0946e70aSDimitry Andric                                                  StringRef Name) {
285*0946e70aSDimitry Andric   assert(Name.startswith(getDerived().getThunkPrefix()) &&
286*0946e70aSDimitry Andric          "Created a thunk with an unexpected prefix!");
287*0946e70aSDimitry Andric 
288*0946e70aSDimitry Andric   Module &M = const_cast<Module &>(*MMI.getModule());
289*0946e70aSDimitry Andric   LLVMContext &Ctx = M.getContext();
290*0946e70aSDimitry Andric   auto Type = FunctionType::get(Type::getVoidTy(Ctx), false);
291*0946e70aSDimitry Andric   Function *F =
292*0946e70aSDimitry Andric       Function::Create(Type, GlobalValue::LinkOnceODRLinkage, Name, &M);
293*0946e70aSDimitry Andric   F->setVisibility(GlobalValue::HiddenVisibility);
294*0946e70aSDimitry Andric   F->setComdat(M.getOrInsertComdat(Name));
295*0946e70aSDimitry Andric 
296*0946e70aSDimitry Andric   // Add Attributes so that we don't create a frame, unwind information, or
297*0946e70aSDimitry Andric   // inline.
298*0946e70aSDimitry Andric   AttrBuilder B;
299*0946e70aSDimitry Andric   B.addAttribute(llvm::Attribute::NoUnwind);
300*0946e70aSDimitry Andric   B.addAttribute(llvm::Attribute::Naked);
301*0946e70aSDimitry Andric   F->addAttributes(llvm::AttributeList::FunctionIndex, B);
302*0946e70aSDimitry Andric 
303*0946e70aSDimitry Andric   // Populate our function a bit so that we can verify.
304*0946e70aSDimitry Andric   BasicBlock *Entry = BasicBlock::Create(Ctx, "entry", F);
305*0946e70aSDimitry Andric   IRBuilder<> Builder(Entry);
306*0946e70aSDimitry Andric 
307*0946e70aSDimitry Andric   Builder.CreateRetVoid();
308*0946e70aSDimitry Andric 
309*0946e70aSDimitry Andric   // MachineFunctions/MachineBasicBlocks aren't created automatically for the
310*0946e70aSDimitry Andric   // IR-level constructs we already made. Create them and insert them into the
311*0946e70aSDimitry Andric   // module.
312*0946e70aSDimitry Andric   MachineFunction &MF = MMI.getOrCreateMachineFunction(*F);
313*0946e70aSDimitry Andric   MachineBasicBlock *EntryMBB = MF.CreateMachineBasicBlock(Entry);
314*0946e70aSDimitry Andric 
315*0946e70aSDimitry Andric   // Insert EntryMBB into MF. It's not in the module until we do this.
316*0946e70aSDimitry Andric   MF.insert(MF.end(), EntryMBB);
317*0946e70aSDimitry Andric   // Set MF properties. We never use vregs...
318*0946e70aSDimitry Andric   MF.getProperties().set(MachineFunctionProperties::Property::NoVRegs);
319*0946e70aSDimitry Andric }
320*0946e70aSDimitry Andric 
321*0946e70aSDimitry Andric template <typename Derived>
322*0946e70aSDimitry Andric bool ThunkInserter<Derived>::run(MachineModuleInfo &MMI, MachineFunction &MF) {
323*0946e70aSDimitry Andric   // If MF is not a thunk, check to see if we need to insert a thunk.
324*0946e70aSDimitry Andric   if (!MF.getName().startswith(getDerived().getThunkPrefix())) {
325*0946e70aSDimitry Andric     // If we've already inserted a thunk, nothing else to do.
326*0946e70aSDimitry Andric     if (InsertedThunks)
327*0946e70aSDimitry Andric       return false;
328*0946e70aSDimitry Andric 
329*0946e70aSDimitry Andric     // Only add a thunk if one of the functions has the corresponding feature
330*0946e70aSDimitry Andric     // enabled in its subtarget, and doesn't enable external thunks.
331*0946e70aSDimitry Andric     // FIXME: Conditionalize on indirect calls so we don't emit a thunk when
332*0946e70aSDimitry Andric     // nothing will end up calling it.
333*0946e70aSDimitry Andric     // FIXME: It's a little silly to look at every function just to enumerate
334*0946e70aSDimitry Andric     // the subtargets, but eventually we'll want to look at them for indirect
335*0946e70aSDimitry Andric     // calls, so maybe this is OK.
336*0946e70aSDimitry Andric     if (!getDerived().mayUseThunk(MF))
337*0946e70aSDimitry Andric       return false;
338*0946e70aSDimitry Andric 
339*0946e70aSDimitry Andric     getDerived().insertThunks(MMI);
340*0946e70aSDimitry Andric     InsertedThunks = true;
341*0946e70aSDimitry Andric     return true;
342*0946e70aSDimitry Andric   }
343*0946e70aSDimitry Andric 
344*0946e70aSDimitry Andric   // If this *is* a thunk function, we need to populate it with the correct MI.
345*0946e70aSDimitry Andric   getDerived().populateThunk(MF);
346*0946e70aSDimitry Andric   return true;
347*0946e70aSDimitry Andric }
348*0946e70aSDimitry Andric 
349*0946e70aSDimitry Andric FunctionPass *llvm::createX86IndirectThunksPass() {
350*0946e70aSDimitry Andric   return new X86IndirectThunks();
351*0946e70aSDimitry Andric }
352*0946e70aSDimitry Andric 
353*0946e70aSDimitry Andric char X86IndirectThunks::ID = 0;
354*0946e70aSDimitry Andric 
355*0946e70aSDimitry Andric bool X86IndirectThunks::doInitialization(Module &M) {
356*0946e70aSDimitry Andric   initTIs(M, TIs);
357*0946e70aSDimitry Andric   return false;
358*0946e70aSDimitry Andric }
359*0946e70aSDimitry Andric 
360*0946e70aSDimitry Andric bool X86IndirectThunks::runOnMachineFunction(MachineFunction &MF) {
361*0946e70aSDimitry Andric   LLVM_DEBUG(dbgs() << getPassName() << '\n');
362*0946e70aSDimitry Andric   auto &MMI = getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
363*0946e70aSDimitry Andric   return runTIs(MMI, MF, TIs);
364*0946e70aSDimitry Andric }
365