LCOV - code coverage report
Current view: top level - lib/ExecutionEngine/Orc - IndirectionUtils.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 86 136 63.2 %
Date: 2018-09-23 13:06:45 Functions: 15 22 68.2 %
Legend: Lines: hit not hit

          Line data    Source code
       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/ExecutionEngine/Orc/IndirectionUtils.h"
      11             : #include "llvm/ADT/STLExtras.h"
      12             : #include "llvm/ADT/Triple.h"
      13             : #include "llvm/ExecutionEngine/Orc/OrcABISupport.h"
      14             : #include "llvm/IR/CallSite.h"
      15             : #include "llvm/IR/IRBuilder.h"
      16             : #include "llvm/Support/Format.h"
      17             : #include "llvm/Transforms/Utils/Cloning.h"
      18             : #include <sstream>
      19             : 
      20             : using namespace llvm;
      21             : using namespace llvm::orc;
      22             : 
      23             : namespace {
      24             : 
      25           0 : class CompileCallbackMaterializationUnit : public orc::MaterializationUnit {
      26             : public:
      27             :   using CompileFunction = JITCompileCallbackManager::CompileFunction;
      28             : 
      29          20 :   CompileCallbackMaterializationUnit(SymbolStringPtr Name,
      30             :                                      CompileFunction Compile)
      31          80 :       : MaterializationUnit(SymbolFlagsMap({{Name, JITSymbolFlags::Exported}})),
      32          40 :         Name(std::move(Name)), Compile(std::move(Compile)) {}
      33             : 
      34             : private:
      35          19 :   void materialize(MaterializationResponsibility R) {
      36             :     SymbolMap Result;
      37          19 :     Result[Name] = JITEvaluatedSymbol(Compile(), JITSymbolFlags::Exported);
      38          19 :     R.resolve(Result);
      39          19 :     R.emit();
      40          19 :   }
      41             : 
      42           0 :   void discard(const JITDylib &JD, SymbolStringPtr Name) {
      43           0 :     llvm_unreachable("Discard should never occur on a LMU?");
      44             :   }
      45             : 
      46             :   SymbolStringPtr Name;
      47             :   CompileFunction Compile;
      48             : };
      49             : 
      50             : } // namespace
      51             : 
      52             : namespace llvm {
      53             : namespace orc {
      54             : 
      55           0 : void JITCompileCallbackManager::anchor() {}
      56           0 : void IndirectStubsManager::anchor() {}
      57             : 
      58             : Expected<JITTargetAddress>
      59          20 : JITCompileCallbackManager::getCompileCallback(CompileFunction Compile) {
      60          20 :   if (auto TrampolineAddr = getAvailableTrampolineAddr()) {
      61          20 :     auto CallbackName = ES.getSymbolStringPool().intern(
      62          20 :         std::string("cc") + std::to_string(++NextCallbackId));
      63             : 
      64          20 :     std::lock_guard<std::mutex> Lock(CCMgrMutex);
      65          20 :     AddrToSymbol[*TrampolineAddr] = CallbackName;
      66          40 :     cantFail(CallbacksJD.define(
      67          40 :         llvm::make_unique<CompileCallbackMaterializationUnit>(
      68             :             std::move(CallbackName), std::move(Compile))));
      69             :     return *TrampolineAddr;
      70             :   } else
      71             :     return TrampolineAddr.takeError();
      72             : }
      73             : 
      74          19 : JITTargetAddress JITCompileCallbackManager::executeCompileCallback(
      75             :     JITTargetAddress TrampolineAddr) {
      76          19 :   SymbolStringPtr Name;
      77             : 
      78             :   {
      79          19 :     std::unique_lock<std::mutex> Lock(CCMgrMutex);
      80             :     auto I = AddrToSymbol.find(TrampolineAddr);
      81             : 
      82             :     // If this address is not associated with a compile callback then report an
      83             :     // error to the execution session and return ErrorHandlerAddress to the
      84             :     // callee.
      85          19 :     if (I == AddrToSymbol.end()) {
      86           0 :       Lock.unlock();
      87             :       std::string ErrMsg;
      88             :       {
      89           0 :         raw_string_ostream ErrMsgStream(ErrMsg);
      90           0 :         ErrMsgStream << "No compile callback for trampoline at "
      91           0 :                      << format("0x%016x", TrampolineAddr);
      92             :       }
      93           0 :       ES.reportError(
      94           0 :           make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode()));
      95           0 :       return ErrorHandlerAddress;
      96             :     } else
      97          19 :       Name = I->second;
      98             :   }
      99             : 
     100          76 :   if (auto Sym = lookup({&CallbacksJD}, Name))
     101          19 :     return Sym->getAddress();
     102             :   else {
     103             :     // If anything goes wrong materializing Sym then report it to the session
     104             :     // and return the ErrorHandlerAddress;
     105           0 :     ES.reportError(Sym.takeError());
     106           0 :     return ErrorHandlerAddress;
     107             :   }
     108             : }
     109             : 
     110             : std::unique_ptr<JITCompileCallbackManager>
     111          21 : createLocalCompileCallbackManager(const Triple &T, ExecutionSession &ES,
     112             :                                   JITTargetAddress ErrorHandlerAddress) {
     113          21 :   switch (T.getArch()) {
     114             :     default: return nullptr;
     115             : 
     116           0 :     case Triple::aarch64: {
     117             :       typedef orc::LocalJITCompileCallbackManager<orc::OrcAArch64> CCMgrT;
     118             :       return llvm::make_unique<CCMgrT>(ES, ErrorHandlerAddress);
     119             :     }
     120             : 
     121           0 :     case Triple::x86: {
     122             :       typedef orc::LocalJITCompileCallbackManager<orc::OrcI386> CCMgrT;
     123             :       return llvm::make_unique<CCMgrT>(ES, ErrorHandlerAddress);
     124             :     }
     125             : 
     126           0 :     case Triple::mips: {
     127             :       typedef orc::LocalJITCompileCallbackManager<orc::OrcMips32Be> CCMgrT;
     128             :       return llvm::make_unique<CCMgrT>(ES, ErrorHandlerAddress);
     129             :     }
     130           0 :     case Triple::mipsel: {
     131             :       typedef orc::LocalJITCompileCallbackManager<orc::OrcMips32Le> CCMgrT;
     132             :       return llvm::make_unique<CCMgrT>(ES, ErrorHandlerAddress);
     133             :     }
     134             :  
     135           0 :     case Triple::mips64:
     136             :     case Triple::mips64el: {
     137             :       typedef orc::LocalJITCompileCallbackManager<orc::OrcMips64> CCMgrT;
     138             :       return llvm::make_unique<CCMgrT>(ES, ErrorHandlerAddress);
     139             :     }
     140             :  
     141          21 :     case Triple::x86_64: {
     142          21 :       if ( T.getOS() == Triple::OSType::Win32 ) {
     143             :         typedef orc::LocalJITCompileCallbackManager<orc::OrcX86_64_Win32> CCMgrT;
     144             :         return llvm::make_unique<CCMgrT>(ES, ErrorHandlerAddress);
     145             :       } else {
     146             :         typedef orc::LocalJITCompileCallbackManager<orc::OrcX86_64_SysV> CCMgrT;
     147             :         return llvm::make_unique<CCMgrT>(ES, ErrorHandlerAddress);
     148             :       }
     149             :     }
     150             : 
     151             :   }
     152             : }
     153             : 
     154             : std::function<std::unique_ptr<IndirectStubsManager>()>
     155          14 : createLocalIndirectStubsManagerBuilder(const Triple &T) {
     156          14 :   switch (T.getArch()) {
     157             :     default:
     158             :       return [](){
     159             :         return llvm::make_unique<
     160           0 :                        orc::LocalIndirectStubsManager<orc::OrcGenericABI>>();
     161             :       };
     162             : 
     163             :     case Triple::aarch64:
     164             :       return [](){
     165             :         return llvm::make_unique<
     166           0 :                        orc::LocalIndirectStubsManager<orc::OrcAArch64>>();
     167             :       };
     168             : 
     169             :     case Triple::x86:
     170             :       return [](){
     171             :         return llvm::make_unique<
     172           0 :                        orc::LocalIndirectStubsManager<orc::OrcI386>>();
     173             :       };
     174             : 
     175             :     case Triple::mips:
     176             :       return [](){
     177             :           return llvm::make_unique<
     178           0 :                       orc::LocalIndirectStubsManager<orc::OrcMips32Be>>();
     179             :       };
     180             : 
     181             :     case Triple::mipsel:
     182             :       return [](){
     183             :           return llvm::make_unique<
     184           0 :                       orc::LocalIndirectStubsManager<orc::OrcMips32Le>>();
     185             :       };
     186             : 
     187             :     case Triple::mips64:
     188             :     case Triple::mips64el:
     189             :       return [](){
     190             :           return llvm::make_unique<
     191           0 :                       orc::LocalIndirectStubsManager<orc::OrcMips64>>();
     192             :       };
     193             :       
     194          14 :     case Triple::x86_64:
     195          14 :       if (T.getOS() == Triple::OSType::Win32) {
     196             :         return [](){
     197             :           return llvm::make_unique<
     198           0 :                      orc::LocalIndirectStubsManager<orc::OrcX86_64_Win32>>();
     199             :         };
     200             :       } else {
     201             :         return [](){
     202             :           return llvm::make_unique<
     203          14 :                      orc::LocalIndirectStubsManager<orc::OrcX86_64_SysV>>();
     204             :         };
     205             :       }
     206             : 
     207             :   }
     208             : }
     209             : 
     210           0 : Constant* createIRTypedAddress(FunctionType &FT, JITTargetAddress Addr) {
     211             :   Constant *AddrIntVal =
     212           0 :     ConstantInt::get(Type::getInt64Ty(FT.getContext()), Addr);
     213             :   Constant *AddrPtrVal =
     214           0 :     ConstantExpr::getCast(Instruction::IntToPtr, AddrIntVal,
     215           0 :                           PointerType::get(&FT, 0));
     216           0 :   return AddrPtrVal;
     217             : }
     218             : 
     219           1 : GlobalVariable* createImplPointer(PointerType &PT, Module &M,
     220             :                                   const Twine &Name, Constant *Initializer) {
     221             :   auto IP = new GlobalVariable(M, &PT, false, GlobalValue::ExternalLinkage,
     222             :                                Initializer, Name, nullptr,
     223           1 :                                GlobalValue::NotThreadLocal, 0, true);
     224             :   IP->setVisibility(GlobalValue::HiddenVisibility);
     225           1 :   return IP;
     226             : }
     227             : 
     228           1 : void makeStub(Function &F, Value &ImplPointer) {
     229             :   assert(F.isDeclaration() && "Can't turn a definition into a stub.");
     230             :   assert(F.getParent() && "Function isn't in a module.");
     231           1 :   Module &M = *F.getParent();
     232           2 :   BasicBlock *EntryBlock = BasicBlock::Create(M.getContext(), "entry", &F);
     233             :   IRBuilder<> Builder(EntryBlock);
     234           1 :   LoadInst *ImplAddr = Builder.CreateLoad(&ImplPointer);
     235             :   std::vector<Value*> CallArgs;
     236           3 :   for (auto &A : F.args())
     237           2 :     CallArgs.push_back(&A);
     238           1 :   CallInst *Call = Builder.CreateCall(ImplAddr, CallArgs);
     239             :   Call->setTailCall();
     240             :   Call->setAttributes(F.getAttributes());
     241           1 :   if (F.getReturnType()->isVoidTy())
     242           1 :     Builder.CreateRetVoid();
     243             :   else
     244           0 :     Builder.CreateRet(Call);
     245           1 : }
     246             : 
     247             : // Utility class for renaming global values and functions during partitioning.
     248             : class GlobalRenamer {
     249             : public:
     250             : 
     251          14 :   static bool needsRenaming(const Value &New) {
     252           7 :     return !New.hasName() || New.getName().startswith("\01L");
     253             :   }
     254             : 
     255           2 :   const std::string& getRename(const Value &Orig) {
     256             :     // See if we have a name for this global.
     257             :     {
     258           2 :       auto I = Names.find(&Orig);
     259           2 :       if (I != Names.end())
     260           0 :         return I->second;
     261             :     }
     262             : 
     263             :     // Nope. Create a new one.
     264             :     // FIXME: Use a more robust uniquing scheme. (This may blow up if the user
     265             :     //        writes a "__orc_anon[[:digit:]]* method).
     266             :     unsigned ID = Names.size();
     267           2 :     std::ostringstream NameStream;
     268             :     NameStream << "__orc_anon" << ID++;
     269           2 :     auto I = Names.insert(std::make_pair(&Orig, NameStream.str()));
     270           2 :     return I.first->second;
     271             :   }
     272             : private:
     273             :   DenseMap<const Value*, std::string> Names;
     274             : };
     275             : 
     276          41 : static void raiseVisibilityOnValue(GlobalValue &V, GlobalRenamer &R) {
     277             :   if (V.hasLocalLinkage()) {
     278           7 :     if (R.needsRenaming(V))
     279           2 :       V.setName(R.getRename(V));
     280             :     V.setLinkage(GlobalValue::ExternalLinkage);
     281             :     V.setVisibility(GlobalValue::HiddenVisibility);
     282             :   }
     283             :   V.setUnnamedAddr(GlobalValue::UnnamedAddr::None);
     284             :   assert(!R.needsRenaming(V) && "Invalid global name.");
     285          41 : }
     286             : 
     287          13 : void makeAllSymbolsExternallyAccessible(Module &M) {
     288             :   GlobalRenamer Renamer;
     289             : 
     290          43 :   for (auto &F : M)
     291          30 :     raiseVisibilityOnValue(F, Renamer);
     292             : 
     293          22 :   for (auto &GV : M.globals())
     294           9 :     raiseVisibilityOnValue(GV, Renamer);
     295             : 
     296          15 :   for (auto &A : M.aliases())
     297           2 :     raiseVisibilityOnValue(A, Renamer);
     298          13 : }
     299             : 
     300          21 : Function* cloneFunctionDecl(Module &Dst, const Function &F,
     301             :                             ValueToValueMapTy *VMap) {
     302             :   Function *NewF =
     303          21 :     Function::Create(cast<FunctionType>(F.getValueType()),
     304          21 :                      F.getLinkage(), F.getName(), &Dst);
     305          21 :   NewF->copyAttributesFrom(&F);
     306             : 
     307          21 :   if (VMap) {
     308           1 :     (*VMap)[&F] = NewF;
     309             :     auto NewArgI = NewF->arg_begin();
     310           3 :     for (auto ArgI = F.arg_begin(), ArgE = F.arg_end(); ArgI != ArgE;
     311             :          ++ArgI, ++NewArgI)
     312           2 :       (*VMap)[&*ArgI] = &*NewArgI;
     313             :   }
     314             : 
     315          21 :   return NewF;
     316             : }
     317             : 
     318           1 : void moveFunctionBody(Function &OrigF, ValueToValueMapTy &VMap,
     319             :                       ValueMaterializer *Materializer,
     320             :                       Function *NewF) {
     321             :   assert(!OrigF.isDeclaration() && "Nothing to move");
     322           1 :   if (!NewF)
     323           1 :     NewF = cast<Function>(VMap[&OrigF]);
     324             :   else
     325             :     assert(VMap[&OrigF] == NewF && "Incorrect function mapping in VMap.");
     326             :   assert(NewF && "Function mapping missing from VMap.");
     327             :   assert(NewF->getParent() != OrigF.getParent() &&
     328             :          "moveFunctionBody should only be used to move bodies between "
     329             :          "modules.");
     330             : 
     331             :   SmallVector<ReturnInst *, 8> Returns; // Ignore returns cloned.
     332           1 :   CloneFunctionInto(NewF, &OrigF, VMap, /*ModuleLevelChanges=*/true, Returns,
     333             :                     "", nullptr, nullptr, Materializer);
     334             :   OrigF.deleteBody();
     335           1 : }
     336             : 
     337           1 : GlobalVariable* cloneGlobalVariableDecl(Module &Dst, const GlobalVariable &GV,
     338             :                                         ValueToValueMapTy *VMap) {
     339             :   GlobalVariable *NewGV = new GlobalVariable(
     340           2 :       Dst, GV.getValueType(), GV.isConstant(),
     341           1 :       GV.getLinkage(), nullptr, GV.getName(), nullptr,
     342           1 :       GV.getThreadLocalMode(), GV.getType()->getAddressSpace());
     343           1 :   NewGV->copyAttributesFrom(&GV);
     344           1 :   if (VMap)
     345           0 :     (*VMap)[&GV] = NewGV;
     346           1 :   return NewGV;
     347             : }
     348             : 
     349           0 : void moveGlobalVariableInitializer(GlobalVariable &OrigGV,
     350             :                                    ValueToValueMapTy &VMap,
     351             :                                    ValueMaterializer *Materializer,
     352             :                                    GlobalVariable *NewGV) {
     353             :   assert(OrigGV.hasInitializer() && "Nothing to move");
     354           0 :   if (!NewGV)
     355           0 :     NewGV = cast<GlobalVariable>(VMap[&OrigGV]);
     356             :   else
     357             :     assert(VMap[&OrigGV] == NewGV &&
     358             :            "Incorrect global variable mapping in VMap.");
     359             :   assert(NewGV->getParent() != OrigGV.getParent() &&
     360             :          "moveGlobalVariableInitializer should only be used to move "
     361             :          "initializers between modules");
     362             : 
     363           0 :   NewGV->setInitializer(MapValue(OrigGV.getInitializer(), VMap, RF_None,
     364             :                                  nullptr, Materializer));
     365           0 : }
     366             : 
     367           0 : GlobalAlias* cloneGlobalAliasDecl(Module &Dst, const GlobalAlias &OrigA,
     368             :                                   ValueToValueMapTy &VMap) {
     369             :   assert(OrigA.getAliasee() && "Original alias doesn't have an aliasee?");
     370           0 :   auto *NewA = GlobalAlias::create(OrigA.getValueType(),
     371             :                                    OrigA.getType()->getPointerAddressSpace(),
     372           0 :                                    OrigA.getLinkage(), OrigA.getName(), &Dst);
     373           0 :   NewA->copyAttributesFrom(&OrigA);
     374           0 :   VMap[&OrigA] = NewA;
     375           0 :   return NewA;
     376             : }
     377             : 
     378           0 : void cloneModuleFlagsMetadata(Module &Dst, const Module &Src,
     379             :                               ValueToValueMapTy &VMap) {
     380           0 :   auto *MFs = Src.getModuleFlagsMetadata();
     381           0 :   if (!MFs)
     382             :     return;
     383           0 :   for (auto *MF : MFs->operands())
     384           0 :     Dst.addModuleFlag(MapMetadata(MF, VMap));
     385             : }
     386             : 
     387             : } // End namespace orc.
     388             : } // End namespace llvm.

Generated by: LCOV version 1.13