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