151 lines
4.8 KiB
C++
151 lines
4.8 KiB
C++
//--------------------------------------------------------------------*- C++ -*-
|
|
// CLING - the C++ LLVM-based InterpreterG :)
|
|
// author: Axel Naumann <axel@cern.ch>
|
|
//
|
|
// 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/RTDyldMemoryManager.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/Target/TargetMachine.h"
|
|
|
|
namespace llvm {
|
|
class Module;
|
|
class RTDyldMemoryManager;
|
|
}
|
|
|
|
namespace cling {
|
|
class Azog;
|
|
class IncrementalExecutor;
|
|
|
|
class IncrementalJIT {
|
|
friend class Azog;
|
|
|
|
///\brief The IncrementalExecutor who owns us.
|
|
IncrementalExecutor& m_Parent;
|
|
|
|
class NotifyObjectLoadedT {
|
|
public:
|
|
typedef std::vector<std::unique_ptr<llvm::object::ObjectFile>> ObjListT;
|
|
typedef std::vector<std::unique_ptr<llvm::RuntimeDyld::LoadedObjectInfo>>
|
|
LoadedObjInfoListT;
|
|
|
|
NotifyObjectLoadedT(IncrementalJIT &jit) : m_JIT(jit) {}
|
|
|
|
void operator()(llvm::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.");
|
|
// We are no ExecutionEngine.
|
|
//for (unsigned I = 0; I < Objects.size(); ++I)
|
|
// m_JIT.m_ExeMM->notifyObjectLoaded(&m_JIT, *Objects[I]);
|
|
};
|
|
|
|
private:
|
|
IncrementalJIT &m_JIT;
|
|
};
|
|
|
|
class NotifyFinalizedT {
|
|
public:
|
|
NotifyFinalizedT(IncrementalJIT &jit) : m_JIT(jit) {}
|
|
void operator()(llvm::ObjectLinkingLayerBase::ObjSetHandleT H) {
|
|
m_JIT.m_UnfinalizedSections.erase(H);
|
|
}
|
|
|
|
private:
|
|
IncrementalJIT &m_JIT;
|
|
};
|
|
|
|
|
|
typedef llvm::ObjectLinkingLayer<NotifyObjectLoadedT> ObjectLayerT;
|
|
typedef llvm::IRCompileLayer<ObjectLayerT> CompileLayerT;
|
|
typedef llvm::LazyEmittingLayer<CompileLayerT> LazyEmitLayerT;
|
|
typedef LazyEmitLayerT::ModuleSetHandleT ModuleSetHandleT;
|
|
|
|
std::unique_ptr<llvm::TargetMachine> m_TM;
|
|
///\brief The RTDyldMemoryManager used to communicate with the
|
|
/// IncrementalExecutor to handle missing or special symbols.
|
|
std::unique_ptr<llvm::RTDyldMemoryManager> m_ExeMM;
|
|
|
|
///\brief Target symbol mangler.
|
|
llvm::Mangler m_Mang;
|
|
|
|
NotifyObjectLoadedT m_NotifyObjectLoaded;
|
|
NotifyFinalizedT m_NotifyFinalized;
|
|
|
|
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);
|
|
m_Mang.getNameWithPrefix(MangledNameStream, Name);
|
|
}
|
|
return MangledName;
|
|
}
|
|
|
|
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.
|
|
uint64_t getSymbolAddress(llvm::StringRef Name) {
|
|
return getSymbolAddressWithoutMangling(Mangle(Name));
|
|
}
|
|
|
|
///\brief Get the address of a symbol from the JIT or the memory manager.
|
|
/// Use this to resolve symbols of known, target-specific names.
|
|
uint64_t getSymbolAddressWithoutMangling(llvm::StringRef Name);
|
|
|
|
size_t addModules(std::vector<llvm::Module*>&& modules);
|
|
void removeModules(size_t handle);
|
|
|
|
IncrementalExecutor& getParent() const { return m_Parent; }
|
|
//void finalizeMemory();
|
|
};
|
|
} // end cling
|
|
#endif // CLING_INCREMENTAL_EXECUTOR_H
|