[Orc] Move Orc code into a namespace (llvm::orc), update Kaleidoscope code.
[oota-llvm.git] / lib / ExecutionEngine / Orc / IndirectionUtils.cpp
1 #include "llvm/ADT/Triple.h"
2 #include "llvm/ExecutionEngine/Orc/CloneSubModule.h"
3 #include "llvm/ExecutionEngine/Orc/IndirectionUtils.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 namespace orc {
12
13 GlobalVariable* createImplPointer(Function &F, const Twine &Name,
14                                   Constant *Initializer) {
15   assert(F.getParent() && "Function isn't in a module.");
16   if (!Initializer)
17     Initializer = Constant::getNullValue(F.getType());
18   Module &M = *F.getParent();
19   return new GlobalVariable(M, F.getType(), false, GlobalValue::ExternalLinkage,
20                             Initializer, Name, nullptr,
21                             GlobalValue::NotThreadLocal, 0, true);
22 }
23
24 void makeStub(Function &F, GlobalVariable &ImplPointer) {
25   assert(F.isDeclaration() && "Can't turn a definition into a stub.");
26   assert(F.getParent() && "Function isn't in a module.");
27   Module &M = *F.getParent();
28   BasicBlock *EntryBlock = BasicBlock::Create(M.getContext(), "entry", &F);
29   IRBuilder<> Builder(EntryBlock);
30   LoadInst *ImplAddr = Builder.CreateLoad(&ImplPointer);
31   std::vector<Value*> CallArgs;
32   for (auto &A : F.args())
33     CallArgs.push_back(&A);
34   CallInst *Call = Builder.CreateCall(ImplAddr, CallArgs);
35   Call->setTailCall();
36   Builder.CreateRet(Call);
37 }
38
39 void partition(Module &M, const ModulePartitionMap &PMap) {
40
41   for (auto &KVPair : PMap) {
42
43     auto ExtractGlobalVars =
44       [&](GlobalVariable &New, const GlobalVariable &Orig,
45           ValueToValueMapTy &VMap) {
46         if (KVPair.second.count(&Orig)) {
47           copyGVInitializer(New, Orig, VMap);
48         }
49         if (New.getLinkage() == GlobalValue::PrivateLinkage) {
50           New.setLinkage(GlobalValue::ExternalLinkage);
51           New.setVisibility(GlobalValue::HiddenVisibility);
52         }
53       };
54
55     auto ExtractFunctions =
56       [&](Function &New, const Function &Orig, ValueToValueMapTy &VMap) {
57         if (KVPair.second.count(&Orig))
58           copyFunctionBody(New, Orig, VMap);
59         if (New.getLinkage() == GlobalValue::InternalLinkage) {
60           New.setLinkage(GlobalValue::ExternalLinkage);
61           New.setVisibility(GlobalValue::HiddenVisibility);
62         }
63       };
64
65     CloneSubModule(*KVPair.first, M, ExtractGlobalVars, ExtractFunctions,
66                    false);
67   }
68 }
69
70 FullyPartitionedModule fullyPartition(Module &M) {
71   FullyPartitionedModule MP;
72
73   ModulePartitionMap PMap;
74
75   for (auto &F : M) {
76
77     if (F.isDeclaration())
78       continue;
79
80     std::string NewModuleName = (M.getName() + "." + F.getName()).str();
81     MP.Functions.push_back(
82       llvm::make_unique<Module>(NewModuleName, M.getContext()));
83     MP.Functions.back()->setDataLayout(M.getDataLayout());
84     PMap[MP.Functions.back().get()].insert(&F);
85   }
86
87   MP.GlobalVars =
88     llvm::make_unique<Module>((M.getName() + ".globals_and_stubs").str(),
89                               M.getContext());
90   MP.GlobalVars->setDataLayout(M.getDataLayout());
91
92   MP.Commons =
93     llvm::make_unique<Module>((M.getName() + ".commons").str(), M.getContext());
94   MP.Commons->setDataLayout(M.getDataLayout());
95
96   // Make sure there's at least an empty set for the stubs map or we'll fail
97   // to clone anything for it (including the decls).
98   PMap[MP.GlobalVars.get()] = ModulePartitionMap::mapped_type();
99   for (auto &GV : M.globals())
100     if (GV.getLinkage() == GlobalValue::CommonLinkage)
101       PMap[MP.Commons.get()].insert(&GV);
102     else
103       PMap[MP.GlobalVars.get()].insert(&GV);
104
105   partition(M, PMap);
106
107   return MP;
108 }
109
110 } // End namespace orc.
111 } // End namespace llvm.