cling/lib/Interpreter/Interpreter.cpp

1062 lines
37 KiB
C++
Raw Normal View History

//------------------------------------------------------------------------------
// CLING - the C++ LLVM-based InterpreterG :)
// author: Lukasz Janyst <ljanyst@cern.ch>
2014-01-07 14:08:37 +04:00
//
// This file is dual-licensed: you can choose to license it under the University
// of Illinois Open Source License or the GNU Lesser General Public License. See
// LICENSE.TXT for details.
//------------------------------------------------------------------------------
#include "cling/Interpreter/Interpreter.h"
#include "cling-compiledata.h"
#include "DynamicLookup.h"
#include "IncrementalExecutor.h"
#include "IncrementalParser.h"
#include "cling/Interpreter/CIFactory.h"
2013-09-17 19:13:38 +04:00
#include "cling/Interpreter/ClangInternalState.h"
#include "cling/Interpreter/CompilationOptions.h"
#include "cling/Interpreter/DynamicLibraryManager.h"
#include "cling/Interpreter/InterpreterCallbacks.h"
#include "cling/Interpreter/LookupHelper.h"
#include "cling/Interpreter/Transaction.h"
2014-02-27 01:37:16 +04:00
#include "cling/Interpreter/Value.h"
#include "cling/Utils/AST.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/GlobalDecl.h"
#include "clang/Basic/TargetInfo.h"
#include "clang/Basic/SourceManager.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/Sema.h"
2014-03-27 17:53:32 +04:00
#include "clang/Sema/SemaDiagnostic.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/raw_ostream.h"
#include <sstream>
#include <string>
#include <vector>
using namespace clang;
namespace {
static cling::Interpreter::ExecutionResult
ConvertExecutionResult(cling::IncrementalExecutor::ExecutionResult ExeRes) {
switch (ExeRes) {
case cling::IncrementalExecutor::kExeSuccess:
return cling::Interpreter::kExeSuccess;
case cling::IncrementalExecutor::kExeFunctionNotCompiled:
return cling::Interpreter::kExeFunctionNotCompiled;
case cling::IncrementalExecutor::kExeUnresolvedSymbols:
return cling::Interpreter::kExeUnresolvedSymbols;
default: break;
}
return cling::Interpreter::kExeSuccess;
}
} // unnamed namespace
namespace cling {
namespace runtime {
namespace internal {
// "Declared" to the JIT in RuntimeUniverse.h
void local_cxa_atexit(void (*func) (void*), void* arg, void* interp) {
Interpreter* cling = (cling::Interpreter*)interp;
cling->AddAtExitFunc(func, arg);
}
} // end namespace internal
} // end namespace runtime
// FIXME: workaround until JIT supports exceptions
jmp_buf* Interpreter::m_JumpBuf;
2013-08-26 19:21:07 +04:00
Interpreter::PushTransactionRAII::PushTransactionRAII(const Interpreter* i)
: m_Interpreter(i) {
CompilationOptions CO;
CO.DeclarationExtraction = 0;
CO.ValuePrinting = 0;
CO.ResultEvaluation = 0;
CO.DynamicScoping = 0;
CO.Debug = 0;
CO.CodeGeneration = 1;
CO.CodeGenerationForModule = 0;
m_Transaction = m_Interpreter->m_IncrParser->beginTransaction(CO);
}
Interpreter::PushTransactionRAII::~PushTransactionRAII() {
pop();
}
2013-08-26 19:21:07 +04:00
void Interpreter::PushTransactionRAII::pop() const {
if (Transaction* T
= m_Interpreter->m_IncrParser->endTransaction(m_Transaction)) {
assert(T == m_Transaction && "Ended different transaction?");
m_Interpreter->m_IncrParser->commitTransaction(T);
}
}
Interpreter::StateDebuggerRAII::StateDebuggerRAII(const Interpreter* i)
: m_Interpreter(i) {
2014-02-28 19:56:12 +04:00
if (!i->isPrintingDebug())
return;
const CompilerInstance& CI = *m_Interpreter->getCI();
m_State.reset(new ClangInternalState(CI.getASTContext(),
CI.getPreprocessor(),
2014-03-03 14:49:01 +04:00
i->getCodeGenerator()->GetModule(),
i->getCodeGenerator(),
"aName"));
}
Interpreter::StateDebuggerRAII::~StateDebuggerRAII() {
pop();
}
void Interpreter::StateDebuggerRAII::pop() const {
2014-02-28 19:56:12 +04:00
if (!m_Interpreter->isPrintingDebug())
return;
m_State->compare("aName");
}
// 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).
2013-09-20 18:01:06 +04:00
std::string 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;
2013-09-20 18:01:06 +04:00
return llvm::sys::fs::getMainExecutable(Argv0, MainAddr);
}
const Parser& Interpreter::getParser() const {
return *m_IncrParser->getParser();
}
CodeGenerator* Interpreter::getCodeGenerator() const {
return m_IncrParser->getCodeGenerator();
}
Interpreter::Interpreter(int argc, const char* const *argv,
const char* llvmdir /*= 0*/) :
2014-02-28 19:56:12 +04:00
m_UniqueCounter(0), m_PrintDebug(false),
m_DynamicLookupEnabled(false), m_RawInputEnabled(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_DyLibManager.reset(new DynamicLibraryManager(getOptions()));
m_IncrParser.reset(new IncrementalParser(this, LeftoverArgs.size(),
&LeftoverArgs[0],
llvmdir));
Sema& SemaRef = getSema();
Preprocessor& PP = SemaRef.getPreprocessor();
// Enable incremental processing, which prevents the preprocessor destroying
// the lexer on EOF token.
PP.enableIncrementalProcessing();
m_LookupHelper.reset(new LookupHelper(new Parser(PP, SemaRef,
/*SkipFunctionBodies*/false,
/*isTemp*/true), this));
if (m_IncrParser->hasCodeGenerator()) {
llvm::Module* theModule = m_IncrParser->getCodeGenerator()->GetModule();
m_Executor.reset(new IncrementalExecutor(theModule));
}
llvm::SmallVector<Transaction*, 2> IncrParserTransactions;
m_IncrParser->Initialize(IncrParserTransactions);
handleFrontendOptions();
2014-03-04 22:26:11 +04:00
AddRuntimeIncludePaths(argv[0]);
// Tell the diagnostic client that we are entering file parsing mode.
DiagnosticConsumer& DClient = getCI()->getDiagnosticClient();
DClient.BeginSourceFile(getCI()->getLangOpts(), &PP);
if (getCI()->getLangOpts().CPlusPlus)
2014-03-27 17:56:11 +04:00
IncludeCXXRuntime();
else
IncludeCRuntime();
// Commit the transactions, now that gCling is set up. It is needed for
// static initialization in these transactions through local_cxa_atexit().
for (llvm::SmallVectorImpl<Transaction*>::const_iterator
I = IncrParserTransactions.begin(), E = IncrParserTransactions.end();
I != E; ++I)
m_IncrParser->commitTransaction(*I);
}
Interpreter::~Interpreter() {
if (m_Executor)
m_Executor->shuttingDown();
for (size_t i = 0, e = m_StoredStates.size(); i != e; ++i)
delete m_StoredStates[i];
2013-08-02 19:05:12 +04:00
getCI()->getDiagnostics().getClient()->EndSourceFile();
}
const char* Interpreter::getVersion() const {
2014-03-05 12:40:58 +04:00
return "cling http://cern.ch/cling - version "
2014-03-04 22:26:11 +04:00
#ifdef CLING_VERSION
2014-03-05 12:40:58 +04:00
CLING_VERSION;
2014-03-04 22:26:11 +04:00
#else
2014-03-05 12:40:58 +04:00
"<unknown>";
2014-03-04 22:26:11 +04:00
#endif
}
void Interpreter::handleFrontendOptions() {
if (m_Opts.ShowVersion) {
llvm::errs() << getVersion() << '\n';
}
if (m_Opts.Help) {
m_Opts.PrintHelp();
}
}
2014-03-04 22:26:11 +04:00
void Interpreter::AddRuntimeIncludePaths(const char* argv0) {
// Add configuration paths to interpreter's include files.
#ifdef CLING_INCLUDE_PATHS
llvm::StringRef InclPaths(CLING_INCLUDE_PATHS);
for (std::pair<llvm::StringRef, llvm::StringRef> Split
= InclPaths.split(':');
!Split.second.empty(); Split = InclPaths.split(':')) {
if (llvm::sys::fs::is_directory(Split.first))
AddIncludePath(Split.first);
InclPaths = Split.second;
}
// Add remaining part
AddIncludePath(InclPaths);
#endif
2014-03-04 22:26:11 +04:00
llvm::SmallString<512> P(GetExecutablePath(argv0));
if (!P.empty()) {
// Remove /cling from foo/bin/clang
llvm::StringRef ExeIncl = llvm::sys::path::parent_path(P);
// Remove /bin from foo/bin
ExeIncl = llvm::sys::path::parent_path(ExeIncl);
P.resize(ExeIncl.size());
// Get foo/include
llvm::sys::path::append(P, "include");
if (llvm::sys::fs::is_directory(P.str()))
AddIncludePath(P.str());
}
}
2014-03-27 17:56:11 +04:00
void Interpreter::IncludeCXXRuntime() {
// 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
declare("#include \"cling/Interpreter/RuntimeUniverse.h\"");
if (getCodeGenerator()) {
// Set up the gCling variable if it can be used
std::stringstream initializer;
initializer << "namespace cling {namespace runtime { "
"cling::Interpreter *gCling=(cling::Interpreter*)"
<< (uintptr_t)this << ";} }";
declare(initializer.str());
}
declare("#include \"cling/Interpreter/ValuePrinter.h\"");
}
void Interpreter::IncludeCRuntime() {
declare("#include \"cling/Interpreter/CValuePrinter.h\"");
}
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 IsFramework = false;
const bool IsSysRootRelative = true;
// Avoid duplicates; just return early if incpath is already in UserEntries.
for (std::vector<HeaderSearchOptions::Entry>::const_iterator
I = headerOpts.UserEntries.begin(),
E = headerOpts.UserEntries.end(); I != E; ++I)
if (I->Path == incpath)
return;
headerOpts.AddPath(incpath, frontend::Angled, IsFramework,
IsSysRootRelative);
Preprocessor& PP = CI->getPreprocessor();
ApplyHeaderSearchOptions(PP.getHeaderSearchInfo(), headerOpts,
PP.getLangOpts(),
PP.getTargetInfo().getTriple());
}
void Interpreter::DumpIncludePath() {
llvm::SmallVector<std::string, 100> IncPaths;
GetIncludePaths(IncPaths, true /*withSystem*/, true /*withFlags*/);
// print'em all
for (unsigned i = 0; i < IncPaths.size(); ++i) {
llvm::errs() << IncPaths[i] <<"\n";
}
}
2013-08-26 19:21:07 +04:00
void Interpreter::storeInterpreterState(const std::string& name) const {
// This may induce deserialization
PushTransactionRAII RAII(this);
2014-03-13 15:33:12 +04:00
CodeGenerator* CG = getCodeGenerator();
ClangInternalState* state
2013-10-21 19:31:21 +04:00
= new ClangInternalState(getCI()->getASTContext(),
2014-03-03 14:49:01 +04:00
getCI()->getPreprocessor(),
2014-03-13 15:33:12 +04:00
CG ? CG->GetModule() : 0,
CG, name);
m_StoredStates.push_back(state);
}
void Interpreter::compareInterpreterState(const std::string& name) const {
short foundAtPos = -1;
for (short i = 0, e = m_StoredStates.size(); i != e; ++i) {
if (m_StoredStates[i]->getName() == name) {
foundAtPos = i;
break;
}
}
assert(foundAtPos>-1 && "The name doesnt exist. Unbalanced store/compare");
// This may induce deserialization
PushTransactionRAII RAII(this);
m_StoredStates[foundAtPos]->compare(name);
}
void Interpreter::printIncludedFiles(llvm::raw_ostream& Out) const {
ClangInternalState::printIncludedFiles(Out, getCI()->getSourceManager());
}
// Adapted from clang/lib/Frontend/CompilerInvocation.cpp
void Interpreter::GetIncludePaths(llvm::SmallVectorImpl<std::string>& incpaths,
bool withSystem, bool withFlags) {
const HeaderSearchOptions Opts(getCI()->getHeaderSearchOpts());
if (withFlags && Opts.Sysroot != "/") {
incpaths.push_back("-isysroot");
incpaths.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)
llvm::report_fatal_error("Invalid option set!");
switch (E.Group) {
case frontend::After:
if (withFlags) incpaths.push_back("-idirafter");
break;
case frontend::Quoted:
if (withFlags) incpaths.push_back("-iquote");
break;
case frontend::System:
if (!withSystem) continue;
if (withFlags) incpaths.push_back("-isystem");
break;
case frontend::IndexHeaderMap:
if (!withSystem) continue;
if (withFlags) incpaths.push_back("-index-header-map");
if (withFlags) incpaths.push_back(E.IsFramework? "-F" : "-I");
break;
case frontend::CSystem:
if (!withSystem) continue;
if (withFlags) incpaths.push_back("-c-isystem");
break;
case frontend::ExternCSystem:
if (!withSystem) continue;
if (withFlags) incpaths.push_back("-extern-c-isystem");
break;
case frontend::CXXSystem:
if (!withSystem) continue;
if (withFlags) incpaths.push_back("-cxx-isystem");
break;
case frontend::ObjCSystem:
if (!withSystem) continue;
if (withFlags) incpaths.push_back("-objc-isystem");
break;
case frontend::ObjCXXSystem:
if (!withSystem) continue;
if (withFlags) incpaths.push_back("-objcxx-isystem");
break;
case frontend::Angled:
if (withFlags) incpaths.push_back(E.IsFramework ? "-F" : "-I");
break;
}
incpaths.push_back(E.Path);
}
if (withSystem && !Opts.ResourceDir.empty()) {
if (withFlags) incpaths.push_back("-resource-dir");
incpaths.push_back(Opts.ResourceDir);
}
if (withSystem && withFlags && !Opts.ModuleCachePath.empty()) {
incpaths.push_back("-fmodule-cache-path");
incpaths.push_back(Opts.ModuleCachePath);
}
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");
}
CompilerInstance* Interpreter::getCI() const {
return m_IncrParser->getCI();
}
const Sema& Interpreter::getSema() const {
return getCI()->getSema();
}
Sema& Interpreter::getSema() {
return getCI()->getSema();
}
llvm::ExecutionEngine* Interpreter::getExecutionEngine() const {
if (!m_Executor) return 0;
return m_Executor->getExecutionEngine();
}
///\brief Maybe transform the input line to implement cint command line
/// semantics (declarations are global) and compile to produce a module.
///
Interpreter::CompilationResult
2014-02-27 01:37:16 +04:00
Interpreter::process(const std::string& input, Value* V /* = 0 */,
Transaction** T /* = 0 */) {
if (isRawInputEnabled() || !ShouldWrapInput(input))
return declare(input, T);
CompilationOptions CO;
CO.DeclarationExtraction = 1;
CO.ValuePrinting = CompilationOptions::VPAuto;
CO.ResultEvaluation = (bool)V;
CO.DynamicScoping = isDynamicLookupEnabled();
2014-02-28 19:56:12 +04:00
CO.Debug = isPrintingDebug();
if (EvaluateInternal(input, CO, V, T) == Interpreter::kFailure) {
return Interpreter::kFailure;
}
return Interpreter::kSuccess;
}
Interpreter::CompilationResult
Interpreter::parse(const std::string& input, Transaction** T /*=0*/) const {
CompilationOptions CO;
CO.CodeGeneration = 0;
CO.DeclarationExtraction = 0;
CO.ValuePrinting = 0;
CO.ResultEvaluation = 0;
CO.DynamicScoping = isDynamicLookupEnabled();
2014-02-28 19:56:12 +04:00
CO.Debug = isPrintingDebug();
return DeclareInternal(input, CO, T);
}
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;
2013-09-23 17:36:32 +04:00
ModuleMap::KnownHeader suggestedModule;
// PP::LookupFile uses it to issue 'nice' diagnostic
SourceLocation fileNameLoc;
PP.LookupFile(fileNameLoc, headerFile, isAngled, LookupFrom, CurDir,
/*SearchPath*/0, /*RelativePath*/ 0, &suggestedModule,
/*SkipCache*/false);
if (!suggestedModule)
return Interpreter::kFailure;
2013-09-23 17:36:32 +04:00
// Copied from PPDirectives.cpp
SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> path;
for (Module *mod = suggestedModule.getModule(); mod; mod = mod->Parent) {
IdentifierInfo* II
= &getSema().getPreprocessor().getIdentifierTable().get(mod->Name);
path.push_back(std::make_pair(II, fileNameLoc));
}
std::reverse(path.begin(), path.end());
// 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;
SourceLocation includeLoc;
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();
return Interpreter::kSuccess;
}
return Interpreter::kFailure;
}
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();
2014-02-28 19:56:12 +04:00
CO.Debug = isPrintingDebug();
// 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());
return DeclareInternal(input, CO);
}
Interpreter::CompilationResult
Interpreter::declare(const std::string& input, Transaction** T/*=0 */) {
CompilationOptions CO;
CO.DeclarationExtraction = 0;
CO.ValuePrinting = 0;
CO.ResultEvaluation = 0;
CO.DynamicScoping = isDynamicLookupEnabled();
2014-02-28 19:56:12 +04:00
CO.Debug = isPrintingDebug();
return DeclareInternal(input, CO, T);
}
Interpreter::CompilationResult
2014-02-27 01:37:16 +04:00
Interpreter::evaluate(const std::string& input, Value& V) {
// 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;
CO.ResultEvaluation = 1;
return EvaluateInternal(input, CO, &V);
}
Interpreter::CompilationResult
2014-02-27 01:37:16 +04:00
Interpreter::echo(const std::string& input, Value* V /* = 0 */) {
CompilationOptions CO;
CO.DeclarationExtraction = 0;
CO.ValuePrinting = CompilationOptions::VPEnabled;
CO.ResultEvaluation = 0;
return EvaluateInternal(input, CO, V);
}
Interpreter::CompilationResult
Interpreter::execute(const std::string& input) {
CompilationOptions CO;
CO.DeclarationExtraction = 0;
CO.ValuePrinting = 0;
CO.ResultEvaluation = 0;
CO.DynamicScoping = 0;
2014-02-28 19:56:12 +04:00
CO.Debug = isPrintingDebug();
2013-10-21 23:31:00 +04:00
return EvaluateInternal(input, CO);
}
Interpreter::CompilationResult Interpreter::emitAllDecls(Transaction* T) {
assert(getCodeGenerator() && "No CodeGenerator?");
m_IncrParser->markWholeTransactionAsUsed(T);
2013-06-25 13:49:04 +04:00
m_IncrParser->codeGenTransaction(T);
// The static initializers might run anything and can thus cause more
// decls that need to end up in a transaction. But this one is done
// with CodeGen...
T->setState(Transaction::kCommitted);
if (runStaticInitializersOnce(*T))
return Interpreter::kSuccess;
return Interpreter::kFailure;
}
bool Interpreter::ShouldWrapInput(const std::string& input) {
2013-10-23 19:48:18 +04:00
// TODO: For future reference.
// Parser* P = const_cast<clang::Parser*>(m_IncrParser->getParser());
// Parser::TentativeParsingAction TA(P);
// TPResult result = P->isCXXDeclarationSpecifier();
// TA.Revert();
// return result == TPResult::True();
llvm::OwningPtr<llvm::MemoryBuffer> buf;
buf.reset(llvm::MemoryBuffer::getMemBuffer(input, "Cling Preparse Buf"));
Lexer WrapLexer(SourceLocation(), getSema().getLangOpts(), input.c_str(),
input.c_str(), input.c_str() + input.size());
Token Tok;
2013-09-23 17:36:32 +04:00
WrapLexer.LexFromRawLexer(Tok);
const tok::TokenKind kind = Tok.getKind();
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;
if (keyword.equals("template"))
return false;
}
else if (kind == tok::hash) {
2013-09-23 17:36:32 +04:00
WrapLexer.LexFromRawLexer(Tok);
if (Tok.is(tok::raw_identifier) && !Tok.needsCleaning()) {
StringRef keyword(Tok.getRawIdentifierData(), Tok.getLength());
if (keyword.equals("include"))
return false;
}
}
return true;
}
void Interpreter::WrapInput(std::string& input, std::string& fname) {
fname = createUniqueWrapper();
2014-02-27 01:37:16 +04:00
input.insert(0, "void " + fname + "(cling::Value*) {\n ");
input.append("\n;\n}");
}
Interpreter::ExecutionResult
2014-02-27 01:37:16 +04:00
Interpreter::RunFunction(const FunctionDecl* FD, Value* res /*=0*/) {
if (getCI()->getDiagnostics().hasErrorOccurred())
return kExeCompilationError;
if (!m_IncrParser->hasCodeGenerator()) {
return kExeNoCodeGen;
}
if (!FD)
return kExeUnkownFunction;
std::string mangledNameIfNeeded;
2013-10-23 02:08:14 +04:00
utils::Analyze::maybeMangleDeclName(FD, mangledNameIfNeeded);
IncrementalExecutor::ExecutionResult ExeRes =
m_Executor->executeFunction(mangledNameIfNeeded.c_str(), res);
return ConvertExecutionResult(ExeRes);
}
const FunctionDecl* Interpreter::DeclareCFunction(StringRef name,
StringRef code,
bool withAccessControl) {
/*
In CallFunc we currently always (intentionally and somewhat necessarily)
always fully specify member function template, however this can lead to
an ambiguity with a class template. For example in
roottest/cling/functionTemplate we get:
input_line_171:3:15: warning: lookup of 'set' in member access expression
is ambiguous; using member of 't'
((t*)obj)->set<int>(*(int*)args[0]);
^
roottest/cling/functionTemplate/t.h:19:9: note: lookup in the object type
't' refers here
void set(T targ) {
^
/usr/include/c++/4.4.5/bits/stl_set.h:87:11: note: lookup from the
current scope refers here
class set
^
This is an intention warning implemented in clang, see
http://llvm.org/viewvc/llvm-project?view=revision&revision=105518
which 'should have been' an error:
C++ [basic.lookup.classref] requires this to be an error, but,
because it's hard to work around, Clang downgrades it to a warning as
an extension.</p>
// C++98 [basic.lookup.classref]p1:
// In a class member access expression (5.2.5), if the . or -> token is
// immediately followed by an identifier followed by a <, the identifier
// must be looked up to determine whether the < is the beginning of a
// template argument list (14.2) or a less-than operator. The identifier
// is first looked up in the class of the object expression. If the
// identifier is not found, it is then looked up in the context of the
// entire postfix-expression and shall name a class or function template. If
// the lookup in the class of the object expression finds a template, the
// name is also looked up in the context of the entire postfix-expression
// and
// -- if the name is not found, the name found in the class of the
// object expression is used, otherwise
// -- if the name is found in the context of the entire postfix-expression
// and does not name a class template, the name found in the class of the
// object expression is used, otherwise
// -- if the name found is a class template, it must refer to the same
// entity as the one found in the class of the object expression,
// otherwise the program is ill-formed.
See -Wambiguous-member-template
An alternative to disabling the diagnostics is to use a pointer to
member function:
#include <set>
using namespace std;
extern "C" int printf(const char*,...);
struct S {
template <typename T>
void set(T) {};
virtual void virtua() { printf("S\n"); }
};
struct T: public S {
void virtua() { printf("T\n"); }
};
int main() {
S *s = new T();
typedef void (S::*Func_p)(int);
Func_p p = &S::set<int>;
(s->*p)(12);
typedef void (S::*Vunc_p)(void);
Vunc_p q = &S::virtua;
(s->*q)(); // prints "T"
return 0;
}
*/
DiagnosticsEngine& Diag = getCI()->getDiagnostics();
Diag.setDiagnosticMapping(
clang::diag::ext_nested_name_member_ref_lookup_ambiguous,
clang::diag::MAP_IGNORE, SourceLocation());
LangOptions& LO = const_cast<LangOptions&>(getCI()->getLangOpts());
bool savedAccessControl = LO.AccessControl;
LO.AccessControl = withAccessControl;
cling::Transaction* T = 0;
cling::Interpreter::CompilationResult CR = declare(code, &T);
LO.AccessControl = savedAccessControl;
if (CR != cling::Interpreter::kSuccess)
return 0;
for (cling::Transaction::const_iterator I = T->decls_begin(),
E = T->decls_end(); I != E; ++I) {
if (I->m_Call != cling::Transaction::kCCIHandleTopLevelDecl)
continue;
if (const LinkageSpecDecl* LSD
= dyn_cast<LinkageSpecDecl>(*I->m_DGR.begin())) {
DeclContext::decl_iterator DeclBegin = LSD->decls_begin();
if (DeclBegin == LSD->decls_end())
continue;
if (const FunctionDecl* D = dyn_cast<FunctionDecl>(*DeclBegin)) {
const IdentifierInfo* II = D->getDeclName().getAsIdentifierInfo();
if (II && II->getName() == name)
return D;
}
}
}
return 0;
}
void*
Interpreter::compileFunction(llvm::StringRef name, llvm::StringRef code,
bool ifUnique, bool withAccessControl) {
//
// Compile the wrapper code.
//
const llvm::GlobalValue* GV = 0;
if (ifUnique)
2014-03-03 14:49:01 +04:00
GV = getCodeGenerator()->GetModule()->getNamedValue(name);
if (!GV) {
const FunctionDecl* FD = DeclareCFunction(name, code, withAccessControl);
if (!FD) return 0;
//
// Get the wrapper function pointer
// from the ExecutionEngine (the JIT).
//
2014-03-03 14:49:01 +04:00
GV = getCodeGenerator()->GetModule()->getNamedValue(name);
}
if (!GV)
return 0;
return m_Executor->getPointerToGlobalFromJIT(*GV);
}
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;
llvm::raw_string_ostream(out) << m_UniqueCounter++;
}
bool Interpreter::isUniqueName(llvm::StringRef name) {
return name.startswith(utils::Synthesize::UniquePrefix);
}
llvm::StringRef Interpreter::createUniqueWrapper() {
const size_t size
= sizeof(utils::Synthesize::UniquePrefix) + sizeof(m_UniqueCounter);
llvm::SmallString<size> out(utils::Synthesize::UniquePrefix);
llvm::raw_svector_ostream(out) << m_UniqueCounter++;
return (getCI()->getASTContext().Idents.getOwn(out)).getName();
}
bool Interpreter::isUniqueWrapper(llvm::StringRef name) {
return name.startswith(utils::Synthesize::UniquePrefix);
}
Interpreter::CompilationResult
Interpreter::DeclareInternal(const std::string& input,
const CompilationOptions& CO,
Transaction** T /* = 0 */) const {
StateDebuggerRAII stateDebugger(this);
if (Transaction* lastT = m_IncrParser->Compile(input, CO)) {
if (lastT->getIssuedDiags() != Transaction::kErrors) {
if (T)
*T = lastT;
return Interpreter::kSuccess;
}
return Interpreter::kFailure;
}
// Even if the transaction was empty it is still success.
return Interpreter::kSuccess;
}
Interpreter::CompilationResult
Interpreter::EvaluateInternal(const std::string& input,
const CompilationOptions& CO,
2014-02-27 01:37:16 +04:00
Value* V, /* = 0 */
Transaction** T /* = 0 */) {
StateDebuggerRAII stateDebugger(this);
// Wrap the expression
std::string WrapperName;
std::string Wrapper = input;
WrapInput(Wrapper, WrapperName);
// Disable warnings which doesn't make sense when using the prompt
// This gets reset with the clang::Diagnostics().Reset(/*soft*/=false)
SourceLocation Loc = m_IncrParser->getLastMemoryBufferEndLoc();
DiagnosticsEngine& Diags = getCI()->getDiagnostics();
Diags.pushMappings(Loc);
Loc = Loc.getLocWithOffset(1);
Diags.setDiagnosticMapping(clang::diag::warn_unused_expr,
clang::diag::MAP_IGNORE, Loc);
Diags.setDiagnosticMapping(clang::diag::warn_unused_call,
clang::diag::MAP_IGNORE, Loc);
Diags.setDiagnosticMapping(clang::diag::warn_unused_comparison,
clang::diag::MAP_IGNORE, Loc);
Diags.setDiagnosticMapping(clang::diag::ext_return_has_expr,
clang::diag::MAP_IGNORE, Loc);
Loc = Loc.getLocWithOffset(1);
if (Transaction* lastT = m_IncrParser->Compile(Wrapper, CO)) {
Diags.popMappings(Loc);
assert((lastT->getState() == Transaction::kCommitted
|| lastT->getState() == Transaction::kRolledBack)
&& "Not committed?");
if (lastT->getIssuedDiags() != Transaction::kErrors) {
if (!lastT->getWrapperFD()) // no wrapper to run
return Interpreter::kSuccess;
else if (RunFunction(lastT->getWrapperFD(), V) < kExeFirstError)
return Interpreter::kSuccess;
}
if (V)
2014-02-27 01:37:16 +04:00
*V = Value();
return Interpreter::kFailure;
}
Diags.popMappings(Loc);
return Interpreter::kSuccess;
}
Interpreter::CompilationResult
Interpreter::loadFile(const std::string& filename,
bool allowSharedLib /*=true*/) {
if (allowSharedLib) {
bool tryCode;
if (getDynamicLibraryManager()->loadLibrary(filename, false, &tryCode)
== DynamicLibraryManager::kLoadLibSuccess)
return kSuccess;
if (!tryCode) {
2013-10-31 17:37:55 +04:00
llvm::errs() << "ERROR in cling::Interpreter::loadFile(): cannot find "
<< filename << "!\n";
return kFailure;
}
}
std::string code;
code += "#include \"" + filename + "\"";
CompilationResult res = declare(code);
return res;
}
void Interpreter::unload(unsigned numberOfTransactions) {
while(true) {
cling::Transaction* T = m_IncrParser->getLastTransaction();
if (InterpreterCallbacks* callbacks = getCallbacks())
callbacks->TransactionUnloaded(*T);
2014-03-13 15:33:25 +04:00
if (m_Executor) // we also might be in fsyntax-only mode.
m_Executor->runAndRemoveStaticDestructors(T);
m_IncrParser->rollbackTransaction(T);
if (!--numberOfTransactions)
break;
}
}
void Interpreter::installLazyFunctionCreator(void* (*fp)(const std::string&)) {
m_Executor->installLazyFunctionCreator(fp);
}
2014-02-27 01:37:16 +04:00
Value Interpreter::Evaluate(const char* expr, DeclContext* DC,
bool ValuePrinterReq) {
Sema& TheSema = getCI()->getSema();
// The evaluation should happen on the global scope, because of the wrapper
// that is created.
//
Prepare dynamic scopes for integration in ROOT; * Merge the DynamicIDHandler into InterpreterCallbacks. The DynamicIDHandler was used to define the failed lookup names as dependent, so that later on they could be "healed" by the EvaluateTSynthesizer - by generating a call to gCling->EvaluateT... * Add a flag in the InterpreterCallbacks giving a hint when the failed lookup is performed - during compilation time or during evaluation type, maybe its name is misnomer. Maybe I should rename it to IsInRuntimeEvalMode or smth like that... * Simplify the evaluation routine. The idea is to be merged with one of the existing - either echo or evaluate * Implement proper mock object as test dynamic symbol resolver callback. Now it fully relies on InterpreterCallbacks. * Implement dynamic expression node marking. Every node that needs runtime resolution is marked as dependent. However, clang marks other nodes as dependent, too (eg. templates). Until now it was very difficult to distinguish between both. Now every "artificially" (marked by us) node's declaration is annotated so that it could be found back easily by using a simple RecursiveASTVisitor. Generally we have two issues when using dynamic scopes - filtering the failed lookups that need to be evaluated at runtime, and filtering the "artificially" marked as dependent dynamic nodes/decls. Whereas the second issue is solved by using the annotations, the first one is more tricky to solve because clang doesn't give us enough information to conclude what should be done. For now I have narrowed down the cases so that dynamic nodes can appear only in function decls. git-svn-id: http://root.cern.ch/svn/root/trunk@48575 27541ba8-7e3a-0410-8455-c3a389f83636
2013-02-14 21:29:30 +04:00
// We can't PushDeclContext, because we don't have scope.
Sema::ContextRAII pushDC(TheSema,
TheSema.getASTContext().getTranslationUnitDecl());
2014-02-27 01:37:16 +04:00
Value Result;
Prepare dynamic scopes for integration in ROOT; * Merge the DynamicIDHandler into InterpreterCallbacks. The DynamicIDHandler was used to define the failed lookup names as dependent, so that later on they could be "healed" by the EvaluateTSynthesizer - by generating a call to gCling->EvaluateT... * Add a flag in the InterpreterCallbacks giving a hint when the failed lookup is performed - during compilation time or during evaluation type, maybe its name is misnomer. Maybe I should rename it to IsInRuntimeEvalMode or smth like that... * Simplify the evaluation routine. The idea is to be merged with one of the existing - either echo or evaluate * Implement proper mock object as test dynamic symbol resolver callback. Now it fully relies on InterpreterCallbacks. * Implement dynamic expression node marking. Every node that needs runtime resolution is marked as dependent. However, clang marks other nodes as dependent, too (eg. templates). Until now it was very difficult to distinguish between both. Now every "artificially" (marked by us) node's declaration is annotated so that it could be found back easily by using a simple RecursiveASTVisitor. Generally we have two issues when using dynamic scopes - filtering the failed lookups that need to be evaluated at runtime, and filtering the "artificially" marked as dependent dynamic nodes/decls. Whereas the second issue is solved by using the annotations, the first one is more tricky to solve because clang doesn't give us enough information to conclude what should be done. For now I have narrowed down the cases so that dynamic nodes can appear only in function decls. git-svn-id: http://root.cern.ch/svn/root/trunk@48575 27541ba8-7e3a-0410-8455-c3a389f83636
2013-02-14 21:29:30 +04:00
getCallbacks()->SetIsRuntime(true);
if (ValuePrinterReq)
echo(expr, &Result);
else
evaluate(expr, Result);
getCallbacks()->SetIsRuntime(false);
return Result;
}
void Interpreter::setCallbacks(InterpreterCallbacks* C) {
// We need it to enable LookupObject callback.
m_Callbacks.reset(C);
// FIXME: We should add a multiplexer in the ASTContext, too.
2014-03-03 20:57:47 +04:00
llvm::IntrusiveRefCntPtr<ExternalASTSource>
astContextExternalSource(getSema().getExternalSource());
clang::ASTContext& Ctx = getSema().getASTContext();
// FIXME: This is a gross hack. We must make multiplexer in the astcontext,
// or a derived class that extends what we need.
2014-03-03 20:57:47 +04:00
Ctx.ExternalSource.resetWithoutRelease(); // FIXME: make sure we delete it.
Ctx.setExternalSource(astContextExternalSource);
}
const Transaction* Interpreter::getFirstTransaction() const {
return m_IncrParser->getFirstTransaction();
}
const Transaction* Interpreter::getLastTransaction() const {
return m_IncrParser->getLastTransaction();
}
void Interpreter::enableDynamicLookup(bool value /*=true*/) {
m_DynamicLookupEnabled = value;
if (isDynamicLookupEnabled()) {
if (loadModuleForHeader("cling/Interpreter/DynamicLookupRuntimeUniverse.h")
!= kSuccess)
declare("#include \"cling/Interpreter/DynamicLookupRuntimeUniverse.h\"");
}
}
Interpreter::ExecutionResult
Interpreter::runStaticInitializersOnce(const Transaction& T) const {
assert(m_IncrParser->hasCodeGenerator() && "Running on what?");
assert(T.getState() == Transaction::kCommitted && "Must be committed");
// Forward to IncrementalExecutor; should not be called by
// anyone except for IncrementalParser.
llvm::Module* module = m_IncrParser->getCodeGenerator()->GetModule();
IncrementalExecutor::ExecutionResult ExeRes
= m_Executor->runStaticInitializersOnce(module);
2014-02-18 11:22:16 +04:00
// Avoid eternal additions to llvm.ident; see
// CodeGenModule::EmitVersionIdentMetadata().
llvm::NamedMDNode *IdentMetadata = module->getNamedMetadata("llvm.ident");
if (IdentMetadata)
module->eraseNamedMetadata(IdentMetadata);
// Reset the module builder to clean up global initializers, c'tors, d'tors
getCodeGenerator()->HandleTranslationUnit(getCI()->getASTContext());
return ConvertExecutionResult(ExeRes);
}
bool Interpreter::addSymbol(const char* symbolName, void* symbolAddress) {
// Forward to IncrementalExecutor;
if (!symbolName || !symbolAddress )
return false;
return m_Executor->addSymbol(symbolName, symbolAddress);
}
void* Interpreter::getAddressOfGlobal(const GlobalDecl& GD,
bool* fromJIT /*=0*/) const {
// Return a symbol's address, and whether it was jitted.
std::string mangledName;
utils::Analyze::maybeMangleDeclName(GD, mangledName);
return getAddressOfGlobal(mangledName.c_str(), fromJIT);
}
2014-03-03 14:48:16 +04:00
void* Interpreter::getAddressOfGlobal(llvm::StringRef SymName,
bool* fromJIT /*=0*/) const {
// Return a symbol's address, and whether it was jitted.
llvm::Module* module = m_IncrParser->getCodeGenerator()->GetModule();
return m_Executor->getAddressOfGlobal(module, SymName, fromJIT);
}
void Interpreter::AddAtExitFunc(void (*Func) (void*), void* Arg) {
m_Executor->AddAtExitFunc(Func, Arg, getLastTransaction());
}
} // namespace cling