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

Generated by: LCOV version 1.13