Home | History | Annotate | Download | only in Orc
      1 //===- LazyEmittingLayer.h - Lazily emit IR to lower JIT layers -*- 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 // Contains the definition for a lazy-emitting layer for the JIT.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #ifndef LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H
     15 #define LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H
     16 
     17 #include "JITSymbol.h"
     18 #include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
     19 #include "llvm/IR/GlobalValue.h"
     20 #include "llvm/IR/Mangler.h"
     21 #include "llvm/IR/Module.h"
     22 #include "llvm/ADT/STLExtras.h"
     23 #include "llvm/ADT/StringMap.h"
     24 #include <list>
     25 
     26 namespace llvm {
     27 namespace orc {
     28 
     29 /// @brief Lazy-emitting IR layer.
     30 ///
     31 ///   This layer accepts sets of LLVM IR Modules (via addModuleSet), but does
     32 /// not immediately emit them the layer below. Instead, emissing to the base
     33 /// layer is deferred until the first time the client requests the address
     34 /// (via JITSymbol::getAddress) for a symbol contained in this layer.
     35 template <typename BaseLayerT> class LazyEmittingLayer {
     36 public:
     37   typedef typename BaseLayerT::ModuleSetHandleT BaseLayerHandleT;
     38 
     39 private:
     40   class EmissionDeferredSet {
     41   public:
     42     EmissionDeferredSet() : EmitState(NotEmitted) {}
     43     virtual ~EmissionDeferredSet() {}
     44 
     45     JITSymbol find(StringRef Name, bool ExportedSymbolsOnly, BaseLayerT &B) {
     46       switch (EmitState) {
     47       case NotEmitted:
     48         if (auto GV = searchGVs(Name, ExportedSymbolsOnly)) {
     49           // Create a std::string version of Name to capture here - the argument
     50           // (a StringRef) may go away before the lambda is executed.
     51           // FIXME: Use capture-init when we move to C++14.
     52           std::string PName = Name;
     53           JITSymbolFlags Flags = JITSymbolBase::flagsFromGlobalValue(*GV);
     54           auto GetAddress =
     55             [this, ExportedSymbolsOnly, PName, &B]() -> TargetAddress {
     56               if (this->EmitState == Emitting)
     57                 return 0;
     58               else if (this->EmitState == NotEmitted) {
     59                 this->EmitState = Emitting;
     60                 Handle = this->emitToBaseLayer(B);
     61                 this->EmitState = Emitted;
     62               }
     63               auto Sym = B.findSymbolIn(Handle, PName, ExportedSymbolsOnly);
     64               return Sym.getAddress();
     65           };
     66           return JITSymbol(std::move(GetAddress), Flags);
     67         } else
     68           return nullptr;
     69       case Emitting:
     70         // Calling "emit" can trigger a recursive call to 'find' (e.g. to check
     71         // for pre-existing definitions of common-symbol), but any symbol in
     72         // this module would already have been found internally (in the
     73         // RuntimeDyld that did the lookup), so just return a nullptr here.
     74         return nullptr;
     75       case Emitted:
     76         return B.findSymbolIn(Handle, Name, ExportedSymbolsOnly);
     77       }
     78       llvm_unreachable("Invalid emit-state.");
     79     }
     80 
     81     void removeModulesFromBaseLayer(BaseLayerT &BaseLayer) {
     82       if (EmitState != NotEmitted)
     83         BaseLayer.removeModuleSet(Handle);
     84     }
     85 
     86     void emitAndFinalize(BaseLayerT &BaseLayer) {
     87       assert(EmitState != Emitting &&
     88              "Cannot emitAndFinalize while already emitting");
     89       if (EmitState == NotEmitted) {
     90         EmitState = Emitting;
     91         Handle = emitToBaseLayer(BaseLayer);
     92         EmitState = Emitted;
     93       }
     94       BaseLayer.emitAndFinalize(Handle);
     95     }
     96 
     97     template <typename ModuleSetT, typename MemoryManagerPtrT,
     98               typename SymbolResolverPtrT>
     99     static std::unique_ptr<EmissionDeferredSet>
    100     create(BaseLayerT &B, ModuleSetT Ms, MemoryManagerPtrT MemMgr,
    101            SymbolResolverPtrT Resolver);
    102 
    103   protected:
    104     virtual const GlobalValue* searchGVs(StringRef Name,
    105                                          bool ExportedSymbolsOnly) const = 0;
    106     virtual BaseLayerHandleT emitToBaseLayer(BaseLayerT &BaseLayer) = 0;
    107 
    108   private:
    109     enum { NotEmitted, Emitting, Emitted } EmitState;
    110     BaseLayerHandleT Handle;
    111   };
    112 
    113   template <typename ModuleSetT, typename MemoryManagerPtrT,
    114             typename SymbolResolverPtrT>
    115   class EmissionDeferredSetImpl : public EmissionDeferredSet {
    116   public:
    117     EmissionDeferredSetImpl(ModuleSetT Ms,
    118                             MemoryManagerPtrT MemMgr,
    119                             SymbolResolverPtrT Resolver)
    120         : Ms(std::move(Ms)), MemMgr(std::move(MemMgr)),
    121           Resolver(std::move(Resolver)) {}
    122 
    123   protected:
    124 
    125     const GlobalValue* searchGVs(StringRef Name,
    126                                  bool ExportedSymbolsOnly) const override {
    127       // FIXME: We could clean all this up if we had a way to reliably demangle
    128       //        names: We could just demangle name and search, rather than
    129       //        mangling everything else.
    130 
    131       // If we have already built the mangled name set then just search it.
    132       if (MangledSymbols) {
    133         auto VI = MangledSymbols->find(Name);
    134         if (VI == MangledSymbols->end())
    135           return nullptr;
    136         auto GV = VI->second;
    137         if (!ExportedSymbolsOnly || GV->hasDefaultVisibility())
    138           return GV;
    139         return nullptr;
    140       }
    141 
    142       // If we haven't built the mangled name set yet, try to build it. As an
    143       // optimization this will leave MangledNames set to nullptr if we find
    144       // Name in the process of building the set.
    145       return buildMangledSymbols(Name, ExportedSymbolsOnly);
    146     }
    147 
    148     BaseLayerHandleT emitToBaseLayer(BaseLayerT &BaseLayer) override {
    149       // We don't need the mangled names set any more: Once we've emitted this
    150       // to the base layer we'll just look for symbols there.
    151       MangledSymbols.reset();
    152       return BaseLayer.addModuleSet(std::move(Ms), std::move(MemMgr),
    153                                     std::move(Resolver));
    154     }
    155 
    156   private:
    157     // If the mangled name of the given GlobalValue matches the given search
    158     // name (and its visibility conforms to the ExportedSymbolsOnly flag) then
    159     // return the symbol. Otherwise, add the mangled name to the Names map and
    160     // return nullptr.
    161     const GlobalValue* addGlobalValue(StringMap<const GlobalValue*> &Names,
    162                                       const GlobalValue &GV,
    163                                       const Mangler &Mang, StringRef SearchName,
    164                                       bool ExportedSymbolsOnly) const {
    165       // Modules don't "provide" decls or common symbols.
    166       if (GV.isDeclaration() || GV.hasCommonLinkage())
    167         return nullptr;
    168 
    169       // Mangle the GV name.
    170       std::string MangledName;
    171       {
    172         raw_string_ostream MangledNameStream(MangledName);
    173         Mang.getNameWithPrefix(MangledNameStream, &GV, false);
    174       }
    175 
    176       // Check whether this is the name we were searching for, and if it is then
    177       // bail out early.
    178       if (MangledName == SearchName)
    179         if (!ExportedSymbolsOnly || GV.hasDefaultVisibility())
    180           return &GV;
    181 
    182       // Otherwise add this to the map for later.
    183       Names[MangledName] = &GV;
    184       return nullptr;
    185     }
    186 
    187     // Build the MangledSymbols map. Bails out early (with MangledSymbols left set
    188     // to nullptr) if the given SearchName is found while building the map.
    189     const GlobalValue* buildMangledSymbols(StringRef SearchName,
    190                                            bool ExportedSymbolsOnly) const {
    191       assert(!MangledSymbols && "Mangled symbols map already exists?");
    192 
    193       auto Symbols = llvm::make_unique<StringMap<const GlobalValue*>>();
    194 
    195       for (const auto &M : Ms) {
    196         Mangler Mang;
    197 
    198         for (const auto &V : M->globals())
    199           if (auto GV = addGlobalValue(*Symbols, V, Mang, SearchName,
    200                                        ExportedSymbolsOnly))
    201             return GV;
    202 
    203         for (const auto &F : *M)
    204           if (auto GV = addGlobalValue(*Symbols, F, Mang, SearchName,
    205                                        ExportedSymbolsOnly))
    206             return GV;
    207       }
    208 
    209       MangledSymbols = std::move(Symbols);
    210       return nullptr;
    211     }
    212 
    213     ModuleSetT Ms;
    214     MemoryManagerPtrT MemMgr;
    215     SymbolResolverPtrT Resolver;
    216     mutable std::unique_ptr<StringMap<const GlobalValue*>> MangledSymbols;
    217   };
    218 
    219   typedef std::list<std::unique_ptr<EmissionDeferredSet>> ModuleSetListT;
    220 
    221   BaseLayerT &BaseLayer;
    222   ModuleSetListT ModuleSetList;
    223 
    224 public:
    225   /// @brief Handle to a set of loaded modules.
    226   typedef typename ModuleSetListT::iterator ModuleSetHandleT;
    227 
    228   /// @brief Construct a lazy emitting layer.
    229   LazyEmittingLayer(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {}
    230 
    231   /// @brief Add the given set of modules to the lazy emitting layer.
    232   template <typename ModuleSetT, typename MemoryManagerPtrT,
    233             typename SymbolResolverPtrT>
    234   ModuleSetHandleT addModuleSet(ModuleSetT Ms,
    235                                 MemoryManagerPtrT MemMgr,
    236                                 SymbolResolverPtrT Resolver) {
    237     return ModuleSetList.insert(
    238         ModuleSetList.end(),
    239         EmissionDeferredSet::create(BaseLayer, std::move(Ms), std::move(MemMgr),
    240                                     std::move(Resolver)));
    241   }
    242 
    243   /// @brief Remove the module set represented by the given handle.
    244   ///
    245   ///   This method will free the memory associated with the given module set,
    246   /// both in this layer, and the base layer.
    247   void removeModuleSet(ModuleSetHandleT H) {
    248     (*H)->removeModulesFromBaseLayer(BaseLayer);
    249     ModuleSetList.erase(H);
    250   }
    251 
    252   /// @brief Search for the given named symbol.
    253   /// @param Name The name of the symbol to search for.
    254   /// @param ExportedSymbolsOnly If true, search only for exported symbols.
    255   /// @return A handle for the given named symbol, if it exists.
    256   JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
    257     // Look for the symbol among existing definitions.
    258     if (auto Symbol = BaseLayer.findSymbol(Name, ExportedSymbolsOnly))
    259       return Symbol;
    260 
    261     // If not found then search the deferred sets. If any of these contain a
    262     // definition of 'Name' then they will return a JITSymbol that will emit
    263     // the corresponding module when the symbol address is requested.
    264     for (auto &DeferredSet : ModuleSetList)
    265       if (auto Symbol = DeferredSet->find(Name, ExportedSymbolsOnly, BaseLayer))
    266         return Symbol;
    267 
    268     // If no definition found anywhere return a null symbol.
    269     return nullptr;
    270   }
    271 
    272   /// @brief Get the address of the given symbol in the context of the set of
    273   ///        compiled modules represented by the handle H.
    274   JITSymbol findSymbolIn(ModuleSetHandleT H, const std::string &Name,
    275                          bool ExportedSymbolsOnly) {
    276     return (*H)->find(Name, ExportedSymbolsOnly, BaseLayer);
    277   }
    278 
    279   /// @brief Immediately emit and finalize the moduleOB set represented by the
    280   ///        given handle.
    281   /// @param H Handle for module set to emit/finalize.
    282   void emitAndFinalize(ModuleSetHandleT H) {
    283     (*H)->emitAndFinalize(BaseLayer);
    284   }
    285 
    286 };
    287 
    288 template <typename BaseLayerT>
    289 template <typename ModuleSetT, typename MemoryManagerPtrT,
    290           typename SymbolResolverPtrT>
    291 std::unique_ptr<typename LazyEmittingLayer<BaseLayerT>::EmissionDeferredSet>
    292 LazyEmittingLayer<BaseLayerT>::EmissionDeferredSet::create(
    293     BaseLayerT &B, ModuleSetT Ms, MemoryManagerPtrT MemMgr,
    294     SymbolResolverPtrT Resolver) {
    295   typedef EmissionDeferredSetImpl<ModuleSetT, MemoryManagerPtrT, SymbolResolverPtrT>
    296     EDS;
    297   return llvm::make_unique<EDS>(std::move(Ms), std::move(MemMgr),
    298                                 std::move(Resolver));
    299 }
    300 
    301 } // End namespace orc.
    302 } // End namespace llvm.
    303 
    304 #endif // LLVM_EXECUTIONENGINE_ORC_LAZYEMITTINGLAYER_H
    305