LCOV - code coverage report
Current view: top level - lib/ExecutionEngine/Orc - LazyReexports.cpp (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 57 88 64.8 %
Date: 2018-10-20 13:21:21 Functions: 7 10 70.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===---------- LazyReexports.cpp - Utilities for lazy reexports ----------===//
       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/LazyReexports.h"
      11             : 
      12             : #include "llvm/ADT/Triple.h"
      13             : #include "llvm/ExecutionEngine/Orc/OrcABISupport.h"
      14             : 
      15             : #define DEBUG_TYPE "orc"
      16             : 
      17             : namespace llvm {
      18             : namespace orc {
      19             : 
      20           0 : void LazyCallThroughManager::NotifyResolvedFunction::anchor() {}
      21             : 
      22          14 : LazyCallThroughManager::LazyCallThroughManager(
      23             :     ExecutionSession &ES, JITTargetAddress ErrorHandlerAddr,
      24          14 :     std::unique_ptr<TrampolinePool> TP)
      25          28 :     : ES(ES), ErrorHandlerAddr(ErrorHandlerAddr), TP(std::move(TP)) {}
      26             : 
      27          20 : Expected<JITTargetAddress> LazyCallThroughManager::getCallThroughTrampoline(
      28             :     JITDylib &SourceJD, SymbolStringPtr SymbolName,
      29             :     std::shared_ptr<NotifyResolvedFunction> NotifyResolved) {
      30          20 :   std::lock_guard<std::mutex> Lock(LCTMMutex);
      31          20 :   auto Trampoline = TP->getTrampoline();
      32             : 
      33          20 :   if (!Trampoline)
      34             :     return Trampoline.takeError();
      35             : 
      36          20 :   Reexports[*Trampoline] = std::make_pair(&SourceJD, std::move(SymbolName));
      37          20 :   Notifiers[*Trampoline] = std::move(NotifyResolved);
      38             :   return *Trampoline;
      39             : }
      40             : 
      41             : JITTargetAddress
      42          20 : LazyCallThroughManager::callThroughToSymbol(JITTargetAddress TrampolineAddr) {
      43             :   JITDylib *SourceJD = nullptr;
      44          20 :   SymbolStringPtr SymbolName;
      45             : 
      46             :   {
      47          20 :     std::lock_guard<std::mutex> Lock(LCTMMutex);
      48             :     auto I = Reexports.find(TrampolineAddr);
      49          20 :     if (I == Reexports.end())
      50           0 :       return ErrorHandlerAddr;
      51          20 :     SourceJD = I->second.first;
      52          20 :     SymbolName = I->second.second;
      53             :   }
      54             : 
      55          20 :   auto LookupResult = ES.lookup({SourceJD}, {SymbolName},
      56         100 :                                 NoDependenciesToRegister, true, nullptr, true);
      57             : 
      58          20 :   if (!LookupResult) {
      59           0 :     ES.reportError(LookupResult.takeError());
      60           0 :     return ErrorHandlerAddr;
      61             :   }
      62             : 
      63             :   assert(LookupResult->size() == 1 && "Unexpected number of results");
      64             :   assert(LookupResult->count(SymbolName) && "Unexpected result");
      65             : 
      66          20 :   auto ResolvedAddr = LookupResult->begin()->second.getAddress();
      67             : 
      68             :   std::shared_ptr<NotifyResolvedFunction> NotifyResolved = nullptr;
      69             :   {
      70             :     std::lock_guard<std::mutex> Lock(LCTMMutex);
      71             :     auto I = Notifiers.find(TrampolineAddr);
      72          20 :     if (I != Notifiers.end()) {
      73             :       NotifyResolved = I->second;
      74             :       Notifiers.erase(I);
      75             :     }
      76             :   }
      77             : 
      78          20 :   if (NotifyResolved) {
      79          38 :     if (auto Err = (*NotifyResolved)(*SourceJD, SymbolName, ResolvedAddr)) {
      80           0 :       ES.reportError(std::move(Err));
      81           0 :       return ErrorHandlerAddr;
      82             :     }
      83             :   }
      84             : 
      85             :   return ResolvedAddr;
      86             : }
      87             : 
      88             : Expected<std::unique_ptr<LazyCallThroughManager>>
      89          14 : createLocalLazyCallThroughManager(const Triple &T, ExecutionSession &ES,
      90             :                                   JITTargetAddress ErrorHandlerAddr) {
      91          14 :   switch (T.getArch()) {
      92           0 :   default:
      93           0 :     return make_error<StringError>(
      94           0 :         std::string("No callback manager available for ") + T.str(),
      95           0 :         inconvertibleErrorCode());
      96             : 
      97           0 :   case Triple::aarch64:
      98           0 :     return LocalLazyCallThroughManager::Create<OrcAArch64>(ES,
      99             :                                                            ErrorHandlerAddr);
     100             : 
     101           0 :   case Triple::x86:
     102           0 :     return LocalLazyCallThroughManager::Create<OrcI386>(ES, ErrorHandlerAddr);
     103             : 
     104           0 :   case Triple::mips:
     105           0 :     return LocalLazyCallThroughManager::Create<OrcMips32Be>(ES,
     106             :                                                             ErrorHandlerAddr);
     107             : 
     108           0 :   case Triple::mipsel:
     109           0 :     return LocalLazyCallThroughManager::Create<OrcMips32Le>(ES,
     110             :                                                             ErrorHandlerAddr);
     111             : 
     112           0 :   case Triple::mips64:
     113             :   case Triple::mips64el:
     114           0 :     return LocalLazyCallThroughManager::Create<OrcMips64>(ES, ErrorHandlerAddr);
     115             : 
     116          14 :   case Triple::x86_64:
     117          14 :     if (T.getOS() == Triple::OSType::Win32)
     118           0 :       return LocalLazyCallThroughManager::Create<OrcX86_64_Win32>(
     119             :           ES, ErrorHandlerAddr);
     120             :     else
     121          28 :       return LocalLazyCallThroughManager::Create<OrcX86_64_SysV>(
     122             :           ES, ErrorHandlerAddr);
     123             :   }
     124             : }
     125             : 
     126          22 : LazyReexportsMaterializationUnit::LazyReexportsMaterializationUnit(
     127             :     LazyCallThroughManager &LCTManager, IndirectStubsManager &ISManager,
     128          22 :     JITDylib &SourceJD, SymbolAliasMap CallableAliases, VModuleKey K)
     129          22 :     : MaterializationUnit(extractFlags(CallableAliases), std::move(K)),
     130             :       LCTManager(LCTManager), ISManager(ISManager), SourceJD(SourceJD),
     131             :       CallableAliases(std::move(CallableAliases)),
     132          22 :       NotifyResolved(LazyCallThroughManager::createNotifyResolvedFunction(
     133             :           [&ISManager](JITDylib &JD, const SymbolStringPtr &SymbolName,
     134             :                        JITTargetAddress ResolvedAddr) {
     135          36 :             return ISManager.updatePointer(*SymbolName, ResolvedAddr);
     136          22 :           })) {}
     137             : 
     138           0 : StringRef LazyReexportsMaterializationUnit::getName() const {
     139           0 :   return "<Lazy Reexports>";
     140             : }
     141             : 
     142          19 : void LazyReexportsMaterializationUnit::materialize(
     143             :     MaterializationResponsibility R) {
     144          19 :   auto RequestedSymbols = R.getRequestedSymbols();
     145             : 
     146             :   SymbolAliasMap RequestedAliases;
     147          38 :   for (auto &RequestedSymbol : RequestedSymbols) {
     148          19 :     auto I = CallableAliases.find(RequestedSymbol);
     149             :     assert(I != CallableAliases.end() && "Symbol not found in alias map?");
     150          19 :     RequestedAliases[I->first] = std::move(I->second);
     151          19 :     CallableAliases.erase(I);
     152             :   }
     153             : 
     154          19 :   if (!CallableAliases.empty())
     155          27 :     R.replace(lazyReexports(LCTManager, ISManager, SourceJD,
     156             :                             std::move(CallableAliases)));
     157             : 
     158          19 :   IndirectStubsManager::StubInitsMap StubInits;
     159          57 :   for (auto &Alias : RequestedAliases) {
     160             : 
     161          19 :     auto CallThroughTrampoline = LCTManager.getCallThroughTrampoline(
     162          38 :         SourceJD, Alias.second.Aliasee, NotifyResolved);
     163             : 
     164          19 :     if (!CallThroughTrampoline) {
     165           0 :       SourceJD.getExecutionSession().reportError(
     166           0 :           CallThroughTrampoline.takeError());
     167           0 :       R.failMaterialization();
     168             :       return;
     169             :     }
     170             : 
     171          19 :     StubInits[*Alias.first] =
     172          19 :         std::make_pair(*CallThroughTrampoline, Alias.second.AliasFlags);
     173             :   }
     174             : 
     175          38 :   if (auto Err = ISManager.createStubs(StubInits)) {
     176           0 :     SourceJD.getExecutionSession().reportError(std::move(Err));
     177           0 :     R.failMaterialization();
     178             :     return;
     179             :   }
     180             : 
     181             :   SymbolMap Stubs;
     182          57 :   for (auto &Alias : RequestedAliases)
     183          38 :     Stubs[Alias.first] = ISManager.findStub(*Alias.first, false);
     184             : 
     185          19 :   R.resolve(Stubs);
     186          19 :   R.emit();
     187             : }
     188             : 
     189           0 : void LazyReexportsMaterializationUnit::discard(const JITDylib &JD,
     190             :                                                const SymbolStringPtr &Name) {
     191             :   assert(CallableAliases.count(Name) &&
     192             :          "Symbol not covered by this MaterializationUnit");
     193           0 :   CallableAliases.erase(Name);
     194           0 : }
     195             : 
     196             : SymbolFlagsMap
     197          22 : LazyReexportsMaterializationUnit::extractFlags(const SymbolAliasMap &Aliases) {
     198             :   SymbolFlagsMap SymbolFlags;
     199          78 :   for (auto &KV : Aliases) {
     200             :     assert(KV.second.AliasFlags.isCallable() &&
     201             :            "Lazy re-exports must be callable symbols");
     202          34 :     SymbolFlags[KV.first] = KV.second.AliasFlags;
     203             :   }
     204          22 :   return SymbolFlags;
     205             : }
     206             : 
     207             : } // End namespace orc.
     208             : } // End namespace llvm.

Generated by: LCOV version 1.13