2012-09-05 13:37:39 +04:00
//--------------------------------------------------------------------*- C++ -*-
// CLING - the C++ LLVM-based InterpreterG :)
// author: Axel Naumann <axel@cern.ch>
2014-01-07 14:08:37 +04:00
//
// 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.
2012-09-05 13:37:39 +04:00
//------------------------------------------------------------------------------
2014-02-19 15:49:24 +04:00
# include "IncrementalExecutor.h"
2012-09-05 13:37:39 +04:00
2013-04-24 20:28:08 +04:00
# include "llvm/IR/Constants.h"
2013-11-01 21:31:18 +04:00
# include "llvm/IR/LLVMContext.h"
2013-04-24 20:28:08 +04:00
# include "llvm/IR/Module.h"
2012-09-05 13:37:39 +04:00
# include "llvm/PassManager.h"
2012-11-17 20:28:14 +04:00
# include "llvm/ADT/SmallPtrSet.h"
2013-02-22 19:59:54 +04:00
# include "llvm/ExecutionEngine/GenericValue.h"
2012-09-05 13:37:39 +04:00
# include "llvm/ExecutionEngine/JIT.h"
# include "llvm/Support/raw_ostream.h"
# include "llvm/Support/DynamicLibrary.h"
2014-03-07 18:09:02 +04:00
using namespace llvm ;
namespace cling {
2012-09-05 13:37:39 +04:00
2014-02-19 15:49:24 +04:00
std : : set < std : : string > IncrementalExecutor : : m_unresolvedSymbols ;
std : : vector < IncrementalExecutor : : LazyFunctionCreatorFunc_t >
IncrementalExecutor : : m_lazyFuncCreator ;
2012-09-05 13:37:39 +04:00
2012-11-17 16:09:08 +04:00
// Keep in source: OwningPtr<ExecutionEngine> needs #include ExecutionEngine
2014-02-28 20:30:56 +04:00
IncrementalExecutor : : IncrementalExecutor ( llvm : : Module * m )
: m_CxaAtExitRemapped ( false ) {
2013-06-25 11:21:14 +04:00
assert ( m & & " llvm::Module must not be null! " ) ;
2013-09-19 13:24:31 +04:00
m_AtExitFuncs . reserve ( 256 ) ;
2014-02-28 20:30:56 +04:00
//
// Create an execution engine to use.
//
assert ( m & & " Module cannot be null " ) ;
// Note: Engine takes ownership of the module.
llvm : : EngineBuilder builder ( m ) ;
std : : string errMsg ;
builder . setErrorStr ( & errMsg ) ;
builder . setOptLevel ( llvm : : CodeGenOpt : : Less ) ;
builder . setEngineKind ( llvm : : EngineKind : : JIT ) ;
builder . setAllocateGVsWithCode ( false ) ;
// EngineBuilder uses default c'ted TargetOptions, too:
llvm : : TargetOptions TargetOpts ;
TargetOpts . NoFramePointerElim = 1 ;
TargetOpts . JITEmitDebugInfo = 1 ;
builder . setTargetOptions ( TargetOpts ) ;
m_engine . reset ( builder . create ( ) ) ;
if ( ! m_engine )
llvm : : errs ( ) < < " cling::IncrementalExecutor::IncrementalExecutor(): "
< < errMsg ;
assert ( m_engine & & " Cannot create module! " ) ;
// install lazy function creators
m_engine - > InstallLazyFunctionCreator ( NotifyLazyFunctionCreators ) ;
2013-06-25 11:21:14 +04:00
}
2012-11-17 16:09:08 +04:00
// Keep in source: ~OwningPtr<ExecutionEngine> needs #include ExecutionEngine
2014-02-19 15:49:24 +04:00
IncrementalExecutor : : ~ IncrementalExecutor ( ) { }
2013-10-03 18:58:48 +04:00
2014-02-19 15:49:24 +04:00
void IncrementalExecutor : : shuttingDown ( ) {
2013-09-19 13:24:31 +04:00
for ( size_t I = 0 , N = m_AtExitFuncs . size ( ) ; I < N ; + + I ) {
const CXAAtExitElement & AEE = m_AtExitFuncs [ N - I - 1 ] ;
( * AEE . m_Func ) ( AEE . m_Arg ) ;
}
}
2012-09-05 13:37:39 +04:00
2014-02-19 15:49:24 +04:00
void IncrementalExecutor : : remapCXAAtExit ( ) {
2014-03-04 21:15:14 +04:00
if ( m_CxaAtExitRemapped )
return ;
2013-11-01 21:31:18 +04:00
llvm : : Function * atExit = m_engine - > FindFunctionNamed ( " __cxa_atexit " ) ;
2014-03-04 21:15:14 +04:00
if ( ! atExit )
return ;
2013-11-01 21:31:18 +04:00
2014-03-04 21:15:14 +04:00
llvm : : Function * clingAtExit
= m_engine - > FindFunctionNamed ( " cling_cxa_atexit " ) ;
assert ( clingAtExit & & " cling_cxa_atexit must exist. " ) ;
2013-10-31 02:40:00 +04:00
void * clingAtExitAddr = m_engine - > getPointerToFunction ( clingAtExit ) ;
assert ( clingAtExitAddr & & " cannot find cling_cxa_atexit " ) ;
m_engine - > updateGlobalMapping ( atExit , clingAtExitAddr ) ;
m_CxaAtExitRemapped = true ;
}
2014-03-04 21:07:03 +04:00
void IncrementalExecutor : : AddAtExitFunc ( void ( * func ) ( void * ) , void * arg ,
2014-03-05 12:34:03 +04:00
const cling : : Transaction * T ) {
2013-09-19 13:24:31 +04:00
// Register a CXAAtExit function
2014-03-04 21:07:03 +04:00
m_AtExitFuncs . push_back ( CXAAtExitElement ( func , arg , T ) ) ;
2013-09-19 13:24:31 +04:00
}
2012-09-05 13:37:39 +04:00
void unresolvedSymbol ( )
{
// throw exception?
2014-02-19 15:49:24 +04:00
llvm : : errs ( ) < < " IncrementalExecutor: calling unresolved symbol, "
2012-11-17 20:28:14 +04:00
" see previous error message! \n " ;
2012-09-05 13:37:39 +04:00
}
2014-02-19 15:49:24 +04:00
void * IncrementalExecutor : : HandleMissingFunction ( const std : : string & mangled_name )
2012-09-05 13:37:39 +04:00
{
// Not found in the map, add the symbol in the list of unresolved symbols
2012-10-07 15:53:16 +04:00
if ( m_unresolvedSymbols . insert ( mangled_name ) . second ) {
2014-02-19 15:49:24 +04:00
llvm : : errs ( ) < < " IncrementalExecutor: use of undefined symbol ' "
2012-10-07 15:53:16 +04:00
< < mangled_name < < " '! \n " ;
}
2012-09-05 13:37:39 +04:00
// Avoid "ISO C++ forbids casting between pointer-to-function and
// pointer-to-object":
return ( void * ) reinterpret_cast < size_t > ( unresolvedSymbol ) ;
}
void *
2014-02-19 15:49:24 +04:00
IncrementalExecutor : : NotifyLazyFunctionCreators ( const std : : string & mangled_name )
2012-09-05 13:37:39 +04:00
{
for ( std : : vector < LazyFunctionCreatorFunc_t > : : iterator it
= m_lazyFuncCreator . begin ( ) , et = m_lazyFuncCreator . end ( ) ;
it ! = et ; + + it ) {
void * ret = ( void * ) ( ( LazyFunctionCreatorFunc_t ) * it ) ( mangled_name ) ;
2014-02-28 20:23:09 +04:00
if ( ret )
2012-10-25 16:58:50 +04:00
return ret ;
2012-09-05 13:37:39 +04:00
}
2012-10-25 16:58:50 +04:00
2012-09-05 13:37:39 +04:00
return HandleMissingFunction ( mangled_name ) ;
}
2012-11-17 20:28:14 +04:00
static void
freeCallersOfUnresolvedSymbols ( llvm : : SmallVectorImpl < llvm : : Function * > &
funcsToFree , llvm : : ExecutionEngine * engine ) {
llvm : : SmallPtrSet < llvm : : Function * , 40 > funcsToFreeUnique ;
for ( size_t i = 0 ; i < funcsToFree . size ( ) ; + + i ) {
llvm : : Function * func = funcsToFree [ i ] ;
2013-10-02 11:24:32 +04:00
assert ( func & & " Cannot free NULL function " ) ;
2012-11-17 20:28:14 +04:00
if ( funcsToFreeUnique . insert ( func ) ) {
for ( llvm : : Value : : use_iterator IU = func - > use_begin ( ) ,
EU = func - > use_end ( ) ; IU ! = EU ; + + IU ) {
llvm : : Instruction * instUser = llvm : : dyn_cast < llvm : : Instruction > ( * IU ) ;
if ( ! instUser ) continue ;
if ( ! instUser - > getParent ( ) ) continue ;
if ( llvm : : Function * userFunc = instUser - > getParent ( ) - > getParent ( ) )
funcsToFree . push_back ( userFunc ) ;
}
}
}
for ( llvm : : SmallPtrSet < llvm : : Function * , 40 > : : iterator
I = funcsToFreeUnique . begin ( ) , E = funcsToFreeUnique . end ( ) ;
I ! = E ; + + I ) {
// This should force the JIT to recompile the function. But the stubs stay,
// and the JIT reuses the stubs now pointing nowhere, i.e. without updating
// the machine code address. Fix the JIT, or hope that MCJIT helps.
//engine->freeMachineCodeForFunction(*I);
engine - > updateGlobalMapping ( * I , 0 ) ;
}
}
2014-02-19 15:49:24 +04:00
IncrementalExecutor : : ExecutionResult
IncrementalExecutor : : executeFunction ( llvm : : StringRef funcname ,
2012-10-05 16:09:51 +04:00
StoredValueRef * returnValue )
2012-09-05 13:37:39 +04:00
{
// Call a function without arguments, or with an SRet argument, see SRet below
// We don't care whether something was unresolved before.
m_unresolvedSymbols . clear ( ) ;
2014-03-04 21:15:14 +04:00
remapCXAAtExit ( ) ;
2012-11-17 20:28:14 +04:00
llvm : : Function * f = m_engine - > FindFunctionNamed ( funcname . str ( ) . c_str ( ) ) ;
2012-09-05 13:37:39 +04:00
if ( ! f ) {
2014-02-19 15:49:24 +04:00
llvm : : errs ( ) < < " IncrementalExecutor::executeFunction: "
2012-11-17 20:28:14 +04:00
" could not find function named " < < funcname < < ' \n ' ;
2012-11-16 00:55:43 +04:00
return kExeFunctionNotCompiled ;
2012-09-05 13:37:39 +04:00
}
2014-02-13 12:52:31 +04:00
typedef void ( * PromptWrapper_t ) ( void * ) ;
2014-02-19 13:03:04 +04:00
union {
PromptWrapper_t wrapperFunction ;
void * address ;
} p2f ;
p2f . address = m_engine - > getPointerToFunction ( f ) ;
2012-09-05 13:37:39 +04:00
// check if there is any unresolved symbol in the list
if ( ! m_unresolvedSymbols . empty ( ) ) {
2012-11-17 20:28:14 +04:00
llvm : : SmallVector < llvm : : Function * , 100 > funcsToFree ;
2012-09-05 13:37:39 +04:00
for ( std : : set < std : : string > : : const_iterator i = m_unresolvedSymbols . begin ( ) ,
e = m_unresolvedSymbols . end ( ) ; i ! = e ; + + i ) {
2014-02-19 15:49:24 +04:00
llvm : : errs ( ) < < " IncrementalExecutor::executeFunction: symbol ' " < < * i
2012-11-17 20:28:14 +04:00
< < " ' unresolved while linking function ' " < < funcname
< < " '! \n " ;
2012-09-05 13:37:39 +04:00
llvm : : Function * ff = m_engine - > FindFunctionNamed ( i - > c_str ( ) ) ;
2013-10-02 11:24:32 +04:00
// i could also reference a global variable, in which case ff == 0.
if ( ff )
funcsToFree . push_back ( ff ) ;
2012-09-05 13:37:39 +04:00
}
2012-11-17 20:28:14 +04:00
freeCallersOfUnresolvedSymbols ( funcsToFree , m_engine . get ( ) ) ;
2012-09-05 13:37:39 +04:00
m_unresolvedSymbols . clear ( ) ;
2012-11-16 00:55:43 +04:00
return kExeUnresolvedSymbols ;
2012-09-05 13:37:39 +04:00
}
2014-02-19 13:03:04 +04:00
// Run the function
( * p2f . wrapperFunction ) ( returnValue ) ;
2012-09-05 13:37:39 +04:00
2012-11-16 00:55:43 +04:00
return kExeSuccess ;
2012-09-05 13:37:39 +04:00
}
2014-02-19 15:49:24 +04:00
IncrementalExecutor : : ExecutionResult
IncrementalExecutor : : runStaticInitializersOnce ( llvm : : Module * m ) {
2012-09-05 13:37:39 +04:00
assert ( m & & " Module must not be null " ) ;
assert ( m_engine & & " Code generation did not create an engine! " ) ;
2012-11-20 20:24:02 +04:00
llvm : : GlobalVariable * GV
= m - > getGlobalVariable ( " llvm.global_ctors " , true ) ;
// Nothing to do is good, too.
if ( ! GV ) return kExeSuccess ;
// Close similarity to
// m_engine->runStaticConstructorsDestructors(false) aka
// llvm::ExecutionEngine::runStaticConstructorsDestructors()
// is intentional; we do an extra pass to check whether the JIT
// managed to collect all the symbols needed by the niitializers.
// Should be an array of '{ i32, void ()* }' structs. The first value is
// the init priority, which we ignore.
llvm : : ConstantArray * InitList
= llvm : : dyn_cast < llvm : : ConstantArray > ( GV - > getInitializer ( ) ) ;
2014-01-22 18:07:11 +04:00
GV - > eraseFromParent ( ) ;
2012-11-20 20:24:02 +04:00
if ( InitList = = 0 )
return kExeSuccess ;
2012-09-05 13:37:39 +04:00
2012-11-20 20:24:02 +04:00
// We don't care whether something was unresolved before.
m_unresolvedSymbols . clear ( ) ;
for ( unsigned i = 0 , e = InitList - > getNumOperands ( ) ; i ! = e ; + + i ) {
llvm : : ConstantStruct * CS
= llvm : : dyn_cast < llvm : : ConstantStruct > ( InitList - > getOperand ( i ) ) ;
if ( CS = = 0 ) continue ;
llvm : : Constant * FP = CS - > getOperand ( 1 ) ;
if ( FP - > isNullValue ( ) )
continue ; // Found a sentinal value, ignore.
// Strip off constant expression casts.
if ( llvm : : ConstantExpr * CE = llvm : : dyn_cast < llvm : : ConstantExpr > ( FP ) )
if ( CE - > isCast ( ) )
FP = CE - > getOperand ( 0 ) ;
// Execute the ctor/dtor function!
if ( llvm : : Function * F = llvm : : dyn_cast < llvm : : Function > ( FP ) ) {
2014-03-04 21:15:14 +04:00
remapCXAAtExit ( ) ;
2012-11-20 20:24:02 +04:00
m_engine - > getPointerToFunction ( F ) ;
// check if there is any unresolved symbol in the list
if ( ! m_unresolvedSymbols . empty ( ) ) {
llvm : : SmallVector < llvm : : Function * , 100 > funcsToFree ;
for ( std : : set < std : : string > : : const_iterator i = m_unresolvedSymbols . begin ( ) ,
e = m_unresolvedSymbols . end ( ) ; i ! = e ; + + i ) {
2014-02-19 15:49:24 +04:00
llvm : : errs ( ) < < " IncrementalExecutor::runStaticInitializersOnce: symbol ' " < < * i
2012-11-20 20:24:02 +04:00
< < " ' unresolved while linking static initializer ' "
< < F - > getName ( ) < < " '! \n " ;
llvm : : Function * ff = m_engine - > FindFunctionNamed ( i - > c_str ( ) ) ;
assert ( ff & & " cannot find function to free " ) ;
funcsToFree . push_back ( ff ) ;
}
freeCallersOfUnresolvedSymbols ( funcsToFree , m_engine . get ( ) ) ;
m_unresolvedSymbols . clear ( ) ;
return kExeUnresolvedSymbols ;
}
2014-03-07 18:09:56 +04:00
executeFunction ( F - > getName ( ) ) ;
//m_engine->runFunction(F, std::vector<llvm::GenericValue>());
// Cleanup also the dangling init functions. They are in the form:
// define internal void @_GLOBAL__I_aN() section "..."{
// entry:
// call void @__cxx_global_var_init(N-1)()
// ret void
// }
//
// define internal void @__cxx_global_var_init(N-1)() section "..." {
// entry:
// call void @_ZN7MyClassC1Ev(%struct.MyClass* @n)
// ret void
// }
// Erase __cxx_global_var_init(N-1)() first.
Function * GlobalVarInitF =
cast < Function > ( F - > getEntryBlock ( ) . getFirstNonPHI ( ) - > getOperand ( 0 ) ) ;
F - > eraseFromParent ( ) ;
GlobalVarInitF - > eraseFromParent ( ) ;
2012-11-20 20:24:02 +04:00
}
2012-09-05 13:37:39 +04:00
}
2012-11-20 20:24:02 +04:00
return kExeSuccess ;
2012-09-05 13:37:39 +04:00
}
2014-02-27 12:53:42 +04:00
void IncrementalExecutor : : runAndRemoveStaticDestructors ( Transaction * T ) {
assert ( T & & " Must be set " ) ;
// Collect all the dtors bound to this transaction.
AtExitFunctions boundToT ;
for ( AtExitFunctions : : iterator I = m_AtExitFuncs . begin ( ) ;
I ! = m_AtExitFuncs . end ( ) ; )
if ( I - > m_FromT = = T ) {
boundToT . push_back ( * I ) ;
I = m_AtExitFuncs . erase ( I ) ;
}
else
+ + I ;
2013-09-19 13:24:31 +04:00
// 'Unload' the cxa_atexit entities.
2014-02-27 12:53:42 +04:00
for ( AtExitFunctions : : reverse_iterator I = boundToT . rbegin ( ) ,
E = boundToT . rend ( ) ; I ! = E ; + + I ) {
2014-02-26 20:00:13 +04:00
const CXAAtExitElement & AEE = * I ;
2013-09-19 13:24:31 +04:00
( * AEE . m_Func ) ( AEE . m_Arg ) ;
}
2012-09-05 13:37:39 +04:00
}
void
2014-02-19 15:49:24 +04:00
IncrementalExecutor : : installLazyFunctionCreator ( LazyFunctionCreatorFunc_t fp )
2012-09-05 13:37:39 +04:00
{
m_lazyFuncCreator . push_back ( fp ) ;
}
2014-02-19 15:49:24 +04:00
bool
IncrementalExecutor : : addSymbol ( const char * symbolName , void * symbolAddress ) {
2012-09-24 13:57:43 +04:00
void * actualAddress
2012-09-05 13:37:39 +04:00
= llvm : : sys : : DynamicLibrary : : SearchForAddressOfSymbol ( symbolName ) ;
2012-09-24 13:57:43 +04:00
if ( actualAddress )
2012-09-05 13:37:39 +04:00
return false ;
llvm : : sys : : DynamicLibrary : : AddSymbol ( symbolName , symbolAddress ) ;
return true ;
}
2012-09-24 13:57:43 +04:00
2014-02-19 15:49:24 +04:00
void * IncrementalExecutor : : getAddressOfGlobal ( llvm : : Module * m ,
2014-03-03 14:48:16 +04:00
llvm : : StringRef symbolName ,
2014-03-04 21:15:14 +04:00
bool * fromJIT /*=0*/ ) {
2012-11-19 02:27:00 +04:00
// Return a symbol's address, and whether it was jitted.
void * address
= llvm : : sys : : DynamicLibrary : : SearchForAddressOfSymbol ( symbolName ) ;
if ( address ) {
if ( fromJIT ) * fromJIT = false ;
} else {
if ( fromJIT ) * fromJIT = true ;
llvm : : GlobalVariable * gvar = m - > getGlobalVariable ( symbolName , true ) ;
if ( ! gvar )
return 0 ;
2012-10-23 12:46:38 +04:00
2014-03-04 21:15:14 +04:00
remapCXAAtExit ( ) ;
2012-11-19 02:27:00 +04:00
address = m_engine - > getPointerToGlobal ( gvar ) ;
2012-09-24 13:57:43 +04:00
}
2012-11-19 02:27:00 +04:00
return address ;
}
2013-12-05 19:22:34 +04:00
void *
2014-03-04 21:15:14 +04:00
IncrementalExecutor : : getPointerToGlobalFromJIT ( const llvm : : GlobalValue & GV ) {
remapCXAAtExit ( ) ;
2013-12-05 19:22:34 +04:00
if ( void * addr = m_engine - > getPointerToGlobalIfAvailable ( & GV ) )
return addr ;
// Function not yet codegened by the JIT, force this to happen now.
return m_engine - > getPointerToGlobal ( & GV ) ;
}
2014-03-07 18:09:02 +04:00
} // end namespace cling