<commit_before>//--------------------------------------------------------------------*- C++ -*-
// CLING - the C++ LLVM-based InterpreterG :)
// author:  <NAME> <<EMAIL>>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

#ifndef CLING_INCREMENTAL_JIT_H
#define CLING_INCREMENTAL_JIT_H

#include <map>
#include <memory>
#include <set>
#include <string>
#include <vector>

#include "llvm/IR/Mangler.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/ExecutionEngine/JITEventListener.h"
#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
#include "llvm/ExecutionEngine/Orc/LazyEmittingLayer.h"
#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
#include "llvm/Target/TargetMachine.h"

namespace llvm {
class Module;
class RTDyldMemoryManager;
}

namespace cling {
class Azog;
class IncrementalExecutor;

class IncrementalJIT {
public:
  using SymbolMapT = llvm::StringMap<llvm::orc::TargetAddress>;

private:
  friend class Azog;

  ///\brief The IncrementalExecutor who owns us.
  IncrementalExecutor& m_Parent;
  llvm::JITEventListener* m_GDBListener; // owned by llvm::ManagedStaticBase

  SymbolMapT m_SymbolMap;

  class NotifyObjectLoadedT {
  public:
    typedef std::vector<std::unique_ptr<llvm::object::OwningBinary<llvm::object::ObjectFile>>> ObjListT;
    typedef std::vector<std::unique_ptr<llvm::RuntimeDyld::LoadedObjectInfo>>
      LoadedObjInfoListT;

    NotifyObjectLoadedT(IncrementalJIT &jit) : m_JIT(jit) {}

    void operator()(llvm::orc::ObjectLinkingLayerBase::ObjSetHandleT H,
                    const ObjListT &Objects,
                    const LoadedObjInfoListT &Infos) const
    {
      m_JIT.m_UnfinalizedSections[H]
        = std::move(m_JIT.m_SectionsAllocatedSinceLastLoad);
      m_JIT.m_SectionsAllocatedSinceLastLoad = SectionAddrSet();
      assert(Objects.size() == Infos.size() &&
             "Incorrect number of Infos for Objects.");
      if (auto GDBListener = m_JIT.m_GDBListener) {
        for (size_t I = 0, N = Objects.size(); I < N; ++I)
          GDBListener->NotifyObjectEmitted(*Objects[I]->getBinary(),
                                           *Infos[I]);
      }

      for (const auto &Object: Objects) {
        for (const auto &Symbol: Object->getBinary()->symbols()) {
          auto Flags = Symbol.getFlags();
          if (Flags & llvm::object::BasicSymbolRef::SF_Undefined)
            continue;
          // FIXME: this should be uncommented once we serve incremental
          // modules from a TU module.
          //if (!(Flags & llvm::object::BasicSymbolRef::SF_Exported))
          //  continue;
          auto NameOrError = Symbol.getName();
          assert(NameOrError);
          auto Name = NameOrError.get();
          if (m_JIT.m_SymbolMap.find(Name) == m_JIT.m_SymbolMap.end()) {
            llvm::orc::JITSymbol Sym
              = m_JIT.m_CompileLayer.findSymbolIn(H, Name, true);
            if (llvm::orc::TargetAddress Addr = Sym.getAddress())
              m_JIT.m_SymbolMap[Name] = Addr;
          }
        }
      }
    }

  private:
    IncrementalJIT &m_JIT;
  };

  class RemovableObjectLinkingLayer:
    public llvm::orc::ObjectLinkingLayer<NotifyObjectLoadedT> {
  public:
    using Base_t = llvm::orc::ObjectLinkingLayer<NotifyObjectLoadedT>;
    using NotifyLoadedFtor = NotifyObjectLoadedT;
    using NotifyFinalizedFtor = typename Base_t::NotifyFinalizedFtor;
    RemovableObjectLinkingLayer(SymbolMapT &SymMap,
                                NotifyObjectLoadedT NotifyLoaded,
                   NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor()):
      Base_t(NotifyLoaded, NotifyFinalized), m_SymbolMap(SymMap)
    {}

    void removeObjectSet(llvm::orc::ObjectLinkingLayerBase::ObjSetHandleT H) {
      struct AccessSymbolTable: public Base_t::LinkedObjectSet {
        const llvm::StringMap<llvm::RuntimeDyld::SymbolInfo>&
        getSymbolTable() const
        {
          return SymbolTable;
        }
      };
      const AccessSymbolTable* HSymTable
        = static_cast<const AccessSymbolTable*>(H->get());
      for (auto&& NameSym: HSymTable->getSymbolTable()) {
        auto iterSymMap = m_SymbolMap.find(NameSym.first());
        if (iterSymMap == m_SymbolMap.end())
          continue;
        // Is this this symbol (address)?
        if (iterSymMap->second == NameSym.second.getAddress())
          m_SymbolMap.erase(iterSymMap);
      }
      llvm::orc::ObjectLinkingLayer<NotifyObjectLoadedT>::removeObjectSet(H);
    }
  private:
    SymbolMapT& m_SymbolMap;
  };

