//------------------------------------------------------------------------------ // CLING - the C++ LLVM-based InterpreterG :) // author: Lukasz Janyst // // 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/Utils/Paths.h" #ifdef _WIN32 #include "cling/Utils/Platform.h" #endif #include "ClingUtils.h" #include "DynamicLookup.h" #include "EnterUserCodeRAII.h" #include "ExternalInterpreterSource.h" #include "ForwardDeclPrinter.h" #include "IncrementalExecutor.h" #include "IncrementalParser.h" #include "MultiplexInterpreterCallbacks.h" #include "TransactionUnloader.h" #include "cling/Interpreter/AutoloadCallback.h" #include "cling/Interpreter/CIFactory.h" #include "cling/Interpreter/ClangInternalState.h" #include "cling/Interpreter/ClingCodeCompleteConsumer.h" #include "cling/Interpreter/CompilationOptions.h" #include "cling/Interpreter/DynamicExprInfo.h" #include "cling/Interpreter/DynamicLibraryManager.h" #include "cling/Interpreter/Exception.h" #include "cling/Interpreter/IncrementalCUDADeviceCompiler.h" #include "cling/Interpreter/LookupHelper.h" #include "cling/Interpreter/Transaction.h" #include "cling/Interpreter/Value.h" #include "cling/Interpreter/Visibility.h" #include "cling/Utils/AST.h" #include "cling/Utils/Casting.h" #include "cling/Utils/Output.h" #include "cling/Utils/SourceNormalization.h" #include "clang/AST/ASTContext.h" #include "clang/AST/GlobalDecl.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" #include "clang/CodeGen/ModuleBuilder.h" #include "clang/Frontend/ASTConsumers.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/Utils.h" #include "clang/Lex/ExternalPreprocessorSource.h" #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/HeaderSearchOptions.h" #include "clang/Lex/Preprocessor.h" #include "clang/Parse/Parser.h" #include "clang/Sema/Sema.h" #include "clang/Sema/SemaDiagnostic.h" #include "llvm/IR/LLVMContext.h" #include "llvm/IR/Module.h" #include "llvm/Support/Path.h" #include #include #include using namespace clang; namespace { static void registerCxaAtExitHelper(void *Self, void (*F)(void *), void *Ctx, void *DSOHandle) { static_cast(Self)->AddAtExitFunc(F, Ctx); } static void registerAtExitHelper(void *Self, void *DSOHandle, void (*F)()) { static_cast(Self)->AddAtExitFunc( reinterpret_cast(F), nullptr); } 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 { Interpreter::PushTransactionRAII::PushTransactionRAII(const Interpreter* i) : m_Interpreter(i) { CompilationOptions CO = m_Interpreter->makeDefaultCompilationOpts(); CO.ResultEvaluation = 0; CO.DynamicScoping = 0; m_Transaction = m_Interpreter->m_IncrParser->beginTransaction(CO); } Interpreter::PushTransactionRAII::~PushTransactionRAII() { pop(); } void Interpreter::PushTransactionRAII::pop() const { if (m_Transaction->getState() == Transaction::kRolledBack) return; IncrementalParser::ParseResultTransaction PRT = m_Interpreter->m_IncrParser->endTransaction(m_Transaction); if (PRT.getPointer()) { assert(PRT.getPointer()==m_Transaction && "Ended different transaction?"); m_Interpreter->m_IncrParser->commitTransaction(PRT); } } Interpreter::StateDebuggerRAII::StateDebuggerRAII(const Interpreter* i) : m_Interpreter(i) { if (m_Interpreter->isPrintingDebug()) { const CompilerInstance& CI = *m_Interpreter->getCI(); CodeGenerator* CG = i->m_IncrParser->getCodeGenerator(); // The ClangInternalState constructor can provoke deserialization, // we need a transaction. PushTransactionRAII pushedT(i); m_State.reset( new ClangInternalState(CI.getASTContext(), CI.getPreprocessor(), CG ? CG->GetModule() : nullptr, CG, "aName")); } } Interpreter::StateDebuggerRAII::~StateDebuggerRAII() { if (m_State) { // The ClangInternalState destructor can provoke deserialization, // we need a transaction. PushTransactionRAII pushedT(m_Interpreter); m_State->compare("aName", m_Interpreter->m_Opts.Verbose()); m_State.reset(); } } const Parser& Interpreter::getParser() const { return *m_IncrParser->getParser(); } Parser& Interpreter::getParser() { return *m_IncrParser->getParser(); } clang::SourceLocation Interpreter::getNextAvailableLoc() const { return m_IncrParser->getNextAvailableUniqueSourceLoc(); } bool Interpreter::isInSyntaxOnlyMode() const { return getCI()->getFrontendOpts().ProgramAction == clang::frontend::ParseSyntaxOnly; } bool Interpreter::isValid() const { // Should we also check m_IncrParser->getFirstTransaction() ? // not much can be done without it (its the initializing transaction) return m_IncrParser && m_IncrParser->isValid() && m_LookupHelper && (isInSyntaxOnlyMode() || m_Executor); } namespace internal { void symbol_requester(); } const char* Interpreter::getVersion() { return ClingStringify(CLING_VERSION); } static bool handleSimpleOptions(const InvocationOptions& Opts) { if (Opts.ShowVersion) { cling::log() << Interpreter::getVersion() << '\n'; } if (Opts.Help) { Opts.PrintHelp(); } return Opts.ShowVersion || Opts.Help; } static void setupCallbacks(Interpreter& Interp, const Interpreter* parentInterp) { // We need InterpreterCallbacks only if it is a parent Interpreter. if (parentInterp) return; // Disable suggestions for ROOT bool showSuggestions = !llvm::StringRef(ClingStringify(CLING_VERSION)).starts_with("ROOT"); std::unique_ptr AutoLoadCB( new AutoloadCallback(&Interp, showSuggestions)); Interp.setCallbacks(std::move(AutoLoadCB)); } Interpreter::Interpreter(int argc, const char* const *argv, const char* llvmdir /*= 0*/, const ModuleFileExtensions& moduleExtensions, void *extraLibHandle, bool noRuntime, const Interpreter* parentInterp) : m_Opts(argc, argv), m_UniqueCounter(parentInterp ? parentInterp->m_UniqueCounter + 1 : 0), m_PrintDebug(false), m_DynamicLookupDeclared(false), m_DynamicLookupEnabled(false), m_RawInputEnabled(false), m_RuntimeOptions{}, m_OptLevel(parentInterp ? parentInterp->m_OptLevel : -1) { if (handleSimpleOptions(m_Opts)) return; auto LLVMCtx = std::make_unique(); TSCtx = std::make_unique(std::move(LLVMCtx)); m_IncrParser.reset(new IncrementalParser(this, llvmdir, moduleExtensions)); if (!m_IncrParser->isValid(false)) return; // Load any requested plugins. getCI()->LoadRequestedPlugins(); // Honor set of `-mllvm` options. This should happen AFTER plugins have been // loaded! if (!m_Opts.CompilerOpts.LLVMArgs.empty()) { unsigned NumArgs = m_Opts.CompilerOpts.LLVMArgs.size(); auto Args = std::make_unique(NumArgs + 2); Args[0] = "cling (LLVM option parsing)"; for (unsigned i = 0; i != NumArgs; ++i) Args[i + 1] = m_Opts.CompilerOpts.LLVMArgs[i].c_str(); Args[NumArgs + 1] = nullptr; llvm::cl::ParseCommandLineOptions(NumArgs + 1, Args.get()); } // Initialize the opt level to what CodeGenOpts says. if (m_OptLevel == -1) setDefaultOptLevel(getCI()->getCodeGenOpts().OptimizationLevel); if (!isInSyntaxOnlyMode() && m_Opts.CompilerOpts.CUDAHost) { // Create temporary folder for all files, which the CUDA device compiler // will generate. llvm::SmallString<256> TmpPath; llvm::StringRef sep = llvm::sys::path::get_separator().data(); llvm::sys::path::system_temp_directory(false, TmpPath); TmpPath.append(sep.data()); TmpPath.append("cling-%%%%"); TmpPath.append(sep.data()); llvm::SmallString<256> TmpFolder; llvm::sys::fs::createUniqueFile(TmpPath.c_str(), TmpFolder); llvm::sys::fs::create_directory(TmpFolder); // The CUDA fatbin file is the connection beetween the CUDA device // compiler and the CodeGen of cling. The file will every time reused. if (getCI()->getCodeGenOpts().CudaGpuBinaryFileName.empty()) getCI()->getCodeGenOpts().CudaGpuBinaryFileName = std::string(TmpFolder.c_str()) + "cling.fatbin"; m_CUDACompiler.reset(new IncrementalCUDADeviceCompiler( TmpFolder.c_str(), m_OptLevel, m_Opts, *(getCI()))); } 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_LookupHelper) return; if (!isInSyntaxOnlyMode() && !m_Opts.CompilerOpts.CUDADevice) { m_Executor.reset(new IncrementalExecutor(SemaRef.Diags, *getCI(), extraLibHandle, m_Opts.Verbose())); if (!m_Executor) return; for (const std::string &P : m_Opts.LibSearchPath) getDynamicLibraryManager()->addSearchPath(P); } bool usingCxxModules = getSema().getLangOpts().Modules; if (usingCxxModules) { // Explicitly create the modulemanager now. If we would create it later // implicitly then it would just overwrite our callbacks we set below. m_IncrParser->getCI()->createASTReader(); // When using C++ modules, we setup the callbacks now that we have them // ready before we parse code for the first time. Without C++ modules // we can't setup the calls now because the clang PCH currently just // overwrites it in the Initialize method and we have no simple way to // initialize them earlier. We handle the non-modules case below. setupCallbacks(*this, parentInterp); } if (m_Opts.CompilerOpts.CUDAHost && !isInSyntaxOnlyMode()) { if (getDynamicLibraryManager()->loadLibrary("libcudart.so", true) == cling::DynamicLibraryManager::LoadLibResult::kLoadLibNotFound){ llvm::errs() << "Error: libcudart.so not found!\n" << "Please add the cuda lib path to LD_LIBRARY_PATH or set it via -L argument.\n"; } } llvm::SmallVector IncrParserTransactions; if (!m_IncrParser->Initialize(IncrParserTransactions, parentInterp)) { // Initialization is not going well, but we still have to commit what // we've been given. Don't clear the DiagnosticsConsumer so the caller // can inspect any errors that have been generated. for (auto&& I: IncrParserTransactions) m_IncrParser->commitTransaction(I, false); return; } // When not using C++ modules, we now have a PCH and we can safely setup // our callbacks without fearing that they get overwritten by clang code. // The modules setup is handled above. if (!usingCxxModules) { setupCallbacks(*this, parentInterp); } llvm::SmallVector Syms; Initialize(noRuntime || m_Opts.NoRuntime, isInSyntaxOnlyMode(), Syms); // Commit the transactions, now that gCling is set up. It is needed for // static initialization in these transactions through // registerCxaAtExitHelper(). for (auto&& I: IncrParserTransactions) m_IncrParser->commitTransaction(I); // Now that the transactions have been commited, force symbol emission // and overrides. if (!isInSyntaxOnlyMode() && !m_Opts.CompilerOpts.CUDADevice) { for (const llvm::StringRef& Sym : Syms) { void* Addr = m_Executor->getPointerToGlobalFromJIT(Sym); #if defined(__linux__) // We need to look for the mangled name of at_quick_exit on linux. if (!Addr && Sym.equals("at_quick_exit")) Addr = m_Executor->getPointerToGlobalFromJIT("_Z13at_quick_exitPFvvE"); #endif if (!Addr) { cling::errs() << "Replaced symbol " << Sym << " cannot be found in JIT!\n"; } else { m_Executor->replaceSymbol(Sym.str().c_str(), Addr); } } } m_IncrParser->SetTransformers(parentInterp); if (!TSCtx->getContext()) { // Never true, but don't tell the compiler. // Force symbols needed by runtime to be included in binaries. // Prevents stripping the symbol due to dead-code optimization. internal::symbol_requester(); } } ///\brief Constructor for the child Interpreter. /// Passing the parent Interpreter as an argument. /// Interpreter::Interpreter(const Interpreter &parentInterpreter, int argc, const char* const *argv, const char* llvmdir /*= 0*/, const ModuleFileExtensions& moduleExtensions/*={}*/, void *ExtraLibHandle, bool noRuntime /*= true*/) : Interpreter(argc, argv, llvmdir, moduleExtensions, ExtraLibHandle, noRuntime, &parentInterpreter) { // Do the "setup" of the connection between this interpreter and // its parent interpreter. if (CompilerInstance* CI = getCIOrNull()) { // The "bridge" between the interpreters. ExternalInterpreterSource *myExternalSource = new ExternalInterpreterSource(&parentInterpreter, this); llvm::IntrusiveRefCntPtr astContextExternalSource(myExternalSource); CI->getASTContext().setExternalSource(astContextExternalSource); // Inform the Translation Unit Decl of I2 that it has to search somewhere // else to find the declarations. CI->getASTContext().getTranslationUnitDecl()->setHasExternalVisibleStorage(true); // Give my IncrementalExecutor a pointer to the Incremental executor of the // parent Interpreter. m_Executor->registerExternalIncrementalExecutor( *parentInterpreter.m_Executor); if (auto C = parentInterpreter.m_IncrParser->getDiagnosticConsumer()) m_IncrParser->setDiagnosticConsumer(C, /*Own=*/false); } } Interpreter::~Interpreter() { // Do this first so m_StoredStates will be ignored if Interpreter::unload // is called later on. for (size_t i = 0, e = m_StoredStates.size(); i != e; ++i) delete m_StoredStates[i]; m_StoredStates.clear(); if (m_Executor) m_Executor->shuttingDown(); // LookupHelper's ~Parser needs the PP from IncrParser's CI, so do this // first: m_LookupHelper.reset(); ShutDown(); // We want to keep the callback alive during the shutdown of Sema, CodeGen // and the ASTContext. For that to happen we shut down the IncrementalParser // explicitly, before the implicit destruction (through the unique_ptr) of // the callbacks. m_IncrParser.reset(nullptr); } Transaction* Interpreter::Initialize(bool NoRuntime, bool SyntaxOnly, llvm::SmallVectorImpl& Globals) { // The Initialize() function is called twice in CUDA mode. The first time // the host interpreter is initialized and the second time the device // interpreter is initialized. Without this if statement, a redefinition // error would occur because process(), declare(), and parse() are designed // to process the code in the host and device interpreter when called by the // host interpreter instance. This means that first the Initialize() // function of the host interpreter is called and the initialization code is // processed in the host and device interpreter. It then calls the // Initialize() function of the device interpreter and throws an error // because the code was already processed in the host Initialize() function. // // declare() is only used to generate a valid Transaction object if (m_Opts.CompilerOpts.CUDADevice) { Transaction* T; declare("", &T); return T; } largestream Strm; const clang::LangOptions& LangOpts = getCI()->getLangOpts(); const void* ThisP = static_cast(this); // PCH/PCM-generation defines syntax-only. If we include definitions, // loading the PCH/PCM will make the runtime barf about dupe definitions. bool EmitDefinitions = !SyntaxOnly; // FIXME: gCling should be const so assignemnt is a compile time error. // Currently the name mangling is coming up wrong for the const version // (on OS X at least, so probably Linux too) and the JIT thinks the symbol // is undefined in a child Interpreter. And speaking of children, should // gCling actually be thisCling, so a child Interpreter can only access // itself? One could use a macro (simillar to __dso_handle) to block // assignemnt and get around the mangling issue. const char* Linkage = LangOpts.CPlusPlus ? "extern \"C\"" : ""; if (!NoRuntime) { if (LangOpts.CPlusPlus) { Strm << "#include \n"; if (EmitDefinitions) Strm << "namespace cling { class Interpreter; namespace runtime { " "Interpreter* gCling=(Interpreter*)" << ThisP << ";\n" "RuntimeOptions* gClingOpts=(RuntimeOptions*)" << &this->m_RuntimeOptions << ";}}\n"; } else { Strm << "#include \n" << "void* gCling"; if (EmitDefinitions) Strm << "=(void*)" << ThisP; Strm << ";\n"; } } // Intercept all atexit calls, as the Interpreter and functions will be long // gone when the -native- versions invoke them. #if defined(__GLIBC__) const char* LinkageCxx = "extern \"C++\""; const char* Attr = LangOpts.CPlusPlus ? " throw () " : ""; #else const char* LinkageCxx = Linkage; const char* Attr = ""; #endif #if defined(__GLIBCXX__) const char* cxa_atexit_is_noexcept = LangOpts.CPlusPlus ? " noexcept" : ""; #else const char* cxa_atexit_is_noexcept = ""; #endif // While __dso_handle is still overriden in the JIT below, // #define __dso_handle is used to mitigate the following problems: // 1. Type of __dso_handle is void* making assignemnt to it legal // 2. Making it void* const in cling would mean possible type mismatch // 3. Cannot override void* __dso_handle in child Interpreter // 4. On Unix where the symbol actually exists, __dso_handle will be // linked into the code before the JIT can say otherwise, so: // [cling] __dso_handle // codegened __dso_handle always printed // [cling] __cxa_atexit(f, 0, __dso_handle) // seg-fault // 5. Code that actually uses __dso_handle will fail as a declaration is // needed which is not possible with the macro. // 6. Assuming 4 is sorted out in user code, calling __cxa_atexit through // atexit below isn't linking to the __dso_handle symbol. // Use __cxa_atexit to intercept all of the following routines Strm << Linkage << " int __cxa_atexit(void (*f)(void*), void*, void*) " << cxa_atexit_is_noexcept << ";\n"; if (EmitDefinitions) Strm << "#define __dso_handle ((void*)" << ThisP << ")\n"; // C atexit, std::atexit -- registered by GenericLLVMIRPlatformSupport // C++ 11 at_quick_exit, std::at_quick_exit if (LangOpts.CPlusPlus && LangOpts.CPlusPlus11) { Strm << LinkageCxx << " int at_quick_exit(void(*f)()) " << Attr; if (EmitDefinitions) Strm << " { return __cxa_atexit((void(*)(void*))f, 0, __dso_handle); }\n"; else Strm << ";\n"; Globals.push_back("at_quick_exit"); } #if defined(_WIN32) // Windows specific: _onexit, _onexit_m, __dllonexit #if !defined(_M_CEE) const char* Spec = "__cdecl"; #else const char* Spec = "__clrcall"; #endif Strm << Linkage << " " << Spec << " int (*__dllonexit(" << "int (" << Spec << " *f)(void**, void**), void**, void**))" "(void**, void**)"; if (EmitDefinitions) Strm << " { __cxa_atexit((void(*)(void*))f, 0, __dso_handle);" " return f; }\n"; else Strm << ";\n"; Globals.push_back("__dllonexit"); #if !defined(_M_CEE_PURE) Strm << Linkage << " " << Spec << " int (*_onexit(" << "int (" << Spec << " *f)()))()"; if (EmitDefinitions) Strm << " { __cxa_atexit((void(*)(void*))f, 0, __dso_handle);" " return f; }\n"; else Strm << ";\n"; Globals.push_back("_onexit"); #endif #endif if (!SyntaxOnly) { // Override the helper symbols injected by GenericLLVMIRPlatformSupport, // before anything can be emitted. m_Executor->replaceSymbol("__lljit.cxa_atexit_helper", utils::FunctionToVoidPtr(®isterCxaAtExitHelper)); m_Executor->replaceSymbol("__lljit.atexit_helper", utils::FunctionToVoidPtr(®isterAtExitHelper)); // Replace __lljit.platform_support_instance which is passed as Self // to the helper functions. We cannot easily replace __dso_handle (in // the code already generated by GenericLLVMIRPlatformSupport) because // it is wired up as a constant (for the current JITDylib)... m_Executor->replaceSymbol("__lljit.platform_support_instance", this); // Still insert __dso_handle for the link phase, as macro is useless then. // TODO: Is this still relevant now that registerCxaAtExitHelper uses the // Self parameter and the DSOHandle argument is basically unused? The only // weird procedure I found to make this matter is: // #undef __dso_handle // extern "C" void *__dso_handle; // then cling::runtime::gCling is identical to &__dso_handle. m_Executor->replaceSymbol("__dso_handle", this); #ifdef _MSC_VER // According to the PE Format spec, in "The .tls Section" // (http://www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx): // 2. When a thread is created, the loader communicates the address // of the thread's TLS array by placing the address of the thread // environment block (TEB) in the FS register. A pointer to the TLS // array is at the offset of 0x2C from the beginning of TEB. This // behavior is Intel x86-specific. static const unsigned long _tls_array = 0x2C; m_Executor->replaceSymbol("_tls_array", (void *)&_tls_array); // Support SEH on Windows. m_Executor->replaceSymbol("_CxxThrowException@8", &_CxxThrowException); #endif #ifdef CLING_WIN_SEH_EXCEPTIONS // Windows C++ SEH handler m_Executor->replaceSymbol("_CxxThrowException", utils::FunctionToVoidPtr(&platform::ClingRaiseSEHException)); #endif } if (m_Opts.Verbose()) cling::errs() << Strm.str().str(); Transaction *T; declare(Strm.str().str(), &T); return T; } void Interpreter::ShutDown() { // Model the shutdown actions done in FrontendAction::EndSourceFile if (CompilerInstance* CI = getCIOrNull()) { CI->getDiagnostics().getClient()->EndSourceFile(); if (CI->hasPreprocessor()) CI->getPreprocessor().EndSourceFile(); bool DisableFree = CI->getFrontendOpts().DisableFree; if (DisableFree) { CI->resetAndLeakSema(); CI->resetAndLeakASTContext(); llvm::BuryPointer(CI->takeASTConsumer().get()); } else { CI->setSema(nullptr); CI->setASTContext(nullptr); CI->setASTConsumer(nullptr); } if (CI->getFrontendOpts().ShowStats) { llvm::errs() << "\nSTATISTICS \n"; CI->getPreprocessor().PrintStats(); CI->getPreprocessor().getIdentifierTable().PrintStats(); CI->getPreprocessor().getHeaderSearchInfo().PrintStats(); CI->getSourceManager().PrintStats(); llvm::errs() << "\n"; } // Cleanup the output streams, and erase the output files if instructed by // the FrontendAction. bool shouldEraseOutputFiles = CI->getDiagnostics().hasErrorOccurred(); CI->clearOutputFiles(/*EraseFiles=*/shouldEraseOutputFiles); LangOptions& LO = CI->getLangOpts(); if (LO.getCompilingModule() != clang::LangOptions::CMK_None) { if (DisableFree) { CI->resetAndLeakPreprocessor(); CI->resetAndLeakSourceManager(); CI->resetAndLeakFileManager(); } else { CI->setPreprocessor(nullptr); CI->setSourceManager(nullptr); CI->setFileManager(nullptr); } } LO.setCompilingModule(clang::LangOptions::CMK_None); } } void Interpreter::AddIncludePaths(llvm::StringRef PathStr, const char* Delm) { CompilerInstance* CI = getCI(); HeaderSearchOptions& HOpts = CI->getHeaderSearchOpts(); // Save the current number of entries size_t Idx = HOpts.UserEntries.size(); utils::AddIncludePaths(PathStr, HOpts, Delm); Preprocessor& PP = CI->getPreprocessor(); SourceManager& SM = PP.getSourceManager(); FileManager& FM = SM.getFileManager(); HeaderSearch& HSearch = PP.getHeaderSearchInfo(); const bool isFramework = false; // Add all the new entries into Preprocessor for (const size_t N = HOpts.UserEntries.size(); Idx < N; ++Idx) { const HeaderSearchOptions::Entry& E = HOpts.UserEntries[Idx]; if (auto DE = FM.getOptionalDirectoryRef(E.Path)) HSearch.AddSearchPath(DirectoryLookup(*DE, SrcMgr::C_User, isFramework), E.Group == frontend::Angled); } if (m_CUDACompiler) m_CUDACompiler->getPTXInterpreter()->AddIncludePaths(PathStr, Delm); } void Interpreter::AddIncludePath(llvm::StringRef PathsStr) { return AddIncludePaths(PathsStr, nullptr); } void Interpreter::DumpIncludePath(llvm::raw_ostream* S) const { utils::DumpIncludePaths(getCI()->getHeaderSearchOpts(), S ? *S : cling::outs(), true /*withSystem*/, true /*withFlags*/); } void Interpreter::DumpDynamicLibraryInfo(llvm::raw_ostream* S) const { if (auto DLM = getDynamicLibraryManager()) DLM->dump(S); } // FIXME: Add stream argument and move DumpIncludePath path here. void Interpreter::dump(llvm::StringRef what, llvm::StringRef filter) { llvm::raw_ostream &where = cling::log(); // `.stats decl' and `.stats asttree FILTER' cause deserialization; force transaction PushTransactionRAII RAII(this); if (what.equals("asttree")) { std::unique_ptr printer = clang::CreateASTDumper(nullptr /*Dump to stdout.*/, filter, true /*DumpDecls*/, false /*Deserialize*/, false /*DumpLookups*/, false /*DumpDeclTypes*/, ADOF_Default /*DumpFormat*/); printer->HandleTranslationUnit(getSema().getASTContext()); } else if (what.equals("ast")) getSema().getASTContext().PrintStats(); else if (what.equals("decl")) ClangInternalState::printLookupTables(where, getSema().getASTContext()); else if (what.equals("undo")) m_IncrParser->printTransactionStructure(); } void Interpreter::storeInterpreterState(const std::string& name) const { // This may induce deserialization PushTransactionRAII RAII(this); CodeGenerator* CG = m_IncrParser->getCodeGenerator(); ClangInternalState* state = new ClangInternalState( getCI()->getASTContext(), getCI()->getPreprocessor(), getLastTransaction()->getCompiledModule(), CG, name); m_StoredStates.push_back(state); } void Interpreter::compareInterpreterState(const std::string &Name) const { const auto Itr = std::find_if( m_StoredStates.begin(), m_StoredStates.end(), [&Name](const ClangInternalState *S) { return S->getName() == Name; }); if (Itr == m_StoredStates.end()) { cling::errs() << "The store point name " << Name << " does not exist." "Unbalanced store / compare\n"; return; } // This may induce deserialization PushTransactionRAII RAII(this); (*Itr)->compare(Name, m_Opts.Verbose()); } void Interpreter::printIncludedFiles(llvm::raw_ostream& Out) const { ClangInternalState::printIncludedFiles(Out, getCI()->getSourceManager()); } namespace valuePrinterInternal { void declarePrintValue(Interpreter &Interp); } std::string Interpreter::toString(const char* type, void* obj) { LockCompilationDuringUserCodeExecutionRAII LCDUCER(*this); cling::valuePrinterInternal::declarePrintValue(*this); std::string buf, ret; llvm::raw_string_ostream ss(buf); ss << "*((std::string*)" << &ret << ") = cling::printValue((" << type << "*)" << obj << ");"; CompilationResult result = process(ss.str().c_str()); if (result != cling::Interpreter::kSuccess) llvm::errs() << "Error in Interpreter::toString: the input " << ss.str() << " cannot be evaluated"; return ret; } void Interpreter::GetIncludePaths(llvm::SmallVectorImpl& incpaths, bool withSystem, bool withFlags) { utils::CopyIncludePaths(getCI()->getHeaderSearchOpts(), incpaths, withSystem, withFlags); } CompilerInstance* Interpreter::getCI() const { return m_IncrParser->getCI(); } CompilerInstance* Interpreter::getCIOrNull() const { return m_IncrParser ? m_IncrParser->getCI() : nullptr; } Sema& Interpreter::getSema() const { return getCI()->getSema(); } DiagnosticsEngine& Interpreter::getDiagnostics() const { return getCI()->getDiagnostics(); } void Interpreter::replaceDiagnosticConsumer(clang::DiagnosticConsumer* Consumer, bool Own) { m_IncrParser->setDiagnosticConsumer(Consumer, Own); } bool Interpreter::hasReplacedDiagnosticConsumer() const { return m_IncrParser->getDiagnosticConsumer() != nullptr; } CompilationOptions Interpreter::makeDefaultCompilationOpts() const { CompilationOptions CO; CO.DeclarationExtraction = 0; CO.EnableShadowing = 0; CO.ValuePrinting = CompilationOptions::VPDisabled; CO.CodeGeneration = m_IncrParser->hasCodeGenerator(); CO.DynamicScoping = isDynamicLookupEnabled(); CO.Debug = isPrintingDebug(); CO.IgnorePromptDiags = 0; CO.CheckPointerValidity = !isRawInputEnabled(); CO.OptLevel = getDefaultOptLevel(); return CO; } const MacroInfo* Interpreter::getMacro(llvm::StringRef Macro) const { clang::Preprocessor& PP = getCI()->getPreprocessor(); if (IdentifierInfo* II = PP.getIdentifierInfo(Macro)) { // If the information about this identifier is out of date, update it from // the external source. // FIXME: getIdentifierInfo will probably do this for us once we update // clang. If so, please remove this manual update. if (II->isOutOfDate()) PP.getExternalSource()->updateOutOfDateIdentifier(*II); MacroDefinition MDef = PP.getMacroDefinition(II); MacroInfo* MI = MDef.getMacroInfo(); return MI; } return nullptr; } std::string Interpreter::getMacroValue(llvm::StringRef Macro, const char* Trim) const { std::string Value; if (const MacroInfo* MI = getMacro(Macro)) { for (const clang::Token& Tok : MI->tokens()) { llvm::SmallString<64> Buffer; Macro = getCI()->getPreprocessor().getSpelling(Tok, Buffer); if (!Value.empty()) Value += " "; Value += Trim ? Macro.trim(Trim).str() : Macro.str(); } } return Value; } ///\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, Value* V /* = 0 */, Transaction** T /* = 0 */, bool disableValuePrinting /* = false*/) { if (!isInSyntaxOnlyMode() && m_Opts.CompilerOpts.CUDAHost) m_CUDACompiler->process(input); std::string wrapReadySource = input; size_t wrapPoint = std::string::npos; if (!isRawInputEnabled()) wrapPoint = utils::getWrapPoint(wrapReadySource, getCI()->getLangOpts()); CompilationOptions CO = makeDefaultCompilationOpts(); CO.EnableShadowing = m_RuntimeOptions.AllowRedefinition && !isRawInputEnabled(); if (isRawInputEnabled() || wrapPoint == std::string::npos) { CO.DeclarationExtraction = 0; CO.ValuePrinting = 0; CO.ResultEvaluation = 0; return DeclareInternal(input, CO, T); } CO.DeclarationExtraction = 1; CO.ValuePrinting = disableValuePrinting ? CompilationOptions::VPDisabled : CompilationOptions::VPAuto; CO.ResultEvaluation = (bool)V; // CO.IgnorePromptDiags = 1; done by EvaluateInternal(). CO.CheckPointerValidity = 1; if (EvaluateInternal(wrapReadySource, CO, V, T, wrapPoint) == Interpreter::kFailure) { return Interpreter::kFailure; } return Interpreter::kSuccess; } Interpreter::CompilationResult Interpreter::parse(const std::string& input, Transaction** T /*=0*/) const { if (!isInSyntaxOnlyMode() && m_Opts.CompilerOpts.CUDAHost) m_CUDACompiler->parse(input); CompilationOptions CO = makeDefaultCompilationOpts(); CO.CodeGeneration = 0; CO.DeclarationExtraction = 0; CO.ValuePrinting = 0; CO.ResultEvaluation = 0; return DeclareInternal(input, CO, T); } ///\returns true if the module was loaded. bool Interpreter::loadModule(const std::string& moduleName, bool complain /*= true*/) { assert(getCI()->getLangOpts().Modules && "Function only relevant when C++ modules are turned on!"); Preprocessor& PP = getCI()->getPreprocessor(); HeaderSearch &HS = PP.getHeaderSearchInfo(); if (Module *M = HS.lookupModule(moduleName, SourceLocation(), /*AllowSearch*/true, /*AllowExtraSearch*/ true)) return loadModule(M, complain); if (complain) llvm::errs() << "Module " << moduleName << " not found.\n"; return false; } bool Interpreter::loadModule(clang::Module* M, bool complain /* = true*/) { assert(getCI()->getLangOpts().Modules && "Function only relevant when C++ modules are turned on!"); assert(M && "Module missing"); if (getSema().isModuleVisible(M)) return true; // We cannot use #pragma clang module import because the on-demand modules // may load a module in the middle of a function body for example. In this // case this triggers an error: // fatal error: import of module '...' appears within function '...' // // if (declare("#pragma clang module import \"" + M->Name + "\"") == // kSuccess) // return true; // FIXME: What about importing submodules such as std.blah. This disables // this functionality. Preprocessor& PP = getCI()->getPreprocessor(); IdentifierInfo* II = PP.getIdentifierInfo(M->Name); SourceLocation ValidLoc = getNextAvailableLoc(); // Don't push the ImportDecl into a ClassDecl or whatever - who knows which // context triggered this import! DeclContext *OldDC = getSema().CurContext; getSema().CurContext = getSema().getASTContext().getTranslationUnitDecl(); bool success = !getSema().ActOnModuleImport(ValidLoc, /*ExportLoc*/ {}, ValidLoc, std::make_pair(II, ValidLoc)).isInvalid(); getSema().CurContext = OldDC; if (success) { // Also make the module visible in the preprocessor to export its macros. PP.makeModuleVisible(M, ValidLoc); return success; } if (complain) { if (M->IsSystem) llvm::errs() << "Failed to load module " << M->Name << "\n"; else llvm::outs() << "Failed to load module " << M->Name << "\n"; } return false; } Interpreter::CompilationResult Interpreter::parseForModule(const std::string& input) { CompilationOptions CO = makeDefaultCompilationOpts(); CO.CodeGenerationForModule = 1; CO.DeclarationExtraction = 0; CO.ValuePrinting = 0; CO.ResultEvaluation = 0; // 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 = getDiagnostics(); Diag.setSeverity(clang::diag::warn_field_is_uninit, clang::diag::Severity::Ignored, SourceLocation()); CompilationResult Result = DeclareInternal(input, CO); Diag.setSeverity(clang::diag::warn_field_is_uninit, clang::diag::Severity::Warning, SourceLocation()); return Result; } Interpreter::CompilationResult Interpreter::CodeCompleteInternal(const std::string& input, unsigned offset) { CompilationOptions CO = makeDefaultCompilationOpts(); CO.DeclarationExtraction = 0; CO.ValuePrinting = 0; CO.ResultEvaluation = 0; CO.CheckPointerValidity = 0; std::string wrapped = input; size_t wrapPos = utils::getWrapPoint(wrapped, getCI()->getLangOpts()); const std::string& Src = WrapInput(wrapped, wrapped, wrapPos); CO.CodeCompletionOffset = offset + wrapPos; StateDebuggerRAII stateDebugger(this); // This triggers the FileEntry to be created and the completion // point to be set in clang. m_IncrParser->Compile(Src, CO); return kSuccess; } Interpreter::CompilationResult Interpreter::declare(const std::string& input, Transaction** T/*=0 */) { if (!isInSyntaxOnlyMode() && m_Opts.CompilerOpts.CUDAHost) m_CUDACompiler->declare(input); CompilationOptions CO = makeDefaultCompilationOpts(); CO.DeclarationExtraction = 0; CO.ValuePrinting = 0; CO.ResultEvaluation = 0; CO.CheckPointerValidity = 0; return DeclareInternal(input, CO, T); } Interpreter::CompilationResult 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 = makeDefaultCompilationOpts(); CO.DeclarationExtraction = 0; CO.ValuePrinting = 0; CO.ResultEvaluation = 1; CO.CheckPointerValidity = 0; return EvaluateInternal(input, CO, &V); } Interpreter::CompilationResult Interpreter::codeComplete(const std::string& line, size_t& cursor, std::vector& completions) const { const char * const argV = "cling"; std::string resourceDir = this->getCI()->getHeaderSearchOpts().ResourceDir; // Remove the extra 3 directory names "/lib/clang/3.9.0" StringRef parentResourceDir = llvm::sys::path::parent_path( llvm::sys::path::parent_path( llvm::sys::path::parent_path(resourceDir))); std::string llvmDir = parentResourceDir.str(); Interpreter childInterpreter(*this, 1, &argV, llvmDir.c_str()); if (!childInterpreter.isValid()) return kFailure; auto childCI = childInterpreter.getCI(); clang::Sema &childSemaRef = childCI->getSema(); // Create the CodeCompleteConsumer with InterpreterCallbacks // from the parent interpreter and set the consumer for the child // interpreter. ClingCodeCompleteConsumer* consumer = new ClingCodeCompleteConsumer( getCI()->getFrontendOpts().CodeCompleteOpts, completions); // Child interpreter CI will own consumer! childCI->setCodeCompletionConsumer(consumer); childSemaRef.CodeCompleter = consumer; // Ignore diagnostics when we tab complete. // This is because we get redefinition errors due to the import of the decls. clang::IgnoringDiagConsumer* ignoringDiagConsumer = new clang::IgnoringDiagConsumer(); childSemaRef.getDiagnostics().setClient(ignoringDiagConsumer, true); DiagnosticsEngine& parentDiagnostics = this->getCI()->getSema().getDiagnostics(); std::unique_ptr ownerDiagConsumer = parentDiagnostics.takeClient(); auto clientDiagConsumer = parentDiagnostics.getClient(); parentDiagnostics.setClient(ignoringDiagConsumer, /*owns*/ false); // The child will desirialize decls from *this. We need a transaction RAII. PushTransactionRAII RAII(this); // Triger the code completion. childInterpreter.CodeCompleteInternal(line, cursor); // Restore the original diagnostics client for parent interpreter. parentDiagnostics.setClient(clientDiagConsumer, ownerDiagConsumer.release() != nullptr); parentDiagnostics.Reset(/*soft=*/true); return kSuccess; } Interpreter::CompilationResult Interpreter::echo(const std::string& input, Value* V /* = 0 */) { CompilationOptions CO = makeDefaultCompilationOpts(); CO.DeclarationExtraction = 0; CO.ValuePrinting = CompilationOptions::VPEnabled; CO.ResultEvaluation = (bool)V; return EvaluateInternal(input, CO, V); } Interpreter::CompilationResult Interpreter::execute(const std::string& input) { CompilationOptions CO = makeDefaultCompilationOpts(); CO.DeclarationExtraction = 0; CO.ValuePrinting = 0; CO.ResultEvaluation = 0; CO.DynamicScoping = 0; return EvaluateInternal(input, CO); } Interpreter::CompilationResult Interpreter::emitAllDecls(Transaction* T) { assert(!isInSyntaxOnlyMode() && "No CodeGenerator?"); m_IncrParser->emitTransaction(T); m_IncrParser->addTransaction(T); T->setState(Transaction::kCollecting); auto PRT = m_IncrParser->endTransaction(T); m_IncrParser->commitTransaction(PRT); if ((T = PRT.getPointer())) if (executeTransaction(*T)) return Interpreter::kSuccess; return Interpreter::kFailure; } static void makeUniqueName(llvm::raw_ostream &Strm, unsigned long long ID) { Strm << utils::Synthesize::UniquePrefix << ID; } static std::string makeUniqueWrapper(unsigned long long ID) { cling::ostrstream Strm; Strm << "void "; makeUniqueName(Strm, ID); Strm << "(void* vpClingValue) {\n "; return Strm.str().str(); } void Interpreter::createUniqueName(std::string &Out) { llvm::raw_string_ostream Strm(Out); makeUniqueName(Strm, m_UniqueCounter++); } bool Interpreter::isUniqueName(llvm::StringRef name) { return name.starts_with(utils::Synthesize::UniquePrefix); } clang::SourceLocation Interpreter::getSourceLocation(bool skipWrapper) const { const Transaction* T = getLatestTransaction(); if (!T) return SourceLocation(); const SourceManager &SM = getCI()->getSourceManager(); if (skipWrapper) { return T->getSourceStart(SM).getLocWithOffset( makeUniqueWrapper(m_UniqueCounter).size()); } return T->getSourceStart(SM); } const std::string& Interpreter::WrapInput(const std::string& Input, std::string& Output, size_t& WrapPoint) const { // If wrapPoint is > length of input, nothing is wrapped! if (WrapPoint < Input.size()) { const std::string Header = makeUniqueWrapper(m_UniqueCounter++); // Suppport Input and Output begin the same string std::string Wrapper = Input.substr(WrapPoint); Wrapper.insert(0, Header); Wrapper.append("\n;\n}"); Wrapper.insert(0, Input.substr(0, WrapPoint)); Wrapper.swap(Output); WrapPoint += Header.size(); return Output; } // in-case std::string::npos was passed WrapPoint = 0; return Input; } Interpreter::ExecutionResult Interpreter::RunFunction(const FunctionDecl* FD, Value* res /*=0*/) { if (getDiagnostics().hasErrorOccurred()) return kExeCompilationError; if (isInSyntaxOnlyMode()) { return kExeNoCodeGen; } if (!FD) return kExeUnkownFunction; std::string mangledNameIfNeeded; utils::Analyze::maybeMangleDeclName(FD, mangledNameIfNeeded); IncrementalExecutor::ExecutionResult ExeRes = m_Executor->executeWrapper(mangledNameIfNeeded, res); return ConvertExecutionResult(ExeRes); } const FunctionDecl* Interpreter::DeclareCFunction(StringRef name, StringRef code, bool withAccessControl, Transaction*& T) { /* 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*)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.

