diff options
Diffstat (limited to 'source/Expression/ClangExpressionParser.cpp')
-rw-r--r-- | source/Expression/ClangExpressionParser.cpp | 621 |
1 files changed, 0 insertions, 621 deletions
diff --git a/source/Expression/ClangExpressionParser.cpp b/source/Expression/ClangExpressionParser.cpp deleted file mode 100644 index 2b344b0..0000000 --- a/source/Expression/ClangExpressionParser.cpp +++ /dev/null @@ -1,621 +0,0 @@ -//===-- ClangExpressionParser.cpp -------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "lldb/Expression/ClangExpressionParser.h" - -#include "lldb/Core/ArchSpec.h" -#include "lldb/Core/DataBufferHeap.h" -#include "lldb/Core/Debugger.h" -#include "lldb/Core/Disassembler.h" -#include "lldb/Core/Log.h" -#include "lldb/Core/Module.h" -#include "lldb/Core/Stream.h" -#include "lldb/Core/StreamFile.h" -#include "lldb/Core/StreamString.h" -#include "lldb/Expression/ClangASTSource.h" -#include "lldb/Expression/ClangExpression.h" -#include "lldb/Expression/ClangExpressionDeclMap.h" -#include "lldb/Expression/ClangModulesDeclVendor.h" -#include "lldb/Expression/ClangPersistentVariables.h" -#include "lldb/Expression/IRExecutionUnit.h" -#include "lldb/Expression/IRDynamicChecks.h" -#include "lldb/Expression/IRInterpreter.h" -#include "lldb/Host/File.h" -#include "lldb/Host/HostInfo.h" -#include "lldb/Symbol/SymbolVendor.h" -#include "lldb/Target/ExecutionContext.h" -#include "lldb/Target/ObjCLanguageRuntime.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/Target.h" - -#include "clang/AST/ASTContext.h" -#include "clang/AST/ExternalASTSource.h" -#include "clang/Basic/FileManager.h" -#include "clang/Basic/TargetInfo.h" -#include "clang/Basic/Version.h" -#include "clang/CodeGen/CodeGenAction.h" -#include "clang/CodeGen/ModuleBuilder.h" -#include "clang/Frontend/CompilerInstance.h" -#include "clang/Frontend/CompilerInvocation.h" -#include "clang/Frontend/FrontendActions.h" -#include "clang/Frontend/FrontendDiagnostic.h" -#include "clang/Frontend/FrontendPluginRegistry.h" -#include "clang/Frontend/TextDiagnosticBuffer.h" -#include "clang/Frontend/TextDiagnosticPrinter.h" -#include "clang/Lex/Preprocessor.h" -#include "clang/Parse/ParseAST.h" -#include "clang/Rewrite/Frontend/FrontendActions.h" -#include "clang/Sema/SemaConsumer.h" -#include "clang/StaticAnalyzer/Frontend/FrontendActions.h" - -#include "llvm/ADT/StringRef.h" -#include "llvm/ExecutionEngine/ExecutionEngine.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/FileSystem.h" -#include "llvm/Support/TargetSelect.h" - -#include "llvm/ExecutionEngine/MCJIT.h" -#include "llvm/IR/LLVMContext.h" -#include "llvm/IR/Module.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/DynamicLibrary.h" -#include "llvm/Support/Host.h" -#include "llvm/Support/Signals.h" - -using namespace clang; -using namespace llvm; -using namespace lldb_private; - -//===----------------------------------------------------------------------===// -// Utility Methods for Clang -//===----------------------------------------------------------------------===// - -std::string GetBuiltinIncludePath(const char *Argv0) { - SmallString<128> P(llvm::sys::fs::getMainExecutable( - Argv0, (void *)(intptr_t) GetBuiltinIncludePath)); - - if (!P.empty()) { - llvm::sys::path::remove_filename(P); // Remove /clang from foo/bin/clang - llvm::sys::path::remove_filename(P); // Remove /bin from foo/bin - - // Get foo/lib/clang/<version>/include - llvm::sys::path::append(P, "lib", "clang", CLANG_VERSION_STRING, - "include"); - } - - return P.str(); -} - -class ClangExpressionParser::LLDBPreprocessorCallbacks : public PPCallbacks -{ - ClangModulesDeclVendor &m_decl_vendor; - ClangPersistentVariables &m_persistent_vars; - StreamString m_error_stream; - bool m_has_errors = false; -public: - LLDBPreprocessorCallbacks(ClangModulesDeclVendor &decl_vendor, - ClangPersistentVariables &persistent_vars) : - m_decl_vendor(decl_vendor), - m_persistent_vars(persistent_vars) - { - } - - virtual void moduleImport(SourceLocation import_location, - ModuleIdPath path, - const clang::Module * /*null*/) - { - std::vector<ConstString> string_path; - - for (const std::pair<IdentifierInfo *, SourceLocation> &component : path) - { - string_path.push_back(ConstString(component.first->getName())); - } - - StreamString error_stream; - - ClangModulesDeclVendor::ModuleVector exported_modules; - - if (!m_decl_vendor.AddModule(string_path, &exported_modules, m_error_stream)) - { - m_has_errors = true; - } - - for (ClangModulesDeclVendor::ModuleID module : exported_modules) - { - m_persistent_vars.AddHandLoadedClangModule(module); - } - } - - bool hasErrors() - { - return m_has_errors; - } - - const std::string &getErrorString() - { - return m_error_stream.GetString(); - } -}; - -//===----------------------------------------------------------------------===// -// Implementation of ClangExpressionParser -//===----------------------------------------------------------------------===// - -ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope, - ClangExpression &expr, - bool generate_debug_info) : - m_expr (expr), - m_compiler (), - m_code_generator (), - m_pp_callbacks(nullptr) -{ - // 1. Create a new compiler instance. - m_compiler.reset(new CompilerInstance()); - - // 2. Install the target. - - lldb::TargetSP target_sp; - if (exe_scope) - target_sp = exe_scope->CalculateTarget(); - - // TODO: figure out what to really do when we don't have a valid target. - // Sometimes this will be ok to just use the host target triple (when we - // evaluate say "2+3", but other expressions like breakpoint conditions - // and other things that _are_ target specific really shouldn't just be - // using the host triple. This needs to be fixed in a better way. - if (target_sp && target_sp->GetArchitecture().IsValid()) - { - std::string triple = target_sp->GetArchitecture().GetTriple().str(); - m_compiler->getTargetOpts().Triple = triple; - } - else - { - m_compiler->getTargetOpts().Triple = llvm::sys::getDefaultTargetTriple(); - } - - if (target_sp->GetArchitecture().GetMachine() == llvm::Triple::x86 || - target_sp->GetArchitecture().GetMachine() == llvm::Triple::x86_64) - { - m_compiler->getTargetOpts().Features.push_back("+sse"); - m_compiler->getTargetOpts().Features.push_back("+sse2"); - } - - // Any arm32 iOS environment, but not on arm64 - if (m_compiler->getTargetOpts().Triple.find("arm64") == std::string::npos && - m_compiler->getTargetOpts().Triple.find("arm") != std::string::npos && - m_compiler->getTargetOpts().Triple.find("ios") != std::string::npos) - { - m_compiler->getTargetOpts().ABI = "apcs-gnu"; - } - - m_compiler->createDiagnostics(); - - // Create the target instance. - m_compiler->setTarget(TargetInfo::CreateTargetInfo( - m_compiler->getDiagnostics(), m_compiler->getInvocation().TargetOpts)); - - assert (m_compiler->hasTarget()); - - // 3. Set options. - - lldb::LanguageType language = expr.Language(); - - switch (language) - { - case lldb::eLanguageTypeC: - break; - case lldb::eLanguageTypeObjC: - m_compiler->getLangOpts().ObjC1 = true; - m_compiler->getLangOpts().ObjC2 = true; - break; - case lldb::eLanguageTypeC_plus_plus: - m_compiler->getLangOpts().CPlusPlus = true; - m_compiler->getLangOpts().CPlusPlus11 = true; - m_compiler->getHeaderSearchOpts().UseLibcxx = true; - break; - case lldb::eLanguageTypeObjC_plus_plus: - default: - m_compiler->getLangOpts().ObjC1 = true; - m_compiler->getLangOpts().ObjC2 = true; - m_compiler->getLangOpts().CPlusPlus = true; - m_compiler->getLangOpts().CPlusPlus11 = true; - m_compiler->getHeaderSearchOpts().UseLibcxx = true; - break; - } - - m_compiler->getLangOpts().Bool = true; - m_compiler->getLangOpts().WChar = true; - m_compiler->getLangOpts().Blocks = true; - m_compiler->getLangOpts().DebuggerSupport = true; // Features specifically for debugger clients - if (expr.DesiredResultType() == ClangExpression::eResultTypeId) - m_compiler->getLangOpts().DebuggerCastResultToId = true; - - m_compiler->getLangOpts().CharIsSigned = - ArchSpec(m_compiler->getTargetOpts().Triple.c_str()).CharIsSignedByDefault(); - - // Spell checking is a nice feature, but it ends up completing a - // lot of types that we didn't strictly speaking need to complete. - // As a result, we spend a long time parsing and importing debug - // information. - m_compiler->getLangOpts().SpellChecking = false; - - lldb::ProcessSP process_sp; - if (exe_scope) - process_sp = exe_scope->CalculateProcess(); - - if (process_sp && m_compiler->getLangOpts().ObjC1) - { - if (process_sp->GetObjCLanguageRuntime()) - { - if (process_sp->GetObjCLanguageRuntime()->GetRuntimeVersion() == eAppleObjC_V2) - m_compiler->getLangOpts().ObjCRuntime.set(ObjCRuntime::MacOSX, VersionTuple(10, 7)); - else - m_compiler->getLangOpts().ObjCRuntime.set(ObjCRuntime::FragileMacOSX, VersionTuple(10, 7)); - - if (process_sp->GetObjCLanguageRuntime()->HasNewLiteralsAndIndexing()) - m_compiler->getLangOpts().DebuggerObjCLiteral = true; - } - } - - m_compiler->getLangOpts().ThreadsafeStatics = false; - m_compiler->getLangOpts().AccessControl = false; // Debuggers get universal access - m_compiler->getLangOpts().DollarIdents = true; // $ indicates a persistent variable name - - // Set CodeGen options - m_compiler->getCodeGenOpts().EmitDeclMetadata = true; - m_compiler->getCodeGenOpts().InstrumentFunctions = false; - m_compiler->getCodeGenOpts().DisableFPElim = true; - m_compiler->getCodeGenOpts().OmitLeafFramePointer = false; - if (generate_debug_info) - m_compiler->getCodeGenOpts().setDebugInfo(CodeGenOptions::FullDebugInfo); - else - m_compiler->getCodeGenOpts().setDebugInfo(CodeGenOptions::NoDebugInfo); - - // Disable some warnings. - m_compiler->getDiagnostics().setSeverityForGroup(clang::diag::Flavor::WarningOrError, - "unused-value", clang::diag::Severity::Ignored, SourceLocation()); - m_compiler->getDiagnostics().setSeverityForGroup(clang::diag::Flavor::WarningOrError, - "odr", clang::diag::Severity::Ignored, SourceLocation()); - - // Inform the target of the language options - // - // FIXME: We shouldn't need to do this, the target should be immutable once - // created. This complexity should be lifted elsewhere. - m_compiler->getTarget().adjust(m_compiler->getLangOpts()); - - // 4. Set up the diagnostic buffer for reporting errors - - m_compiler->getDiagnostics().setClient(new clang::TextDiagnosticBuffer); - - // 5. Set up the source management objects inside the compiler - - clang::FileSystemOptions file_system_options; - m_file_manager.reset(new clang::FileManager(file_system_options)); - - if (!m_compiler->hasSourceManager()) - m_compiler->createSourceManager(*m_file_manager.get()); - - m_compiler->createFileManager(); - m_compiler->createPreprocessor(TU_Complete); - - if (ClangModulesDeclVendor *decl_vendor = target_sp->GetClangModulesDeclVendor()) - { - std::unique_ptr<PPCallbacks> pp_callbacks(new LLDBPreprocessorCallbacks(*decl_vendor, target_sp->GetPersistentVariables())); - m_pp_callbacks = static_cast<LLDBPreprocessorCallbacks*>(pp_callbacks.get()); - m_compiler->getPreprocessor().addPPCallbacks(std::move(pp_callbacks)); - } - - // 6. Most of this we get from the CompilerInstance, but we - // also want to give the context an ExternalASTSource. - m_selector_table.reset(new SelectorTable()); - m_builtin_context.reset(new Builtin::Context()); - - std::unique_ptr<clang::ASTContext> ast_context(new ASTContext(m_compiler->getLangOpts(), - m_compiler->getSourceManager(), - m_compiler->getPreprocessor().getIdentifierTable(), - *m_selector_table.get(), - *m_builtin_context.get())); - - ast_context->InitBuiltinTypes(m_compiler->getTarget()); - - ClangExpressionDeclMap *decl_map = m_expr.DeclMap(); - - if (decl_map) - { - llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> ast_source(decl_map->CreateProxy()); - decl_map->InstallASTContext(ast_context.get()); - ast_context->setExternalSource(ast_source); - } - - m_compiler->setASTContext(ast_context.release()); - - std::string module_name("$__lldb_module"); - - m_llvm_context.reset(new LLVMContext()); - m_code_generator.reset(CreateLLVMCodeGen(m_compiler->getDiagnostics(), - module_name, - m_compiler->getHeaderSearchOpts(), - m_compiler->getPreprocessorOpts(), - m_compiler->getCodeGenOpts(), - *m_llvm_context)); -} - -ClangExpressionParser::~ClangExpressionParser() -{ -} - -unsigned -ClangExpressionParser::Parse (Stream &stream) -{ - TextDiagnosticBuffer *diag_buf = static_cast<TextDiagnosticBuffer*>(m_compiler->getDiagnostics().getClient()); - - diag_buf->FlushDiagnostics (m_compiler->getDiagnostics()); - - const char *expr_text = m_expr.Text(); - - clang::SourceManager &SourceMgr = m_compiler->getSourceManager(); - bool created_main_file = false; - if (m_compiler->getCodeGenOpts().getDebugInfo() == CodeGenOptions::FullDebugInfo) - { - std::string temp_source_path; - - int temp_fd = -1; - llvm::SmallString<PATH_MAX> result_path; - FileSpec tmpdir_file_spec; - if (HostInfo::GetLLDBPath(lldb::ePathTypeLLDBTempSystemDir, tmpdir_file_spec)) - { - tmpdir_file_spec.AppendPathComponent("lldb-%%%%%%.expr"); - temp_source_path = std::move(tmpdir_file_spec.GetPath()); - llvm::sys::fs::createUniqueFile(temp_source_path, temp_fd, result_path); - } - else - { - llvm::sys::fs::createTemporaryFile("lldb", "expr", temp_fd, result_path); - } - - if (temp_fd != -1) - { - lldb_private::File file (temp_fd, true); - const size_t expr_text_len = strlen(expr_text); - size_t bytes_written = expr_text_len; - if (file.Write(expr_text, bytes_written).Success()) - { - if (bytes_written == expr_text_len) - { - file.Close(); - SourceMgr.setMainFileID(SourceMgr.createFileID( - m_file_manager->getFile(result_path), - SourceLocation(), SrcMgr::C_User)); - created_main_file = true; - } - } - } - } - - if (!created_main_file) - { - std::unique_ptr<MemoryBuffer> memory_buffer = MemoryBuffer::getMemBufferCopy(expr_text, __FUNCTION__); - SourceMgr.setMainFileID(SourceMgr.createFileID(std::move(memory_buffer))); - } - - diag_buf->BeginSourceFile(m_compiler->getLangOpts(), &m_compiler->getPreprocessor()); - - ASTConsumer *ast_transformer = m_expr.ASTTransformer(m_code_generator.get()); - - if (ClangExpressionDeclMap *decl_map = m_expr.DeclMap()) - decl_map->InstallCodeGenerator(m_code_generator.get()); - - if (ast_transformer) - ParseAST(m_compiler->getPreprocessor(), ast_transformer, m_compiler->getASTContext()); - else - ParseAST(m_compiler->getPreprocessor(), m_code_generator.get(), m_compiler->getASTContext()); - - diag_buf->EndSourceFile(); - - TextDiagnosticBuffer::const_iterator diag_iterator; - - int num_errors = 0; - - if (m_pp_callbacks && m_pp_callbacks->hasErrors()) - { - num_errors++; - - stream.PutCString(m_pp_callbacks->getErrorString().c_str()); - } - - for (diag_iterator = diag_buf->warn_begin(); - diag_iterator != diag_buf->warn_end(); - ++diag_iterator) - stream.Printf("warning: %s\n", (*diag_iterator).second.c_str()); - - for (diag_iterator = diag_buf->err_begin(); - diag_iterator != diag_buf->err_end(); - ++diag_iterator) - { - num_errors++; - stream.Printf("error: %s\n", (*diag_iterator).second.c_str()); - } - - for (diag_iterator = diag_buf->note_begin(); - diag_iterator != diag_buf->note_end(); - ++diag_iterator) - stream.Printf("note: %s\n", (*diag_iterator).second.c_str()); - - if (!num_errors) - { - if (m_expr.DeclMap() && !m_expr.DeclMap()->ResolveUnknownTypes()) - { - stream.Printf("error: Couldn't infer the type of a variable\n"); - num_errors++; - } - } - - return num_errors; -} - -static bool FindFunctionInModule (ConstString &mangled_name, - llvm::Module *module, - const char *orig_name) -{ - for (llvm::Module::iterator fi = module->getFunctionList().begin(), fe = module->getFunctionList().end(); - fi != fe; - ++fi) - { - if (fi->getName().str().find(orig_name) != std::string::npos) - { - mangled_name.SetCString(fi->getName().str().c_str()); - return true; - } - } - - return false; -} - -Error -ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr, - lldb::addr_t &func_end, - std::shared_ptr<IRExecutionUnit> &execution_unit_sp, - ExecutionContext &exe_ctx, - bool &can_interpret, - ExecutionPolicy execution_policy) -{ - func_addr = LLDB_INVALID_ADDRESS; - func_end = LLDB_INVALID_ADDRESS; - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - Error err; - - std::unique_ptr<llvm::Module> llvm_module_ap (m_code_generator->ReleaseModule()); - - if (!llvm_module_ap.get()) - { - err.SetErrorToGenericError(); - err.SetErrorString("IR doesn't contain a module"); - return err; - } - - // Find the actual name of the function (it's often mangled somehow) - - ConstString function_name; - - if (!FindFunctionInModule(function_name, llvm_module_ap.get(), m_expr.FunctionName())) - { - err.SetErrorToGenericError(); - err.SetErrorStringWithFormat("Couldn't find %s() in the module", m_expr.FunctionName()); - return err; - } - else - { - if (log) - log->Printf("Found function %s for %s", function_name.AsCString(), m_expr.FunctionName()); - } - - execution_unit_sp.reset(new IRExecutionUnit (m_llvm_context, // handed off here - llvm_module_ap, // handed off here - function_name, - exe_ctx.GetTargetSP(), - m_compiler->getTargetOpts().Features)); - - ClangExpressionDeclMap *decl_map = m_expr.DeclMap(); // result can be NULL - - if (decl_map) - { - Stream *error_stream = NULL; - Target *target = exe_ctx.GetTargetPtr(); - if (target) - error_stream = target->GetDebugger().GetErrorFile().get(); - - IRForTarget ir_for_target(decl_map, - m_expr.NeedsVariableResolution(), - *execution_unit_sp, - error_stream, - function_name.AsCString()); - - bool ir_can_run = ir_for_target.runOnModule(*execution_unit_sp->GetModule()); - - Error interpret_error; - Process *process = exe_ctx.GetProcessPtr(); - - bool interpret_function_calls = !process ? false : process->CanInterpretFunctionCalls(); - can_interpret = IRInterpreter::CanInterpret(*execution_unit_sp->GetModule(), *execution_unit_sp->GetFunction(), interpret_error, interpret_function_calls); - - - if (!ir_can_run) - { - err.SetErrorString("The expression could not be prepared to run in the target"); - return err; - } - - if (!can_interpret && execution_policy == eExecutionPolicyNever) - { - err.SetErrorStringWithFormat("Can't run the expression locally: %s", interpret_error.AsCString()); - return err; - } - - if (!process && execution_policy == eExecutionPolicyAlways) - { - err.SetErrorString("Expression needed to run in the target, but the target can't be run"); - return err; - } - - if (execution_policy == eExecutionPolicyAlways || !can_interpret) - { - if (m_expr.NeedsValidation() && process) - { - if (!process->GetDynamicCheckers()) - { - DynamicCheckerFunctions *dynamic_checkers = new DynamicCheckerFunctions(); - - StreamString install_errors; - - if (!dynamic_checkers->Install(install_errors, exe_ctx)) - { - if (install_errors.GetString().empty()) - err.SetErrorString ("couldn't install checkers, unknown error"); - else - err.SetErrorString (install_errors.GetString().c_str()); - - return err; - } - - process->SetDynamicCheckers(dynamic_checkers); - - if (log) - log->Printf("== [ClangUserExpression::Evaluate] Finished installing dynamic checkers =="); - } - - IRDynamicChecks ir_dynamic_checks(*process->GetDynamicCheckers(), function_name.AsCString()); - - if (!ir_dynamic_checks.runOnModule(*execution_unit_sp->GetModule())) - { - err.SetErrorToGenericError(); - err.SetErrorString("Couldn't add dynamic checks to the expression"); - return err; - } - } - - execution_unit_sp->GetRunnableInfo(err, func_addr, func_end); - } - } - else - { - execution_unit_sp->GetRunnableInfo(err, func_addr, func_end); - } - - return err; -} - -bool -ClangExpressionParser::GetGenerateDebugInfo () const -{ - if (m_compiler) - return m_compiler->getCodeGenOpts().getDebugInfo() == CodeGenOptions::FullDebugInfo; - return false; -} |