  typedef RemovableObjectLinkingLayer ObjectLayerT;
  typedef llvm::orc::IRCompileLayer<ObjectLayerT> CompileLayerT;
  typedef llvm::orc::LazyEmittingLayer<CompileLayerT> LazyEmitLayerT;
  typedef LazyEmitLayerT::ModuleSetHandleT ModuleSetHandleT;

  std::unique_ptr<llvm::TargetMachine> m_TM;
  llvm::DataLayout m_TMDataLayout;

  ///\brief The RTDyldMemoryManager used to communicate with the
  /// IncrementalExecutor to handle missing or special symbols.
  std::unique_ptr<llvm::RTDyldMemoryManager> m_ExeMM;

  NotifyObjectLoadedT m_NotifyObjectLoaded;

  ObjectLayerT m_ObjectLayer;
  CompileLayerT m_CompileLayer;
  LazyEmitLayerT m_LazyEmitLayer;

  // We need to store ObjLayerT::ObjSetHandles for each of the object sets
  // that have been emitted but not yet finalized so that we can forward the
  // mapSectionAddress calls appropriately.
  typedef std::set<const void *> SectionAddrSet;
  struct ObjSetHandleCompare {
    bool operator()(ObjectLayerT::ObjSetHandleT H1,
                    ObjectLayerT::ObjSetHandleT H2) const {
      return &*H1 < &*H2;
    }
  };
  SectionAddrSet m_SectionsAllocatedSinceLastLoad;
  std::map<ObjectLayerT::ObjSetHandleT, SectionAddrSet, ObjSetHandleCompare>
    m_UnfinalizedSections;

  ///\brief Vector of ModuleSetHandleT. UnloadHandles index into that
  /// vector.
  std::vector<ModuleSetHandleT> m_UnloadPoints;


  std::string Mangle(llvm::StringRef Name) {
    std::string MangledName;
    {
      llvm::raw_string_ostream MangledNameStream(MangledName);
      llvm::Mangler::getNameWithPrefix(MangledNameStream, Name,
                                       m_TMDataLayout);
    }
    return MangledName;
  }

  llvm::orc::JITSymbol getInjectedSymbols(llvm::StringRef Name) const;

public:
  IncrementalJIT(IncrementalExecutor& exe,
                 std::unique_ptr<llvm::TargetMachine> TM);

  ///\brief Get the address of a symbol from the JIT or the memory manager,
  /// mangling the name as needed. Use this to resolve symbols as coming
  /// from clang's mangler.
  /// \param Name - name to look for. This name might still get mangled
  ///   (prefixed by '_') to make IR versus symbol names.
  /// \param AlsoInProcess - Sometimes you only care about JITed symbols. If so,
  ///   pass `false` here to not resolve the symbol through dlsym().
  uint64_t getSymbolAddress(llvm::StringRef Name, bool AlsoInProcess) {
    return getSymbolAddressWithoutMangling(Mangle(Name), AlsoInProcess)
      .getAddress();
  }

  ///\brief Get the address of a symbol from the JIT or the memory manager.
  /// Use this to resolve symbols of known, target-specific names.
  llvm::orc::JITSymbol getSymbolAddressWithoutMangling(llvm::StringRef Name,
                                                       bool AlsoInProcess);

  size_t addModules(std::vector<llvm::Module*>&& modules);
  void removeModules(size_t handle);

  IncrementalExecutor& getParent() const { return m_Parent; }

  void
  RemoveUnfinalizedSection(llvm::orc::ObjectLinkingLayerBase::ObjSetHandleT H) {
    m_UnfinalizedSections.erase(H);
  }
};
} // end cling
#endif // CLING_INCREMENTAL_EXECUTOR_H
<commit_msg>Very likely fix GCC access check issue.<commit_after>//--------------------------------------------------------------------*- C++ -*-
// CLING - the C++ LLVM-based InterpreterG :)
// author:  <NAME> <<EMAIL>>
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------

