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