LCOV - code coverage report
Current view: top level - lib/ExecutionEngine/Orc - OrcMCJITReplacement.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 120 148 81.1 %
Date: 2017-09-14 15:23:50 Functions: 31 39 79.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===- OrcMCJITReplacement.h - Orc based MCJIT replacement ------*- C++ -*-===//
       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             : // Orc based MCJIT replacement.
      11             : //
      12             : //===----------------------------------------------------------------------===//
      13             : 
      14             : #ifndef LLVM_LIB_EXECUTIONENGINE_ORC_ORCMCJITREPLACEMENT_H
      15             : #define LLVM_LIB_EXECUTIONENGINE_ORC_ORCMCJITREPLACEMENT_H
      16             : 
      17             : #include "llvm/ADT/ArrayRef.h"
      18             : #include "llvm/ADT/STLExtras.h"
      19             : #include "llvm/ADT/StringRef.h"
      20             : #include "llvm/ExecutionEngine/ExecutionEngine.h"
      21             : #include "llvm/ExecutionEngine/GenericValue.h"
      22             : #include "llvm/ExecutionEngine/JITSymbol.h"
      23             : #include "llvm/ExecutionEngine/Orc/CompileUtils.h"
      24             : #include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
      25             : #include "llvm/ExecutionEngine/Orc/LazyEmittingLayer.h"
      26             : #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
      27             : #include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
      28             : #include "llvm/ExecutionEngine/RuntimeDyld.h"
      29             : #include "llvm/IR/DataLayout.h"
      30             : #include "llvm/IR/Function.h"
      31             : #include "llvm/IR/Mangler.h"
      32             : #include "llvm/IR/Module.h"
      33             : #include "llvm/Object/Archive.h"
      34             : #include "llvm/Object/Binary.h"
      35             : #include "llvm/Object/ObjectFile.h"
      36             : #include "llvm/Support/Error.h"
      37             : #include "llvm/Support/ErrorHandling.h"
      38             : #include "llvm/Support/raw_ostream.h"
      39             : #include "llvm/Target/TargetMachine.h"
      40             : #include <algorithm>
      41             : #include <cassert>
      42             : #include <cstddef>
      43             : #include <cstdint>
      44             : #include <map>
      45             : #include <memory>
      46             : #include <set>
      47             : #include <string>
      48             : #include <vector>
      49             : 
      50             : namespace llvm {
      51             : 
      52             : class ObjectCache;
      53             : 
      54             : namespace orc {
      55             : 
      56         253 : class OrcMCJITReplacement : public ExecutionEngine {
      57             :   // OrcMCJITReplacement needs to do a little extra book-keeping to ensure that
      58             :   // Orc's automatic finalization doesn't kick in earlier than MCJIT clients are
      59             :   // expecting - see finalizeMemory.
      60          69 :   class MCJITReplacementMemMgr : public MCJITMemoryManager {
      61             :   public:
      62             :     MCJITReplacementMemMgr(OrcMCJITReplacement &M,
      63             :                            std::shared_ptr<MCJITMemoryManager> ClientMM)
      64         267 :       : M(M), ClientMM(std::move(ClientMM)) {}
      65             : 
      66         106 :     uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment,
      67             :                                  unsigned SectionID,
      68             :                                  StringRef SectionName) override {
      69             :       uint8_t *Addr =
      70         212 :           ClientMM->allocateCodeSection(Size, Alignment, SectionID,
      71         106 :                                         SectionName);
      72         212 :       M.SectionsAllocatedSinceLastLoad.insert(Addr);
      73         106 :       return Addr;
      74             :     }
      75             : 
      76         206 :     uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment,
      77             :                                  unsigned SectionID, StringRef SectionName,
      78             :                                  bool IsReadOnly) override {
      79         618 :       uint8_t *Addr = ClientMM->allocateDataSection(Size, Alignment, SectionID,
      80         412 :                                                     SectionName, IsReadOnly);
      81         412 :       M.SectionsAllocatedSinceLastLoad.insert(Addr);
      82         206 :       return Addr;
      83             :     }
      84             : 
      85          14 :     void reserveAllocationSpace(uintptr_t CodeSize, uint32_t CodeAlign,
      86             :                                 uintptr_t RODataSize, uint32_t RODataAlign,
      87             :                                 uintptr_t RWDataSize,
      88             :                                 uint32_t RWDataAlign) override {
      89          42 :       return ClientMM->reserveAllocationSpace(CodeSize, CodeAlign,
      90             :                                               RODataSize, RODataAlign,
      91          28 :                                               RWDataSize, RWDataAlign);
      92             :     }
      93             : 
      94         105 :     bool needsToReserveAllocationSpace() override {
      95         210 :       return ClientMM->needsToReserveAllocationSpace();
      96             :     }
      97             : 
      98          73 :     void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr,
      99             :                           size_t Size) override {
     100         146 :       return ClientMM->registerEHFrames(Addr, LoadAddr, Size);
     101             :     }
     102             : 
     103          26 :     void deregisterEHFrames() override {
     104          52 :       return ClientMM->deregisterEHFrames();
     105             :     }
     106             : 
     107         105 :     void notifyObjectLoaded(RuntimeDyld &RTDyld,
     108             :                             const object::ObjectFile &O) override {
     109         210 :       return ClientMM->notifyObjectLoaded(RTDyld, O);
     110             :     }
     111             : 
     112         105 :     void notifyObjectLoaded(ExecutionEngine *EE,
     113             :                             const object::ObjectFile &O) override {
     114         210 :       return ClientMM->notifyObjectLoaded(EE, O);
     115             :     }
     116             : 
     117          88 :     bool finalizeMemory(std::string *ErrMsg = nullptr) override {
     118             :       // Each set of objects loaded will be finalized exactly once, but since
     119             :       // symbol lookup during relocation may recursively trigger the
     120             :       // loading/relocation of other modules, and since we're forwarding all
     121             :       // finalizeMemory calls to a single underlying memory manager, we need to
     122             :       // defer forwarding the call on until all necessary objects have been
     123             :       // loaded. Otherwise, during the relocation of a leaf object, we will end
     124             :       // up finalizing memory, causing a crash further up the stack when we
     125             :       // attempt to apply relocations to finalized memory.
     126             :       // To avoid finalizing too early, look at how many objects have been
     127             :       // loaded but not yet finalized. This is a bit of a hack that relies on
     128             :       // the fact that we're lazily emitting object files: The only way you can
     129             :       // get more than one set of objects loaded but not yet finalized is if
     130             :       // they were loaded during relocation of another set.
     131         176 :       if (M.UnfinalizedSections.size() == 1)
     132         176 :         return ClientMM->finalizeMemory(ErrMsg);
     133             :       return false;
     134             :     }
     135             : 
     136             :   private:
     137             :     OrcMCJITReplacement &M;
     138             :     std::shared_ptr<MCJITMemoryManager> ClientMM;
     139             :   };
     140             : 
     141          23 :   class LinkingResolver : public JITSymbolResolver {
     142             :   public:
     143          89 :     LinkingResolver(OrcMCJITReplacement &M) : M(M) {}
     144             : 
     145           0 :     JITSymbol findSymbol(const std::string &Name) override {
     146           0 :       return M.ClientResolver->findSymbol(Name);
     147             :     }
     148             : 
     149          79 :     JITSymbol findSymbolInLogicalDylib(const std::string &Name) override {
     150         174 :       if (auto Sym = M.findMangledSymbol(Name))
     151          63 :         return Sym;
     152          32 :       return M.ClientResolver->findSymbolInLogicalDylib(Name);
     153             :     }
     154             : 
     155             :   private:
     156             :     OrcMCJITReplacement &M;
     157             :   };
     158             : 
     159             : private:
     160             :   static ExecutionEngine *
     161          89 :   createOrcMCJITReplacement(std::string *ErrorMsg,
     162             :                             std::shared_ptr<MCJITMemoryManager> MemMgr,
     163             :                             std::shared_ptr<JITSymbolResolver> Resolver,
     164             :                             std::unique_ptr<TargetMachine> TM) {
     165         178 :     return new OrcMCJITReplacement(std::move(MemMgr), std::move(Resolver),
     166         534 :                                    std::move(TM));
     167             :   }
     168             : 
     169             : public:
     170          89 :   OrcMCJITReplacement(
     171             :       std::shared_ptr<MCJITMemoryManager> MemMgr,
     172             :       std::shared_ptr<JITSymbolResolver> ClientResolver,
     173             :       std::unique_ptr<TargetMachine> TM)
     174         445 :       : ExecutionEngine(TM->createDataLayout()), TM(std::move(TM)),
     175             :         MemMgr(std::make_shared<MCJITReplacementMemMgr>(*this,
     176          89 :                                                         std::move(MemMgr))),
     177             :         Resolver(std::make_shared<LinkingResolver>(*this)),
     178          89 :         ClientResolver(std::move(ClientResolver)), NotifyObjectLoaded(*this),
     179             :         NotifyFinalized(*this),
     180         210 :         ObjectLayer([this]() { return this->MemMgr; }, NotifyObjectLoaded,
     181             :                     NotifyFinalized),
     182         178 :         CompileLayer(ObjectLayer, SimpleCompiler(*this->TM)),
     183        2136 :         LazyEmitLayer(CompileLayer) {}
     184             : 
     185             :   static void Register() {
     186       72306 :     OrcMCJITReplacementCtor = createOrcMCJITReplacement;
     187             :   }
     188             : 
     189         102 :   void addModule(std::unique_ptr<Module> M) override {
     190             :     // If this module doesn't have a DataLayout attached then attach the
     191             :     // default.
     192         204 :     if (M->getDataLayout().isDefault()) {
     193         180 :       M->setDataLayout(getDataLayout());
     194             :     } else {
     195             :       assert(M->getDataLayout() == getDataLayout() && "DataLayout Mismatch");
     196             :     }
     197         102 :     auto *MPtr = M.release();
     198         102 :     ShouldDelete[MPtr] = true;
     199          26 :     auto Deleter = [this](Module *Mod) {
     200          52 :       auto I = ShouldDelete.find(Mod);
     201          78 :       if (I != ShouldDelete.end() && I->second)
     202          26 :         delete Mod;
     203         128 :     };
     204         408 :     LocalModules.push_back(std::shared_ptr<Module>(MPtr, std::move(Deleter)));
     205         816 :     cantFail(LazyEmitLayer.addModule(LocalModules.back(), Resolver));
     206         102 :   }
     207             : 
     208           0 :   void addObjectFile(std::unique_ptr<object::ObjectFile> O) override {
     209             :     auto Obj =
     210           0 :       std::make_shared<object::OwningBinary<object::ObjectFile>>(std::move(O),
     211           0 :                                                                  nullptr);
     212           0 :     cantFail(ObjectLayer.addObject(std::move(Obj), Resolver));
     213           0 :   }
     214             : 
     215           2 :   void addObjectFile(object::OwningBinary<object::ObjectFile> O) override {
     216             :     auto Obj =
     217           6 :       std::make_shared<object::OwningBinary<object::ObjectFile>>(std::move(O));
     218          14 :     cantFail(ObjectLayer.addObject(std::move(Obj), Resolver));
     219           2 :   }
     220             : 
     221           1 :   void addArchive(object::OwningBinary<object::Archive> A) override {
     222           2 :     Archives.push_back(std::move(A));
     223           1 :   }
     224             :   
     225           0 :   bool removeModule(Module *M) override {
     226           0 :     for (auto I = LocalModules.begin(), E = LocalModules.end(); I != E; ++I) {
     227           0 :       if (I->get() == M) {
     228           0 :         ShouldDelete[M] = false;
     229           0 :         LocalModules.erase(I);
     230           0 :         return true;
     231             :       }
     232             :     }
     233             :     return false;
     234             :   }
     235             : 
     236         219 :   uint64_t getSymbolAddress(StringRef Name) {
     237         657 :     return cantFail(findSymbol(Name).getAddress());
     238             :   }
     239             : 
     240         219 :   JITSymbol findSymbol(StringRef Name) {
     241         657 :     return findMangledSymbol(Mangle(Name));
     242             :   }
     243             : 
     244          88 :   void finalizeObject() override {
     245             :     // This is deprecated - Aim to remove in ExecutionEngine.
     246             :     // REMOVE IF POSSIBLE - Doesn't make sense for New JIT.
     247          88 :   }
     248             : 
     249           0 :   void mapSectionAddress(const void *LocalAddress,
     250             :                          uint64_t TargetAddress) override {
     251           0 :     for (auto &P : UnfinalizedSections)
     252           0 :       if (P.second.count(LocalAddress))
     253           0 :         ObjectLayer.mapSectionAddress(P.first, LocalAddress, TargetAddress);
     254           0 :   }
     255             : 
     256           0 :   uint64_t getGlobalValueAddress(const std::string &Name) override {
     257           0 :     return getSymbolAddress(Name);
     258             :   }
     259             : 
     260          11 :   uint64_t getFunctionAddress(const std::string &Name) override {
     261          11 :     return getSymbolAddress(Name);
     262             :   }
     263             : 
     264         208 :   void *getPointerToFunction(Function *F) override {
     265         208 :     uint64_t FAddr = getSymbolAddress(F->getName());
     266         208 :     return reinterpret_cast<void *>(static_cast<uintptr_t>(FAddr));
     267             :   }
     268             : 
     269           0 :   void *getPointerToNamedFunction(StringRef Name,
     270             :                                   bool AbortOnFailure = true) override {
     271           0 :     uint64_t Addr = getSymbolAddress(Name);
     272           0 :     if (!Addr && AbortOnFailure)
     273           0 :       llvm_unreachable("Missing symbol!");
     274           0 :     return reinterpret_cast<void *>(static_cast<uintptr_t>(Addr));
     275             :   }
     276             : 
     277             :   GenericValue runFunction(Function *F,
     278             :                            ArrayRef<GenericValue> ArgValues) override;
     279             : 
     280           1 :   void setObjectCache(ObjectCache *NewCache) override {
     281           2 :     CompileLayer.getCompiler().setObjectCache(NewCache);
     282           1 :   }
     283             : 
     284          12 :   void setProcessAllSections(bool ProcessAllSections) override {
     285          24 :     ObjectLayer.setProcessAllSections(ProcessAllSections);
     286          12 :   }
     287             : 
     288             :   void runStaticConstructorsDestructors(bool isDtors) override;
     289             : 
     290             : private:
     291         298 :   JITSymbol findMangledSymbol(StringRef Name) {
     292        1016 :     if (auto Sym = LazyEmitLayer.findSymbol(Name, false))
     293         176 :       return Sym;
     294         506 :     if (auto Sym = ClientResolver->findSymbol(Name))
     295         104 :       return Sym;
     296          34 :     if (auto Sym = scanArchives(Name))
     297           2 :       return Sym;
     298             : 
     299             :     return nullptr;
     300             :   }
     301             : 
     302          18 :   JITSymbol scanArchives(StringRef Name) {
     303          72 :     for (object::OwningBinary<object::Archive> &OB : Archives) {
     304           2 :       object::Archive *A = OB.getBinary();
     305             :       // Look for our symbols in each Archive
     306           2 :       auto OptionalChildOrErr = A->findSym(Name);
     307           2 :       if (!OptionalChildOrErr)
     308           0 :         report_fatal_error(OptionalChildOrErr.takeError());
     309           2 :       auto &OptionalChild = *OptionalChildOrErr;
     310           2 :       if (OptionalChild) {
     311             :         // FIXME: Support nested archives?
     312             :         Expected<std::unique_ptr<object::Binary>> ChildBinOrErr =
     313           2 :             OptionalChild->getAsBinary();
     314           2 :         if (!ChildBinOrErr) {
     315             :           // TODO: Actually report errors helpfully.
     316           0 :           consumeError(ChildBinOrErr.takeError());
     317           0 :           continue;
     318             :         }
     319           2 :         std::unique_ptr<object::Binary> &ChildBin = ChildBinOrErr.get();
     320           4 :         if (ChildBin->isObject()) {
     321             :           std::unique_ptr<object::ObjectFile> ChildObj(
     322           6 :             static_cast<object::ObjectFile*>(ChildBinOrErr->release()));
     323             :           auto Obj =
     324             :             std::make_shared<object::OwningBinary<object::ObjectFile>>(
     325           4 :               std::move(ChildObj), nullptr);
     326          14 :           cantFail(ObjectLayer.addObject(std::move(Obj), Resolver));
     327           2 :           if (auto Sym = ObjectLayer.findSymbol(Name, true))
     328           2 :             return Sym;
     329             :         }
     330             :       }
     331             :     }
     332             :     return nullptr;
     333             :   }
     334             : 
     335             :   class NotifyObjectLoadedT {
     336             :   public:
     337             :     using LoadedObjInfoListT =
     338             :         std::vector<std::unique_ptr<RuntimeDyld::LoadedObjectInfo>>;
     339             : 
     340          89 :     NotifyObjectLoadedT(OrcMCJITReplacement &M) : M(M) {}
     341             : 
     342         105 :     void operator()(RTDyldObjectLinkingLayerBase::ObjHandleT H,
     343             :                     const RTDyldObjectLinkingLayer::ObjectPtr &Obj,
     344             :                     const LoadedObjectInfo &Info) const {
     345         210 :       M.UnfinalizedSections[H] = std::move(M.SectionsAllocatedSinceLastLoad);
     346         420 :       M.SectionsAllocatedSinceLastLoad = SectionAddrSet();
     347         420 :       M.MemMgr->notifyObjectLoaded(&M, *Obj->getBinary());
     348         105 :     }
     349             :   private:
     350             :     OrcMCJITReplacement &M;
     351             :   };
     352             : 
     353             :   class NotifyFinalizedT {
     354             :   public:
     355          89 :     NotifyFinalizedT(OrcMCJITReplacement &M) : M(M) {}
     356             : 
     357             :     void operator()(RTDyldObjectLinkingLayerBase::ObjHandleT H) {
     358         210 :       M.UnfinalizedSections.erase(H);
     359             :     }
     360             : 
     361             :   private:
     362             :     OrcMCJITReplacement &M;
     363             :   };
     364             : 
     365         219 :   std::string Mangle(StringRef Name) {
     366         219 :     std::string MangledName;
     367             :     {
     368         438 :       raw_string_ostream MangledNameStream(MangledName);
     369         657 :       Mang.getNameWithPrefix(MangledNameStream, Name, getDataLayout());
     370             :     }
     371         219 :     return MangledName;
     372             :   }
     373             : 
     374             :   using ObjectLayerT = RTDyldObjectLinkingLayer;
     375             :   using CompileLayerT = IRCompileLayer<ObjectLayerT, orc::SimpleCompiler>;
     376             :   using LazyEmitLayerT = LazyEmittingLayer<CompileLayerT>;
     377             : 
     378             :   std::unique_ptr<TargetMachine> TM;
     379             :   std::shared_ptr<MCJITReplacementMemMgr> MemMgr;
     380             :   std::shared_ptr<LinkingResolver> Resolver;
     381             :   std::shared_ptr<JITSymbolResolver> ClientResolver;
     382             :   Mangler Mang;
     383             : 
     384             :   // IMPORTANT: ShouldDelete *must* come before LocalModules: The shared_ptr
     385             :   // delete blocks in LocalModules refer to the ShouldDelete map, so
     386             :   // LocalModules needs to be destructed before ShouldDelete.
     387             :   std::map<Module*, bool> ShouldDelete;
     388             :   std::vector<std::shared_ptr<Module>> LocalModules;
     389             : 
     390             :   NotifyObjectLoadedT NotifyObjectLoaded;
     391             :   NotifyFinalizedT NotifyFinalized;
     392             : 
     393             :   ObjectLayerT ObjectLayer;
     394             :   CompileLayerT CompileLayer;
     395             :   LazyEmitLayerT LazyEmitLayer;
     396             : 
     397             :   // We need to store ObjLayerT::ObjSetHandles for each of the object sets
     398             :   // that have been emitted but not yet finalized so that we can forward the
     399             :   // mapSectionAddress calls appropriately.
     400             :   using SectionAddrSet = std::set<const void *>;
     401             :   struct ObjHandleCompare {
     402             :     bool operator()(ObjectLayerT::ObjHandleT H1,
     403             :                     ObjectLayerT::ObjHandleT H2) const {
     404         584 :       return &*H1 < &*H2;
     405             :     }
     406             :   };
     407             :   SectionAddrSet SectionsAllocatedSinceLastLoad;
     408             :   std::map<ObjectLayerT::ObjHandleT, SectionAddrSet, ObjHandleCompare>
     409             :       UnfinalizedSections;
     410             : 
     411             :   std::vector<object::OwningBinary<object::Archive>> Archives;
     412             : };
     413             : 
     414             : } // end namespace orc
     415             : 
     416             : } // end namespace llvm
     417             : 
     418             : #endif // LLVM_LIB_EXECUTIONENGINE_ORC_MCJITREPLACEMENT_H

Generated by: LCOV version 1.13