#ifndef CLING_INCREMENTAL_JIT_H
#define CLING_INCREMENTAL_JIT_H

#include <map>
#include <memory>
#include <set>
#include <string>
#include <vector>

#include "llvm/IR/Mangler.h"
#include "llvm/IR/GlobalValue.h"
#include "llvm/ExecutionEngine/JITEventListener.h"
#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
#include "llvm/ExecutionEngine/Orc/LazyEmittingLayer.h"
#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
#include "llvm/Target/TargetMachine.h"

namespace llvm {
class Module;
class RTDyldMemoryManager;
}

namespace cling {
class Azog;
class IncrementalExecutor;

class IncrementalJIT {
public:
  using SymbolMapT = llvm::StringMap<llvm::orc::TargetAddress>;

private:
  friend class Azog;

  ///\brief The IncrementalExecutor who owns us.
  IncrementalExecutor& m_Parent;
  llvm::JITEventListener* m_GDBListener; // owned by llvm::ManagedStaticBase

  SymbolMapT m_SymbolMap;

  class NotifyObjectLoadedT {
  public:
    typedef std::vector<std::unique_ptr<llvm::object::OwningBinary<llvm::object::ObjectFile>>> ObjListT;
    typedef std::vector<std::unique_ptr<llvm::RuntimeDyld::LoadedObjectInfo>>
      LoadedObjInfoListT;

    NotifyObjectLoadedT(IncrementalJIT &jit) : m_JIT(jit) {}

    void operator()(llvm::orc::ObjectLinkingLayerBase::ObjSetHandleT H,
                    const ObjListT &Objects,
                    const LoadedObjInfoListT &Infos) const
    {
      m_JIT.m_UnfinalizedSections[H]
        = std::move(m_JIT.m_SectionsAllocatedSinceLastLoad);
      m_JIT.m_SectionsAllocatedSinceLastLoad = SectionAddrSet();
      assert(Objects.size() == Infos.size() &&
             "Incorrect number of Infos for Objects.");
      if (auto GDBListener = m_JIT.m_GDBListener) {
        for (size_t I = 0, N = Objects.size(); I < N; ++I)
          GDBListener->NotifyObjectEmitted(*Objects[I]->getBinary(),
                                           *Infos[I]);
      }

      for (const auto &Object: Objects) {
        for (const auto &Symbol: Object->getBinary()->symbols()) {
          auto Flags = Symbol.getFlags();
          if (Flags & llvm::object::BasicSymbolRef::SF_Undefined)
            continue;
          // FIXME: this should be uncommented once we serve incremental
          // modules from a TU module.
          //if (!(Flags & llvm::object::BasicSymbolRef::SF_Exported))
          //  continue;
          auto NameOrError = Symbol.getName();
          assert(NameOrError);
          auto Name = NameOrError.get();
          if (m_JIT.m_SymbolMap.find(Name) == m_JIT.m_SymbolMap.end()) {
            llvm::orc::JITSymbol Sym
              = m_JIT.m_CompileLayer.findSymbolIn(H, Name, true);
            if (llvm::orc::TargetAddress Addr = Sym.getAddress())
              m_JIT.m_SymbolMap[Name] = Addr;
          }
        }
      }
    }

  private:
    IncrementalJIT &m_JIT;
  };

  class RemovableObjectLinkingLayer:
    public llvm::orc::ObjectLinkingLayer<NotifyObjectLoadedT> {
  public:
    using Base_t = llvm::orc::ObjectLinkingLayer<NotifyObjectLoadedT>;
    using NotifyLoadedFtor = NotifyObjectLoadedT;
    using NotifyFinalizedFtor = typename Base_t::NotifyFinalizedFtor;
    RemovableObjectLinkingLayer(SymbolMapT &SymMap,
                                NotifyObjectLoadedT NotifyLoaded,
                   NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor()):
      Base_t(NotifyLoaded, NotifyFinalized), m_SymbolMap(SymMap)
    {}

    void removeObjectSet(llvm::orc::ObjectLinkingLayerBase::ObjSetHandleT H) {
      struct AccessSymbolTable: public LinkedObjectSet {
        const llvm::StringMap<llvm::RuntimeDyld::SymbolInfo>&
        getSymbolTable() const
        {
          return SymbolTable;
        }
      };
      const AccessSymbolTable* HSymTable
        = static_cast<const AccessSymbolTable*>(H->get());
      for (auto&& NameSym: HSymTable->getSymbolTable()) {
        auto iterSymMap = m_SymbolMap.find(NameSym.first());
        if (iterSymMap == m_SymbolMap.end())
          continue;
        // Is this this symbol (address)?
        if (iterSymMap->second == NameSym.second.getAddress())
          m_SymbolMap.erase(iterSymMap);
      }
      llvm::orc::ObjectLinkingLayer<NotifyObjectLoadedT>::removeObjectSet(H);
    }
  private:
    SymbolMapT& m_SymbolMap;
  };

