diff options
Diffstat (limited to 'llvm/lib/ExecutionEngine/Orc')
-rw-r--r-- | llvm/lib/ExecutionEngine/Orc/CMakeLists.txt | 1 | ||||
-rw-r--r-- | llvm/lib/ExecutionEngine/Orc/CloneSubModule.cpp | 106 | ||||
-rw-r--r-- | llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp | 158 |
3 files changed, 178 insertions, 87 deletions
diff --git a/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt b/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt index 18f0441c466..b38b4594057 100644 --- a/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt +++ b/llvm/lib/ExecutionEngine/Orc/CMakeLists.txt @@ -1,4 +1,5 @@ add_llvm_library(LLVMOrcJIT + CloneSubModule.cpp ExecutionUtils.cpp IndirectionUtils.cpp OrcMCJITReplacement.cpp diff --git a/llvm/lib/ExecutionEngine/Orc/CloneSubModule.cpp b/llvm/lib/ExecutionEngine/Orc/CloneSubModule.cpp new file mode 100644 index 00000000000..c9810097d7d --- /dev/null +++ b/llvm/lib/ExecutionEngine/Orc/CloneSubModule.cpp @@ -0,0 +1,106 @@ +#include "llvm/ExecutionEngine/Orc/CloneSubModule.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/GlobalVariable.h" +#include "llvm/IR/Module.h" +#include "llvm/Transforms/Utils/Cloning.h" + +namespace llvm { +namespace orc { + +void copyGVInitializer(GlobalVariable &New, const GlobalVariable &Orig, + ValueToValueMapTy &VMap) { + if (Orig.hasInitializer()) + New.setInitializer(MapValue(Orig.getInitializer(), VMap)); +} + +void copyFunctionBody(Function &New, const Function &Orig, + ValueToValueMapTy &VMap) { + if (!Orig.isDeclaration()) { + Function::arg_iterator DestI = New.arg_begin(); + for (Function::const_arg_iterator J = Orig.arg_begin(); J != Orig.arg_end(); + ++J) { + DestI->setName(J->getName()); + VMap[J] = DestI++; + } + + SmallVector<ReturnInst *, 8> Returns; // Ignore returns cloned. + CloneFunctionInto(&New, &Orig, VMap, /*ModuleLevelChanges=*/true, Returns); + } +} + +void CloneSubModule(llvm::Module &Dst, const Module &Src, + HandleGlobalVariableFtor HandleGlobalVariable, + HandleFunctionFtor HandleFunction, bool CloneInlineAsm) { + + ValueToValueMapTy VMap; + + if (CloneInlineAsm) + Dst.appendModuleInlineAsm(Src.getModuleInlineAsm()); + + // Copy global variables (but not initializers, yet). + for (Module::const_global_iterator I = Src.global_begin(), E = Src.global_end(); + I != E; ++I) { + GlobalVariable *GV = new GlobalVariable( + Dst, I->getType()->getElementType(), I->isConstant(), I->getLinkage(), + (Constant *)nullptr, I->getName(), (GlobalVariable *)nullptr, + I->getThreadLocalMode(), I->getType()->getAddressSpace()); + GV->copyAttributesFrom(I); + VMap[I] = GV; + } + + // Loop over the functions in the module, making external functions as before + for (Module::const_iterator I = Src.begin(), E = Src.end(); I != E; ++I) { + Function *NF = + Function::Create(cast<FunctionType>(I->getType()->getElementType()), + I->getLinkage(), I->getName(), &Dst); + NF->copyAttributesFrom(I); + VMap[I] = NF; + } + + // Loop over the aliases in the module + for (Module::const_alias_iterator I = Src.alias_begin(), E = Src.alias_end(); + I != E; ++I) { + auto *PTy = cast<PointerType>(I->getType()); + auto *GA = GlobalAlias::create(PTy, I->getLinkage(), I->getName(), &Dst); + GA->copyAttributesFrom(I); + VMap[I] = GA; + } + + // Now that all of the things that global variable initializer can refer to + // have been created, loop through and copy the global variable referrers + // over... We also set the attributes on the global now. + for (Module::const_global_iterator I = Src.global_begin(), E = Src.global_end(); + I != E; ++I) { + GlobalVariable &GV = *cast<GlobalVariable>(VMap[I]); + HandleGlobalVariable(GV, *I, VMap); + } + + // Similarly, copy over function bodies now... + // + for (Module::const_iterator I = Src.begin(), E = Src.end(); I != E; ++I) { + Function &F = *cast<Function>(VMap[I]); + HandleFunction(F, *I, VMap); + } + + // And aliases + for (Module::const_alias_iterator I = Src.alias_begin(), E = Src.alias_end(); + I != E; ++I) { + GlobalAlias *GA = cast<GlobalAlias>(VMap[I]); + if (const Constant *C = I->getAliasee()) + GA->setAliasee(MapValue(C, VMap)); + } + + // And named metadata.... + for (Module::const_named_metadata_iterator I = Src.named_metadata_begin(), + E = Src.named_metadata_end(); + I != E; ++I) { + const NamedMDNode &NMD = *I; + NamedMDNode *NewNMD = Dst.getOrInsertNamedMetadata(NMD.getName()); + for (unsigned i = 0, e = NMD.getNumOperands(); i != e; ++i) + NewNMD->addOperand(MapMetadata(NMD.getOperand(i), VMap)); + } + +} + +} // End namespace orc. +} // End namespace llvm. diff --git a/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp b/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp index 4ed87303148..75b610876b7 100644 --- a/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp +++ b/llvm/lib/ExecutionEngine/Orc/IndirectionUtils.cpp @@ -9,10 +9,10 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/Triple.h" +#include "llvm/ExecutionEngine/Orc/CloneSubModule.h" #include "llvm/ExecutionEngine/Orc/IndirectionUtils.h" #include "llvm/IR/CallSite.h" #include "llvm/IR/IRBuilder.h" -#include "llvm/Transforms/Utils/Cloning.h" #include <set> #include <sstream> @@ -32,11 +32,9 @@ GlobalVariable* createImplPointer(PointerType &PT, Module &M, const Twine &Name, Constant *Initializer) { if (!Initializer) Initializer = Constant::getNullValue(&PT); - auto IP = new GlobalVariable(M, &PT, false, GlobalValue::ExternalLinkage, - Initializer, Name, nullptr, - GlobalValue::NotThreadLocal, 0, true); - IP->setVisibility(GlobalValue::HiddenVisibility); - return IP; + return new GlobalVariable(M, &PT, false, GlobalValue::ExternalLinkage, + Initializer, Name, nullptr, + GlobalValue::NotThreadLocal, 0, true); } void makeStub(Function &F, GlobalVariable &ImplPointer) { @@ -52,10 +50,7 @@ void makeStub(Function &F, GlobalVariable &ImplPointer) { CallInst *Call = Builder.CreateCall(ImplAddr, CallArgs); Call->setTailCall(); Call->setAttributes(F.getAttributes()); - if (F.getReturnType()->isVoidTy()) - Builder.CreateRetVoid(); - else - Builder.CreateRet(Call); + Builder.CreateRet(Call); } // Utility class for renaming global values and functions during partitioning. @@ -89,94 +84,83 @@ private: DenseMap<const Value*, std::string> Names; }; -static void raiseVisibilityOnValue(GlobalValue &V, GlobalRenamer &R) { - if (V.hasLocalLinkage()) { - if (R.needsRenaming(V)) - V.setName(R.getRename(V)); - V.setLinkage(GlobalValue::ExternalLinkage); - V.setVisibility(GlobalValue::HiddenVisibility); +void partition(Module &M, const ModulePartitionMap &PMap) { + + GlobalRenamer Renamer; + + for (auto &KVPair : PMap) { + + auto ExtractGlobalVars = + [&](GlobalVariable &New, const GlobalVariable &Orig, + ValueToValueMapTy &VMap) { + if (KVPair.second.count(&Orig)) { + copyGVInitializer(New, Orig, VMap); + } + if (New.hasLocalLinkage()) { + if (Renamer.needsRenaming(New)) + New.setName(Renamer.getRename(Orig)); + New.setLinkage(GlobalValue::ExternalLinkage); + New.setVisibility(GlobalValue::HiddenVisibility); + } + assert(!Renamer.needsRenaming(New) && "Invalid global name."); + }; + + auto ExtractFunctions = + [&](Function &New, const Function &Orig, ValueToValueMapTy &VMap) { + if (KVPair.second.count(&Orig)) + copyFunctionBody(New, Orig, VMap); + if (New.hasLocalLinkage()) { + if (Renamer.needsRenaming(New)) + New.setName(Renamer.getRename(Orig)); + New.setLinkage(GlobalValue::ExternalLinkage); + New.setVisibility(GlobalValue::HiddenVisibility); + } + assert(!Renamer.needsRenaming(New) && "Invalid function name."); + }; + + CloneSubModule(*KVPair.first, M, ExtractGlobalVars, ExtractFunctions, + false); } - V.setUnnamedAddr(false); - assert(!R.needsRenaming(V) && "Invalid global name."); } -void makeAllSymbolsExternallyAccessible(Module &M) { - GlobalRenamer Renamer; +FullyPartitionedModule fullyPartition(Module &M) { + FullyPartitionedModule MP; - for (auto &F : M) - raiseVisibilityOnValue(F, Renamer); + ModulePartitionMap PMap; - for (auto &GV : M.globals()) - raiseVisibilityOnValue(GV, Renamer); -} + for (auto &F : M) { -Function* cloneFunctionDecl(Module &Dst, const Function &F, - ValueToValueMapTy *VMap) { - assert(F.getParent() != &Dst && "Can't copy decl over existing function."); - Function *NewF = - Function::Create(cast<FunctionType>(F.getType()->getElementType()), - F.getLinkage(), F.getName(), &Dst); - NewF->copyAttributesFrom(&F); - - if (VMap) { - (*VMap)[&F] = NewF; - auto NewArgI = NewF->arg_begin(); - for (auto ArgI = F.arg_begin(), ArgE = F.arg_end(); ArgI != ArgE; - ++ArgI, ++NewArgI) - (*VMap)[ArgI] = NewArgI; + if (F.isDeclaration()) + continue; + + std::string NewModuleName = (M.getName() + "." + F.getName()).str(); + MP.Functions.push_back( + llvm::make_unique<Module>(NewModuleName, M.getContext())); + MP.Functions.back()->setDataLayout(M.getDataLayout()); + PMap[MP.Functions.back().get()].insert(&F); } - return NewF; -} + MP.GlobalVars = + llvm::make_unique<Module>((M.getName() + ".globals_and_stubs").str(), + M.getContext()); + MP.GlobalVars->setDataLayout(M.getDataLayout()); -void moveFunctionBody(Function &OrigF, ValueToValueMapTy &VMap, - ValueMaterializer *Materializer, - Function *NewF) { - assert(!OrigF.isDeclaration() && "Nothing to move"); - if (!NewF) - NewF = cast<Function>(VMap[&OrigF]); - else - assert(VMap[&OrigF] == NewF && "Incorrect function mapping in VMap."); - assert(NewF && "Function mapping missing from VMap."); - assert(NewF->getParent() != OrigF.getParent() && - "moveFunctionBody should only be used to move bodies between " - "modules."); - - SmallVector<ReturnInst *, 8> Returns; // Ignore returns cloned. - CloneFunctionInto(NewF, &OrigF, VMap, /*ModuleLevelChanges=*/true, Returns, - "", nullptr, nullptr, Materializer); - OrigF.deleteBody(); -} + MP.Commons = + llvm::make_unique<Module>((M.getName() + ".commons").str(), M.getContext()); + MP.Commons->setDataLayout(M.getDataLayout()); -GlobalVariable* cloneGlobalVariableDecl(Module &Dst, const GlobalVariable &GV, - ValueToValueMapTy *VMap) { - assert(GV.getParent() != &Dst && "Can't copy decl over existing global var."); - GlobalVariable *NewGV = new GlobalVariable( - Dst, GV.getType()->getElementType(), GV.isConstant(), - GV.getLinkage(), nullptr, GV.getName(), nullptr, - GV.getThreadLocalMode(), GV.getType()->getAddressSpace()); - NewGV->copyAttributesFrom(&GV); - if (VMap) - (*VMap)[&GV] = NewGV; - return NewGV; -} + // Make sure there's at least an empty set for the stubs map or we'll fail + // to clone anything for it (including the decls). + PMap[MP.GlobalVars.get()] = ModulePartitionMap::mapped_type(); + for (auto &GV : M.globals()) + if (GV.getLinkage() == GlobalValue::CommonLinkage) + PMap[MP.Commons.get()].insert(&GV); + else + PMap[MP.GlobalVars.get()].insert(&GV); + + partition(M, PMap); -void moveGlobalVariableInitializer(GlobalVariable &OrigGV, - ValueToValueMapTy &VMap, - ValueMaterializer *Materializer, - GlobalVariable *NewGV) { - assert(OrigGV.hasInitializer() && "Nothing to move"); - if (!NewGV) - NewGV = cast<GlobalVariable>(VMap[&OrigGV]); - else - assert(VMap[&OrigGV] == NewGV && - "Incorrect global variable mapping in VMap."); - assert(NewGV->getParent() != OrigGV.getParent() && - "moveGlobalVariable should only be used to move initializers between " - "modules"); - - NewGV->setInitializer(MapValue(OrigGV.getInitializer(), VMap, RF_None, - nullptr, Materializer)); + return MP; } } // End namespace orc. |