LCOV - code coverage report
Current view: top level - include/llvm/ExecutionEngine/Orc - LazyEmittingLayer.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 60 67 89.6 %
Date: 2017-09-14 15:23:50 Functions: 11 11 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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          48 : template <typename BaseLayerT> class LazyEmittingLayer {
      42             : public:
      43             : 
      44             :   using BaseLayerHandleT = typename BaseLayerT::ModuleHandleT;
      45             : 
      46             : private:
      47          81 :   class EmissionDeferredModule {
      48             :   public:
      49         103 :     EmissionDeferredModule(std::shared_ptr<Module> M,
      50             :                            std::shared_ptr<JITSymbolResolver> Resolver)
      51         514 :       : M(std::move(M)), Resolver(std::move(Resolver)) {}
      52             : 
      53         264 :     JITSymbol find(StringRef Name, bool ExportedSymbolsOnly, BaseLayerT &B) {
      54         264 :       switch (EmitState) {
      55         105 :       case NotEmitted:
      56         105 :         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         204 :           std::string PName = Name;
      61         102 :           JITSymbolFlags Flags = JITSymbolFlags::fromGlobalValue(*GV);
      62         306 :           auto GetAddress =
      63        1525 :             [this, ExportedSymbolsOnly, PName, &B]() -> Expected<JITTargetAddress> {
      64         101 :               if (this->EmitState == Emitting)
      65           0 :                 return 0;
      66         101 :               else if (this->EmitState == NotEmitted) {
      67         101 :                 this->EmitState = Emitting;
      68         303 :                 if (auto HandleOrErr = this->emitToBaseLayer(B))
      69         202 :                   Handle = std::move(*HandleOrErr);
      70             :                 else
      71           0 :                   return HandleOrErr.takeError();
      72         101 :                 this->EmitState = Emitted;
      73             :               }
      74         303 :               if (auto Sym = B.findSymbolIn(Handle, PName, ExportedSymbolsOnly))
      75         101 :                 return Sym.getAddress();
      76           0 :               else if (auto Err = Sym.takeError())
      77           0 :                 return std::move(Err);
      78             :               else
      79           0 :                 llvm_unreachable("Successful symbol lookup should return "
      80             :                                  "definition address here");
      81             :           };
      82         612 :           return JITSymbol(std::move(GetAddress), Flags);
      83             :         } else
      84             :           return nullptr;
      85           0 :       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         159 :       case Emitted:
      92         636 :         return B.findSymbolIn(Handle, Name, ExportedSymbolsOnly);
      93             :       }
      94           0 :       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         105 :     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         210 :       if (MangledSymbols) {
     123           6 :         auto VI = MangledSymbols->find(Name);
     124           9 :         if (VI == MangledSymbols->end())
     125             :           return nullptr;
     126           1 :         auto GV = VI->second;
     127           1 :         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         102 :       return buildMangledSymbols(Name, ExportedSymbolsOnly);
     136             :     }
     137             : 
     138         101 :     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         202 :       MangledSymbols.reset();
     142         505 :       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         185 :     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         324 :       if (GV.isDeclaration() || GV.hasCommonLinkage())
     155             :         return nullptr;
     156             : 
     157             :       // Mangle the GV name.
     158         139 :       std::string MangledName;
     159             :       {
     160         278 :         raw_string_ostream MangledNameStream(MangledName);
     161         139 :         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         139 :       if (MangledName == SearchName)
     167         101 :         if (!ExportedSymbolsOnly || GV.hasDefaultVisibility())
     168             :           return &GV;
     169             : 
     170             :       // Otherwise add this to the map for later.
     171          76 :       Names[MangledName] = &GV;
     172          38 :       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         102 :     const GlobalValue* buildMangledSymbols(StringRef SearchName,
     178             :                                            bool ExportedSymbolsOnly) const {
     179             :       assert(!MangledSymbols && "Mangled symbols map already exists?");
     180             : 
     181         204 :       auto Symbols = llvm::make_unique<StringMap<const GlobalValue*>>();
     182             : 
     183         204 :       Mangler Mang;
     184             : 
     185         594 :       for (const auto &GO : M->global_objects())
     186         370 :           if (auto GV = addGlobalValue(*Symbols, GO, Mang, SearchName,
     187             :                                        ExportedSymbolsOnly))
     188         101 :             return GV;
     189             : 
     190           1 :       MangledSymbols = std::move(Symbols);
     191           1 :       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         180 :   LazyEmittingLayer(BaseLayerT &BaseLayer) : BaseLayer(BaseLayer) {}
     213             : 
     214             :   /// @brief Add the given module to the lazy emitting layer.
     215             :   Expected<ModuleHandleT>
     216         103 :   addModule(std::shared_ptr<Module> M,
     217             :             std::shared_ptr<JITSymbolResolver> Resolver) {
     218             :     return ModuleList.insert(
     219             :         ModuleList.end(),
     220         103 :         llvm::make_unique<EmissionDeferredModule>(std::move(M),
     221         515 :                                                   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         298 :   JITSymbol findSymbol(const std::string &Name, bool ExportedSymbolsOnly) {
     239             :     // Look for the symbol among existing definitions.
     240         820 :     if (auto Symbol = BaseLayer.findSymbol(Name, ExportedSymbolsOnly))
     241          74 :       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         936 :     for (auto &DeferredMod : ModuleList)
     247         690 :       if (auto Symbol = DeferredMod->find(Name, ExportedSymbolsOnly, BaseLayer))
     248         102 :         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

Generated by: LCOV version 1.13