2012-09-05 13:37:39 +04:00
//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// version: $Id$
// author: Lukasz Janyst <ljanyst@cern.ch>
//------------------------------------------------------------------------------
# include "cling/Interpreter/Interpreter.h"
# include "DynamicLookup.h"
# include "ExecutionContext.h"
# include "IncrementalParser.h"
# include "cling/Interpreter/CIFactory.h"
2012-10-02 14:30:25 +04:00
# include "cling/Interpreter/CompilationOptions.h"
2012-09-05 13:37:39 +04:00
# include "cling/Interpreter/InterpreterCallbacks.h"
2012-10-02 14:30:25 +04:00
# include "cling/Interpreter/LookupHelper.h"
2012-10-05 16:09:51 +04:00
# include "cling/Interpreter/StoredValueRef.h"
2012-10-02 14:34:22 +04:00
# include "cling/Interpreter/Transaction.h"
2012-10-02 14:30:25 +04:00
# include "cling/Utils/AST.h"
2012-09-05 13:37:39 +04:00
# include "clang/AST/ASTContext.h"
# include "clang/AST/Mangle.h"
# include "clang/AST/DeclarationName.h"
# include "clang/Basic/TargetInfo.h"
# include "clang/CodeGen/ModuleBuilder.h"
# include "clang/Frontend/CompilerInstance.h"
# include "clang/Frontend/Utils.h"
# include "clang/Lex/Preprocessor.h"
# include "clang/Parse/Parser.h"
# include "clang/Sema/Lookup.h"
# include "clang/Sema/Overload.h"
# include "clang/Sema/Scope.h"
# include "clang/Sema/Sema.h"
# include "clang/Sema/SemaInternal.h"
# include "clang/Sema/TemplateDeduction.h"
# include "llvm/Linker.h"
# include "llvm/LLVMContext.h"
# include "llvm/Support/DynamicLibrary.h"
# include "llvm/Support/ErrorHandling.h"
# include "llvm/Support/MemoryBuffer.h"
# include "llvm/Support/Path.h"
# include <iostream>
# include <sstream>
# include <vector>
using namespace clang ;
namespace {
static bool tryLinker ( const std : : string & filename ,
const cling : : InvocationOptions & Opts ,
llvm : : Module * module ) {
assert ( module & & " Module must exist for linking! " ) ;
llvm : : Linker L ( " cling " , module , llvm : : Linker : : QuietWarnings
| llvm : : Linker : : QuietErrors ) ;
for ( std : : vector < llvm : : sys : : Path > : : const_iterator I
= Opts . LibSearchPath . begin ( ) , E = Opts . LibSearchPath . end ( ) ; I ! = E ;
+ + I ) {
L . addPath ( * I ) ;
}
L . addSystemPaths ( ) ;
bool Native = true ;
if ( L . LinkInLibrary ( filename , Native ) ) {
// that didn't work, try bitcode:
llvm : : sys : : Path FilePath ( filename ) ;
std : : string Magic ;
if ( ! FilePath . getMagicNumber ( Magic , 64 ) ) {
// filename doesn't exist...
L . releaseModule ( ) ;
return false ;
}
if ( llvm : : sys : : IdentifyFileType ( Magic . c_str ( ) , 64 )
= = llvm : : sys : : Bitcode_FileType ) {
// We are promised a bitcode file, complain if it fails
L . setFlags ( 0 ) ;
if ( L . LinkInFile ( llvm : : sys : : Path ( filename ) , Native ) ) {
L . releaseModule ( ) ;
return false ;
}
} else {
// Nothing the linker can handle
L . releaseModule ( ) ;
return false ;
}
} else if ( Native ) {
// native shared library, load it!
llvm : : sys : : Path SoFile = L . FindLib ( filename ) ;
assert ( ! SoFile . isEmpty ( ) & & " The shared lib exists but can't find it! " ) ;
std : : string errMsg ;
bool hasError = llvm : : sys : : DynamicLibrary
: : LoadLibraryPermanently ( SoFile . str ( ) . c_str ( ) , & errMsg ) ;
if ( hasError ) {
llvm : : errs ( ) < < " Could not load shared library! \n "
< < " \n "
< < errMsg . c_str ( ) ;
L . releaseModule ( ) ;
return false ;
}
}
L . releaseModule ( ) ;
return true ;
}
static bool canWrapForCall ( const std : : string & input_line ) {
// Whether input_line can be wrapped into a function.
// "1" can, "#include <vector>" can't.
if ( input_line . length ( ) > 1 & & input_line [ 0 ] = = ' # ' ) return false ;
if ( input_line . compare ( 0 , strlen ( " extern " ) , " extern " ) = = 0 ) return false ;
if ( input_line . compare ( 0 , strlen ( " using " ) , " using " ) = = 0 ) return false ;
return true ;
}
} // unnamed namespace
namespace cling {
// "Declared" to the JIT in RuntimeUniverse.h
namespace runtime {
namespace internal {
int local_cxa_atexit ( void ( * func ) ( void * ) , void * arg ,
void * dso , Interpreter * interp ) {
return interp - > CXAAtExit ( func , arg , dso ) ;
}
struct __trigger__cxa_atexit {
~ __trigger__cxa_atexit ( ) ;
} ;
__trigger__cxa_atexit : : ~ __trigger__cxa_atexit ( ) { }
}
}
// This function isn't referenced outside its translation unit, but it
// can't use the "static" keyword because its address is used for
// GetMainExecutable (since some platforms don't support taking the
// address of main, and some platforms can't implement GetMainExecutable
// without being given the address of a function in the main executable).
llvm : : sys : : Path GetExecutablePath ( const char * Argv0 ) {
// This just needs to be some symbol in the binary; C++ doesn't
// allow taking the address of ::main however.
void * MainAddr = ( void * ) ( intptr_t ) GetExecutablePath ;
return llvm : : sys : : Path : : GetMainExecutable ( Argv0 , MainAddr ) ;
}
void Interpreter : : unload ( ) {
m_IncrParser - > unloadTransaction ( 0 ) ;
}
Interpreter : : Interpreter ( int argc , const char * const * argv ,
const char * llvmdir /*= 0*/ ) :
m_UniqueCounter ( 0 ) , m_PrintAST ( false ) , m_DynamicLookupEnabled ( false ) {
m_LLVMContext . reset ( new llvm : : LLVMContext ) ;
std : : vector < unsigned > LeftoverArgsIdx ;
m_Opts = InvocationOptions : : CreateFromArgs ( argc , argv , LeftoverArgsIdx ) ;
std : : vector < const char * > LeftoverArgs ;
for ( size_t I = 0 , N = LeftoverArgsIdx . size ( ) ; I < N ; + + I ) {
LeftoverArgs . push_back ( argv [ LeftoverArgsIdx [ I ] ] ) ;
}
m_IncrParser . reset ( new IncrementalParser ( this , LeftoverArgs . size ( ) ,
& LeftoverArgs [ 0 ] ,
llvmdir ) ) ;
m_LookupHelper . reset ( new LookupHelper ( m_IncrParser - > getParser ( ) ) ) ;
m_ExecutionContext . reset ( new ExecutionContext ( ) ) ;
// Add path to interpreter's include files
// Try to find the headers in the src folder first
# ifdef CLING_SRCDIR_INCL
llvm : : sys : : Path SrcP ( CLING_SRCDIR_INCL ) ;
if ( SrcP . canRead ( ) )
AddIncludePath ( SrcP . str ( ) ) ;
# endif
llvm : : sys : : Path P = GetExecutablePath ( argv [ 0 ] ) ;
if ( ! P . isEmpty ( ) ) {
P . eraseComponent ( ) ; // Remove /cling from foo/bin/clang
P . eraseComponent ( ) ; // Remove /bin from foo/bin
// Get foo/include
P . appendComponent ( " include " ) ;
if ( P . canRead ( ) )
AddIncludePath ( P . str ( ) ) ;
else {
# ifdef CLING_INSTDIR_INCL
llvm : : sys : : Path InstP ( CLING_INSTDIR_INCL ) ;
if ( InstP . canRead ( ) )
AddIncludePath ( InstP . str ( ) ) ;
# endif
}
}
m_ExecutionContext - > addSymbol ( " local_cxa_atexit " ,
( void * ) ( intptr_t ) & cling : : runtime : : internal : : local_cxa_atexit ) ;
2012-10-04 17:09:52 +04:00
// Enable incremental processing, which prevents the preprocessor destroying
// the lexer on EOF token.
getSema ( ) . getPreprocessor ( ) . enableIncrementalProcessing ( ) ;
2012-09-05 13:37:39 +04:00
if ( getCI ( ) - > getLangOpts ( ) . CPlusPlus ) {
// Set up common declarations which are going to be available
// only at runtime
// Make sure that the universe won't be included to compile time by using
// -D __CLING__ as CompilerInstance's arguments
# ifdef _WIN32
// We have to use the #defined __CLING__ on windows first.
//FIXME: Find proper fix.
declare ( " #ifdef __CLING__ \n #endif " ) ;
# endif
2012-09-26 17:27:48 +04:00
declare ( " #include \" cling/Interpreter/RuntimeUniverse.h \" " ) ;
2012-09-05 13:37:39 +04:00
declare ( " #include \" cling/Interpreter/ValuePrinter.h \" " ) ;
// Set up the gCling variable
std : : stringstream initializer ;
initializer < < " gCling=(cling::Interpreter*) " < < ( uintptr_t ) this < < " ; " ;
evaluate ( initializer . str ( ) ) ;
}
else {
declare ( " #include \" cling/Interpreter/CValuePrinter.h \" " ) ;
}
handleFrontendOptions ( ) ;
}
Interpreter : : ~ Interpreter ( ) {
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 ) ;
}
}
const char * Interpreter : : getVersion ( ) const {
return " $Id$ " ;
}
void Interpreter : : handleFrontendOptions ( ) {
if ( m_Opts . ShowVersion ) {
llvm : : outs ( ) < < getVersion ( ) < < ' \n ' ;
}
if ( m_Opts . Help ) {
m_Opts . PrintHelp ( ) ;
}
}
void Interpreter : : AddIncludePath ( llvm : : StringRef incpath )
{
// Add the given path to the list of directories in which the interpreter
// looks for include files. Only one path item can be specified at a
// time, i.e. "path1:path2" is not supported.
CompilerInstance * CI = getCI ( ) ;
HeaderSearchOptions & headerOpts = CI - > getHeaderSearchOpts ( ) ;
const bool IsUserSupplied = false ;
const bool IsFramework = false ;
const bool IsSysRootRelative = true ;
headerOpts . AddPath ( incpath , frontend : : Angled , IsUserSupplied , IsFramework ,
IsSysRootRelative ) ;
Preprocessor & PP = CI - > getPreprocessor ( ) ;
ApplyHeaderSearchOptions ( PP . getHeaderSearchInfo ( ) , headerOpts ,
PP . getLangOpts ( ) ,
PP . getTargetInfo ( ) . getTriple ( ) ) ;
}
// Copied from clang/lib/Frontend/CompilerInvocation.cpp
void Interpreter : : DumpIncludePath ( ) {
const HeaderSearchOptions Opts ( getCI ( ) - > getHeaderSearchOpts ( ) ) ;
std : : vector < std : : string > Res ;
if ( Opts . Sysroot ! = " / " ) {
Res . push_back ( " -isysroot " ) ;
Res . push_back ( Opts . Sysroot ) ;
}
/// User specified include entries.
for ( unsigned i = 0 , e = Opts . UserEntries . size ( ) ; i ! = e ; + + i ) {
const HeaderSearchOptions : : Entry & E = Opts . UserEntries [ i ] ;
if ( E . IsFramework & & ( E . Group ! = frontend : : Angled | | ! E . IsUserSupplied ) )
llvm : : report_fatal_error ( " Invalid option set! " ) ;
if ( E . IsUserSupplied ) {
switch ( E . Group ) {
case frontend : : After :
Res . push_back ( " -idirafter " ) ;
break ;
case frontend : : Quoted :
Res . push_back ( " -iquote " ) ;
break ;
case frontend : : System :
Res . push_back ( " -isystem " ) ;
break ;
case frontend : : IndexHeaderMap :
Res . push_back ( " -index-header-map " ) ;
Res . push_back ( E . IsFramework ? " -F " : " -I " ) ;
break ;
case frontend : : CSystem :
Res . push_back ( " -c-isystem " ) ;
break ;
case frontend : : CXXSystem :
Res . push_back ( " -cxx-isystem " ) ;
break ;
case frontend : : ObjCSystem :
Res . push_back ( " -objc-isystem " ) ;
break ;
case frontend : : ObjCXXSystem :
Res . push_back ( " -objcxx-isystem " ) ;
break ;
case frontend : : Angled :
Res . push_back ( E . IsFramework ? " -F " : " -I " ) ;
break ;
}
} else {
if ( E . Group ! = frontend : : Angled & & E . Group ! = frontend : : System )
llvm : : report_fatal_error ( " Invalid option set! " ) ;
Res . push_back ( E . Group = = frontend : : Angled ? " -iwithprefixbefore " :
" -iwithprefix " ) ;
}
Res . push_back ( E . Path ) ;
}
if ( ! Opts . ResourceDir . empty ( ) ) {
Res . push_back ( " -resource-dir " ) ;
Res . push_back ( Opts . ResourceDir ) ;
}
if ( ! Opts . ModuleCachePath . empty ( ) ) {
Res . push_back ( " -fmodule-cache-path " ) ;
Res . push_back ( Opts . ModuleCachePath ) ;
}
if ( ! Opts . UseStandardSystemIncludes )
Res . push_back ( " -nostdinc " ) ;
if ( ! Opts . UseStandardCXXIncludes )
Res . push_back ( " -nostdinc++ " ) ;
if ( Opts . UseLibcxx )
Res . push_back ( " -stdlib=libc++ " ) ;
if ( Opts . Verbose )
Res . push_back ( " -v " ) ;
// print'em all
for ( unsigned i = 0 ; i < Res . size ( ) ; + + i ) {
llvm : : outs ( ) < < Res [ i ] < < " \n " ;
}
}
CompilerInstance * Interpreter : : getCI ( ) const {
return m_IncrParser - > getCI ( ) ;
}
2012-10-03 16:40:41 +04:00
const Sema & Interpreter : : getSema ( ) const {
return getCI ( ) - > getSema ( ) ;
}
2012-10-03 16:57:09 +04:00
Sema & Interpreter : : getSema ( ) {
return getCI ( ) - > getSema ( ) ;
}
2012-09-05 13:37:39 +04:00
llvm : : ExecutionEngine * Interpreter : : getExecutionEngine ( ) const {
return m_ExecutionContext - > getExecutionEngine ( ) ;
}
llvm : : Module * Interpreter : : getModule ( ) const {
return m_IncrParser - > getCodeGenerator ( ) - > GetModule ( ) ;
}
///\brief Maybe transform the input line to implement cint command line
/// semantics (declarations are global) and compile to produce a module.
///
Interpreter : : CompilationResult
2012-10-05 16:09:51 +04:00
Interpreter : : process ( const std : : string & input , StoredValueRef * V /* = 0 */ ,
2012-09-05 13:37:39 +04:00
const Decl * * D /* = 0 */ ) {
CompilationOptions CO ;
CO . DeclarationExtraction = 1 ;
CO . ValuePrinting = CompilationOptions : : VPAuto ;
2012-10-15 17:42:09 +04:00
CO . ResultEvaluation = ( bool ) V ;
2012-09-05 13:37:39 +04:00
CO . DynamicScoping = isDynamicLookupEnabled ( ) ;
CO . Debug = isPrintingAST ( ) ;
if ( ! canWrapForCall ( input ) )
return declare ( input , D ) ;
2012-09-18 19:14:58 +04:00
if ( EvaluateInternal ( input , CO , V ) = = Interpreter : : kFailure ) {
2012-09-05 13:37:39 +04:00
if ( D )
* D = 0 ;
return Interpreter : : kFailure ;
}
if ( D )
* D = m_IncrParser - > getLastTransaction ( ) - > getFirstDecl ( ) . getSingleDecl ( ) ;
return Interpreter : : kSuccess ;
}
Interpreter : : CompilationResult
Interpreter : : parse ( const std : : string & input ) {
CompilationOptions CO ;
CO . CodeGeneration = 0 ;
CO . DeclarationExtraction = 0 ;
CO . ValuePrinting = 0 ;
2012-10-15 17:42:09 +04:00
CO . ResultEvaluation = 0 ;
2012-09-05 13:37:39 +04:00
CO . DynamicScoping = isDynamicLookupEnabled ( ) ;
CO . Debug = isPrintingAST ( ) ;
2012-09-18 19:14:58 +04:00
return DeclareInternal ( input , CO ) ;
2012-09-05 13:37:39 +04:00
}
Interpreter : : CompilationResult
Interpreter : : declare ( const std : : string & input , const Decl * * D /* = 0 */ ) {
CompilationOptions CO ;
CO . DeclarationExtraction = 0 ;
CO . ValuePrinting = 0 ;
2012-10-15 17:42:09 +04:00
CO . ResultEvaluation = 0 ;
2012-09-05 13:37:39 +04:00
CO . DynamicScoping = isDynamicLookupEnabled ( ) ;
CO . Debug = isPrintingAST ( ) ;
2012-09-18 19:14:58 +04:00
return DeclareInternal ( input , CO , D ) ;
2012-09-05 13:37:39 +04:00
}
Interpreter : : CompilationResult
2012-10-05 16:09:51 +04:00
Interpreter : : evaluate ( const std : : string & input , StoredValueRef * V /* = 0 */ ) {
2012-09-05 13:37:39 +04:00
// Here we might want to enforce further restrictions like: Only one
// ExprStmt can be evaluated and etc. Such enforcement cannot happen in the
// worker, because it is used from various places, where there is no such
// rule
CompilationOptions CO ;
CO . DeclarationExtraction = 0 ;
CO . ValuePrinting = 0 ;
2012-10-15 17:42:09 +04:00
CO . ResultEvaluation = ( bool ) V ;
2012-09-05 13:37:39 +04:00
2012-09-18 19:14:58 +04:00
return EvaluateInternal ( input , CO , V ) ;
2012-09-05 13:37:39 +04:00
}
Interpreter : : CompilationResult
2012-10-05 16:09:51 +04:00
Interpreter : : echo ( const std : : string & input , StoredValueRef * V /* = 0 */ ) {
2012-09-05 13:37:39 +04:00
CompilationOptions CO ;
CO . DeclarationExtraction = 0 ;
CO . ValuePrinting = CompilationOptions : : VPEnabled ;
2012-10-15 17:42:09 +04:00
CO . ResultEvaluation = 0 ;
2012-09-05 13:37:39 +04:00
2012-09-18 19:14:58 +04:00
return EvaluateInternal ( input , CO , V ) ;
2012-09-05 13:37:39 +04:00
}
void Interpreter : : WrapInput ( std : : string & input , std : : string & fname ) {
fname = createUniqueWrapper ( ) ;
input . insert ( 0 , " void " + fname + " () { \n " ) ;
input . append ( " \n ; \n } " ) ;
}
2012-10-05 16:09:51 +04:00
bool Interpreter : : RunFunction ( llvm : : StringRef fname ,
clang : : QualType retType ,
StoredValueRef * res ) {
2012-09-05 13:37:39 +04:00
if ( getCI ( ) - > getDiagnostics ( ) . hasErrorOccurred ( ) )
return false ;
if ( ! m_IncrParser - > hasCodeGenerator ( ) ) {
return true ;
}
std : : string mangledNameIfNeeded ;
2012-09-18 19:05:53 +04:00
Sema & S = getCI ( ) - > getSema ( ) ;
FunctionDecl * FD
2012-09-24 13:57:43 +04:00
= cast_or_null < FunctionDecl > ( utils : : Lookup : : Named ( & S , fname . str ( ) . c_str ( ) ) ) ;
2012-09-18 19:05:53 +04:00
2012-09-05 13:37:39 +04:00
if ( FD ) {
2012-09-24 19:20:19 +04:00
mangleName ( FD , mangledNameIfNeeded ) ;
2012-10-05 16:09:51 +04:00
m_ExecutionContext - > executeFunction ( mangledNameIfNeeded . c_str ( ) ,
getCI ( ) - > getASTContext ( ) ,
retType , res ) ;
2012-09-05 13:37:39 +04:00
return true ;
}
return false ;
}
void Interpreter : : createUniqueName ( std : : string & out ) {
2012-10-17 12:52:24 +04:00
out = utils : : Synthesize : : UniquePrefix ;
2012-09-05 13:37:39 +04:00
llvm : : raw_string_ostream ( out ) < < m_UniqueCounter + + ;
}
2012-10-09 13:48:54 +04:00
bool Interpreter : : isUniqueName ( llvm : : StringRef name ) {
2012-10-17 12:52:24 +04:00
return name . startswith ( utils : : Synthesize : : UniquePrefix ) ;
2012-10-09 13:48:54 +04:00
}
llvm : : StringRef Interpreter : : createUniqueWrapper ( ) {
2012-10-17 12:52:24 +04:00
const size_t size
= sizeof ( utils : : Synthesize : : UniquePrefix ) + sizeof ( m_UniqueCounter ) ;
llvm : : SmallString < size > out ( utils : : Synthesize : : UniquePrefix ) ;
2012-10-09 13:48:54 +04:00
llvm : : raw_svector_ostream ( out ) < < m_UniqueCounter + + ;
return ( getCI ( ) - > getASTContext ( ) . Idents . getOwn ( out ) ) . getName ( ) ;
}
bool Interpreter : : isUniqueWrapper ( llvm : : StringRef name ) {
2012-10-17 12:52:24 +04:00
return name . startswith ( utils : : Synthesize : : UniquePrefix ) ;
2012-10-09 13:48:54 +04:00
}
2012-09-05 13:37:39 +04:00
Interpreter : : CompilationResult
2012-09-18 19:14:58 +04:00
Interpreter : : DeclareInternal ( const std : : string & input ,
const CompilationOptions & CO ,
const clang : : Decl * * D /* = 0 */ ) {
2012-09-05 13:37:39 +04:00
if ( m_IncrParser - > Compile ( input , CO ) ! = IncrementalParser : : kFailed ) {
if ( D )
* D = m_IncrParser - > getLastTransaction ( ) - > getFirstDecl ( ) . getSingleDecl ( ) ;
return Interpreter : : kSuccess ;
}
return Interpreter : : kFailure ;
}
Interpreter : : CompilationResult
2012-09-18 19:14:58 +04:00
Interpreter : : EvaluateInternal ( const std : : string & input ,
const CompilationOptions & CO ,
2012-10-05 16:09:51 +04:00
StoredValueRef * V /* = 0 */ ) {
2012-09-05 13:37:39 +04:00
DiagnosticsEngine & Diag = getCI ( ) - > getDiagnostics ( ) ;
// Disable warnings which doesn't make sense when using the prompt
// This gets reset with the clang::Diagnostics().Reset()
Diag . setDiagnosticMapping ( clang : : diag : : warn_unused_expr ,
clang : : diag : : MAP_IGNORE , SourceLocation ( ) ) ;
Diag . setDiagnosticMapping ( clang : : diag : : warn_unused_call ,
clang : : diag : : MAP_IGNORE , SourceLocation ( ) ) ;
2012-09-24 17:53:23 +04:00
Diag . setDiagnosticMapping ( clang : : diag : : warn_unused_comparison ,
clang : : diag : : MAP_IGNORE , SourceLocation ( ) ) ;
2012-09-05 13:37:39 +04:00
// Wrap the expression
std : : string WrapperName ;
std : : string Wrapper = input ;
WrapInput ( Wrapper , WrapperName ) ;
QualType RetTy = getCI ( ) - > getASTContext ( ) . VoidTy ;
if ( V ) {
2012-10-15 17:42:09 +04:00
const Transaction * CurT = m_IncrParser - > Parse ( Wrapper , CO ) ;
2012-09-05 13:37:39 +04:00
assert ( CurT - > size ( ) & & " No decls created by Parse! " ) ;
// Find the wrapper function declaration.
//
// Note: The parse may have created a whole set of decls if a template
// instantiation happened. Our wrapper function should be the
// last decl in the set.
//
2012-10-15 17:42:09 +04:00
FunctionDecl * FD
2012-09-05 13:37:39 +04:00
= dyn_cast < FunctionDecl > ( CurT - > getLastDecl ( ) . getSingleDecl ( ) ) ;
2012-10-15 17:42:09 +04:00
assert ( FD & & " No Decls Parsed? " ) ;
2012-10-15 20:57:53 +04:00
if ( Expr * lastExpr = utils : : Analyze : : GetLastExpr ( FD ) ) {
RetTy = lastExpr - > getType ( ) ;
2012-09-05 13:37:39 +04:00
}
2012-10-15 20:57:53 +04:00
2012-09-05 13:37:39 +04:00
m_IncrParser - > commitCurrentTransaction ( ) ;
}
else
m_IncrParser - > Compile ( Wrapper , CO ) ;
// get the result
if ( ! V ) {
2012-10-05 16:09:51 +04:00
if ( RunFunction ( WrapperName , RetTy ) ) {
2012-09-05 13:37:39 +04:00
return Interpreter : : kSuccess ;
}
2012-10-15 17:42:09 +04:00
} else if ( RunFunction ( WrapperName , RetTy , V ) ) { // Why we have to pass-in
// the type again?
2012-09-05 13:37:39 +04:00
return Interpreter : : kSuccess ;
} else {
2012-10-05 16:09:51 +04:00
* V = StoredValueRef : : invalidValue ( ) ;
2012-09-05 13:37:39 +04:00
}
return Interpreter : : kFailure ;
}
bool Interpreter : : loadFile ( const std : : string & filename ,
bool allowSharedLib /*=true*/ ) {
if ( allowSharedLib ) {
llvm : : Module * module = m_IncrParser - > getCodeGenerator ( ) - > GetModule ( ) ;
if ( module ) {
if ( tryLinker ( filename , getOptions ( ) , module ) )
return true ;
if ( filename . compare ( 0 , 3 , " lib " ) = = 0 ) {
// starts with "lib", try without (the llvm::Linker forces
// a "lib" in front, which makes it liblib...
if ( tryLinker ( filename . substr ( 3 , std : : string : : npos ) ,
getOptions ( ) , module ) )
return true ;
}
}
}
std : : string code ;
code + = " #include \" " + filename + " \" " ;
return declare ( code ) = = Interpreter : : kSuccess ;
}
2012-09-26 17:27:48 +04:00
void Interpreter : : installLazyFunctionCreator ( void * ( * fp ) ( const std : : string & ) ) {
2012-09-05 13:37:39 +04:00
m_ExecutionContext - > installLazyFunctionCreator ( fp ) ;
}
2012-10-05 16:09:51 +04:00
StoredValueRef Interpreter : : Evaluate ( const char * expr , DeclContext * DC ,
bool ValuePrinterReq ) {
2012-09-05 13:37:39 +04:00
Sema & TheSema = getCI ( ) - > getSema ( ) ;
if ( ! DC )
DC = TheSema . getASTContext ( ) . getTranslationUnitDecl ( ) ;
// Set up the declaration context
DeclContext * CurContext ;
CurContext = TheSema . CurContext ;
TheSema . CurContext = DC ;
2012-10-05 16:09:51 +04:00
StoredValueRef Result ;
2012-10-09 14:21:17 +04:00
if ( TheSema . getExternalSource ( ) ) {
2012-09-05 13:37:39 +04:00
( ValuePrinterReq ) ? echo ( expr , & Result ) : evaluate ( expr , & Result ) ;
}
else
( ValuePrinterReq ) ? echo ( expr , & Result ) : evaluate ( expr , & Result ) ;
TheSema . CurContext = CurContext ;
return Result ;
}
void Interpreter : : setCallbacks ( InterpreterCallbacks * C ) {
2012-10-10 17:00:17 +04:00
// We need it to enable LookupObject callback.
2012-10-02 14:30:25 +04:00
m_Callbacks . reset ( C ) ;
2012-09-05 13:37:39 +04:00
}
void Interpreter : : enableDynamicLookup ( bool value /*=true*/ ) {
m_DynamicLookupEnabled = value ;
if ( isDynamicLookupEnabled ( ) ) {
declare ( " #include \" cling/Interpreter/DynamicLookupRuntimeUniverse.h \" " ) ;
}
2012-10-10 17:00:17 +04:00
else
setCallbacks ( 0 ) ;
2012-09-05 13:37:39 +04:00
}
void Interpreter : : runStaticInitializersOnce ( ) const {
// Forward to ExecutionContext; should not be called by
// anyone except for IncrementalParser.
llvm : : Module * module = m_IncrParser - > getCodeGenerator ( ) - > GetModule ( ) ;
m_ExecutionContext - > runStaticInitializersOnce ( module ) ;
}
int Interpreter : : CXAAtExit ( void ( * func ) ( void * ) , void * arg , void * dso ) {
// Register a CXAAtExit function
Decl * LastTLD
= m_IncrParser - > getLastTransaction ( ) - > getLastDecl ( ) . getSingleDecl ( ) ;
m_AtExitFuncs . push_back ( CXAAtExitElement ( func , arg , dso , LastTLD ) ) ;
return 0 ; // happiness
}
2012-09-24 19:20:19 +04:00
void Interpreter : : mangleName ( const clang : : NamedDecl * D ,
std : : string & mangledName ) const {
2012-09-24 13:57:43 +04:00
///Get the mangled name of a NamedDecl.
///
///D - mangle this decl's name
///mangledName - put the mangled name in here
2012-09-24 16:11:46 +04:00
if ( ! m_MangleCtx ) {
m_MangleCtx . reset ( getCI ( ) - > getASTContext ( ) . createMangleContext ( ) ) ;
}
if ( m_MangleCtx - > shouldMangleDeclName ( D ) ) {
2012-09-24 13:57:43 +04:00
llvm : : raw_string_ostream RawStr ( mangledName ) ;
2012-09-24 16:11:46 +04:00
m_MangleCtx - > mangleName ( D , RawStr ) ;
2012-09-24 13:57:43 +04:00
RawStr . flush ( ) ;
} else {
mangledName = D - > getNameAsString ( ) ;
}
}
bool Interpreter : : addSymbol ( const char * symbolName , void * symbolAddress ) {
2012-09-05 13:37:39 +04:00
// Forward to ExecutionContext;
if ( ! symbolName | | ! symbolAddress )
return false ;
return m_ExecutionContext - > addSymbol ( symbolName , symbolAddress ) ;
}
2012-09-24 13:57:43 +04:00
void * Interpreter : : getAddressOfGlobal ( const clang : : NamedDecl * D ,
bool * fromJIT /*=0*/ ) const {
// Return a symbol's address, and whether it was jitted.
std : : string mangledName ;
2012-09-24 19:20:19 +04:00
mangleName ( D , mangledName ) ;
2012-09-24 16:11:46 +04:00
llvm : : Module * module = m_IncrParser - > getCodeGenerator ( ) - > GetModule ( ) ;
return m_ExecutionContext - > getAddressOfGlobal ( module ,
mangledName . c_str ( ) ,
fromJIT ) ;
2012-09-24 13:57:43 +04:00
}
2012-09-05 13:37:39 +04:00
} // namespace cling