1 #include "llvm/ADT/Triple.h" 2 #include "llvm/ExecutionEngine/Orc/IndirectionUtils.h" 3 #include "llvm/ExecutionEngine/Orc/CloneSubModule.h" 4 #include "llvm/IR/CallSite.h" 5 #include "llvm/IR/IRBuilder.h" 6 #include <set> 7 8 using namespace llvm; 9 10 namespace llvm { 11 12 JITIndirections makeCallsSingleIndirect( 13 Module &M, const std::function<bool(const Function &)> &ShouldIndirect, 14 const char *JITImplSuffix, const char *JITAddrSuffix) { 15 std::vector<Function *> Worklist; 16 std::vector<std::string> FuncNames; 17 18 for (auto &F : M) 19 if (ShouldIndirect(F) && (F.user_begin() != F.user_end())) { 20 Worklist.push_back(&F); 21 FuncNames.push_back(F.getName()); 22 } 23 24 for (auto *F : Worklist) { 25 GlobalVariable *FImplAddr = new GlobalVariable( 26 M, F->getType(), false, GlobalValue::ExternalLinkage, 27 Constant::getNullValue(F->getType()), F->getName() + JITAddrSuffix, 28 nullptr, GlobalValue::NotThreadLocal, 0, true); 29 FImplAddr->setVisibility(GlobalValue::HiddenVisibility); 30 31 for (auto *U : F->users()) { 32 assert(isa<Instruction>(U) && "Cannot indirect non-instruction use"); 33 IRBuilder<> Builder(cast<Instruction>(U)); 34 U->replaceUsesOfWith(F, Builder.CreateLoad(FImplAddr)); 35 } 36 } 37 38 return JITIndirections( 39 FuncNames, [=](StringRef S) -> std::string { return std::string(S); }, 40 [=](StringRef S) 41 -> std::string { return std::string(S) + JITAddrSuffix; }); 42 } 43 44 JITIndirections makeCallsDoubleIndirect( 45 Module &M, const std::function<bool(const Function &)> &ShouldIndirect, 46 const char *JITImplSuffix, const char *JITAddrSuffix) { 47 48 std::vector<Function *> Worklist; 49 std::vector<std::string> FuncNames; 50 51 for (auto &F : M) 52 if (!F.isDeclaration() && !F.hasAvailableExternallyLinkage() && 53 ShouldIndirect(F)) 54 Worklist.push_back(&F); 55 56 for (auto *F : Worklist) { 57 std::string OrigName = F->getName(); 58 F->setName(OrigName + JITImplSuffix); 59 FuncNames.push_back(OrigName); 60 61 GlobalVariable *FImplAddr = new GlobalVariable( 62 M, F->getType(), false, GlobalValue::ExternalLinkage, 63 Constant::getNullValue(F->getType()), OrigName + JITAddrSuffix, nullptr, 64 GlobalValue::NotThreadLocal, 0, true); 65 FImplAddr->setVisibility(GlobalValue::HiddenVisibility); 66 67 Function *FRedirect = 68 Function::Create(F->getFunctionType(), F->getLinkage(), OrigName, &M); 69 70 F->replaceAllUsesWith(FRedirect); 71 72 BasicBlock *EntryBlock = 73 BasicBlock::Create(M.getContext(), "entry", FRedirect); 74 75 IRBuilder<> Builder(EntryBlock); 76 LoadInst *FImplLoadedAddr = Builder.CreateLoad(FImplAddr); 77 78 std::vector<Value *> CallArgs; 79 for (Value &Arg : FRedirect->args()) 80 CallArgs.push_back(&Arg); 81 CallInst *Call = Builder.CreateCall(FImplLoadedAddr, CallArgs); 82 Call->setTailCall(); 83 Builder.CreateRet(Call); 84 } 85 86 return JITIndirections( 87 FuncNames, [=](StringRef S) 88 -> std::string { return std::string(S) + JITImplSuffix; }, 89 [=](StringRef S) 90 -> std::string { return std::string(S) + JITAddrSuffix; }); 91 } 92 93 std::vector<std::unique_ptr<Module>> 94 explode(const Module &OrigMod, 95 const std::function<bool(const Function &)> &ShouldExtract) { 96 97 std::vector<std::unique_ptr<Module>> NewModules; 98 99 // Split all the globals, non-indirected functions, etc. into a single module. 100 auto ExtractGlobalVars = [&](GlobalVariable &New, const GlobalVariable &Orig, 101 ValueToValueMapTy &VMap) { 102 copyGVInitializer(New, Orig, VMap); 103 if (New.getLinkage() == GlobalValue::PrivateLinkage) { 104 New.setLinkage(GlobalValue::ExternalLinkage); 105 New.setVisibility(GlobalValue::HiddenVisibility); 106 } 107 }; 108 109 auto ExtractNonImplFunctions = 110 [&](Function &New, const Function &Orig, ValueToValueMapTy &VMap) { 111 if (!ShouldExtract(New)) 112 copyFunctionBody(New, Orig, VMap); 113 }; 114 115 NewModules.push_back(CloneSubModule(OrigMod, ExtractGlobalVars, 116 ExtractNonImplFunctions, true)); 117 118 // Preserve initializers for Common linkage vars, and make private linkage 119 // globals external: they are now provided by the globals module extracted 120 // above. 121 auto DropGlobalVars = [&](GlobalVariable &New, const GlobalVariable &Orig, 122 ValueToValueMapTy &VMap) { 123 if (New.getLinkage() == GlobalValue::CommonLinkage) 124 copyGVInitializer(New, Orig, VMap); 125 else if (New.getLinkage() == GlobalValue::PrivateLinkage) 126 New.setLinkage(GlobalValue::ExternalLinkage); 127 }; 128 129 // Split each 'impl' function out in to its own module. 130 for (const auto &Func : OrigMod) { 131 if (Func.isDeclaration() || !ShouldExtract(Func)) 132 continue; 133 134 auto ExtractNamedFunction = 135 [&](Function &New, const Function &Orig, ValueToValueMapTy &VMap) { 136 if (New.getName() == Func.getName()) 137 copyFunctionBody(New, Orig, VMap); 138 }; 139 140 NewModules.push_back( 141 CloneSubModule(OrigMod, DropGlobalVars, ExtractNamedFunction, false)); 142 } 143 144 return NewModules; 145 } 146 147 std::vector<std::unique_ptr<Module>> 148 explode(const Module &OrigMod, const JITIndirections &Indirections) { 149 std::set<std::string> ImplNames; 150 151 for (const auto &FuncName : Indirections.IndirectedNames) 152 ImplNames.insert(Indirections.GetImplName(FuncName)); 153 154 return explode( 155 OrigMod, [&](const Function &F) { return ImplNames.count(F.getName()); }); 156 } 157 } 158