LCOV - code coverage report
Current view: top level - include/llvm/ExecutionEngine/Orc - ThreadSafeModule.h (source / functions) Hit Total Coverage
Test: llvm-toolchain.info Lines: 24 24 100.0 %
Date: 2018-10-20 13:21:21 Functions: 4 4 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //===----------- ThreadSafeModule.h -- Layer interfaces ---------*- 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             : // Thread safe wrappers and utilities for Module and LLVMContext.
      11             : //
      12             : //===----------------------------------------------------------------------===//
      13             : 
      14             : #ifndef LLVM_EXECUTIONENGINE_ORC_THREADSAFEMODULEWRAPPER_H
      15             : #define LLVM_EXECUTIONENGINE_ORC_THREADSAFEMODULEWRAPPER_H
      16             : 
      17             : #include "llvm/IR/LLVMContext.h"
      18             : #include "llvm/IR/Module.h"
      19             : #include "llvm/Support/Compiler.h"
      20             : 
      21             : #include <functional>
      22             : #include <memory>
      23             : #include <mutex>
      24             : 
      25             : namespace llvm {
      26             : namespace orc {
      27             : 
      28             : /// An LLVMContext together with an associated mutex that can be used to lock
      29             : /// the context to prevent concurrent access by other threads.
      30         524 : class ThreadSafeContext {
      31             : private:
      32          44 :   struct State {
      33          45 :     State(std::unique_ptr<LLVMContext> Ctx) : Ctx(std::move(Ctx)) {}
      34             : 
      35             :     std::unique_ptr<LLVMContext> Ctx;
      36             :     std::recursive_mutex Mutex;
      37             :   };
      38             : 
      39             : public:
      40             :   // RAII based lock for ThreadSafeContext.
      41             :   class LLVM_NODISCARD Lock {
      42             :   private:
      43             :     using UnderlyingLock = std::lock_guard<std::recursive_mutex>;
      44             : 
      45             :   public:
      46          88 :     Lock(std::shared_ptr<State> S)
      47          88 :         : S(std::move(S)),
      48          88 :           L(llvm::make_unique<UnderlyingLock>(this->S->Mutex)) {}
      49             : 
      50             :   private:
      51             :     std::shared_ptr<State> S;
      52             :     std::unique_ptr<UnderlyingLock> L;
      53             :   };
      54             : 
      55             :   /// Construct a null context.
      56             :   ThreadSafeContext() = default;
      57             : 
      58             :   /// Construct a ThreadSafeContext from the given LLVMContext.
      59             :   ThreadSafeContext(std::unique_ptr<LLVMContext> NewCtx)
      60          45 :       : S(std::make_shared<State>(std::move(NewCtx))) {
      61             :     assert(S->Ctx != nullptr &&
      62             :            "Can not construct a ThreadSafeContext from a nullptr");
      63             :   }
      64             : 
      65             :   /// Returns a pointer to the LLVMContext that was used to construct this
      66             :   /// instance, or null if the instance was default constructed.
      67          51 :   LLVMContext *getContext() { return S ? S->Ctx.get() : nullptr; }
      68             : 
      69             :   /// Returns a pointer to the LLVMContext that was used to construct this
      70             :   /// instance, or null if the instance was default constructed.
      71             :   const LLVMContext *getContext() const { return S ? S->Ctx.get() : nullptr; }
      72             : 
      73          88 :   Lock getLock() {
      74             :     assert(S && "Can not lock an empty ThreadSafeContext");
      75          88 :     return Lock(S);
      76             :   }
      77             : 
      78             : private:
      79             :   std::shared_ptr<State> S;
      80             : };
      81             : 
      82             : /// An LLVM Module together with a shared ThreadSafeContext.
      83             : class ThreadSafeModule {
      84             : public:
      85             :   /// Default construct a ThreadSafeModule. This results in a null module and
      86             :   /// null context.
      87             :   ThreadSafeModule() = default;
      88             : 
      89          52 :   ThreadSafeModule(ThreadSafeModule &&Other) = default;
      90             : 
      91          30 :   ThreadSafeModule &operator=(ThreadSafeModule &&Other) {
      92             :     // We have to explicitly define this move operator to copy the fields in
      93             :     // reverse order (i.e. module first) to ensure the dependencies are
      94             :     // protected: The old module that is being overwritten must be destroyed
      95             :     // *before* the context that it depends on.
      96             :     // We also need to lock the context to make sure the module tear-down
      97             :     // does not overlap any other work on the context.
      98          30 :     if (M) {
      99          28 :       auto L = getContextLock();
     100          28 :       M = nullptr;
     101             :     }
     102          30 :     M = std::move(Other.M);
     103             :     TSCtx = std::move(Other.TSCtx);
     104          30 :     return *this;
     105             :   }
     106             : 
     107             :   /// Construct a ThreadSafeModule from a unique_ptr<Module> and a
     108             :   /// unique_ptr<LLVMContext>. This creates a new ThreadSafeContext from the
     109             :   /// given context.
     110             :   ThreadSafeModule(std::unique_ptr<Module> M, std::unique_ptr<LLVMContext> Ctx)
     111             :       : M(std::move(M)), TSCtx(std::move(Ctx)) {}
     112             : 
     113             :   /// Construct a ThreadSafeModule from a unique_ptr<Module> and an
     114             :   /// existing ThreadSafeContext.
     115             :   ThreadSafeModule(std::unique_ptr<Module> M, ThreadSafeContext TSCtx)
     116             :       : M(std::move(M)), TSCtx(std::move(TSCtx)) {}
     117             : 
     118        1008 :   ~ThreadSafeModule() {
     119             :     // We need to lock the context while we destruct the module.
     120         504 :     if (M) {
     121          18 :       auto L = getContextLock();
     122          18 :       M = nullptr;
     123             :     }
     124         504 :   }
     125             : 
     126             :   /// Get the module wrapped by this ThreadSafeModule.
     127             :   Module *getModule() { return M.get(); }
     128             : 
     129             :   /// Get the module wrapped by this ThreadSafeModule.
     130             :   const Module *getModule() const { return M.get(); }
     131             : 
     132             :   /// Take out a lock on the ThreadSafeContext for this module.
     133          86 :   ThreadSafeContext::Lock getContextLock() { return TSCtx.getLock(); }
     134             : 
     135             :   /// Boolean conversion: This ThreadSafeModule will evaluate to true if it
     136             :   /// wraps a non-null module.
     137             :   explicit operator bool() {
     138          13 :     if (M) {
     139             :       assert(TSCtx.getContext() &&
     140             :              "Non-null module must have non-null context");
     141             :       return true;
     142             :     }
     143             :     return false;
     144             :   }
     145             : 
     146             : private:
     147             :   std::unique_ptr<Module> M;
     148             :   ThreadSafeContext TSCtx;
     149             : };
     150             : 
     151             : using GVPredicate = std::function<bool(const GlobalValue &)>;
     152             : using GVModifier = std::function<void(GlobalValue &)>;
     153             : 
     154             : /// Clones the given module on to a new context.
     155             : ThreadSafeModule
     156             : cloneToNewContext(ThreadSafeModule &TSMW,
     157             :                   GVPredicate ShouldCloneDef = GVPredicate(),
     158             :                   GVModifier UpdateClonedDefSource = GVModifier());
     159             : 
     160             : } // End namespace orc
     161             : } // End namespace llvm
     162             : 
     163             : #endif // LLVM_EXECUTIONENGINE_ORC_THREADSAFEMODULEWRAPPER_H

Generated by: LCOV version 1.13