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"
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;
19 if (ShouldIndirect(F) && (F.user_begin() != F.user_end())) {
20 Worklist.push_back(&F);
21 FuncNames.push_back(F.getName());
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);
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));
38 return JITIndirections(
39 FuncNames, [=](StringRef S) -> std::string { return std::string(S); },
41 -> std::string { return std::string(S) + JITAddrSuffix; });
44 JITIndirections makeCallsDoubleIndirect(
45 Module &M, const std::function<bool(const Function &)> &ShouldIndirect,
46 const char *JITImplSuffix, const char *JITAddrSuffix) {
48 std::vector<Function *> Worklist;
49 std::vector<std::string> FuncNames;
52 if (!F.isDeclaration() && !F.hasAvailableExternallyLinkage() &&
54 Worklist.push_back(&F);
56 for (auto *F : Worklist) {
57 std::string OrigName = F->getName();
58 F->setName(OrigName + JITImplSuffix);
59 FuncNames.push_back(OrigName);
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);
68 Function::Create(F->getFunctionType(), F->getLinkage(), OrigName, &M);
70 F->replaceAllUsesWith(FRedirect);
72 BasicBlock *EntryBlock =
73 BasicBlock::Create(M.getContext(), "entry", FRedirect);
75 IRBuilder<> Builder(EntryBlock);
76 LoadInst *FImplLoadedAddr = Builder.CreateLoad(FImplAddr);
78 std::vector<Value *> CallArgs;
79 for (Value &Arg : FRedirect->args())
80 CallArgs.push_back(&Arg);
81 CallInst *Call = Builder.CreateCall(FImplLoadedAddr, CallArgs);
83 Builder.CreateRet(Call);
86 return JITIndirections(
87 FuncNames, [=](StringRef S)
88 -> std::string { return std::string(S) + JITImplSuffix; },
90 -> std::string { return std::string(S) + JITAddrSuffix; });
93 std::vector<std::unique_ptr<Module>>
94 explode(const Module &OrigMod,
95 const std::function<bool(const Function &)> &ShouldExtract) {
97 std::vector<std::unique_ptr<Module>> NewModules;
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);
109 auto ExtractNonImplFunctions =
110 [&](Function &New, const Function &Orig, ValueToValueMapTy &VMap) {
111 if (!ShouldExtract(New))
112 copyFunctionBody(New, Orig, VMap);
115 NewModules.push_back(CloneSubModule(OrigMod, ExtractGlobalVars,
116 ExtractNonImplFunctions, true));
118 // Preserve initializers for Common linkage vars, and make private linkage
119 // globals external: they are now provided by the globals module extracted
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);
129 // Split each 'impl' function out in to its own module.
130 for (const auto &Func : OrigMod) {
131 if (Func.isDeclaration() || !ShouldExtract(Func))
134 auto ExtractNamedFunction =
135 [&](Function &New, const Function &Orig, ValueToValueMapTy &VMap) {
136 if (New.getName() == Func.getName())
137 copyFunctionBody(New, Orig, VMap);
140 NewModules.push_back(
141 CloneSubModule(OrigMod, DropGlobalVars, ExtractNamedFunction, false));
147 std::vector<std::unique_ptr<Module>>
148 explode(const Module &OrigMod, const JITIndirections &Indirections) {
149 std::set<std::string> ImplNames;
151 for (const auto &FuncName : Indirections.IndirectedNames)
152 ImplNames.insert(Indirections.GetImplName(FuncName));
155 OrigMod, [&](const Function &F) { return ImplNames.count(F.getName()); });