Home | History | Annotate | Download | only in Orc
      1 //===-- RTDyldObjectLinkingLayer.cpp - RuntimeDyld backed ORC ObjectLayer -===//
      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/RTDyldObjectLinkingLayer.h"
     11 
     12 namespace {
     13 
     14 using namespace llvm;
     15 using namespace llvm::orc;
     16 
     17 class VSOSearchOrderResolver : public JITSymbolResolver {
     18 public:
     19   VSOSearchOrderResolver(MaterializationResponsibility &MR) : MR(MR) {}
     20 
     21   Expected<LookupResult> lookup(const LookupSet &Symbols) {
     22     auto &ES = MR.getTargetVSO().getExecutionSession();
     23     SymbolNameSet InternedSymbols;
     24 
     25     for (auto &S : Symbols)
     26       InternedSymbols.insert(ES.getSymbolStringPool().intern(S));
     27 
     28     auto RegisterDependencies = [&](const SymbolDependenceMap &Deps) {
     29       MR.addDependenciesForAll(Deps);
     30     };
     31 
     32     auto InternedResult =
     33         MR.getTargetVSO().withSearchOrderDo([&](const VSOList &VSOs) {
     34           return ES.lookup(VSOs, InternedSymbols, RegisterDependencies, false);
     35         });
     36 
     37     if (!InternedResult)
     38       return InternedResult.takeError();
     39 
     40     LookupResult Result;
     41     for (auto &KV : *InternedResult)
     42       Result[*KV.first] = std::move(KV.second);
     43 
     44     return Result;
     45   }
     46 
     47   Expected<LookupFlagsResult> lookupFlags(const LookupSet &Symbols) {
     48     auto &ES = MR.getTargetVSO().getExecutionSession();
     49 
     50     SymbolNameSet InternedSymbols;
     51 
     52     for (auto &S : Symbols)
     53       InternedSymbols.insert(ES.getSymbolStringPool().intern(S));
     54 
     55     SymbolFlagsMap InternedResult;
     56     MR.getTargetVSO().withSearchOrderDo([&](const VSOList &VSOs) {
     57       // An empty search order is pathalogical, but allowed.
     58       if (VSOs.empty())
     59         return;
     60 
     61       assert(VSOs.front() && "VSOList entry can not be null");
     62       InternedResult = VSOs.front()->lookupFlags(InternedSymbols);
     63     });
     64 
     65     LookupFlagsResult Result;
     66     for (auto &KV : InternedResult)
     67       Result[*KV.first] = std::move(KV.second);
     68 
     69     return Result;
     70   }
     71 
     72 private:
     73   MaterializationResponsibility &MR;
     74 };
     75 
     76 } // end anonymous namespace
     77 
     78 namespace llvm {
     79 namespace orc {
     80 
     81 RTDyldObjectLinkingLayer2::RTDyldObjectLinkingLayer2(
     82     ExecutionSession &ES, GetMemoryManagerFunction GetMemoryManager,
     83     NotifyLoadedFunction NotifyLoaded, NotifyFinalizedFunction NotifyFinalized)
     84     : ObjectLayer(ES), GetMemoryManager(GetMemoryManager),
     85       NotifyLoaded(std::move(NotifyLoaded)),
     86       NotifyFinalized(std::move(NotifyFinalized)), ProcessAllSections(false) {}
     87 
     88 void RTDyldObjectLinkingLayer2::emit(MaterializationResponsibility R,
     89                                      VModuleKey K,
     90                                      std::unique_ptr<MemoryBuffer> O) {
     91   assert(O && "Object must not be null");
     92 
     93   auto &ES = getExecutionSession();
     94 
     95   auto ObjFile = object::ObjectFile::createObjectFile(*O);
     96   if (!ObjFile) {
     97     getExecutionSession().reportError(ObjFile.takeError());
     98     R.failMaterialization();
     99   }
    100 
    101   auto MemoryManager = GetMemoryManager(K);
    102 
    103   VSOSearchOrderResolver Resolver(R);
    104   auto RTDyld = llvm::make_unique<RuntimeDyld>(*MemoryManager, Resolver);
    105   RTDyld->setProcessAllSections(ProcessAllSections);
    106 
    107   {
    108     std::lock_guard<std::mutex> Lock(RTDyldLayerMutex);
    109 
    110     assert(!ActiveRTDylds.count(K) &&
    111            "An active RTDyld already exists for this key?");
    112     ActiveRTDylds[K] = RTDyld.get();
    113 
    114     assert(!MemMgrs.count(K) &&
    115            "A memory manager already exists for this key?");
    116     MemMgrs[K] = std::move(MemoryManager);
    117   }
    118 
    119   auto Info = RTDyld->loadObject(**ObjFile);
    120 
    121   {
    122     std::set<StringRef> InternalSymbols;
    123     for (auto &Sym : (*ObjFile)->symbols()) {
    124       if (!(Sym.getFlags() & object::BasicSymbolRef::SF_Global)) {
    125         if (auto SymName = Sym.getName())
    126           InternalSymbols.insert(*SymName);
    127         else {
    128           ES.reportError(SymName.takeError());
    129           R.failMaterialization();
    130           return;
    131         }
    132       }
    133     }
    134 
    135     SymbolMap Symbols;
    136     for (auto &KV : RTDyld->getSymbolTable())
    137       if (!InternalSymbols.count(KV.first))
    138         Symbols[ES.getSymbolStringPool().intern(KV.first)] = KV.second;
    139 
    140     R.resolve(Symbols);
    141   }
    142 
    143   if (NotifyLoaded)
    144     NotifyLoaded(K, **ObjFile, *Info);
    145 
    146   RTDyld->finalizeWithMemoryManagerLocking();
    147 
    148   {
    149     std::lock_guard<std::mutex> Lock(RTDyldLayerMutex);
    150     ActiveRTDylds.erase(K);
    151   }
    152 
    153   if (RTDyld->hasError()) {
    154     ES.reportError(make_error<StringError>(RTDyld->getErrorString(),
    155                                            inconvertibleErrorCode()));
    156     R.failMaterialization();
    157     return;
    158   }
    159 
    160   R.finalize();
    161 
    162   if (NotifyFinalized)
    163     NotifyFinalized(K);
    164 }
    165 
    166 void RTDyldObjectLinkingLayer2::mapSectionAddress(
    167     VModuleKey K, const void *LocalAddress, JITTargetAddress TargetAddr) const {
    168   std::lock_guard<std::mutex> Lock(RTDyldLayerMutex);
    169   auto ActiveRTDyldItr = ActiveRTDylds.find(K);
    170 
    171   assert(ActiveRTDyldItr != ActiveRTDylds.end() &&
    172          "No active RTDyld instance found for key");
    173   ActiveRTDyldItr->second->mapSectionAddress(LocalAddress, TargetAddr);
    174 }
    175 
    176 } // End namespace orc.
    177 } // End namespace llvm.
    178