X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=blobdiff_plain;f=lib%2FExecutionEngine%2FOrc%2FIndirectionUtils.cpp;h=6b8dc3e7faecd8a97022d3c89241531c41809378;hp=2fcfb82237ca6f7a664ff326f3ec8f41d85ff906;hb=a2184e96e69ad96e3f414a0889da0f2b1689ffdb;hpb=02d62886678db69e8cc86baec381c5d86517fb25 diff --git a/lib/ExecutionEngine/Orc/IndirectionUtils.cpp b/lib/ExecutionEngine/Orc/IndirectionUtils.cpp index 2fcfb82237c..6b8dc3e7fae 100644 --- a/lib/ExecutionEngine/Orc/IndirectionUtils.cpp +++ b/lib/ExecutionEngine/Orc/IndirectionUtils.cpp @@ -1,3 +1,12 @@ +//===---- IndirectionUtils.cpp - Utilities for call indirection in Orc ----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + #include "llvm/ADT/Triple.h" #include "llvm/ExecutionEngine/Orc/CloneSubModule.h" #include "llvm/ExecutionEngine/Orc/IndirectionUtils.h" @@ -8,150 +17,104 @@ using namespace llvm; namespace llvm { - -JITIndirections makeCallsSingleIndirect( - Module &M, const std::function &ShouldIndirect, - const char *JITImplSuffix, const char *JITAddrSuffix) { - std::vector Worklist; - std::vector FuncNames; - - for (auto &F : M) - if (ShouldIndirect(F) && (F.user_begin() != F.user_end())) { - Worklist.push_back(&F); - FuncNames.push_back(F.getName()); - } - - for (auto *F : Worklist) { - GlobalVariable *FImplAddr = new GlobalVariable( - M, F->getType(), false, GlobalValue::ExternalLinkage, - Constant::getNullValue(F->getType()), F->getName() + JITAddrSuffix, - nullptr, GlobalValue::NotThreadLocal, 0, true); - FImplAddr->setVisibility(GlobalValue::HiddenVisibility); - - for (auto *U : F->users()) { - assert(isa(U) && "Cannot indirect non-instruction use"); - IRBuilder<> Builder(cast(U)); - U->replaceUsesOfWith(F, Builder.CreateLoad(FImplAddr)); - } - } - - return JITIndirections( - FuncNames, [=](StringRef S) -> std::string { return std::string(S); }, - [=](StringRef S) - -> std::string { return std::string(S) + JITAddrSuffix; }); +namespace orc { + +GlobalVariable* createImplPointer(Function &F, const Twine &Name, + Constant *Initializer) { + assert(F.getParent() && "Function isn't in a module."); + if (!Initializer) + Initializer = Constant::getNullValue(F.getType()); + Module &M = *F.getParent(); + return new GlobalVariable(M, F.getType(), false, GlobalValue::ExternalLinkage, + Initializer, Name, nullptr, + GlobalValue::NotThreadLocal, 0, true); } -JITIndirections makeCallsDoubleIndirect( - Module &M, const std::function &ShouldIndirect, - const char *JITImplSuffix, const char *JITAddrSuffix) { - - std::vector Worklist; - std::vector FuncNames; - - for (auto &F : M) - if (!F.isDeclaration() && !F.hasAvailableExternallyLinkage() && - ShouldIndirect(F)) - Worklist.push_back(&F); - - for (auto *F : Worklist) { - std::string OrigName = F->getName(); - F->setName(OrigName + JITImplSuffix); - FuncNames.push_back(OrigName); - - GlobalVariable *FImplAddr = new GlobalVariable( - M, F->getType(), false, GlobalValue::ExternalLinkage, - Constant::getNullValue(F->getType()), OrigName + JITAddrSuffix, nullptr, - GlobalValue::NotThreadLocal, 0, true); - FImplAddr->setVisibility(GlobalValue::HiddenVisibility); +void makeStub(Function &F, GlobalVariable &ImplPointer) { + assert(F.isDeclaration() && "Can't turn a definition into a stub."); + assert(F.getParent() && "Function isn't in a module."); + Module &M = *F.getParent(); + BasicBlock *EntryBlock = BasicBlock::Create(M.getContext(), "entry", &F); + IRBuilder<> Builder(EntryBlock); + LoadInst *ImplAddr = Builder.CreateLoad(&ImplPointer); + std::vector CallArgs; + for (auto &A : F.args()) + CallArgs.push_back(&A); + CallInst *Call = Builder.CreateCall(ImplAddr, CallArgs); + Call->setTailCall(); + Builder.CreateRet(Call); +} - Function *FRedirect = - Function::Create(F->getFunctionType(), F->getLinkage(), OrigName, &M); +void partition(Module &M, const ModulePartitionMap &PMap) { - F->replaceAllUsesWith(FRedirect); + for (auto &KVPair : PMap) { - BasicBlock *EntryBlock = - BasicBlock::Create(M.getContext(), "entry", FRedirect); + auto ExtractGlobalVars = + [&](GlobalVariable &New, const GlobalVariable &Orig, + ValueToValueMapTy &VMap) { + if (KVPair.second.count(&Orig)) { + copyGVInitializer(New, Orig, VMap); + } + if (New.getLinkage() == GlobalValue::PrivateLinkage) { + New.setLinkage(GlobalValue::ExternalLinkage); + New.setVisibility(GlobalValue::HiddenVisibility); + } + }; - IRBuilder<> Builder(EntryBlock); - LoadInst *FImplLoadedAddr = Builder.CreateLoad(FImplAddr); + auto ExtractFunctions = + [&](Function &New, const Function &Orig, ValueToValueMapTy &VMap) { + if (KVPair.second.count(&Orig)) + copyFunctionBody(New, Orig, VMap); + if (New.getLinkage() == GlobalValue::InternalLinkage) { + New.setLinkage(GlobalValue::ExternalLinkage); + New.setVisibility(GlobalValue::HiddenVisibility); + } + }; - std::vector CallArgs; - for (Value &Arg : FRedirect->args()) - CallArgs.push_back(&Arg); - CallInst *Call = Builder.CreateCall(FImplLoadedAddr, CallArgs); - Call->setTailCall(); - Builder.CreateRet(Call); + CloneSubModule(*KVPair.first, M, ExtractGlobalVars, ExtractFunctions, + false); } - - return JITIndirections( - FuncNames, [=](StringRef S) - -> std::string { return std::string(S) + JITImplSuffix; }, - [=](StringRef S) - -> std::string { return std::string(S) + JITAddrSuffix; }); } -std::vector> -explode(const Module &OrigMod, - const std::function &ShouldExtract) { - - std::vector> NewModules; +FullyPartitionedModule fullyPartition(Module &M) { + FullyPartitionedModule MP; - // Split all the globals, non-indirected functions, etc. into a single module. - auto ExtractGlobalVars = [&](GlobalVariable &New, const GlobalVariable &Orig, - ValueToValueMapTy &VMap) { - copyGVInitializer(New, Orig, VMap); - if (New.getLinkage() == GlobalValue::PrivateLinkage) { - New.setLinkage(GlobalValue::ExternalLinkage); - New.setVisibility(GlobalValue::HiddenVisibility); - } - }; + ModulePartitionMap PMap; - auto ExtractNonImplFunctions = - [&](Function &New, const Function &Orig, ValueToValueMapTy &VMap) { - if (!ShouldExtract(New)) - copyFunctionBody(New, Orig, VMap); - }; + for (auto &F : M) { - NewModules.push_back(CloneSubModule(OrigMod, ExtractGlobalVars, - ExtractNonImplFunctions, true)); - - // Preserve initializers for Common linkage vars, and make private linkage - // globals external: they are now provided by the globals module extracted - // above. - auto DropGlobalVars = [&](GlobalVariable &New, const GlobalVariable &Orig, - ValueToValueMapTy &VMap) { - if (New.getLinkage() == GlobalValue::CommonLinkage) - copyGVInitializer(New, Orig, VMap); - else if (New.getLinkage() == GlobalValue::PrivateLinkage) - New.setLinkage(GlobalValue::ExternalLinkage); - }; - - // Split each 'impl' function out in to its own module. - for (const auto &Func : OrigMod) { - if (Func.isDeclaration() || !ShouldExtract(Func)) + if (F.isDeclaration()) continue; - auto ExtractNamedFunction = - [&](Function &New, const Function &Orig, ValueToValueMapTy &VMap) { - if (New.getName() == Func.getName()) - copyFunctionBody(New, Orig, VMap); - }; - - NewModules.push_back( - CloneSubModule(OrigMod, DropGlobalVars, ExtractNamedFunction, false)); + std::string NewModuleName = (M.getName() + "." + F.getName()).str(); + MP.Functions.push_back( + llvm::make_unique(NewModuleName, M.getContext())); + MP.Functions.back()->setDataLayout(M.getDataLayout()); + PMap[MP.Functions.back().get()].insert(&F); } - return NewModules; -} + MP.GlobalVars = + llvm::make_unique((M.getName() + ".globals_and_stubs").str(), + M.getContext()); + MP.GlobalVars->setDataLayout(M.getDataLayout()); -std::vector> -explode(const Module &OrigMod, const JITIndirections &Indirections) { - std::set ImplNames; + MP.Commons = + llvm::make_unique((M.getName() + ".commons").str(), M.getContext()); + MP.Commons->setDataLayout(M.getDataLayout()); - for (const auto &FuncName : Indirections.IndirectedNames) - ImplNames.insert(Indirections.GetImplName(FuncName)); + // 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); - return explode( - OrigMod, [&](const Function &F) { return ImplNames.count(F.getName()); }); -} + partition(M, PMap); + + return MP; } + +} // End namespace orc. +} // End namespace llvm.