blob: e75092b2485eca8a77913defb30edfd213e9e5ba [file] [log] [blame]
Lang Hames93de2a12015-01-23 21:25:00 +00001#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
8using namespace llvm;
9
10namespace llvm {
11
12JITIndirections 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
44JITIndirections 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
93std::vector<std::unique_ptr<Module>>
94explode(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
147std::vector<std::unique_ptr<Module>>
148explode(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}