cling/lib/Interpreter/Interpreter.cpp

946 lines
33 KiB
C++
Raw Normal View History

//------------------------------------------------------------------------------
// 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"
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/StoredValueRef.h"
#include "cling/Interpreter/Transaction.h"
#include "cling/Utils/AST.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Mangle.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/ParseDiagnostic.h" // FIXME: remove this back-dependency!
// when clang is ready.
#include "clang/Parse/Parser.h"
#include "clang/Sema/Sema.h"
#include "clang/Sema/SemaInternal.h"
#include "llvm/IR/LLVMContext.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::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;
}
} // unnamed namespace
namespace cling {
namespace runtime {
namespace internal {
// "Declared" to the JIT in RuntimeUniverse.h
int local_cxa_atexit(void (*func) (void*), void* arg, void* dso,
void* interp) {
Interpreter* cling = (cling::Interpreter*)interp;
IncrementalParser* incrP = cling->m_IncrParser.get();
// FIXME: Bind to the module symbols.
Decl* lastTLD = incrP->getLastTransaction()->getLastDecl().getSingleDecl();
int result = cling->m_ExecutionContext->CXAAtExit(func, arg, dso, lastTLD);
return result;
}
} // end namespace internal
} // end namespace runtime
}
namespace cling {
#if (!_WIN32)
// "Declared" to the JIT in RuntimeUniverse.h
namespace runtime {
namespace internal {
struct __trigger__cxa_atexit {
~__trigger__cxa_atexit();
} /*S*/;
__trigger__cxa_atexit::~__trigger__cxa_atexit() {
if (std::getenv("bar") == (char*)-1) {
llvm::errs() <<
"UNEXPECTED cling::runtime::internal::__trigger__cxa_atexit\n";
}
}
}
}
#endif
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);
}
}
// 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();
}
void Interpreter::unload() {
m_IncrParser->unloadTransaction(0);
}
Interpreter::Interpreter(int argc, const char* const *argv,
const char* llvmdir /*= 0*/) :
m_UniqueCounter(0), m_PrintAST(false), m_PrintIR(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();
m_LookupHelper.reset(new LookupHelper(new Parser(SemaRef.getPreprocessor(),
SemaRef,
/*SkipFunctionBodies*/false,
/*isTemp*/true), this));
if (m_IncrParser->hasCodeGenerator()) {
llvm::Module* theModule = m_IncrParser->getCodeGenerator()->GetModule();
m_ExecutionContext.reset(new ExecutionContext(theModule));
}
m_IncrParser->Initialize();
// 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);
#else
2013-09-20 18:01:06 +04:00
llvm::SmallString<512> P(GetExecutablePath(argv[0]));
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() + 1);
P[ExeIncl.size()] = 0;
// Get foo/include
2013-09-20 18:01:06 +04:00
llvm::sys::path::append(P, "include");
2013-09-20 20:24:19 +04:00
if (llvm::sys::fs::is_directory(P.str()))
AddIncludePath(P.str());
}
#endif
// Enable incremental processing, which prevents the preprocessor destroying
// the lexer on EOF token.
getSema().getPreprocessor().enableIncrementalProcessing();
handleFrontendOptions();
// Tell the diagnostic client that we are entering file parsing mode.
DiagnosticConsumer& DClient = getCI()->getDiagnosticClient();
DClient.BeginSourceFile(getCI()->getLangOpts(),
&getCI()->getPreprocessor());
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
declare("#include \"cling/Interpreter/RuntimeUniverse.h\"");
declare("#include \"cling/Interpreter/ValuePrinter.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());
}
// Find cling::runtime::internal::local_cxa_atexit
2013-09-19 20:15:47 +04:00
// We do not have an active transaction and that lookup might trigger
// deserialization
PushTransactionRAII pushedT(this);
NamespaceDecl* NSD = utils::Lookup::Namespace(&getSema(), "cling");
NSD = utils::Lookup::Namespace(&getSema(), "runtime");
NSD = utils::Lookup::Namespace(&getSema(), "internal");
NamedDecl* ND = utils::Lookup::Named(&getSema(), "local_cxa_atexit", NSD);
std::string mangledName;
maybeMangleDeclName(ND, mangledName);
m_ExecutionContext->addSymbol(mangledName.c_str(),
(void*)(intptr_t)&runtime::internal::local_cxa_atexit);
}
else {
declare("#include \"cling/Interpreter/CValuePrinter.h\"");
}
}
Interpreter::~Interpreter() {
2013-08-02 19:05:12 +04:00
getCI()->getDiagnostics().getClient()->EndSourceFile();
}
const char* Interpreter::getVersion() const {
return "$Id$";
}
void Interpreter::handleFrontendOptions() {
if (m_Opts.ShowVersion) {
llvm::errs() << getVersion() << '\n';
}
if (m_Opts.Help) {
m_Opts.PrintHelp();
}
}
void Interpreter::AddIncludePath(llvm::StringRef incpath)
{
// Add the given path to the list of directories in which the interpreter
// looks for include files. Only one path item can be specified at a
// time, i.e. "path1:path2" is not supported.
CompilerInstance* CI = getCI();
HeaderSearchOptions& headerOpts = CI->getHeaderSearchOpts();
const bool IsFramework = false;
const bool IsSysRootRelative = true;
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 {
ClangInternalState* state
= new ClangInternalState(getCI()->getASTContext(), name);
m_StoredStates.push_back(state);
}
void Interpreter::compareInterpreterState(const std::string& name) const {
ClangInternalState* state
= new ClangInternalState(getCI()->getASTContext(), name);
for (unsigned i = 0, e = m_StoredStates.size(); i != e; ++i) {
if (m_StoredStates[i]->getName() == name) {
state->compare(*m_StoredStates[i]);
m_StoredStates.erase(m_StoredStates.begin() + i);
break;
}
}
}
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 {
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
Interpreter::process(const std::string& input, StoredValueRef* 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();
CO.Debug = isPrintingAST();
CO.IRDebug = isPrintingIR();
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();
CO.Debug = isPrintingAST();
CO.IRDebug = isPrintingIR();
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();
CO.Debug = isPrintingAST();
CO.IRDebug = isPrintingIR();
// 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();
CO.Debug = isPrintingAST();
CO.IRDebug = isPrintingIR();
return DeclareInternal(input, CO, T);
}
Interpreter::CompilationResult
Interpreter::evaluate(const std::string& input, StoredValueRef& 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
Interpreter::echo(const std::string& input, StoredValueRef* 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;
CO.Debug = isPrintingAST();
CO.IRDebug = isPrintingIR();
// Disable warnings which doesn't make sense when using the prompt
// This gets reset with the clang::Diagnostics().Reset()
// 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();
// Wrap the expression
std::string WrapperName;
std::string Wrapper = input;
WrapInput(Wrapper, WrapperName);
const Transaction* lastT = m_IncrParser->Compile(Wrapper, CO);
assert(lastT->getState() == Transaction::kCommitted && "Must be committed");
if (lastT->getIssuedDiags() == Transaction::kNone)
if (RunFunction(lastT->getWrapperFD()) < kExeFirstError)
return Interpreter::kSuccess;
return Interpreter::kFailure;
}
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) {
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();
input.insert(0, "void " + fname + "() {\n ");
input.append("\n;\n}");
}
Interpreter::ExecutionResult
Interpreter::RunFunction(const FunctionDecl* FD, StoredValueRef* res /*=0*/) {
if (getCI()->getDiagnostics().hasErrorOccurred())
return kExeCompilationError;
if (!m_IncrParser->hasCodeGenerator()) {
return kExeNoCodeGen;
}
if (!FD)
return kExeUnkownFunction;
std::string mangledNameIfNeeded;
maybeMangleDeclName(FD, mangledNameIfNeeded);
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()));
return ConvertExecutionResult(ExeRes);
}
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 {
// Disable warnings which doesn't make sense when using the prompt
// This gets reset with the clang::Diagnostics().Reset()
ignoreFakeDiagnostics();
Transaction* lastT = m_IncrParser->Compile(input, CO);
if (lastT->getIssuedDiags() != Transaction::kErrors) {
if (T)
*T = lastT;
return Interpreter::kSuccess;
}
return Interpreter::kFailure;
}
Interpreter::CompilationResult
Interpreter::EvaluateInternal(const std::string& input,
const CompilationOptions& CO,
StoredValueRef* V, /* = 0 */
Transaction** T /* = 0 */) {
// Disable warnings which doesn't make sense when using the prompt
// This gets reset with the clang::Diagnostics().Reset()
ignoreFakeDiagnostics();
// Wrap the expression
std::string WrapperName;
std::string Wrapper = input;
WrapInput(Wrapper, WrapperName);
Transaction* lastT = m_IncrParser->Compile(Wrapper, CO);
assert((!V || lastT->size()) && "No decls created!?");
assert((lastT->getState() == Transaction::kCommitted
|| lastT->getState() == Transaction::kRolledBack)
&& "Not committed?");
assert(lastT->getWrapperFD() && "Must have wrapper!");
if (lastT->getIssuedDiags() != Transaction::kErrors)
if (RunFunction(lastT->getWrapperFD(), V) < kExeFirstError)
return Interpreter::kSuccess;
if (V)
*V = StoredValueRef::invalidValue();
return Interpreter::kFailure;
}
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)
return kFailure;
}
std::string code;
code += "#include \"" + filename + "\"";
CompilationResult res = declare(code);
return res;
}
void Interpreter::installLazyFunctionCreator(void* (*fp)(const std::string&)) {
m_ExecutionContext->installLazyFunctionCreator(fp);
}
void Interpreter::suppressLazyFunctionCreatorDiags(bool suppressed/*=true*/) {
m_ExecutionContext->suppressLazyFunctionCreatorDiags(suppressed);
}
StoredValueRef 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());
StoredValueRef 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.
llvm::OwningPtr<ExternalASTSource> astContextExternalSource;
astContextExternalSource.reset(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.
Ctx.ExternalSource.take(); // FIXME: make sure we delete it.
Ctx.setExternalSource(astContextExternalSource);
}
//FIXME: Get rid of that.
clang::ASTDeserializationListener*
Interpreter::getASTDeserializationListener() const {
if (!m_Callbacks)
return 0;
return m_Callbacks->getInterpreterDeserializationListener();
}
const Transaction* Interpreter::getFirstTransaction() const {
return m_IncrParser->getFirstTransaction();
}
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 ExecutionContext; should not be called by
// anyone except for IncrementalParser.
llvm::Module* module = m_IncrParser->getCodeGenerator()->GetModule();
ExecutionContext::ExecutionResult ExeRes
= m_ExecutionContext->runStaticInitializersOnce(module);
// Reset the module builder to clean up global initializers, c'tors, d'tors
getCodeGenerator()->HandleTranslationUnit(getCI()->getASTContext());
return ConvertExecutionResult(ExeRes);
}
void Interpreter::runStaticDestructorsOnce() {
m_ExecutionContext->runStaticDestructorsOnce(getModule());
}
void Interpreter::maybeMangleDeclName(const clang::NamedDecl* D,
std::string& mangledName) const {
///Get the mangled name of a NamedDecl.
///
///D - mangle this decl's name
///mangledName - put the mangled name in here
if (!m_MangleCtx) {
m_MangleCtx.reset(getCI()->getASTContext().createMangleContext());
}
if (m_MangleCtx->shouldMangleDeclName(D)) {
llvm::raw_string_ostream RawStr(mangledName);
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_Complete, RawStr);
break;
default :
m_MangleCtx->mangleName(D, RawStr);
break;
}
RawStr.flush();
} else {
mangledName = D->getNameAsString();
}
}
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());
Diag.setDiagnosticMapping(clang::diag::ext_return_has_expr,
clang::diag::MAP_IGNORE, SourceLocation());
// Very very ugly. TODO: Revisit and extract out as interpreter arg
Diag.setDiagnosticMapping(clang::diag::ext_auto_type_specifier,
clang::diag::MAP_IGNORE, SourceLocation());
}
bool Interpreter::addSymbol(const char* symbolName, void* symbolAddress) {
// Forward to ExecutionContext;
if (!symbolName || !symbolAddress )
return false;
return m_ExecutionContext->addSymbol(symbolName, symbolAddress);
}
void* Interpreter::getAddressOfGlobal(const clang::NamedDecl* D,
bool* fromJIT /*=0*/) const {
// Return a symbol's address, and whether it was jitted.
std::string mangledName;
maybeMangleDeclName(D, mangledName);
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.
llvm::Module* module = m_IncrParser->getCodeGenerator()->GetModule();
return m_ExecutionContext->getAddressOfGlobal(module, SymName, fromJIT);
}
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.
return getCodeGenerator()->ConvertType(QT);
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
}
} // namespace cling