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