1 //===---- IndirectThunks.h - Indirect Thunk Base Class ----------*- C++ -*-===// 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 /// \file 10 /// Contains a base class for Passes that inject an MI thunk. 11 /// 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_CODEGEN_INDIRECTTHUNKS_H 15 #define LLVM_CODEGEN_INDIRECTTHUNKS_H 16 17 #include "llvm/CodeGen/MachineFunction.h" 18 #include "llvm/CodeGen/MachineModuleInfo.h" 19 #include "llvm/IR/IRBuilder.h" 20 #include "llvm/IR/Module.h" 21 22 namespace llvm { 23 24 template <typename Derived> class ThunkInserter { 25 Derived &getDerived() { return *static_cast<Derived *>(this); } 26 27 protected: 28 bool InsertedThunks; 29 void doInitialization(Module &M) {} 30 void createThunkFunction(MachineModuleInfo &MMI, StringRef Name, 31 bool Comdat = true); 32 33 public: 34 void init(Module &M) { 35 InsertedThunks = false; 36 getDerived().doInitialization(M); 37 } 38 // return `true` if `MMI` or `MF` was modified 39 bool run(MachineModuleInfo &MMI, MachineFunction &MF); 40 }; 41 42 template <typename Derived> 43 void ThunkInserter<Derived>::createThunkFunction(MachineModuleInfo &MMI, 44 StringRef Name, bool Comdat) { 45 assert(Name.startswith(getDerived().getThunkPrefix()) && 46 "Created a thunk with an unexpected prefix!"); 47 48 Module &M = const_cast<Module &>(*MMI.getModule()); 49 LLVMContext &Ctx = M.getContext(); 50 auto Type = FunctionType::get(Type::getVoidTy(Ctx), false); 51 Function *F = Function::Create(Type, 52 Comdat ? GlobalValue::LinkOnceODRLinkage 53 : GlobalValue::InternalLinkage, 54 Name, &M); 55 if (Comdat) { 56 F->setVisibility(GlobalValue::HiddenVisibility); 57 F->setComdat(M.getOrInsertComdat(Name)); 58 } 59 60 // Add Attributes so that we don't create a frame, unwind information, or 61 // inline. 62 AttrBuilder B; 63 B.addAttribute(llvm::Attribute::NoUnwind); 64 B.addAttribute(llvm::Attribute::Naked); 65 F->addAttributes(llvm::AttributeList::FunctionIndex, B); 66 67 // Populate our function a bit so that we can verify. 68 BasicBlock *Entry = BasicBlock::Create(Ctx, "entry", F); 69 IRBuilder<> Builder(Entry); 70 71 Builder.CreateRetVoid(); 72 73 // MachineFunctions aren't created automatically for the IR-level constructs 74 // we already made. Create them and insert them into the module. 75 MachineFunction &MF = MMI.getOrCreateMachineFunction(*F); 76 // A MachineBasicBlock must not be created for the Entry block; code 77 // generation from an empty naked function in C source code also does not 78 // generate one. At least GlobalISel asserts if this invariant isn't 79 // respected. 80 81 // Set MF properties. We never use vregs... 82 MF.getProperties().set(MachineFunctionProperties::Property::NoVRegs); 83 } 84 85 template <typename Derived> 86 bool ThunkInserter<Derived>::run(MachineModuleInfo &MMI, MachineFunction &MF) { 87 // If MF is not a thunk, check to see if we need to insert a thunk. 88 if (!MF.getName().startswith(getDerived().getThunkPrefix())) { 89 // If we've already inserted a thunk, nothing else to do. 90 if (InsertedThunks) 91 return false; 92 93 // Only add a thunk if one of the functions has the corresponding feature 94 // enabled in its subtarget, and doesn't enable external thunks. 95 // FIXME: Conditionalize on indirect calls so we don't emit a thunk when 96 // nothing will end up calling it. 97 // FIXME: It's a little silly to look at every function just to enumerate 98 // the subtargets, but eventually we'll want to look at them for indirect 99 // calls, so maybe this is OK. 100 if (!getDerived().mayUseThunk(MF)) 101 return false; 102 103 getDerived().insertThunks(MMI); 104 InsertedThunks = true; 105 return true; 106 } 107 108 // If this *is* a thunk function, we need to populate it with the correct MI. 109 getDerived().populateThunk(MF); 110 return true; 111 } 112 113 } // namespace llvm 114 115 #endif 116