2012-09-05 13:37:39 +04:00
//--------------------------------------------------------------------*- C++ -*-
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id$
// author: Axel Naumann <axel@cern.ch>
//------------------------------------------------------------------------------
# include "ExecutionContext.h"
2012-10-05 16:09:51 +04:00
# include "cling/Interpreter/StoredValueRef.h"
2012-09-05 13:37:39 +04:00
2012-11-20 20:24:02 +04:00
# include "llvm/Constants.h"
2012-09-05 13:37:39 +04:00
# include "llvm/Module.h"
# include "llvm/PassManager.h"
2012-11-17 20:28:14 +04:00
# include "llvm/ADT/SmallPtrSet.h"
2012-09-05 13:37:39 +04:00
# include "llvm/Analysis/Verifier.h"
# include "llvm/Assembly/PrintModulePass.h"
# include "llvm/ExecutionEngine/JIT.h"
# include "llvm/Support/raw_ostream.h"
# include "llvm/Support/DynamicLibrary.h"
using namespace cling ;
std : : set < std : : string > ExecutionContext : : m_unresolvedSymbols ;
std : : vector < ExecutionContext : : LazyFunctionCreatorFunc_t >
ExecutionContext : : m_lazyFuncCreator ;
2012-10-25 18:50:54 +04:00
bool ExecutionContext : : m_LazyFuncCreatorDiagsSuppressed = false ;
2012-10-25 13:17:45 +04:00
2012-11-17 16:09:08 +04:00
// Keep in source: OwningPtr<ExecutionEngine> needs #include ExecutionEngine
2012-09-05 13:37:39 +04:00
ExecutionContext : : ExecutionContext ( ) :
m_RunningStaticInits ( false ) ,
m_CxaAtExitRemapped ( false )
2012-11-17 16:09:08 +04:00
{ }
// Keep in source: ~OwningPtr<ExecutionEngine> needs #include ExecutionEngine
ExecutionContext : : ~ ExecutionContext ( ) { }
2012-09-05 13:37:39 +04:00
void
ExecutionContext : : InitializeBuilder ( llvm : : Module * m )
{
//
// Create an execution engine to use.
//
assert ( m & & " Module cannot be null " ) ;
2012-11-17 15:29:35 +04:00
// Note: Engine takes ownership of the module.
2012-09-05 13:37:39 +04:00
llvm : : EngineBuilder builder ( m ) ;
2012-11-17 15:29:35 +04:00
2012-09-05 13:37:39 +04:00
std : : string errMsg ;
builder . setErrorStr ( & errMsg ) ;
2012-11-17 15:29:35 +04:00
builder . setOptLevel ( llvm : : CodeGenOpt : : Less ) ;
2012-09-05 13:37:39 +04:00
builder . setEngineKind ( llvm : : EngineKind : : JIT ) ;
builder . setAllocateGVsWithCode ( false ) ;
2012-11-17 16:09:08 +04:00
// EngineBuilder uses default c'ted TargetOptions, too:
llvm : : TargetOptions TargetOpts ;
TargetOpts . NoFramePointerElim = 1 ;
TargetOpts . JITExceptionHandling = 1 ;
TargetOpts . JITEmitDebugInfo = 1 ;
builder . setTargetOptions ( TargetOpts ) ;
m_engine . reset ( builder . create ( ) ) ;
2012-11-17 15:29:35 +04:00
if ( ! m_engine )
llvm : : errs ( ) < < " cling::ExecutionContext::InitializeBuilder(): " < < errMsg ;
assert ( m_engine & & " Cannot create module! " ) ;
2012-09-05 13:37:39 +04:00
2012-11-17 15:29:35 +04:00
// install lazy function creators
2012-09-05 13:37:39 +04:00
m_engine - > InstallLazyFunctionCreator ( NotifyLazyFunctionCreators ) ;
}
void unresolvedSymbol ( )
{
// throw exception?
2012-11-17 20:28:14 +04:00
llvm : : errs ( ) < < " ExecutionContext: calling unresolved symbol, "
" see previous error message! \n " ;
2012-09-05 13:37:39 +04:00
}
void * ExecutionContext : : HandleMissingFunction ( const std : : string & mangled_name )
{
// 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 ) {
llvm : : errs ( ) < < " ExecutionContext: use of undefined symbol ' "
< < 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 *
ExecutionContext : : NotifyLazyFunctionCreators ( const std : : string & mangled_name )
{
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 ) ;
2012-10-25 16:58:50 +04:00
if ( ret )
return ret ;
2012-09-05 13:37:39 +04:00
}
2012-10-25 16:58:50 +04:00
2012-10-25 18:10:41 +04:00
if ( m_LazyFuncCreatorDiagsSuppressed )
2012-10-25 16:58:50 +04:00
return 0 ;
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 ] ;
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 ) ;
}
}
2012-11-16 00:55:43 +04:00
ExecutionContext : : ExecutionResult
2012-09-05 13:37:39 +04:00
ExecutionContext : : executeFunction ( llvm : : StringRef funcname ,
2012-10-05 16:09:51 +04:00
const clang : : ASTContext & Ctx ,
clang : : QualType retType ,
StoredValueRef * returnValue )
2012-09-05 13:37:39 +04:00
{
// Call a function without arguments, or with an SRet argument, see SRet below
if ( ! m_CxaAtExitRemapped ) {
// Rewire atexit:
llvm : : Function * atExit = m_engine - > FindFunctionNamed ( " __cxa_atexit " ) ;
2012-11-17 20:28:14 +04:00
llvm : : Function * clingAtExit
= m_engine - > FindFunctionNamed ( " cling_cxa_atexit " ) ;
2012-09-05 13:37:39 +04:00
if ( atExit & & clingAtExit ) {
void * clingAtExitAddr = m_engine - > getPointerToFunction ( clingAtExit ) ;
assert ( clingAtExitAddr & & " cannot find cling_cxa_atexit " ) ;
m_engine - > updateGlobalMapping ( atExit , clingAtExitAddr ) ;
m_CxaAtExitRemapped = true ;
}
}
// We don't care whether something was unresolved before.
m_unresolvedSymbols . clear ( ) ;
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 ) {
2012-11-17 20:28:14 +04:00
llvm : : errs ( ) < < " ExecutionContext::executeFunction: "
" 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
}
m_engine - > getPointerToFunction ( f ) ;
// 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 ) {
2012-11-17 20:28:14 +04:00
llvm : : errs ( ) < < " ExecutionContext::executeFunction: symbol ' " < < * i
< < " ' unresolved while linking function ' " < < funcname
< < " '! \n " ;
2012-09-05 13:37:39 +04:00
llvm : : Function * ff = m_engine - > FindFunctionNamed ( i - > c_str ( ) ) ;
assert ( ff & & " cannot find function to free " ) ;
2012-11-17 20:28:14 +04:00
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
}
std : : vector < llvm : : GenericValue > args ;
bool wantReturn = ( returnValue ) ;
2012-10-05 16:09:51 +04:00
StoredValueRef aggregateRet ;
2012-09-05 13:37:39 +04:00
if ( f - > hasStructRetAttr ( ) ) {
// Function expects to receive the storage for the returned aggregate as
2012-10-05 16:09:51 +04:00
// first argument. Allocate returnValue:
aggregateRet = StoredValueRef : : allocate ( Ctx , retType ) ;
if ( returnValue ) {
* returnValue = aggregateRet ;
} else {
returnValue = & aggregateRet ;
}
args . push_back ( returnValue - > get ( ) . value ) ;
2012-09-05 13:37:39 +04:00
// will get set as arg0, must not assign.
wantReturn = false ;
}
if ( wantReturn ) {
2012-10-05 16:09:51 +04:00
llvm : : GenericValue gvRet = m_engine - > runFunction ( f , args ) ;
// rescue the ret value (which might be aggregate) from the stack
* returnValue = StoredValueRef : : bitwiseCopy ( Ctx , Value ( gvRet , retType ) ) ;
2012-09-05 13:37:39 +04:00
} else {
m_engine - > runFunction ( f , args ) ;
}
2012-11-16 00:55:43 +04:00
return kExeSuccess ;
2012-09-05 13:37:39 +04:00
}
2012-11-20 20:24:02 +04:00
ExecutionContext : : ExecutionResult
2012-09-05 13:37:39 +04:00
ExecutionContext : : runStaticInitializersOnce ( llvm : : Module * m ) {
assert ( m & & " Module must not be null " ) ;
if ( ! m_engine )
InitializeBuilder ( m ) ;
assert ( m_engine & & " Code generation did not create an engine! " ) ;
2012-11-20 20:24:02 +04:00
if ( m_RunningStaticInits )
return kExeSuccess ;
2012-09-05 13:37:39 +04:00
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 ( ) ) ;
if ( InitList = = 0 )
return kExeSuccess ;
2012-09-05 13:37:39 +04:00
2012-11-20 20:24:02 +04:00
m_RunningStaticInits = true ;
// 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 ) ) {
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 ) {
llvm : : errs ( ) < < " ExecutionContext::runStaticInitializersOnce: symbol ' " < < * i
< < " ' 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 ( ) ;
m_RunningStaticInits = false ;
return kExeUnresolvedSymbols ;
}
m_engine - > runFunction ( F , std : : vector < llvm : : GenericValue > ( ) ) ;
}
2012-09-05 13:37:39 +04:00
}
2012-11-20 20:24:02 +04:00
GV - > eraseFromParent ( ) ;
m_RunningStaticInits = false ;
return kExeSuccess ;
2012-09-05 13:37:39 +04:00
}
void
ExecutionContext : : runStaticDestructorsOnce ( llvm : : Module * m ) {
assert ( m & & " Module must not be null " ) ;
assert ( m_engine & & " Code generation did not create an engine! " ) ;
llvm : : GlobalVariable * gdtors
= m - > getGlobalVariable ( " llvm.global_dtors " , true ) ;
if ( gdtors ) {
m_engine - > runStaticConstructorsDestructors ( true ) ;
}
}
int
ExecutionContext : : verifyModule ( llvm : : Module * m )
{
//
// Verify generated module.
//
bool mod_has_errs = llvm : : verifyModule ( * m , llvm : : PrintMessageAction ) ;
if ( mod_has_errs ) {
return 1 ;
}
return 0 ;
}
void
ExecutionContext : : printModule ( llvm : : Module * m )
{
//
// Print module LLVM code in human-readable form.
//
llvm : : PassManager PM ;
PM . add ( llvm : : createPrintModulePass ( & llvm : : outs ( ) ) ) ;
PM . run ( * m ) ;
}
void
ExecutionContext : : installLazyFunctionCreator ( LazyFunctionCreatorFunc_t fp )
{
m_lazyFuncCreator . push_back ( fp ) ;
}
2012-09-24 13:57:43 +04:00
bool ExecutionContext : : addSymbol ( const char * symbolName , void * symbolAddress ) {
2012-09-05 13:37:39 +04:00
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
2012-09-24 16:11:46 +04:00
void * ExecutionContext : : getAddressOfGlobal ( llvm : : Module * m ,
const char * symbolName ,
bool * fromJIT /*=0*/ ) const {
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
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 ;
}