  typedef RemovableObjectLinkingLayer ObjectLayerT;
  typedef llvm::orc::IRCompileLayer<ObjectLayerT> CompileLayerT;
  typedef llvm::orc::LazyEmittingLayer<CompileLayerT> LazyEmitLayerT;
  typedef LazyEmitLayerT::ModuleSetHandleT ModuleSetHandleT;

  std::unique_ptr<llvm::TargetMachine> m_TM;
  llvm::DataLayout m_TMDataLayout;

  ///\brief The RTDyldMemoryManager used to communicate with the
  /// IncrementalExecutor to handle missing or special symbols.
  std::unique_ptr<llvm::RTDyldMemoryManager> m_ExeMM;

  NotifyObjectLoadedT m_NotifyObjectLoaded;

  ObjectLayerT m_ObjectLayer;
  CompileLayerT m_CompileLayer;
  LazyEmitLayerT m_LazyEmitLayer;

  // We need to store ObjLayerT::ObjSetHandles for each of the object sets
  // that have been emitted but not yet finalized so that we can forward the
  // mapSectionAddress calls appropriately.
  typedef std::set<const void *> SectionAddrSet;
  struct ObjSetHandleCompare {
    bool operator()(ObjectLayerT::ObjSetHandleT H1,
                    ObjectLayerT::ObjSetHandleT H2) const {
      return &*H1 < &*H2;
    }
  };
  SectionAddrSet m_SectionsAllocatedSinceLastLoad;
  std::map<ObjectLayerT::ObjSetHandleT, SectionAddrSet, ObjSetHandleCompare>
    m_UnfinalizedSections;

  ///\brief Vector of ModuleSetHandleT. UnloadHandles index into that
  /// vector.
  std::vector<ModuleSetHandleT> m_UnloadPoints;


  std::string Mangle(llvm::StringRef Name) {
    std::string MangledName;
    {
      llvm::raw_string_ostream MangledNameStream(MangledName);
      llvm::Mangler::getNameWithPrefix(MangledNameStream, Name,
                                       m_TMDataLayout);
    }
    return MangledName;
  }

  llvm::orc::JITSymbol getInjectedSymbols(llvm::StringRef Name) const;

public:
  IncrementalJIT(IncrementalExecutor& exe,
                 std::unique_ptr<llvm::TargetMachine> TM);

  ///\brief Get the address of a symbol from the JIT or the memory manager,
  /// mangling the name as needed. Use this to resolve symbols as coming
  /// from clang's mangler.
  /// \param Name - name to look for. This name might still get mangled
  ///   (prefixed by '_') to make IR versus symbol names.
  /// \param AlsoInProcess - Sometimes you only care about JITed symbols. If so,
  ///   pass `false` here to not resolve the symbol through dlsym().
  uint64_t getSymbolAddress(llvm::StringRef Name, bool AlsoInProcess) {
    return getSymbolAddressWithoutMangling(Mangle(Name), AlsoInProcess)
      .getAddress();
  }

  ///\brief Get the address of a symbol from the JIT or the memory manager.
  /// Use this to resolve symbols of known, target-specific names.
  llvm::orc::JITSymbol getSymbolAddressWithoutMangling(llvm::StringRef Name,
                                                       bool AlsoInProcess);

  size_t addModules(std::vector<llvm::Module*>&& modules);
  void removeModules(size_t handle);

  IncrementalExecutor& getParent() const { return m_Parent; }

  void
  RemoveUnfinalizedSection(llvm::orc::ObjectLinkingLayerBase::ObjSetHandleT H) {
    m_UnfinalizedSections.erase(H);
  }
};
} // end cling
#endif // CLING_INCREMENTAL_EXECUTOR_H

{'fraction_non_alphanumeric': 0.12101631116687578, 'fraction_numerical': 0.0008782936010037642, 'mean_word_length': 3.125517598343685, 'pattern_counts': {'":': 0, '<': 63, '<?xml version=': 0, '>': 73, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 10, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4717108', 'n_tokens_mistral': 4866, 'n_tokens_neox': 4740, 'n_words': 1068}