2015-02-03 21:32:09 +01:00
//--------------------------------------------------------------------*- 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
2016-12-14 15:32:18 -05:00
# include "cling/Utils/Output.h"
2015-02-03 21:32:09 +01:00
# include <map>
# include <memory>
# include <set>
# include <string>
# include <vector>
# include "llvm/IR/Mangler.h"
# include "llvm/IR/GlobalValue.h"
2015-02-25 11:25:50 +01:00
# include "llvm/ExecutionEngine/JITEventListener.h"
2015-02-03 21:32:09 +01:00
# include "llvm/ExecutionEngine/Orc/CompileUtils.h"
# include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
# include "llvm/ExecutionEngine/Orc/LazyEmittingLayer.h"
# include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
2015-02-25 11:25:50 +01:00
# include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
2015-02-03 21:32:09 +01:00
# include "llvm/Target/TargetMachine.h"
namespace llvm {
2016-06-17 22:12:53 +02:00
class Module ;
class RTDyldMemoryManager ;
2015-02-03 21:32:09 +01:00
}
namespace cling {
class Azog ;
class IncrementalExecutor ;
class IncrementalJIT {
2016-06-17 22:12:53 +02:00
public :
using SymbolMapT = llvm : : StringMap < llvm : : orc : : TargetAddress > ;
private :
2015-02-03 21:32:09 +01:00
friend class Azog ;
///\brief The IncrementalExecutor who owns us.
IncrementalExecutor & m_Parent ;
2015-03-19 16:17:58 +01:00
llvm : : JITEventListener * m_GDBListener ; // owned by llvm::ManagedStaticBase
2015-02-03 21:32:09 +01:00
2016-06-17 22:12:53 +02:00
SymbolMapT m_SymbolMap ;
2016-05-30 17:08:28 +02:00
2015-02-03 21:32:09 +01:00
class NotifyObjectLoadedT {
public :
2016-04-22 15:13:51 +02:00
typedef std : : vector < std : : unique_ptr < llvm : : object : : OwningBinary < llvm : : object : : ObjectFile > > > ObjListT ;
2015-02-03 21:32:09 +01:00
typedef std : : vector < std : : unique_ptr < llvm : : RuntimeDyld : : LoadedObjectInfo > >
2016-06-17 22:12:53 +02:00
LoadedObjInfoListT ;
2015-02-03 21:32:09 +01:00
NotifyObjectLoadedT ( IncrementalJIT & jit ) : m_JIT ( jit ) { }
2016-04-22 15:13:51 +02:00
void operator ( ) ( llvm : : orc : : ObjectLinkingLayerBase : : ObjSetHandleT H ,
2015-02-03 21:32:09 +01:00
const ObjListT & Objects ,
2016-06-17 22:12:53 +02:00
const LoadedObjInfoListT & Infos ) const
{
2015-02-03 21:32:09 +01:00
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. " ) ;
2016-04-28 09:58:03 +02:00
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 ] ) ;
}
2016-05-30 17:08:28 +02:00
2016-06-17 22:12:53 +02:00
for ( const auto & Object : Objects ) {
2016-05-30 17:08:28 +02:00
for ( const auto & Symbol : Object - > getBinary ( ) - > symbols ( ) ) {
auto Flags = Symbol . getFlags ( ) ;
if ( Flags & llvm : : object : : BasicSymbolRef : : SF_Undefined )
continue ;
2016-06-03 08:36:47 +02:00
// FIXME: this should be uncommented once we serve incremental
// modules from a TU module.
//if (!(Flags & llvm::object::BasicSymbolRef::SF_Exported))
// continue;
2016-05-30 17:08:28 +02:00
auto NameOrError = Symbol . getName ( ) ;
2016-07-05 16:28:33 -05:00
if ( ! NameOrError )
continue ;
2016-05-30 17:08:28 +02:00
auto Name = NameOrError . get ( ) ;
if ( m_JIT . m_SymbolMap . find ( Name ) = = m_JIT . m_SymbolMap . end ( ) ) {
2016-06-17 22:12:53 +02:00
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 ;
2016-05-30 17:08:28 +02:00
}
}
}
2016-06-17 22:12:53 +02:00
}
2015-02-03 21:32:09 +01:00
private :
IncrementalJIT & m_JIT ;
} ;
2016-06-17 22:12:53 +02:00
class RemovableObjectLinkingLayer :
public llvm : : orc : : ObjectLinkingLayer < NotifyObjectLoadedT > {
public :
using Base_t = llvm : : orc : : ObjectLinkingLayer < NotifyObjectLoadedT > ;
using NotifyLoadedFtor = NotifyObjectLoadedT ;
2016-08-18 14:22:32 -04:00
using NotifyFinalizedFtor = Base_t : : NotifyFinalizedFtor ;
2016-06-17 22:12:53 +02:00
RemovableObjectLinkingLayer ( SymbolMapT & SymMap ,
NotifyObjectLoadedT NotifyLoaded ,
NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor ( ) ) :
Base_t ( NotifyLoaded , NotifyFinalized ) , m_SymbolMap ( SymMap )
{ }
void removeObjectSet ( llvm : : orc : : ObjectLinkingLayerBase : : ObjSetHandleT H ) {
2016-06-26 17:13:09 +03:00
struct AccessSymbolTable : public LinkedObjectSet {
2016-06-17 22:12:53 +02:00
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 ;
2016-04-22 15:13:51 +02:00
typedef llvm : : orc : : IRCompileLayer < ObjectLayerT > CompileLayerT ;
typedef llvm : : orc : : LazyEmittingLayer < CompileLayerT > LazyEmitLayerT ;
2015-02-03 21:32:09 +01:00
typedef LazyEmitLayerT : : ModuleSetHandleT ModuleSetHandleT ;
std : : unique_ptr < llvm : : TargetMachine > m_TM ;
2016-04-22 15:13:51 +02:00
llvm : : DataLayout m_TMDataLayout ;
2015-02-03 21:32:09 +01:00
///\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 >
2016-06-17 22:12:53 +02:00
m_UnfinalizedSections ;
2015-02-03 21:32:09 +01:00
///\brief Vector of ModuleSetHandleT. UnloadHandles index into that
/// vector.
std : : vector < ModuleSetHandleT > m_UnloadPoints ;
std : : string Mangle ( llvm : : StringRef Name ) {
2016-12-14 15:32:18 -05:00
stdstrstream MangledName ;
llvm : : Mangler : : getNameWithPrefix ( MangledName , Name , m_TMDataLayout ) ;
return MangledName . str ( ) ;
2015-02-03 21:32:09 +01:00
}
2016-09-18 20:23:45 -04:00
llvm : : orc : : JITSymbol getInjectedSymbols ( const std : : string & Name ) const ;
2016-06-14 11:07:29 +02:00
2015-02-03 21:32:09 +01:00
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.
2015-12-04 12:25:14 +01:00
/// \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().
2016-09-18 20:23:45 -04:00
uint64_t getSymbolAddress ( const std : : string & Name , bool AlsoInProcess ) {
2016-04-22 15:13:51 +02:00
return getSymbolAddressWithoutMangling ( Mangle ( Name ) , AlsoInProcess )
. getAddress ( ) ;
2015-02-03 21:32:09 +01:00
}
///\brief Get the address of a symbol from the JIT or the memory manager.
/// Use this to resolve symbols of known, target-specific names.
2016-09-18 20:23:45 -04:00
llvm : : orc : : JITSymbol getSymbolAddressWithoutMangling ( const std : : string & Name ,
2016-04-22 15:13:51 +02:00
bool AlsoInProcess ) ;
2015-02-03 21:32:09 +01:00
size_t addModules ( std : : vector < llvm : : Module * > & & modules ) ;
void removeModules ( size_t handle ) ;
IncrementalExecutor & getParent ( ) const { return m_Parent ; }
2016-04-29 10:55:56 +02:00
void
RemoveUnfinalizedSection ( llvm : : orc : : ObjectLinkingLayerBase : : ObjSetHandleT H ) {
m_UnfinalizedSections . erase ( H ) ;
}
2016-09-30 19:20:52 -04:00
///\brief Get the address of a symbol from the process' loaded libraries.
/// \param Name - symbol to look for
/// \param Addr - known address of the symbol that can be cached later use
2016-10-01 00:36:12 -04:00
/// \param Jit - add to the injected symbols cache
2016-09-30 19:20:52 -04:00
/// \returns The address of the symbol and whether it was cached
2016-10-01 00:36:12 -04:00
std : : pair < void * , bool >
lookupSymbol ( llvm : : StringRef Name , void * Addr = nullptr , bool Jit = false ) ;
2015-02-03 21:32:09 +01:00
} ;
} // end cling
# endif // CLING_INCREMENTAL_EXECUTOR_H