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

Generated by: LCOV version 1.13