ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope, Expression &expr, bool generate_debug_info) : ExpressionParser (exe_scope, expr, generate_debug_info), m_compiler (), m_builtin_context (), m_selector_table (), m_code_generator (), m_pp_callbacks(nullptr) { // 1. Create a new compiler instance. m_compiler.reset(new CompilerInstance()); // Register the support for object-file-wrapped Clang modules. std::shared_ptr<clang::PCHContainerOperations> pch_operations = m_compiler->getPCHContainerOperations(); pch_operations->registerWriter(llvm::make_unique<ObjectFilePCHContainerWriter>()); pch_operations->registerReader(llvm::make_unique<ObjectFilePCHContainerReader>()); // 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(); } m_compiler->getTargetOpts().CPU = ""; 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: case lldb::eLanguageTypeC89: case lldb::eLanguageTypeC99: case lldb::eLanguageTypeC11: // FIXME: the following language option is a temporary workaround, // to "ask for C, get C++." // For now, the expression parser must use C++ anytime the // language is a C family language, because the expression parser // uses features of C++ to capture values. m_compiler->getLangOpts().CPlusPlus = true; break; case lldb::eLanguageTypeObjC: m_compiler->getLangOpts().ObjC1 = true; m_compiler->getLangOpts().ObjC2 = true; // FIXME: the following language option is a temporary workaround, // to "ask for ObjC, get ObjC++" (see comment above). m_compiler->getLangOpts().CPlusPlus = true; break; case lldb::eLanguageTypeC_plus_plus: case lldb::eLanguageTypeC_plus_plus_11: case lldb::eLanguageTypeC_plus_plus_14: m_compiler->getLangOpts().CPlusPlus11 = true; m_compiler->getHeaderSearchOpts().UseLibcxx = true; // fall thru ... case lldb::eLanguageTypeC_plus_plus_03: m_compiler->getLangOpts().CPlusPlus = true; // FIXME: the following language option is a temporary workaround, // to "ask for C++, get ObjC++". Apple hopes to remove this requirement // on non-Apple platforms, but for now it is needed. m_compiler->getLangOpts().ObjC1 = true; break; case lldb::eLanguageTypeObjC_plus_plus: case lldb::eLanguageTypeUnknown: 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() == Expression::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() == ObjCLanguageRuntime::ObjCRuntimeVersions::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()) { ClangPersistentVariables *clang_persistent_vars = llvm::cast<ClangPersistentVariables>(target_sp->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC)); std::unique_ptr<PPCallbacks> pp_callbacks(new LLDBPreprocessorCallbacks(*decl_vendor, *clang_persistent_vars)); 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()); ClangExpressionHelper *type_system_helper = dyn_cast<ClangExpressionHelper>(m_expr.GetTypeSystemHelper()); ClangExpressionDeclMap *decl_map = type_system_helper->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_ast_context.reset(new ClangASTContext(m_compiler->getTargetOpts().Triple.c_str())); m_ast_context->setASTContext(ast_context.get()); 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 (ExecutionContextScope *exe_scope, Expression &expr, bool generate_debug_info) : ExpressionParser (exe_scope, expr, generate_debug_info), m_compiler (), m_code_generator (), m_pp_callbacks(nullptr) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); // We can't compile expressions without a target. So if the exe_scope is null or doesn't have a target, // then we just need to get out of here. I'll lldb_assert and not make any of the compiler objects since // I can't return errors directly from the constructor. Further calls will check if the compiler was made and // bag out if it wasn't. if (!exe_scope) { lldb_assert(exe_scope, "Can't make an expression parser with a null scope.", __FUNCTION__, __FILE__, __LINE__); return; } lldb::TargetSP target_sp; target_sp = exe_scope->CalculateTarget(); if (!target_sp) { lldb_assert(exe_scope, "Can't make an expression parser with a null target.", __FUNCTION__, __FILE__, __LINE__); return; } // 1. Create a new compiler instance. m_compiler.reset(new CompilerInstance()); lldb::LanguageType frame_lang = expr.Language(); // defaults to lldb::eLanguageTypeUnknown bool overridden_target_opts = false; lldb_private::LanguageRuntime *lang_rt = nullptr; std::string abi; ArchSpec target_arch; target_arch = target_sp->GetArchitecture(); const auto target_machine = target_arch.GetMachine(); // If the expression is being evaluated in the context of an existing // stack frame, we introspect to see if the language runtime is available. lldb::StackFrameSP frame_sp = exe_scope->CalculateStackFrame(); lldb::ProcessSP process_sp = exe_scope->CalculateProcess(); // Make sure the user hasn't provided a preferred execution language // with `expression --language X -- ...` if (frame_sp && frame_lang == lldb::eLanguageTypeUnknown) frame_lang = frame_sp->GetLanguage(); if (process_sp && frame_lang != lldb::eLanguageTypeUnknown) { lang_rt = process_sp->GetLanguageRuntime(frame_lang); if (log) log->Printf("Frame has language of type %s", Language::GetNameForLanguageType(frame_lang)); } // 2. Configure the compiler with a set of default options that are appropriate // for most situations. if (target_arch.IsValid()) { std::string triple = target_arch.GetTriple().str(); m_compiler->getTargetOpts().Triple = triple; if (log) log->Printf("Using %s as the target triple", m_compiler->getTargetOpts().Triple.c_str()); } else { // If we get here we don't have a valid target and just have to guess. // 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. In such a case the language runtime should expose an overridden options set (3), // below. m_compiler->getTargetOpts().Triple = llvm::sys::getDefaultTargetTriple(); if (log) log->Printf("Using default target triple of %s", m_compiler->getTargetOpts().Triple.c_str()); } // Now add some special fixes for known architectures: // 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"; } // Supported subsets of x86 if (target_machine == llvm::Triple::x86 || target_machine == llvm::Triple::x86_64) { m_compiler->getTargetOpts().Features.push_back("+sse"); m_compiler->getTargetOpts().Features.push_back("+sse2"); } // Set the target CPU to generate code for. // This will be empty for any CPU that doesn't really need to make a special CPU string. m_compiler->getTargetOpts().CPU = target_arch.GetClangTargetCPU(); // Set the target ABI abi = GetClangTargetABI(target_arch); if (!abi.empty()) m_compiler->getTargetOpts().ABI = abi; // 3. Now allow the runtime to provide custom configuration options for the target. // In this case, a specialized language runtime is available and we can query it for extra options. // For 99% of use cases, this will not be needed and should be provided when basic platform detection is not enough. if (lang_rt) overridden_target_opts = lang_rt->GetOverrideExprOptions(m_compiler->getTargetOpts()); if (overridden_target_opts) if (log) { log->Debug("Using overridden target options for the expression evaluation"); auto opts = m_compiler->getTargetOpts(); log->Debug("Triple: '%s'", opts.Triple.c_str()); log->Debug("CPU: '%s'", opts.CPU.c_str()); log->Debug("FPMath: '%s'", opts.FPMath.c_str()); log->Debug("ABI: '%s'", opts.ABI.c_str()); log->Debug("LinkerVersion: '%s'", opts.LinkerVersion.c_str()); StringList::LogDump(log, opts.FeaturesAsWritten, "FeaturesAsWritten"); StringList::LogDump(log, opts.Features, "Features"); StringList::LogDump(log, opts.Reciprocals, "Reciprocals"); } // 4. Create and install the target on the compiler. m_compiler->createDiagnostics(); auto target_info = TargetInfo::CreateTargetInfo(m_compiler->getDiagnostics(), m_compiler->getInvocation().TargetOpts); if (log) { log->Printf("Using SIMD alignment: %d", target_info->getSimdDefaultAlign()); log->Printf("Target datalayout string: '%s'", target_info->getDataLayout().getStringRepresentation().c_str()); log->Printf("Target ABI: '%s'", target_info->getABI().str().c_str()); log->Printf("Target vector alignment: %d", target_info->getMaxVectorAlign()); } m_compiler->setTarget(target_info); assert (m_compiler->hasTarget()); // 5. Set language options. lldb::LanguageType language = expr.Language(); switch (language) { case lldb::eLanguageTypeC: case lldb::eLanguageTypeC89: case lldb::eLanguageTypeC99: case lldb::eLanguageTypeC11: // FIXME: the following language option is a temporary workaround, // to "ask for C, get C++." // For now, the expression parser must use C++ anytime the // language is a C family language, because the expression parser // uses features of C++ to capture values. m_compiler->getLangOpts().CPlusPlus = true; break; case lldb::eLanguageTypeObjC: m_compiler->getLangOpts().ObjC1 = true; m_compiler->getLangOpts().ObjC2 = true; // FIXME: the following language option is a temporary workaround, // to "ask for ObjC, get ObjC++" (see comment above). m_compiler->getLangOpts().CPlusPlus = true; break; case lldb::eLanguageTypeC_plus_plus: case lldb::eLanguageTypeC_plus_plus_11: case lldb::eLanguageTypeC_plus_plus_14: m_compiler->getLangOpts().CPlusPlus11 = true; m_compiler->getHeaderSearchOpts().UseLibcxx = true; LLVM_FALLTHROUGH; case lldb::eLanguageTypeC_plus_plus_03: m_compiler->getLangOpts().CPlusPlus = true; // FIXME: the following language option is a temporary workaround, // to "ask for C++, get ObjC++". Apple hopes to remove this requirement // on non-Apple platforms, but for now it is needed. m_compiler->getLangOpts().ObjC1 = true; break; case lldb::eLanguageTypeObjC_plus_plus: case lldb::eLanguageTypeUnknown: 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() == Expression::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; if (process_sp && m_compiler->getLangOpts().ObjC1) { if (process_sp->GetObjCLanguageRuntime()) { if (process_sp->GetObjCLanguageRuntime()->GetRuntimeVersion() == ObjCLanguageRuntime::ObjCRuntimeVersions::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()); // 6. Set up the diagnostic buffer for reporting errors m_compiler->getDiagnostics().setClient(new ClangDiagnosticManagerAdapter); // 7. 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()) { ClangPersistentVariables *clang_persistent_vars = llvm::cast<ClangPersistentVariables>(target_sp->GetPersistentExpressionStateForLanguage(lldb::eLanguageTypeC)); std::unique_ptr<PPCallbacks> pp_callbacks(new LLDBPreprocessorCallbacks(*decl_vendor, *clang_persistent_vars)); m_pp_callbacks = static_cast<LLDBPreprocessorCallbacks*>(pp_callbacks.get()); m_compiler->getPreprocessor().addPPCallbacks(std::move(pp_callbacks)); } // 8. 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()); ClangExpressionHelper *type_system_helper = dyn_cast<ClangExpressionHelper>(m_expr.GetTypeSystemHelper()); ClangExpressionDeclMap *decl_map = type_system_helper->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_ast_context.reset(new ClangASTContext(m_compiler->getTargetOpts().Triple.c_str())); m_ast_context->setASTContext(ast_context.get()); 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)); }