// 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 using namespace std; extern "C" int printf(const char*,...); struct S { template 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; (s->*p)(12); typedef void (S::*Vunc_p)(void); Vunc_p q = &S::virtua; (s->*q)(); // prints "T" return 0; } */ DiagnosticsEngine& Diag = getDiagnostics(); Diag.setSeverity(clang::diag::ext_nested_name_member_ref_lookup_ambiguous, clang::diag::Severity::Ignored, SourceLocation()); LangOptions& LO = const_cast(getCI()->getLangOpts()); bool savedAccessControl = LO.AccessControl; LO.AccessControl = withAccessControl; T = nullptr; cling::Interpreter::CompilationResult CR = declare(code.str(), &T); LO.AccessControl = savedAccessControl; Diag.setSeverity(clang::diag::ext_nested_name_member_ref_lookup_ambiguous, clang::diag::Severity::Warning, SourceLocation()); if (CR != cling::Interpreter::kSuccess) return nullptr; 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(*I->m_DGR.begin())) { DeclContext::decl_iterator DeclBegin = LSD->decls_begin(); if (DeclBegin == LSD->decls_end()) continue; if (const FunctionDecl* D = dyn_cast(*DeclBegin)) { const IdentifierInfo* II = D->getDeclName().getAsIdentifierInfo(); if (II && II->getName() == name) return D; } } } return nullptr; } void* Interpreter::compileFunction(llvm::StringRef name, llvm::StringRef code, bool ifUnique, bool withAccessControl) { // // Compile the wrapper code. // if (isInSyntaxOnlyMode()) return nullptr; if (ifUnique) { if (void* Addr = (void*)getAddressOfGlobal(name)) { return Addr; } } Transaction* T = nullptr; const FunctionDecl* FD = DeclareCFunction(name, code, withAccessControl, T); if (!FD || !T) return nullptr; // Get the wrapper function pointer from the ExecutionEngine (the JIT). return m_Executor->getPointerToGlobalFromJIT(name); } void* Interpreter::compileDtorCallFor(const clang::RecordDecl* RD) { void* &addr = m_DtorWrappers[RD]; if (addr) return addr; if (const CXXRecordDecl *CXX = dyn_cast(RD)) { // Don't generate a stub for a destructor that does nothing // This also fixes printing of lambdas and C structures as they // have no dtor test/ValuePrinter/Destruction.C if (CXX->hasIrrelevantDestructor()) return nullptr; } smallstream funcname; funcname << "__cling_Destruct_" << RD; largestream code; code << "extern \"C\" void " << funcname.str() << "(void* obj){((" << utils::TypeName::GetFullyQualifiedName( clang::QualType(RD->getTypeForDecl(), 0), RD->getASTContext()) << "*)obj)->~" << RD->getNameAsString() << "();}"; // ifUniq = false: we know it's unique, no need to check. addr = compileFunction(funcname.str(), code.str(), false /*ifUniq*/, false /*withAccessControl*/); return addr; } Interpreter::CompilationResult Interpreter::DeclareInternal(const std::string& input, const CompilationOptions& CO, Transaction** T /* = 0 */) const { assert(CO.DeclarationExtraction == 0 && CO.ValuePrinting == 0 && CO.ResultEvaluation == 0 && "Compilation Options not compatible with \"declare\" mode."); StateDebuggerRAII stateDebugger(this); IncrementalParser::ParseResultTransaction PRT = m_IncrParser->Compile(input, CO); if (PRT.getInt() == IncrementalParser::kFailed) return Interpreter::kFailure; if (T) *T = PRT.getPointer(); return Interpreter::kSuccess; } Interpreter::CompilationResult Interpreter::EvaluateInternal(const std::string& input, CompilationOptions CO, Value* V, /* = 0 */ Transaction** /* T = 0 */, size_t wrapPoint /* = 0*/) { StateDebuggerRAII stateDebugger(this); // Wrap the expression std::string WrapperBuffer; const std::string& Wrapper = WrapInput(input, WrapperBuffer, wrapPoint); // We have wrapped and need to disable warnings that are caused by // non-default C++ at the prompt: CO.IgnorePromptDiags = 1; IncrementalParser::ParseResultTransaction PRT = m_IncrParser->Compile(Wrapper, CO); Transaction* lastT = PRT.getPointer(); if (lastT && lastT->getState() != Transaction::kCommitted) { assert((lastT->getState() == Transaction::kCommitted || lastT->getState() == Transaction::kRolledBack || lastT->getState() == Transaction::kRolledBackWithErrors) && "Not committed?"); if (V) *V = Value(); return kFailure; } // Might not have a Transaction if (PRT.getInt() == IncrementalParser::kFailed) { if (V) *V = Value(); return kFailure; } if (!lastT) { // Empty transactions are good, too! if (V) *V = Value(); return kSuccess; } Value resultV; if (!V) V = &resultV; if (m_Opts.CompilerOpts.CUDADevice || !lastT->getWrapperFD()) // no wrapper to run return Interpreter::kSuccess; else { bool WantValuePrinting = lastT->getCompilationOpts().ValuePrinting != CompilationOptions::VPDisabled; ExecutionResult res = RunFunction(lastT->getWrapperFD(), V); if (res < kExeFirstError) { if (WantValuePrinting && V->isValid() // the !V->needsManagedAllocation() case is handled by // dumpIfNoStorage. && V->needsManagedAllocation()) V->dump(); return Interpreter::kSuccess; } else { return Interpreter::kFailure; } } return Interpreter::kSuccess; } std::string Interpreter::lookupFileOrLibrary(llvm::StringRef file) { std::string canonicalFile = DynamicLibraryManager::normalizePath(file); if (canonicalFile.empty()) canonicalFile = file.str(); //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." ConstSearchDirIterator FromDir = nullptr; const FileEntry* FromFile = nullptr; ConstSearchDirIterator* CurDir = nullptr; Preprocessor& PP = getCI()->getPreprocessor(); // PP::LookupFile uses it to issue 'nice' diagnostic SourceLocation fileNameLoc; auto FE = PP.LookupFile(fileNameLoc, canonicalFile, isAngled, FromDir, FromFile, CurDir, /*SearchPath*/nullptr, /*RelativePath*/ nullptr, /*suggestedModule*/nullptr, /*IsMapped*/ nullptr, /*IsFrameworkFound*/ nullptr, /*SkipCache*/ false, /*OpenFile*/ false, /*CacheFail*/ false); if (FE) return FE->getName().str(); return getDynamicLibraryManager()->lookupLibrary(canonicalFile); } Interpreter::CompilationResult Interpreter::loadLibrary(const std::string& filename, bool lookup) { DynamicLibraryManager* DLM = getDynamicLibraryManager(); std::string canonicalLib; if (lookup) canonicalLib = DLM->lookupLibrary(filename); const std::string &library = lookup ? canonicalLib : filename; if (!library.empty()) { switch (DLM->loadLibrary(library, /*permanent*/false, /*resolved*/true)) { case DynamicLibraryManager::kLoadLibSuccess: // Intentional fall through case DynamicLibraryManager::kLoadLibAlreadyLoaded: return kSuccess; case DynamicLibraryManager::kLoadLibNotFound: assert(0 && "Cannot find library with existing canonical name!"); return kFailure; default: // Not a source file (canonical name is non-empty) but can't load. return kFailure; } } return kMoreInputExpected; } Interpreter::CompilationResult Interpreter::loadHeader(const std::string& filename, Transaction** T /*= 0*/) { std::string code; code += "#include \"" + filename + "\""; CompilationOptions CO = makeDefaultCompilationOpts(); CO.DeclarationExtraction = 0; CO.ValuePrinting = 0; CO.ResultEvaluation = 0; CO.CheckPointerValidity = 1; CompilationResult res = DeclareInternal(code, CO, T); return res; } void Interpreter::unload(Transaction& T) { T.setUnloading(); // Clear any stored states that reference the llvm::Module. // Do it first in case const auto *Module = T.getCompiledModule(); if (Module && !m_StoredStates.empty()) { const auto Predicate = [&Module](const ClangInternalState* S) { return S->getModule() == Module; }; auto Itr = std::find_if(m_StoredStates.begin(), m_StoredStates.end(), Predicate); while (Itr != m_StoredStates.end()) { if (m_Opts.Verbose()) { cling::errs() << "Unloading Transaction forced state '" << (*Itr)->getName() << "' to be destroyed\n"; } m_StoredStates.erase(Itr); Itr = std::find_if(m_StoredStates.begin(), m_StoredStates.end(), Predicate); } } // Clear any cached transaction states. for (unsigned i = 0; i < kNumTransactions; ++i) { if (m_CachedTrns[i] == &T) { m_CachedTrns[i] = nullptr; break; } } if (InterpreterCallbacks* callbacks = getCallbacks()) callbacks->TransactionUnloaded(T); if (m_Executor) // we also might be in fsyntax-only mode. m_Executor->runAndRemoveStaticDestructors(&T); // We can revert the most recent transaction or a nested transaction of a // transaction that is not in the middle of the transaction collection // (i.e. at the end or not yet added to the collection at all). assert(!T.getTopmostParent()->getNext() && "Can not revert previous transactions"); assert((T.getState() != Transaction::kRolledBack || T.getState() != Transaction::kRolledBackWithErrors) && "Transaction already rolled back."); if (getOptions().ErrorOut) { // Tag the transaction as "won't need to be committed" (ROOT-10798). T.setState(Transaction::kRolledBack); return; } if (InterpreterCallbacks* callbacks = getCallbacks()) callbacks->TransactionRollback(T); TransactionUnloader U(this, &getCI()->getSema(), m_IncrParser->getCodeGenerator(), m_Executor.get()); if (U.RevertTransaction(&T)) T.setState(Transaction::kRolledBack); else T.setState(Transaction::kRolledBackWithErrors); m_IncrParser->deregisterTransaction(T); } void Interpreter::unload(unsigned numberOfTransactions) { const Transaction *First = m_IncrParser->getFirstTransaction(); if (!First) { cling::errs() << "cling: No transactions to unload!"; return; } for (unsigned i = 0; i < numberOfTransactions; ++i) { cling::Transaction* T = m_IncrParser->getLastTransaction(); if (T == First) { cling::errs() << "cling: Can't unload first transaction! Unloaded " << i << " of " << numberOfTransactions << "\n"; return; } unload(*T); } } Interpreter::CompilationResult Interpreter::loadFile(const std::string& filename, bool allowSharedLib /*=true*/, Transaction** T /*= 0*/) { if (allowSharedLib) { CompilationResult result = loadLibrary(filename, true); if (result!=kMoreInputExpected) return result; } return loadHeader(filename, T); } static void runAndRemoveStaticDestructorsImpl(IncrementalExecutor &executor, std::vector &transactions, unsigned int begin, unsigned int end) { for(auto i = begin; i != end; --i) { if (transactions[i-1] != nullptr) executor.runAndRemoveStaticDestructors(const_cast(transactions[i-1])); } } void Interpreter::runAndRemoveStaticDestructors(unsigned numberOfTransactions) { if (!m_Executor) return; auto transactions( m_IncrParser->getAllTransactions() ); unsigned int min = 0; if (transactions.size() > numberOfTransactions) { min = transactions.size() - numberOfTransactions; } runAndRemoveStaticDestructorsImpl(*m_Executor, transactions, transactions.size(), min); } void Interpreter::runAndRemoveStaticDestructors() { if (!m_Executor) return; auto transactions( m_IncrParser->getAllTransactions() ); runAndRemoveStaticDestructorsImpl(*m_Executor, transactions, transactions.size(), 0); } void Interpreter::addGenerator(std::unique_ptr G) { if (m_Executor) m_Executor->addGenerator(std::move(G)); } 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. // // We can't PushDeclContext, because we don't have scope. Sema::ContextRAII pushDC(TheSema, TheSema.getASTContext().getTranslationUnitDecl()); Value Result; getCallbacks()->SetIsRuntime(true); if (ValuePrinterReq) echo(expr, &Result); else evaluate(expr, Result); getCallbacks()->SetIsRuntime(false); return Result; } void Interpreter::setCallbacks(std::unique_ptr C) { // We need it to enable LookupObject callback. if (!m_Callbacks) { m_Callbacks.reset(new MultiplexInterpreterCallbacks(this)); if (m_Executor) m_Executor->setCallbacks(m_Callbacks.get()); } static_cast(m_Callbacks.get()) ->addCallback(std::move(C)); } const DynamicLibraryManager* Interpreter::getDynamicLibraryManager() const { assert(m_Executor.get() && "We must have an executor"); return &m_Executor->getDynamicLibraryManager(); } DynamicLibraryManager* Interpreter::getDynamicLibraryManager() { return const_cast(const_cast( this)->getDynamicLibraryManager()); } const Transaction* Interpreter::getFirstTransaction() const { return m_IncrParser->getFirstTransaction(); } const Transaction* Interpreter::getLastTransaction() const { return m_IncrParser->getLastTransaction(); } const Transaction* Interpreter::getLastWrapperTransaction() const { return m_IncrParser->getLastWrapperTransaction(); } const Transaction* Interpreter::getCurrentTransaction() const { return m_IncrParser->getCurrentTransaction(); } const Transaction* Interpreter::getLatestTransaction() const { if (const Transaction* T = m_IncrParser->getCurrentTransaction()) return T; return m_IncrParser->getLastTransaction(); } void Interpreter::enableDynamicLookup(bool value /*=true*/) { if (!m_DynamicLookupDeclared && value) { // No dynlookup for the dynlookup header! m_DynamicLookupEnabled = false; declare("#include "); } m_DynamicLookupDeclared = true; // Enable it *after* parsing the headers. m_DynamicLookupEnabled = value; } Interpreter::ExecutionResult Interpreter::executeTransaction(Transaction& T) { assert(!isInSyntaxOnlyMode() && "Running on what?"); assert(T.getState() == Transaction::kCommitted && "Must be committed"); if (!T.getModule()) return Interpreter::kExeNoModule; IncrementalExecutor::ExecutionResult ExeRes = IncrementalExecutor::kExeSuccess; // CUDA device code is not direct executable // the code is executed by a CUDA library function in the host code if (!m_Opts.CompilerOpts.CUDADevice) // Forward to IncrementalExecutor; should not be called by // anyone except for IncrementalParser. ExeRes = m_Executor->runStaticInitializersOnce(T); return ConvertExecutionResult(ExeRes); } 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); #if defined(_WIN32) // For some unknown reason, Clang 5.0 adds a special symbol ('\01') in front // of the mangled names on Windows, making them impossible to find // TODO: remove this piece of code and try again when updating Clang std::string mncp = mangledName; // use corrected symbol for "external" lookup if (mncp.size() > 2 && mncp[1] == '?' && mncp.compare(1, 14, std::string("?__cling_Un1Qu"))) { mncp.erase(0, 1); } void *addr = getAddressOfGlobal(mncp, fromJIT); if (addr) return addr; // if failed, proceed with original symbol for lookups in JIT tables #endif return getAddressOfGlobal(mangledName, fromJIT); } void* Interpreter::getAddressOfGlobal(llvm::StringRef SymName, bool* fromJIT /*=0*/) const { // Return a symbol's address, and whether it was jitted. if (isInSyntaxOnlyMode()) return nullptr; return m_Executor->getAddressOfGlobal(SymName, fromJIT); } void Interpreter::AddAtExitFunc(void (*Func) (void*), void* Arg) { m_Executor->AddAtExitFunc(Func, Arg, getLatestTransaction()); } void Interpreter::runAtExitFuncs() { assert(!isInSyntaxOnlyMode() && "Must have JIT"); m_Executor->runAtExitFuncs(); } void Interpreter::GenerateAutoLoadingMap(llvm::StringRef inFile, llvm::StringRef outFile, bool enableMacros, bool enableLogs) { const char *const dummy="cling_fwd_declarator"; // Create an interpreter without any runtime, producing the fwd decls. // FIXME: CIFactory appends extra 3 folders to the llvmdir. std::string llvmdir = getCI()->getHeaderSearchOpts().ResourceDir + "/../../../"; cling::Interpreter fwdGen(1, &dummy, llvmdir.c_str(), /*moduleExtensions*/ {}, /*ExtraLibHandle*/ nullptr, /*noRuntime=*/true); // Copy the same header search options to the new instance. Preprocessor& fwdGenPP = fwdGen.getCI()->getPreprocessor(); HeaderSearchOptions headerOpts = getCI()->getHeaderSearchOpts(); clang::ApplyHeaderSearchOptions(fwdGenPP.getHeaderSearchInfo(), headerOpts, fwdGenPP.getLangOpts(), fwdGenPP.getTargetInfo().getTriple()); CompilationOptions CO = makeDefaultCompilationOpts(); CO.DeclarationExtraction = 0; CO.ValuePrinting = 0; CO.ResultEvaluation = 0; CO.DynamicScoping = 0; std::string includeFile = std::string("#include \"") + inFile.str() + "\""; IncrementalParser::ParseResultTransaction PRT = fwdGen.m_IncrParser->Compile(includeFile, CO); cling::Transaction* T = PRT.getPointer(); // If this was already #included we will get a T == 0. if (PRT.getInt() == IncrementalParser::kFailed || !T) return; std::error_code EC; llvm::raw_fd_ostream out(outFile.data(), EC, llvm::sys::fs::OpenFlags::OF_None); llvm::raw_fd_ostream log((outFile + ".skipped").str().c_str(), EC, llvm::sys::fs::OpenFlags::OF_None); log << "Generated for :" << inFile << "\n"; forwardDeclare(*T, fwdGenPP, fwdGen.getCI()->getSema().getASTContext(), out, enableMacros, &log); } void Interpreter::forwardDeclare(Transaction& T, Preprocessor& P, clang::ASTContext& Ctx, llvm::raw_ostream& out, bool enableMacros /*=false*/, llvm::raw_ostream* logs /*=0*/, IgnoreFilesFunc_t ignoreFiles /*= return always false*/) const { llvm::raw_null_ostream null; if (!logs) logs = &null; ForwardDeclPrinter visitor(out, *logs, P, Ctx, T, 0, false, ignoreFiles); visitor.printStats(); // Avoid assertion in the ~IncrementalParser. T.setState(Transaction::kCommitted); } namespace runtime { namespace internal { CLING_LIB_EXPORT Value EvaluateDynamicExpression(Interpreter* interp, DynamicExprInfo* DEI, clang::DeclContext* DC) { Value ret = [&] { LockCompilationDuringUserCodeExecutionRAII LCDUCER(*interp); return interp->Evaluate(DEI->getExpr(), DC, DEI->isValuePrinterRequested()); }(); if (!ret.isValid()) { std::string msg = "Error evaluating expression "; CompilationException::throwingHandler(nullptr, (msg + DEI->getExpr()).c_str(), false /*backtrace*/); } return ret; } } // namespace internal } // namespace runtime } //end namespace cling