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"
# 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 ( ) ;
2012-11-02 15:51:05 +04:00
} S ;
__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 ( ) ;
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 ;
}
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 ;
mangleName ( FD , mangledNameIfNeeded ) ;
2012-11-16 00:55:43 +04:00
ExecutionContext : : ExecutionResult ExeRes =
m_ExecutionContext - > executeFunction ( mangledNameIfNeeded . c_str ( ) ,
getCI ( ) - > getASTContext ( ) ,
FD - > getResultType ( ) , res ) ;
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 ) {
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
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 ( ) ;
// 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-10-18 16:24:04 +04:00
( ValuePrinterReq ) ? echo ( expr , & Result ) : evaluate ( expr , Result ) ;
2012-09-05 13:37:39 +04:00
}
else
2012-10-18 16:24:04 +04:00
( ValuePrinterReq ) ? echo ( expr , & Result ) : evaluate ( expr , Result ) ;
2012-09-05 13:37:39 +04:00
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
}
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 ( ) ) {
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
}
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
}
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 ( ) ;
}
}
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 ;
2012-09-24 19:20:19 +04:00
mangleName ( 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
}
2012-09-05 13:37:39 +04:00
} // namespace cling