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/Basic/TargetInfo.h"
Add support in TClingCallFunc for calling virtual functions: when we have a
CallFunc representation of a member function, we have its concrete address, and
if there is derived class there is no way how to evaluate the vtable and call the
correct virtual.
In order to evaluate the member's vtable, we either have to calculate it (which
is platform/implementation dependent) or create a trampoline function which calls
the target function. Thus codegen will generate code for vtable evaluation. The
trampolines are created for functions that could be possibly virtual - non-static
member functions, declared as virutal. A trampoline looks like this:
void unique_name(Base* This, MyClass2* a, MyClass3* b, double c, MyClass* ret) {
if (ret)
*ret = This->function(*a, *b, c);
else
This->function(*a, *b, c);
}
where we pass in explicitly the address that CallFunc is given (This), followed
by set of arguments (possibly needing conversion) and if the target is non-void
a last argument that is used to provide a storage for the return result.
The given arguments and the required by *LLVM* IR may differ - in that case
simple argument conversions are done. For now primary pointers and builtins, which
covers pretty much entire LLVM type system.
Note that the first implementation is very rough and suboptimal, however it is
very good starting point (milestone):
* Common code is extracted out in its separate routines (here a lot of refactoring more
could be done).
* cling::Value now stores besides clang::QualType, describing (soft-of inaccurately)
the llvm::GenericValue, LLVM-type which is the actual description of the generic value.
* cling::Value naming conventions improved;
* cling::Interpreter::getLLVMType is added temporarily and soon will be removed.
* TClingCallFunc now preallocates space for the this ptr and the return result.
(instead of multiple array copies)
* TClingCallFunc now stores not llvm::GenericValues but cling::StoredValueRefs
because the type conversions need llvm::GenericValue's description (which
essentially is the type).
* Does better default argument evaluation: it could be even *more betterer* if
we query Sema to fold for us the constant expressions instead of decompiling them
to source and using cling for evaluation.
* Return storage implemented.
And, yes that is the longest commit message in my life...
Implementation of argument conversion is revised.
git-svn-id: http://root.cern.ch/svn/root/trunk@48537 27541ba8-7e3a-0410-8455-c3a389f83636
2013-02-11 21:30:03 +04:00
# include "clang/CodeGen/CodeGenModule.h"
2012-09-05 13:37:39 +04:00
# include "clang/CodeGen/ModuleBuilder.h"
# include "clang/Frontend/CompilerInstance.h"
# include "clang/Frontend/Utils.h"
# include "clang/Lex/Preprocessor.h"
2012-12-05 14:04:42 +04:00
# include "clang/Parse/ParseDiagnostic.h" // FIXME: remove this back-dependency!
// when clang is ready.
2012-11-15 04:11:14 +04:00
# include "clang/Parse/Parser.h"
2012-09-05 13:37:39 +04:00
# include "clang/Sema/Sema.h"
# include "clang/Sema/SemaInternal.h"
# include "llvm/Linker.h"
# include "llvm/LLVMContext.h"
# include "llvm/Support/Path.h"
# include <sstream>
# include <vector>
using namespace clang ;
namespace {
2012-11-20 20:24:02 +04:00
static cling : : Interpreter : : ExecutionResult
ConvertExecutionResult ( cling : : ExecutionContext : : ExecutionResult ExeRes ) {
switch ( ExeRes ) {
case cling : : ExecutionContext : : kExeSuccess :
return cling : : Interpreter : : kExeSuccess ;
case cling : : ExecutionContext : : kExeFunctionNotCompiled :
return cling : : Interpreter : : kExeFunctionNotCompiled ;
case cling : : ExecutionContext : : kExeUnresolvedSymbols :
return cling : : Interpreter : : kExeUnresolvedSymbols ;
default : break ;
}
return cling : : Interpreter : : kExeSuccess ;
}
2012-09-05 13:37:39 +04:00
} // unnamed namespace
2012-11-02 15:51:05 +04:00
// "Declared" to the JIT in RuntimeUniverse.h
extern " C "
int cling__runtime__internal__local_cxa_atexit ( void ( * func ) ( void * ) , void * arg ,
void * dso ,
void * interp ) {
return ( ( cling : : Interpreter * ) interp ) - > CXAAtExit ( func , arg , dso ) ;
}
namespace cling {
# if (!_WIN32)
2012-09-05 13:37:39 +04:00
// "Declared" to the JIT in RuntimeUniverse.h
namespace runtime {
namespace internal {
struct __trigger__cxa_atexit {
~ __trigger__cxa_atexit ( ) ;
2013-02-21 21:31:30 +04:00
} /*S*/ ;
2012-11-02 15:51:05 +04:00
__trigger__cxa_atexit : : ~ __trigger__cxa_atexit ( ) {
if ( std : : getenv ( " bar " ) = = ( char * ) - 1 ) {
llvm : : errs ( ) < <
" UNEXPECTED cling::runtime::internal::__trigger__cxa_atexit \n " ;
}
}
2012-09-05 13:37:39 +04:00
}
2012-11-02 16:56:40 +04:00
}
2012-11-02 15:51:05 +04:00
# endif
2012-09-05 13:37:39 +04:00
// 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 ) ;
}
2012-11-16 03:51:52 +04:00
const Parser & Interpreter : : getParser ( ) const {
return * m_IncrParser - > getParser ( ) ;
}
2012-11-15 01:23:31 +04:00
CodeGenerator * Interpreter : : getCodeGenerator ( ) const {
return m_IncrParser - > getCodeGenerator ( ) ;
}
2012-09-05 13:37:39 +04:00
void Interpreter : : unload ( ) {
m_IncrParser - > unloadTransaction ( 0 ) ;
}
Interpreter : : Interpreter ( int argc , const char * const * argv ,
const char * llvmdir /*= 0*/ ) :
2012-12-06 15:36:29 +04:00
m_UniqueCounter ( 0 ) , m_PrintAST ( false ) , m_DynamicLookupEnabled ( false ) ,
m_RawInputEnabled ( false ) {
2012-09-05 13:37:39 +04:00
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 ) ) ;
2012-11-15 04:11:14 +04:00
Sema & SemaRef = getSema ( ) ;
m_LookupHelper . reset ( new LookupHelper ( new Parser ( SemaRef . getPreprocessor ( ) ,
SemaRef ,
/*SkipFunctionBodies*/ false ,
/*isTemp*/ true ) ) ) ;
2012-09-05 13:37:39 +04:00
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
}
}
2012-11-02 15:51:05 +04:00
m_ExecutionContext - > addSymbol ( " cling__runtime__internal__local_cxa_atexit " ,
( void * ) ( intptr_t ) & cling__runtime__internal__local_cxa_atexit ) ;
2012-09-05 13:37:39 +04:00
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 < < " ; " ;
2012-10-18 15:56:20 +04:00
execute ( initializer . str ( ) ) ;
2012-09-05 13:37:39 +04:00
}
else {
declare ( " #include \" cling/Interpreter/CValuePrinter.h \" " ) ;
}
handleFrontendOptions ( ) ;
2012-11-20 17:21:00 +04:00
// Tell the diagnostic client that we are entering file parsing mode.
DiagnosticConsumer & DClient = getCI ( ) - > getDiagnosticClient ( ) ;
DClient . BeginSourceFile ( getCI ( ) - > getLangOpts ( ) ,
& getCI ( ) - > getPreprocessor ( ) ) ;
2012-09-05 13:37:39 +04:00
}
Interpreter : : ~ Interpreter ( ) {
2012-11-20 17:21:00 +04:00
DiagnosticConsumer & DClient = getCI ( ) - > getDiagnosticClient ( ) ;
DClient . EndSourceFile ( ) ;
2012-09-05 13:37:39 +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 ) ;
}
}
const char * Interpreter : : getVersion ( ) const {
return " $Id$ " ;
}
void Interpreter : : handleFrontendOptions ( ) {
if ( m_Opts . ShowVersion ) {
2013-01-17 19:27:14 +04:00
llvm : : errs ( ) < < getVersion ( ) < < ' \n ' ;
2012-09-05 13:37:39 +04:00
}
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 ( ) ;
2012-11-15 21:07:44 +04:00
const bool IsUserSupplied = true ;
2012-09-05 13:37:39 +04:00
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 ( ) ) ;
}
void Interpreter : : DumpIncludePath ( ) {
2012-11-15 21:07:44 +04:00
llvm : : SmallVector < std : : string , 100 > IncPaths ;
GetIncludePaths ( IncPaths , true /*withSystem*/ , true /*withFlags*/ ) ;
// print'em all
for ( unsigned i = 0 ; i < IncPaths . size ( ) ; + + i ) {
2013-01-17 19:27:14 +04:00
llvm : : errs ( ) < < IncPaths [ i ] < < " \n " ;
2012-11-15 21:07:44 +04:00
}
}
// Adapted from clang/lib/Frontend/CompilerInvocation.cpp
void Interpreter : : GetIncludePaths ( llvm : : SmallVectorImpl < std : : string > & incpaths ,
bool withSystem , bool withFlags ) {
2012-09-05 13:37:39 +04:00
const HeaderSearchOptions Opts ( getCI ( ) - > getHeaderSearchOpts ( ) ) ;
2012-11-15 21:07:44 +04:00
if ( withFlags & & Opts . Sysroot ! = " / " ) {
incpaths . push_back ( " -isysroot " ) ;
incpaths . push_back ( Opts . Sysroot ) ;
2012-09-05 13:37:39 +04:00
}
/// 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 :
2012-11-15 21:07:44 +04:00
if ( withFlags ) incpaths . push_back ( " -idirafter " ) ;
2012-09-05 13:37:39 +04:00
break ;
case frontend : : Quoted :
2012-11-15 21:07:44 +04:00
if ( withFlags ) incpaths . push_back ( " -iquote " ) ;
2012-09-05 13:37:39 +04:00
break ;
case frontend : : System :
2012-11-15 21:07:44 +04:00
if ( ! withSystem ) continue ;
if ( withFlags ) incpaths . push_back ( " -isystem " ) ;
2012-09-05 13:37:39 +04:00
break ;
case frontend : : IndexHeaderMap :
2012-11-15 21:07:44 +04:00
if ( ! withSystem ) continue ;
if ( withFlags ) incpaths . push_back ( " -index-header-map " ) ;
if ( withFlags ) incpaths . push_back ( E . IsFramework ? " -F " : " -I " ) ;
2012-09-05 13:37:39 +04:00
break ;
case frontend : : CSystem :
2012-11-15 21:07:44 +04:00
if ( ! withSystem ) continue ;
if ( withFlags ) incpaths . push_back ( " -c-isystem " ) ;
2012-09-05 13:37:39 +04:00
break ;
case frontend : : CXXSystem :
2012-11-15 21:07:44 +04:00
if ( ! withSystem ) continue ;
if ( withFlags ) incpaths . push_back ( " -cxx-isystem " ) ;
2012-09-05 13:37:39 +04:00
break ;
case frontend : : ObjCSystem :
2012-11-15 21:07:44 +04:00
if ( ! withSystem ) continue ;
if ( withFlags ) incpaths . push_back ( " -objc-isystem " ) ;
2012-09-05 13:37:39 +04:00
break ;
case frontend : : ObjCXXSystem :
2012-11-15 21:07:44 +04:00
if ( ! withSystem ) continue ;
if ( withFlags ) incpaths . push_back ( " -objcxx-isystem " ) ;
2012-09-05 13:37:39 +04:00
break ;
case frontend : : Angled :
2012-11-15 21:07:44 +04:00
if ( withFlags ) incpaths . push_back ( E . IsFramework ? " -F " : " -I " ) ;
2012-09-05 13:37:39 +04:00
break ;
}
} else {
2012-11-15 21:07:44 +04:00
if ( ! withSystem ) continue ;
2012-09-05 13:37:39 +04:00
if ( E . Group ! = frontend : : Angled & & E . Group ! = frontend : : System )
llvm : : report_fatal_error ( " Invalid option set! " ) ;
2012-11-15 21:07:44 +04:00
if ( withFlags )
incpaths . push_back ( E . Group = = frontend : : Angled ?
" -iwithprefixbefore " :
" -iwithprefix " ) ;
2012-09-05 13:37:39 +04:00
}
2012-11-15 21:07:44 +04:00
incpaths . push_back ( E . Path ) ;
2012-09-05 13:37:39 +04:00
}
2012-11-15 21:07:44 +04:00
if ( withSystem & & ! Opts . ResourceDir . empty ( ) ) {
if ( withFlags ) incpaths . push_back ( " -resource-dir " ) ;
incpaths . push_back ( Opts . ResourceDir ) ;
2012-09-05 13:37:39 +04:00
}
2012-11-15 21:07:44 +04:00
if ( withSystem & & withFlags & & ! Opts . ModuleCachePath . empty ( ) ) {
incpaths . push_back ( " -fmodule-cache-path " ) ;
incpaths . push_back ( Opts . ModuleCachePath ) ;
2012-09-05 13:37:39 +04:00
}
2012-11-15 21:07:44 +04:00
if ( withSystem & & withFlags & & ! Opts . UseStandardSystemIncludes )
incpaths . push_back ( " -nostdinc " ) ;
if ( withSystem & & withFlags & & ! Opts . UseStandardCXXIncludes )
incpaths . push_back ( " -nostdinc++ " ) ;
if ( withSystem & & withFlags & & Opts . UseLibcxx )
incpaths . push_back ( " -stdlib=libc++ " ) ;
if ( withSystem & & withFlags & & Opts . Verbose )
incpaths . push_back ( " -v " ) ;
2012-09-05 13:37:39 +04:00
}
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 */ ) {
2012-12-06 14:38:56 +04:00
if ( isRawInputEnabled ( ) )
return declare ( input , D ) ;
2012-09-05 13:37:39 +04:00
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 ( ) ;
2012-12-10 15:17:43 +04:00
if ( ! ShouldWrapInput ( input ) )
2012-09-05 13:37:39 +04:00
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
}
2013-01-23 18:41:15 +04:00
Interpreter : : CompilationResult
Interpreter : : loadModuleForHeader ( const std : : string & headerFile ) {
Preprocessor & PP = getCI ( ) - > getPreprocessor ( ) ;
//Copied from clang's PPDirectives.cpp
bool isAngled = false ;
// Clang doc says:
// "LookupFrom is set when this is a \#include_next directive, it specifies
// the file to start searching from."
const DirectoryLookup * LookupFrom = 0 ;
const DirectoryLookup * CurDir = 0 ;
Module * module = 0 ;
2013-01-23 20:05:23 +04:00
PP . LookupFile ( headerFile , isAngled , LookupFrom , CurDir , /*SearchPath*/ 0 ,
/*RelativePath*/ 0 , & module , /*SkipCache*/ false ) ;
2013-01-23 18:41:15 +04:00
if ( ! module )
return Interpreter : : kFailure ;
SourceLocation fileNameLoc ;
ModuleIdPath path = std : : make_pair ( PP . getIdentifierInfo ( module - > Name ) ,
fileNameLoc ) ;
2013-01-24 14:54:57 +04:00
// Pretend that the module came from an inclusion directive, so that clang
// will create an implicit import declaration to capture it in the AST.
bool isInclude = true ;
2013-01-23 18:41:15 +04:00
SourceLocation includeLoc ;
2013-01-24 14:54:57 +04:00
if ( getCI ( ) - > loadModule ( includeLoc , path , Module : : AllVisible , isInclude ) ) {
// After module load we need to "force" Sema to generate the code for
// things like dynamic classes.
getSema ( ) . ActOnEndOfTranslationUnit ( ) ;
2013-01-23 18:41:15 +04:00
return Interpreter : : kSuccess ;
2013-01-24 14:54:57 +04:00
}
2013-01-23 18:41:15 +04:00
return Interpreter : : kFailure ;
}
2012-12-25 08:57:07 +04:00
Interpreter : : CompilationResult
Interpreter : : parseForModule ( const std : : string & input ) {
CompilationOptions CO ;
CO . CodeGeneration = 1 ;
CO . CodeGenerationForModule = 1 ;
CO . DeclarationExtraction = 0 ;
CO . ValuePrinting = 0 ;
CO . ResultEvaluation = 0 ;
CO . DynamicScoping = isDynamicLookupEnabled ( ) ;
CO . Debug = isPrintingAST ( ) ;
2013-02-14 21:10:38 +04:00
// When doing parseForModule avoid warning about the user code
// being loaded ... we probably might as well extend this to
// ALL warnings ... but this will suffice for now (working
// around a real bug in QT :().
DiagnosticsEngine & Diag = getCI ( ) - > getDiagnostics ( ) ;
Diag . setDiagnosticMapping ( clang : : diag : : warn_field_is_uninit ,
clang : : diag : : MAP_IGNORE , SourceLocation ( ) ) ;
2012-12-25 08:57:07 +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-18 16:24:04 +04:00
Interpreter : : evaluate ( const std : : string & input , StoredValueRef & V ) {
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-18 16:24:04 +04:00
CO . ResultEvaluation = 1 ;
2012-09-05 13:37:39 +04:00
2012-10-18 16:24:04 +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
}
2012-10-18 15:56:20 +04:00
Interpreter : : CompilationResult
Interpreter : : execute ( const std : : string & input ) {
CompilationOptions CO ;
CO . DeclarationExtraction = 0 ;
CO . ValuePrinting = 0 ;
CO . ResultEvaluation = 0 ;
CO . DynamicScoping = 0 ;
CO . Debug = isPrintingAST ( ) ;
// Disable warnings which doesn't make sense when using the prompt
// This gets reset with the clang::Diagnostics().Reset()
2012-10-18 16:05:53 +04:00
// TODO: Here might be useful to issue unused variable diagnostic,
// because we don't do declaration extraction and the decl won't be visible
// anymore.
ignoreFakeDiagnostics ( ) ;
2012-10-18 15:56:20 +04:00
// Wrap the expression
std : : string WrapperName ;
std : : string Wrapper = input ;
WrapInput ( Wrapper , WrapperName ) ;
2012-11-20 07:26:52 +04:00
const Transaction * lastT = m_IncrParser - > Compile ( Wrapper , CO ) ;
if ( lastT - > getIssuedDiags ( ) = = Transaction : : kNone )
2012-10-19 16:23:34 +04:00
if ( lastT - > getState ( ) = = Transaction : : kCommitted
2012-11-16 00:55:43 +04:00
& & RunFunction ( lastT - > getWrapperFD ( ) ) < kExeFirstError )
2012-10-18 15:56:20 +04:00
return Interpreter : : kSuccess ;
return Interpreter : : kFailure ;
}
2012-11-21 06:28:31 +04:00
Interpreter : : CompilationResult Interpreter : : codegen ( Transaction * T ) {
m_IncrParser - > commitTransaction ( T ) ;
if ( T - > getState ( ) = = Transaction : : kCommitted )
return Interpreter : : kSuccess ;
return Interpreter : : kFailure ;
}
2012-12-11 18:43:40 +04:00
bool Interpreter : : ShouldWrapInput ( const std : : string & input ) {
2012-12-10 15:17:43 +04:00
llvm : : OwningPtr < llvm : : MemoryBuffer > buf ;
buf . reset ( llvm : : MemoryBuffer : : getMemBuffer ( input , " Cling Preparse Buf " ) ) ;
2012-12-11 18:43:40 +04:00
Lexer WrapLexer ( SourceLocation ( ) , getSema ( ) . getLangOpts ( ) , input . c_str ( ) ,
input . c_str ( ) , input . c_str ( ) + input . size ( ) ) ;
2012-12-10 15:17:43 +04:00
Token Tok ;
WrapLexer . Lex ( Tok ) ;
2012-12-11 18:43:40 +04:00
const tok : : TokenKind kind = Tok . getKind ( ) ;
2012-12-10 15:17:43 +04:00
if ( kind = = tok : : raw_identifier & & ! Tok . needsCleaning ( ) ) {
StringRef keyword ( Tok . getRawIdentifierData ( ) , Tok . getLength ( ) ) ;
if ( keyword . equals ( " using " ) )
return false ;
if ( keyword . equals ( " extern " ) )
return false ;
if ( keyword . equals ( " namespace " ) )
return false ;
2013-02-18 17:22:39 +04:00
if ( keyword . equals ( " template " ) )
return false ;
2012-12-10 15:17:43 +04:00
}
2012-12-11 18:43:40 +04:00
else if ( kind = = tok : : hash ) {
WrapLexer . Lex ( Tok ) ;
if ( Tok . is ( tok : : raw_identifier ) & & ! Tok . needsCleaning ( ) ) {
StringRef keyword ( Tok . getRawIdentifierData ( ) , Tok . getLength ( ) ) ;
if ( keyword . equals ( " include " ) )
return false ;
}
2012-12-10 15:17:43 +04:00
}
2012-12-11 18:43:40 +04:00
return true ;
2012-12-10 15:17:43 +04:00
}
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-11-16 00:55:43 +04:00
Interpreter : : ExecutionResult
Interpreter : : RunFunction ( const FunctionDecl * FD , StoredValueRef * res /*=0*/ ) {
2012-09-05 13:37:39 +04:00
if ( getCI ( ) - > getDiagnostics ( ) . hasErrorOccurred ( ) )
2012-11-16 00:55:43 +04:00
return kExeCompilationError ;
2012-09-05 13:37:39 +04:00
if ( ! m_IncrParser - > hasCodeGenerator ( ) ) {
2012-11-16 00:55:43 +04:00
return kExeNoCodeGen ;
2012-09-05 13:37:39 +04:00
}
2012-10-19 15:56:52 +04:00
if ( ! FD )
2012-11-16 00:55:43 +04:00
return kExeUnkownFunction ;
2012-09-05 13:37:39 +04:00
2012-10-19 15:56:52 +04:00
std : : string mangledNameIfNeeded ;
2013-02-12 19:38:44 +04:00
maybeMangleDeclName ( FD , mangledNameIfNeeded ) ;
2012-11-16 00:55:43 +04:00
ExecutionContext : : ExecutionResult ExeRes =
m_ExecutionContext - > executeFunction ( mangledNameIfNeeded . c_str ( ) ,
getCI ( ) - > getASTContext ( ) ,
FD - > getResultType ( ) , res ) ;
Add support in TClingCallFunc for calling virtual functions: when we have a
CallFunc representation of a member function, we have its concrete address, and
if there is derived class there is no way how to evaluate the vtable and call the
correct virtual.
In order to evaluate the member's vtable, we either have to calculate it (which
is platform/implementation dependent) or create a trampoline function which calls
the target function. Thus codegen will generate code for vtable evaluation. The
trampolines are created for functions that could be possibly virtual - non-static
member functions, declared as virutal. A trampoline looks like this:
void unique_name(Base* This, MyClass2* a, MyClass3* b, double c, MyClass* ret) {
if (ret)
*ret = This->function(*a, *b, c);
else
This->function(*a, *b, c);
}
where we pass in explicitly the address that CallFunc is given (This), followed
by set of arguments (possibly needing conversion) and if the target is non-void
a last argument that is used to provide a storage for the return result.
The given arguments and the required by *LLVM* IR may differ - in that case
simple argument conversions are done. For now primary pointers and builtins, which
covers pretty much entire LLVM type system.
Note that the first implementation is very rough and suboptimal, however it is
very good starting point (milestone):
* Common code is extracted out in its separate routines (here a lot of refactoring more
could be done).
* cling::Value now stores besides clang::QualType, describing (soft-of inaccurately)
the llvm::GenericValue, LLVM-type which is the actual description of the generic value.
* cling::Value naming conventions improved;
* cling::Interpreter::getLLVMType is added temporarily and soon will be removed.
* TClingCallFunc now preallocates space for the this ptr and the return result.
(instead of multiple array copies)
* TClingCallFunc now stores not llvm::GenericValues but cling::StoredValueRefs
because the type conversions need llvm::GenericValue's description (which
essentially is the type).
* Does better default argument evaluation: it could be even *more betterer* if
we query Sema to fold for us the constant expressions instead of decompiling them
to source and using cling for evaluation.
* Return storage implemented.
And, yes that is the longest commit message in my life...
Implementation of argument conversion is revised.
git-svn-id: http://root.cern.ch/svn/root/trunk@48537 27541ba8-7e3a-0410-8455-c3a389f83636
2013-02-11 21:30:03 +04:00
if ( res & & res - > isValid ( ) )
res - > get ( ) . setLLVMType ( getLLVMType ( res - > get ( ) . getClangType ( ) ) ) ;
2012-11-20 20:24:02 +04:00
return ConvertExecutionResult ( ExeRes ) ;
2012-09-05 13:37:39 +04:00
}
void Interpreter : : createUniqueName ( std : : string & out ) {
Add support in TClingCallFunc for calling virtual functions: when we have a
CallFunc representation of a member function, we have its concrete address, and
if there is derived class there is no way how to evaluate the vtable and call the
correct virtual.
In order to evaluate the member's vtable, we either have to calculate it (which
is platform/implementation dependent) or create a trampoline function which calls
the target function. Thus codegen will generate code for vtable evaluation. The
trampolines are created for functions that could be possibly virtual - non-static
member functions, declared as virutal. A trampoline looks like this:
void unique_name(Base* This, MyClass2* a, MyClass3* b, double c, MyClass* ret) {
if (ret)
*ret = This->function(*a, *b, c);
else
This->function(*a, *b, c);
}
where we pass in explicitly the address that CallFunc is given (This), followed
by set of arguments (possibly needing conversion) and if the target is non-void
a last argument that is used to provide a storage for the return result.
The given arguments and the required by *LLVM* IR may differ - in that case
simple argument conversions are done. For now primary pointers and builtins, which
covers pretty much entire LLVM type system.
Note that the first implementation is very rough and suboptimal, however it is
very good starting point (milestone):
* Common code is extracted out in its separate routines (here a lot of refactoring more
could be done).
* cling::Value now stores besides clang::QualType, describing (soft-of inaccurately)
the llvm::GenericValue, LLVM-type which is the actual description of the generic value.
* cling::Value naming conventions improved;
* cling::Interpreter::getLLVMType is added temporarily and soon will be removed.
* TClingCallFunc now preallocates space for the this ptr and the return result.
(instead of multiple array copies)
* TClingCallFunc now stores not llvm::GenericValues but cling::StoredValueRefs
because the type conversions need llvm::GenericValue's description (which
essentially is the type).
* Does better default argument evaluation: it could be even *more betterer* if
we query Sema to fold for us the constant expressions instead of decompiling them
to source and using cling for evaluation.
* Return storage implemented.
And, yes that is the longest commit message in my life...
Implementation of argument conversion is revised.
git-svn-id: http://root.cern.ch/svn/root/trunk@48537 27541ba8-7e3a-0410-8455-c3a389f83636
2013-02-11 21:30:03 +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
2012-11-20 07:26:52 +04:00
const Transaction * lastT = m_IncrParser - > Compile ( input , CO ) ;
2012-11-20 13:43:17 +04:00
if ( lastT - > getIssuedDiags ( ) ! = Transaction : : kErrors ) {
2012-09-05 13:37:39 +04:00
if ( D )
2012-11-20 07:26:52 +04:00
* D = lastT - > getFirstDecl ( ) . getSingleDecl ( ) ;
2012-09-05 13:37:39 +04:00
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
// Disable warnings which doesn't make sense when using the prompt
// This gets reset with the clang::Diagnostics().Reset()
2012-10-18 16:05:53 +04:00
ignoreFakeDiagnostics ( ) ;
2012-09-05 13:37:39 +04:00
// Wrap the expression
std : : string WrapperName ;
std : : string Wrapper = input ;
WrapInput ( Wrapper , WrapperName ) ;
2012-11-20 07:26:52 +04:00
Transaction * lastT = 0 ;
2012-09-05 13:37:39 +04:00
if ( V ) {
2012-11-20 07:26:52 +04:00
lastT = m_IncrParser - > Parse ( Wrapper , CO ) ;
assert ( lastT - > size ( ) & & " No decls created by Parse! " ) ;
2012-09-05 13:37:39 +04:00
2012-11-20 07:26:52 +04:00
m_IncrParser - > commitTransaction ( lastT ) ;
2012-09-05 13:37:39 +04:00
}
else
2012-11-20 07:26:52 +04:00
lastT = m_IncrParser - > Compile ( Wrapper , CO ) ;
2012-10-19 16:23:34 +04:00
if ( lastT - > getState ( ) = = Transaction : : kCommitted
2012-11-16 00:55:43 +04:00
& & RunFunction ( lastT - > getWrapperFD ( ) , V ) < kExeFirstError )
2012-09-05 13:37:39 +04:00
return Interpreter : : kSuccess ;
2012-10-18 13:38:39 +04:00
else if ( V )
2012-10-18 13:33:29 +04:00
* V = StoredValueRef : : invalidValue ( ) ;
2012-09-05 13:37:39 +04:00
return Interpreter : : kFailure ;
}
2012-11-15 22:23:11 +04:00
void Interpreter : : addLoadedFile ( const std : : string & name ,
Interpreter : : LoadedFileInfo : : FileType type ,
const llvm : : sys : : DynamicLibrary * dyLib ) {
m_LoadedFiles . push_back ( new LoadedFileInfo ( name , type , dyLib ) ) ;
}
2012-11-15 18:50:59 +04:00
Interpreter : : CompilationResult
Interpreter : : loadFile ( const std : : string & filename ,
bool allowSharedLib /*=true*/ ) {
2012-11-16 17:39:09 +04:00
if ( allowSharedLib ) {
bool tryCode ;
if ( loadLibrary ( filename , false , & tryCode )
= = kLoadLibSuccess )
return kSuccess ;
if ( ! tryCode )
return kFailure ;
}
2012-11-16 01:36:41 +04:00
2012-09-05 13:37:39 +04:00
std : : string code ;
code + = " #include \" " + filename + " \" " ;
2012-11-15 22:23:11 +04:00
CompilationResult res = declare ( code ) ;
if ( res = = kSuccess )
2012-11-16 17:39:09 +04:00
addLoadedFile ( filename , LoadedFileInfo : : kSource ) ;
2012-11-15 22:23:11 +04:00
return res ;
2012-09-05 13:37:39 +04:00
}
2012-11-15 20:41:30 +04:00
2012-11-15 18:50:59 +04:00
Interpreter : : LoadLibResult
2012-11-16 01:36:41 +04:00
Interpreter : : tryLinker ( const std : : string & filename , bool permanent ,
bool & tryCode ) {
2012-11-15 20:41:30 +04:00
using namespace llvm : : sys ;
2012-11-16 01:36:41 +04:00
tryCode = true ;
2012-11-15 18:50:59 +04:00
llvm : : Module * module = m_IncrParser - > getCodeGenerator ( ) - > GetModule ( ) ;
2012-11-15 20:41:30 +04:00
assert ( module & & " Module must exist for linking! " ) ;
llvm : : Linker L ( " cling " , module , llvm : : Linker : : QuietWarnings
| llvm : : Linker : : QuietErrors ) ;
2012-11-15 22:23:11 +04:00
struct LinkerModuleReleaseRAII {
LinkerModuleReleaseRAII ( llvm : : Linker & L ) : m_L ( L ) { }
~ LinkerModuleReleaseRAII ( ) { m_L . releaseModule ( ) ; }
llvm : : Linker & m_L ;
} LinkerModuleReleaseRAII_ ( L ) ;
2012-11-15 20:41:30 +04:00
const InvocationOptions & Opts = getOptions ( ) ;
for ( std : : vector < 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:
Path FilePath ( filename ) ;
std : : string Magic ;
2013-02-07 17:14:26 +04:00
// 512 bytes should suffice to extrace PE magic
2013-02-07 17:11:08 +04:00
if ( ! FilePath . getMagicNumber ( Magic , 512 ) ) {
2012-11-15 20:41:30 +04:00
// filename doesn't exist...
2012-11-16 01:36:41 +04:00
// tryCode because it might be found through -I
2012-11-15 22:23:11 +04:00
return kLoadLibError ;
2012-11-15 18:50:59 +04:00
}
2013-02-07 17:11:08 +04:00
if ( IdentifyFileType ( Magic . c_str ( ) , 512 ) ! = Bitcode_FileType ) {
2012-11-15 20:41:30 +04:00
// Nothing the linker can handle
2012-11-15 22:23:11 +04:00
return kLoadLibError ;
2012-11-15 18:50:59 +04:00
}
2012-11-15 22:23:11 +04:00
// We are promised a bitcode file, complain if it fails
L . setFlags ( 0 ) ;
if ( L . LinkInFile ( Path ( filename ) , Native ) ) {
2012-11-16 01:36:41 +04:00
tryCode = false ;
2012-11-15 22:23:11 +04:00
return kLoadLibError ;
}
addLoadedFile ( filename , LoadedFileInfo : : kBitcode ) ;
return kLoadLibSuccess ;
}
if ( Native ) {
2012-11-16 01:36:41 +04:00
tryCode = false ;
2012-11-15 20:41:30 +04:00
// native shared library, load it!
Path SoFile = L . FindLib ( filename ) ;
assert ( ! SoFile . isEmpty ( ) & & " The shared lib exists but can't find it! " ) ;
std : : string errMsg ;
// TODO: !permanent case
DynamicLibrary DyLib
= DynamicLibrary : : getPermanentLibrary ( SoFile . str ( ) . c_str ( ) , & errMsg ) ;
2012-11-16 01:36:41 +04:00
if ( ! DyLib . isValid ( ) ) {
llvm : : errs ( ) < < " cling::Interpreter::tryLinker(): " < < errMsg < < ' \n ' ;
2012-11-15 22:23:11 +04:00
return kLoadLibError ;
2012-11-16 01:36:41 +04:00
}
2012-11-15 22:23:11 +04:00
std : : pair < std : : set < llvm : : sys : : DynamicLibrary > : : iterator , bool > insRes
= m_DyLibs . insert ( DyLib ) ;
if ( ! insRes . second )
return kLoadLibExists ;
2012-11-16 15:30:31 +04:00
addLoadedFile ( SoFile . str ( ) , LoadedFileInfo : : kDynamicLibrary ,
2012-11-15 22:23:11 +04:00
& ( * insRes . first ) ) ;
return kLoadLibSuccess ;
2012-11-15 20:41:30 +04:00
}
2012-11-15 22:23:11 +04:00
return kLoadLibError ;
2012-11-15 20:41:30 +04:00
}
Interpreter : : LoadLibResult
2012-11-16 01:36:41 +04:00
Interpreter : : loadLibrary ( const std : : string & filename , bool permanent ,
bool * tryCode ) {
bool tryCodeDummy ;
LoadLibResult res = tryLinker ( filename , permanent ,
tryCode ? * tryCode : tryCodeDummy ) ;
2012-11-15 22:23:11 +04:00
if ( res ! = kLoadLibError ) {
2012-11-15 20:41:30 +04:00
return res ;
}
if ( filename . compare ( 0 , 3 , " lib " ) = = 0 ) {
// starts with "lib", try without (the llvm::Linker forces
// a "lib" in front, which makes it liblib...
2012-11-16 01:36:41 +04:00
res = tryLinker ( filename . substr ( 3 , std : : string : : npos ) , permanent ,
tryCodeDummy ) ;
2012-11-15 22:23:11 +04:00
if ( res ! = kLoadLibError )
2012-11-15 20:41:30 +04:00
return res ;
2012-11-15 18:50:59 +04:00
}
2012-11-15 22:23:11 +04:00
return kLoadLibError ;
2012-11-15 18:50:59 +04:00
}
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-25 18:07:19 +04:00
void Interpreter : : suppressLazyFunctionCreatorDiags ( bool suppressed /*=true*/ ) {
m_ExecutionContext - > suppressLazyFunctionCreatorDiags ( suppressed ) ;
2012-10-25 13:17:45 +04:00
}
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 ( ) ;
2013-02-14 21:29:30 +04:00
// We can't PushDeclContext, because we don't have scope.
Sema : : ContextRAII pushedDC ( TheSema , DC ) ;
2012-09-05 13:37:39 +04:00
2012-10-05 16:09:51 +04:00
StoredValueRef Result ;
2013-02-14 21:29:30 +04:00
getCallbacks ( ) - > SetIsRuntime ( true ) ;
if ( ValuePrinterReq )
echo ( expr , & Result ) ;
else
evaluate ( expr , Result ) ;
getCallbacks ( ) - > SetIsRuntime ( false ) ;
2012-09-05 13:37:39 +04:00
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
}
2012-10-19 17:30:06 +04:00
const Transaction * Interpreter : : getFirstTransaction ( ) const {
return m_IncrParser - > getFirstTransaction ( ) ;
}
2012-09-05 13:37:39 +04:00
void Interpreter : : enableDynamicLookup ( bool value /*=true*/ ) {
m_DynamicLookupEnabled = value ;
if ( isDynamicLookupEnabled ( ) ) {
2013-02-21 21:31:30 +04:00
// Need to know whether this is in a module or not:
//declare("#include \"cling/Interpreter/DynamicLookupRuntimeUniverse.h\"");
loadModuleForHeader ( " cling/Interpreter/DynamicLookupRuntimeUniverse.h " ) ;
2012-09-05 13:37:39 +04:00
}
2012-10-10 17:00:17 +04:00
else
setCallbacks ( 0 ) ;
2012-09-05 13:37:39 +04:00
}
2012-11-20 20:24:02 +04:00
Interpreter : : ExecutionResult
Interpreter : : runStaticInitializersOnce ( ) const {
2012-09-05 13:37:39 +04:00
// Forward to ExecutionContext; should not be called by
// anyone except for IncrementalParser.
llvm : : Module * module = m_IncrParser - > getCodeGenerator ( ) - > GetModule ( ) ;
2012-11-20 20:24:02 +04:00
ExecutionContext : : ExecutionResult ExeRes
= m_ExecutionContext - > runStaticInitializersOnce ( module ) ;
return ConvertExecutionResult ( ExeRes ) ;
2012-09-05 13:37:39 +04:00
}
2013-02-08 22:11:36 +04:00
Interpreter : : ExecutionResult
Interpreter : : runStaticDestructorsOnce ( ) {
for ( size_t I = 0 , E = m_AtExitFuncs . size ( ) ; I < E ; + + I ) {
const CXAAtExitElement & AEE = m_AtExitFuncs [ E - I - 1 ] ;
( * AEE . m_Func ) ( AEE . m_Arg ) ;
}
m_AtExitFuncs . clear ( ) ;
2013-02-09 00:46:52 +04:00
return kExeSuccess ;
2013-02-08 22:11:36 +04:00
}
2012-09-05 13:37:39 +04:00
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
}
2013-02-12 19:38:44 +04:00
void Interpreter : : maybeMangleDeclName ( 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 ) ;
2013-02-12 19:38:44 +04:00
switch ( D - > getKind ( ) ) {
case Decl : : CXXConstructor :
//Ctor_Complete, // Complete object ctor
//Ctor_Base, // Base object ctor
//Ctor_CompleteAllocating // Complete object allocating ctor (unused)
m_MangleCtx - > mangleCXXCtor ( cast < CXXConstructorDecl > ( D ) ,
Ctor_Complete , RawStr ) ;
break ;
case Decl : : CXXDestructor :
//Dtor_Deleting, // Deleting dtor
//Dtor_Complete, // Complete object dtor
//Dtor_Base // Base object dtor
m_MangleCtx - > mangleCXXDtor ( cast < CXXDestructorDecl > ( D ) ,
Dtor_Deleting , RawStr ) ;
break ;
default :
m_MangleCtx - > mangleName ( D , RawStr ) ;
break ;
}
2012-09-24 13:57:43 +04:00
RawStr . flush ( ) ;
} else {
mangledName = D - > getNameAsString ( ) ;
}
}
2012-10-18 16:05:53 +04:00
void Interpreter : : ignoreFakeDiagnostics ( ) const {
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 ( ) ) ;
Diag . setDiagnosticMapping ( clang : : diag : : warn_unused_comparison ,
clang : : diag : : MAP_IGNORE , SourceLocation ( ) ) ;
2012-11-11 16:53:21 +04:00
Diag . setDiagnosticMapping ( clang : : diag : : ext_return_has_expr ,
2012-12-05 14:04:42 +04:00
clang : : diag : : MAP_IGNORE , SourceLocation ( ) ) ;
// Very very ugly. TODO: Revisit and extract out as interpreter arg
Diag . setDiagnosticMapping ( clang : : diag : : ext_auto_type_specifier ,
2012-11-11 16:53:21 +04:00
clang : : diag : : MAP_IGNORE , SourceLocation ( ) ) ;
2012-10-18 16:05:53 +04:00
}
2012-09-24 13:57:43 +04:00
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 ;
2013-02-12 19:38:44 +04:00
maybeMangleDeclName ( D , mangledName ) ;
2012-11-16 19:32:43 +04:00
return getAddressOfGlobal ( mangledName . c_str ( ) , fromJIT ) ;
}
void * Interpreter : : getAddressOfGlobal ( const char * SymName ,
bool * fromJIT /*=0*/ ) const {
// Return a symbol's address, and whether it was jitted.
2012-09-24 16:11:46 +04:00
llvm : : Module * module = m_IncrParser - > getCodeGenerator ( ) - > GetModule ( ) ;
2012-11-16 19:32:43 +04:00
return m_ExecutionContext - > getAddressOfGlobal ( module , SymName , fromJIT ) ;
2012-09-24 13:57:43 +04:00
}
Add support in TClingCallFunc for calling virtual functions: when we have a
CallFunc representation of a member function, we have its concrete address, and
if there is derived class there is no way how to evaluate the vtable and call the
correct virtual.
In order to evaluate the member's vtable, we either have to calculate it (which
is platform/implementation dependent) or create a trampoline function which calls
the target function. Thus codegen will generate code for vtable evaluation. The
trampolines are created for functions that could be possibly virtual - non-static
member functions, declared as virutal. A trampoline looks like this:
void unique_name(Base* This, MyClass2* a, MyClass3* b, double c, MyClass* ret) {
if (ret)
*ret = This->function(*a, *b, c);
else
This->function(*a, *b, c);
}
where we pass in explicitly the address that CallFunc is given (This), followed
by set of arguments (possibly needing conversion) and if the target is non-void
a last argument that is used to provide a storage for the return result.
The given arguments and the required by *LLVM* IR may differ - in that case
simple argument conversions are done. For now primary pointers and builtins, which
covers pretty much entire LLVM type system.
Note that the first implementation is very rough and suboptimal, however it is
very good starting point (milestone):
* Common code is extracted out in its separate routines (here a lot of refactoring more
could be done).
* cling::Value now stores besides clang::QualType, describing (soft-of inaccurately)
the llvm::GenericValue, LLVM-type which is the actual description of the generic value.
* cling::Value naming conventions improved;
* cling::Interpreter::getLLVMType is added temporarily and soon will be removed.
* TClingCallFunc now preallocates space for the this ptr and the return result.
(instead of multiple array copies)
* TClingCallFunc now stores not llvm::GenericValues but cling::StoredValueRefs
because the type conversions need llvm::GenericValue's description (which
essentially is the type).
* Does better default argument evaluation: it could be even *more betterer* if
we query Sema to fold for us the constant expressions instead of decompiling them
to source and using cling for evaluation.
* Return storage implemented.
And, yes that is the longest commit message in my life...
Implementation of argument conversion is revised.
git-svn-id: http://root.cern.ch/svn/root/trunk@48537 27541ba8-7e3a-0410-8455-c3a389f83636
2013-02-11 21:30:03 +04:00
const llvm : : Type * Interpreter : : getLLVMType ( QualType QT ) {
if ( ! m_IncrParser - > hasCodeGenerator ( ) )
return 0 ;
// Note: The first thing this routine does is getCanonicalType(), so we
// do not need to do that first.
CodeGen : : CodeGenModule * CGM = getCodeGenerator ( ) - > GetBuilder ( ) ;
CodeGen : : CodeGenTypes & CGT = CGM - > getTypes ( ) ;
//llvm::Type* Ty = CGT.ConvertTypeForMem(QT);
return CGT . ConvertType ( QT ) ;
}
2012-09-05 13:37:39 +04:00
} // namespace cling