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