//------------------------------------------------------------------------------ // CLING - the C++ LLVM-based InterpreterG :) // version: $Id$ // author: Lukasz Janyst //------------------------------------------------------------------------------ #include "cling/Interpreter/Interpreter.h" #include "cling/Interpreter/LookupHelper.h" #include "cling/Utils/AST.h" #include "CompilationOptions.h" #include "DynamicLookup.h" #include "ExecutionContext.h" #include "IncrementalParser.h" #include "cling/Interpreter/CIFactory.h" #include "cling/Interpreter/InterpreterCallbacks.h" #include "cling/Interpreter/Value.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Mangle.h" #include "clang/AST/DeclarationName.h" #include "clang/Basic/TargetInfo.h" #include "clang/CodeGen/ModuleBuilder.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/Utils.h" #include "clang/Lex/Preprocessor.h" #include "clang/Parse/Parser.h" #include "clang/Sema/Lookup.h" #include "clang/Sema/Overload.h" #include "clang/Sema/Scope.h" #include "clang/Sema/Sema.h" #include "clang/Sema/SemaInternal.h" #include "clang/Sema/TemplateDeduction.h" #include "llvm/Linker.h" #include "llvm/LLVMContext.h" #include "llvm/Support/DynamicLibrary.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" #include #include #include using namespace clang; namespace { static bool tryLinker(const std::string& filename, const cling::InvocationOptions& Opts, llvm::Module* module) { assert(module && "Module must exist for linking!"); llvm::Linker L("cling", module, llvm::Linker::QuietWarnings | llvm::Linker::QuietErrors); for (std::vector::const_iterator I = Opts.LibSearchPath.begin(), E = Opts.LibSearchPath.end(); I != E; ++I) { L.addPath(*I); } L.addSystemPaths(); bool Native = true; if (L.LinkInLibrary(filename, Native)) { // that didn't work, try bitcode: llvm::sys::Path FilePath(filename); std::string Magic; if (!FilePath.getMagicNumber(Magic, 64)) { // filename doesn't exist... L.releaseModule(); return false; } if (llvm::sys::IdentifyFileType(Magic.c_str(), 64) == llvm::sys::Bitcode_FileType) { // We are promised a bitcode file, complain if it fails L.setFlags(0); if (L.LinkInFile(llvm::sys::Path(filename), Native)) { L.releaseModule(); return false; } } else { // Nothing the linker can handle L.releaseModule(); return false; } } else if (Native) { // native shared library, load it! llvm::sys::Path SoFile = L.FindLib(filename); assert(!SoFile.isEmpty() && "The shared lib exists but can't find it!"); std::string errMsg; bool hasError = llvm::sys::DynamicLibrary ::LoadLibraryPermanently(SoFile.str().c_str(), &errMsg); if (hasError) { llvm::errs() << "Could not load shared library!\n" << "\n" << errMsg.c_str(); L.releaseModule(); return false; } } L.releaseModule(); return true; } static bool canWrapForCall(const std::string& input_line) { // Whether input_line can be wrapped into a function. // "1" can, "#include " can't. if (input_line.length() > 1 && input_line[0] == '#') return false; if (input_line.compare(0, strlen("extern "), "extern ") == 0) return false; if (input_line.compare(0, strlen("using "), "using ") == 0) return false; return true; } } // unnamed namespace namespace cling { // "Declared" to the JIT in RuntimeUniverse.h namespace runtime { namespace internal { int local_cxa_atexit(void (*func) (void*), void* arg, void* dso, Interpreter* interp) { return interp->CXAAtExit(func, arg, dso); } struct __trigger__cxa_atexit { ~__trigger__cxa_atexit(); }; __trigger__cxa_atexit::~__trigger__cxa_atexit() {} } } // This function isn't referenced outside its translation unit, but it // can't use the "static" keyword because its address is used for // GetMainExecutable (since some platforms don't support taking the // address of main, and some platforms can't implement GetMainExecutable // without being given the address of a function in the main executable). llvm::sys::Path GetExecutablePath(const char *Argv0) { // This just needs to be some symbol in the binary; C++ doesn't // allow taking the address of ::main however. void *MainAddr = (void*) (intptr_t) GetExecutablePath; return llvm::sys::Path::GetMainExecutable(Argv0, MainAddr); } 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_DynamicLookupEnabled(false) { m_LLVMContext.reset(new llvm::LLVMContext); std::vector LeftoverArgsIdx; m_Opts = InvocationOptions::CreateFromArgs(argc, argv, LeftoverArgsIdx); std::vector LeftoverArgs; for (size_t I = 0, N = LeftoverArgsIdx.size(); I < N; ++I) { LeftoverArgs.push_back(argv[LeftoverArgsIdx[I]]); } m_IncrParser.reset(new IncrementalParser(this, LeftoverArgs.size(), &LeftoverArgs[0], llvmdir)); m_LookupHelper.reset(new LookupHelper(m_IncrParser->getParser())); m_ExecutionContext.reset(new ExecutionContext()); // Add path to interpreter's include files // Try to find the headers in the src folder first #ifdef CLING_SRCDIR_INCL llvm::sys::Path SrcP(CLING_SRCDIR_INCL); if (SrcP.canRead()) AddIncludePath(SrcP.str()); #endif llvm::sys::Path P = GetExecutablePath(argv[0]); if (!P.isEmpty()) { P.eraseComponent(); // Remove /cling from foo/bin/clang P.eraseComponent(); // Remove /bin from foo/bin // Get foo/include P.appendComponent("include"); if (P.canRead()) AddIncludePath(P.str()); else { #ifdef CLING_INSTDIR_INCL llvm::sys::Path InstP(CLING_INSTDIR_INCL); if (InstP.canRead()) AddIncludePath(InstP.str()); #endif } } m_ExecutionContext->addSymbol("local_cxa_atexit", (void*)(intptr_t)&cling::runtime::internal::local_cxa_atexit); 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\""); // Set up the gCling variable std::stringstream initializer; initializer << "gCling=(cling::Interpreter*)" << (uintptr_t)this << ";"; evaluate(initializer.str()); } else { declare("#include \"cling/Interpreter/CValuePrinter.h\""); } handleFrontendOptions(); } Interpreter::~Interpreter() { for (size_t I = 0, N = m_AtExitFuncs.size(); I < N; ++I) { const CXAAtExitElement& AEE = m_AtExitFuncs[N - I - 1]; (*AEE.m_Func)(AEE.m_Arg); } } const char* Interpreter::getVersion() const { return "$Id$"; } void Interpreter::handleFrontendOptions() { if (m_Opts.ShowVersion) { llvm::outs() << 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 IsUserSupplied = false; const bool IsFramework = false; const bool IsSysRootRelative = true; headerOpts.AddPath(incpath, frontend::Angled, IsUserSupplied, IsFramework, IsSysRootRelative); Preprocessor& PP = CI->getPreprocessor(); ApplyHeaderSearchOptions(PP.getHeaderSearchInfo(), headerOpts, PP.getLangOpts(), PP.getTargetInfo().getTriple()); } // Copied from clang/lib/Frontend/CompilerInvocation.cpp void Interpreter::DumpIncludePath() { const HeaderSearchOptions Opts(getCI()->getHeaderSearchOpts()); std::vector Res; if (Opts.Sysroot != "/") { Res.push_back("-isysroot"); Res.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 || !E.IsUserSupplied)) llvm::report_fatal_error("Invalid option set!"); if (E.IsUserSupplied) { switch (E.Group) { case frontend::After: Res.push_back("-idirafter"); break; case frontend::Quoted: Res.push_back("-iquote"); break; case frontend::System: Res.push_back("-isystem"); break; case frontend::IndexHeaderMap: Res.push_back("-index-header-map"); Res.push_back(E.IsFramework? "-F" : "-I"); break; case frontend::CSystem: Res.push_back("-c-isystem"); break; case frontend::CXXSystem: Res.push_back("-cxx-isystem"); break; case frontend::ObjCSystem: Res.push_back("-objc-isystem"); break; case frontend::ObjCXXSystem: Res.push_back("-objcxx-isystem"); break; case frontend::Angled: Res.push_back(E.IsFramework ? "-F" : "-I"); break; } } else { if (E.Group != frontend::Angled && E.Group != frontend::System) llvm::report_fatal_error("Invalid option set!"); Res.push_back(E.Group == frontend::Angled ? "-iwithprefixbefore" : "-iwithprefix"); } Res.push_back(E.Path); } if (!Opts.ResourceDir.empty()) { Res.push_back("-resource-dir"); Res.push_back(Opts.ResourceDir); } if (!Opts.ModuleCachePath.empty()) { Res.push_back("-fmodule-cache-path"); Res.push_back(Opts.ModuleCachePath); } if (!Opts.UseStandardSystemIncludes) Res.push_back("-nostdinc"); if (!Opts.UseStandardCXXIncludes) Res.push_back("-nostdinc++"); if (Opts.UseLibcxx) Res.push_back("-stdlib=libc++"); if (Opts.Verbose) Res.push_back("-v"); // print'em all for (unsigned i = 0; i < Res.size(); ++i) { llvm::outs() << Res[i] <<"\n"; } } CompilerInstance* Interpreter::getCI() const { return m_IncrParser->getCI(); } 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, Value* V /* = 0 */, const Decl** D /* = 0 */) { CompilationOptions CO; CO.DeclarationExtraction = 1; CO.ValuePrinting = CompilationOptions::VPAuto; CO.DynamicScoping = isDynamicLookupEnabled(); CO.Debug = isPrintingAST(); if (!canWrapForCall(input)) return declare(input, D); if (EvaluateInternal(input, CO, V) == Interpreter::kFailure) { if (D) *D = 0; return Interpreter::kFailure; } if (D) *D = m_IncrParser->getLastTransaction()->getFirstDecl().getSingleDecl(); return Interpreter::kSuccess; } Interpreter::CompilationResult Interpreter::parse(const std::string& input) { CompilationOptions CO; CO.CodeGeneration = 0; CO.DeclarationExtraction = 0; CO.ValuePrinting = 0; CO.DynamicScoping = isDynamicLookupEnabled(); CO.Debug = isPrintingAST(); return DeclareInternal(input, CO); } Interpreter::CompilationResult Interpreter::declare(const std::string& input, const Decl** D /* = 0 */) { CompilationOptions CO; CO.DeclarationExtraction = 0; CO.ValuePrinting = 0; CO.DynamicScoping = isDynamicLookupEnabled(); CO.Debug = isPrintingAST(); return DeclareInternal(input, CO, D); } Interpreter::CompilationResult Interpreter::evaluate(const std::string& input, Value* V /* = 0 */) { // 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; return EvaluateInternal(input, CO, V); } Interpreter::CompilationResult Interpreter::echo(const std::string& input, Value* V /* = 0 */) { CompilationOptions CO; CO.DeclarationExtraction = 0; CO.ValuePrinting = CompilationOptions::VPEnabled; return EvaluateInternal(input, CO, V); } void Interpreter::WrapInput(std::string& input, std::string& fname) { fname = createUniqueWrapper(); input.insert(0, "void " + fname + "() {\n "); input.append("\n;\n}"); } llvm::StringRef Interpreter::createUniqueWrapper() { const size_t size = sizeof("__cling_Un1Qu3") + sizeof(m_UniqueCounter); llvm::SmallString out("__cling_Un1Qu3"); llvm::raw_svector_ostream(out) << m_UniqueCounter++; return (getCI()->getASTContext().Idents.getOwn(out)).getName(); } bool Interpreter::RunFunction(llvm::StringRef fname, llvm::GenericValue* res) { if (getCI()->getDiagnostics().hasErrorOccurred()) return false; if (!m_IncrParser->hasCodeGenerator()) { return true; } std::string mangledNameIfNeeded; Sema& S = getCI()->getSema(); FunctionDecl* FD = cast_or_null(utils::Lookup::Named(&S, fname.str().c_str())); if (FD) { getMangledName(FD, mangledNameIfNeeded); m_ExecutionContext->executeFunction(mangledNameIfNeeded.c_str(), res); return true; } return false; } void Interpreter::createUniqueName(std::string& out) { out = "Un1Qu3"; llvm::raw_string_ostream(out) << m_UniqueCounter++; } Interpreter::CompilationResult Interpreter::DeclareInternal(const std::string& input, const CompilationOptions& CO, const clang::Decl** D /* = 0 */) { if (m_IncrParser->Compile(input, CO) != IncrementalParser::kFailed) { if (D) *D = m_IncrParser->getLastTransaction()->getFirstDecl().getSingleDecl(); return Interpreter::kSuccess; } return Interpreter::kFailure; } Interpreter::CompilationResult Interpreter::EvaluateInternal(const std::string& input, const CompilationOptions& CO, Value* V /* = 0 */) { Sema& TheSema = getCI()->getSema(); 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()); // Wrap the expression std::string WrapperName; std::string Wrapper = input; WrapInput(Wrapper, WrapperName); QualType RetTy = getCI()->getASTContext().VoidTy; if (V) { const Transaction* CurT = m_IncrParser->Parse(Wrapper); assert(CurT->size() && "No decls created by Parse!"); // Find the wrapper function declaration. // // Note: The parse may have created a whole set of decls if a template // instantiation happened. Our wrapper function should be the // last decl in the set. // FunctionDecl* TopLevelFD = dyn_cast(CurT->getLastDecl().getSingleDecl()); assert(TopLevelFD && "No Decls Parsed?"); DeclContext* CurContext = TheSema.CurContext; TheSema.CurContext = TopLevelFD; ASTContext& Context(getCI()->getASTContext()); // We have to be able to mark the expression for printout. There are three // scenarios: // 0: Expression printing disabled - don't do anything just disable the // consumer // is our marker, even if there wasn't missing ';'. // 1: Expression printing enabled - make sure we don't have NullStmt, // which is used as a marker to suppress the print out. // 2: Expression printing auto - do nothing - rely on the omitted ';' to // not produce the suppress marker. if (CompoundStmt* CS = dyn_cast(TopLevelFD->getBody())) { // Collect all Stmts, contained in the CompoundStmt llvm::SmallVector Stmts; for (CompoundStmt::body_iterator iStmt = CS->body_begin(), eStmt = CS->body_end(); iStmt != eStmt; ++iStmt) Stmts.push_back(*iStmt); size_t indexOfLastExpr = Stmts.size(); while(indexOfLastExpr--) { // find the trailing expression statement (skip e.g. null statements) if (Expr* E = dyn_cast_or_null(Stmts[indexOfLastExpr])) { RetTy = E->getType(); if (!RetTy->isVoidType()) { // Change the void function's return type FunctionProtoType::ExtProtoInfo EPI; QualType FuncTy = Context.getFunctionType(RetTy,/* ArgArray = */0, /* NumArgs = */0, EPI); TopLevelFD->setType(FuncTy); // Strip the parenthesis if any if (ParenExpr* PE = dyn_cast(E)) E = PE->getSubExpr(); // Change it with return stmt Stmts[indexOfLastExpr] = TheSema.ActOnReturnStmt(SourceLocation(), E).take(); } // even if void: we found an expression break; } } // case 1: if (CO.ValuePrinting == CompilationOptions::VPEnabled) if (indexOfLastExpr < Stmts.size() - 1 && isa(Stmts[indexOfLastExpr + 1])) Stmts.erase(Stmts.begin() + indexOfLastExpr); // Stmts.insert(Stmts.begin() + indexOfLastExpr + 1, // TheSema.ActOnNullStmt(SourceLocation()).take()); // Update the CompoundStmt body CS->setStmts(TheSema.getASTContext(), Stmts.data(), Stmts.size()); } TheSema.CurContext = CurContext; m_IncrParser->commitCurrentTransaction(); } else m_IncrParser->Compile(Wrapper, CO); // get the result if (!V) { if (RunFunction(WrapperName)) { return Interpreter::kSuccess; } } else if (RunFunction(WrapperName, &V->value)) { V->type = RetTy; return Interpreter::kSuccess; } else { *V = Value(); } return Interpreter::kFailure; } bool Interpreter::loadFile(const std::string& filename, bool allowSharedLib /*=true*/) { if (allowSharedLib) { llvm::Module* module = m_IncrParser->getCodeGenerator()->GetModule(); if (module) { if (tryLinker(filename, getOptions(), module)) return true; if (filename.compare(0, 3, "lib") == 0) { // starts with "lib", try without (the llvm::Linker forces // a "lib" in front, which makes it liblib... if (tryLinker(filename.substr(3, std::string::npos), getOptions(), module)) return true; } } } std::string code; code += "#include \"" + filename + "\""; return declare(code) == Interpreter::kSuccess; } class ParserExt : public Parser { public: static TypeResult ParseTypeNameFwd(Parser* P, SourceRange *Range = 0, Declarator::TheContext Context = Declarator::TypeNameContext, AccessSpecifier AS = AS_none, Decl **OwnedType = 0) { return ((ParserExt*)P)->ParseTypeName(Range, Context, AS, OwnedType); } static const Token& NextTokenFwd(Parser* P) { return ((ParserExt*)P)->NextToken(); } static bool SkipUntilFwd(Parser* P, tok::TokenKind T, bool StopAtSemi = true, bool DontConsume = false, bool StopAtCodeCompletion = false) { return ((ParserExt*)P)->SkipUntil(T, StopAtSemi, DontConsume, StopAtCodeCompletion); } static bool TryAnnotateCXXScopeTokenFwd(Parser* P, bool EnteringContext = false) { return ((ParserExt*)P)->TryAnnotateCXXScopeToken(EnteringContext); } static bool TryAnnotateTypeOrScopeTokenFwd(Parser* P, bool EnteringContext = false, bool NeedType = false) { return ((ParserExt*)P)->TryAnnotateTypeOrScopeToken(EnteringContext); } static ParsedType getTypeAnnotationFwd(Token &Tok) { return ParserExt::getTypeAnnotation(Tok); } static SourceLocation ConsumeTokenFwd(Parser* P) { return ((ParserExt*)P)->ConsumeToken(); } static bool ParseUnqualifiedIdFwd(Parser* P, CXXScopeSpec &SS, bool EnteringContext, bool AllowDestructorName, bool AllowConstructorName, ParsedType ObjectType, SourceLocation& TemplateKWLoc, UnqualifiedId &Result) { return ((ParserExt*)P)->ParseUnqualifiedId(SS, EnteringContext, AllowDestructorName, AllowConstructorName, ObjectType, TemplateKWLoc, Result); } static ExprResult ParseAssignmentExpressionFwd(Parser* P, TypeCastState isTypeCast = NotTypeCast) { return ((ParserExt*)P)->ParseAssignmentExpression(isTypeCast); } static void EnterScopeFwd(Parser* P, unsigned ScopeFlags) { ((ParserExt*)P)->EnterScope(ScopeFlags); } static void ExitScopeFwd(Parser* P) { ((ParserExt*)P)->ExitScope(); } }; void Interpreter::installLazyFunctionCreator( void* (*fp)(const std::string&)) { m_ExecutionContext->installLazyFunctionCreator(fp); } Value Interpreter::Evaluate(const char* expr, DeclContext* DC, bool ValuePrinterReq) { Sema& TheSema = getCI()->getSema(); if (!DC) DC = TheSema.getASTContext().getTranslationUnitDecl(); // Set up the declaration context DeclContext* CurContext; CurContext = TheSema.CurContext; TheSema.CurContext = DC; Value Result; if (TheSema.ExternalSource) { DynamicIDHandler* DIDH = static_cast(TheSema.ExternalSource); DIDH->Callbacks->setEnabled(); (ValuePrinterReq) ? echo(expr, &Result) : evaluate(expr, &Result); DIDH->Callbacks->setEnabled(false); } else (ValuePrinterReq) ? echo(expr, &Result) : evaluate(expr, &Result); TheSema.CurContext = CurContext; return Result; } void Interpreter::setCallbacks(InterpreterCallbacks* C) { Sema& S = getCI()->getSema(); assert(S.ExternalSource && "No ExternalSource set!"); static_cast(S.ExternalSource)->Callbacks = C; } void Interpreter::enableDynamicLookup(bool value /*=true*/) { m_DynamicLookupEnabled = value; Sema& S = getCI()->getSema(); if (isDynamicLookupEnabled()) { assert(!S.ExternalSource && "Already set Sema ExternalSource"); // Load the dynamic lookup specifics. declare("#include \"cling/Interpreter/DynamicLookupRuntimeUniverse.h\""); S.ExternalSource = new DynamicIDHandler(&S); } else { delete S.ExternalSource; S.ExternalSource = 0; } } void Interpreter::runStaticInitializersOnce() const { // Forward to ExecutionContext; should not be called by // anyone except for IncrementalParser. llvm::Module* module = m_IncrParser->getCodeGenerator()->GetModule(); m_ExecutionContext->runStaticInitializersOnce(module); } int Interpreter::CXAAtExit(void (*func) (void*), void* arg, void* dso) { // Register a CXAAtExit function Decl* LastTLD = m_IncrParser->getLastTransaction()->getLastDecl().getSingleDecl(); m_AtExitFuncs.push_back(CXAAtExitElement(func, arg, dso, LastTLD)); return 0; // happiness } void Interpreter::getMangledName(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); m_MangleCtx->mangleName(D, RawStr); RawStr.flush(); } else { mangledName = D->getNameAsString(); } } 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; getMangledName(D, mangledName); llvm::Module* module = m_IncrParser->getCodeGenerator()->GetModule(); return m_ExecutionContext->getAddressOfGlobal(module, mangledName.c_str(), fromJIT); } } // namespace cling