Skip to content

Commit 12e3a06

Browse files
authored
[lldb][ClangExpressionParser][NFC] Factor LangOptions logic out of ClangExpressionParser constructor (#101669)
We plan to eventually use the Clang driver to initialize the `CompilerInstance`. This should make refactorings of this code more straightforward. **Changes**: * Introduced `SetupLangOpts` and `SetupImportStdModuleLangOpts` * Called them from `ClangExpressionParser::ClangExpressionParser`
1 parent ab819d7 commit 12e3a06

File tree

3 files changed

+125
-110
lines changed

3 files changed

+125
-110
lines changed

lldb/include/lldb/Expression/Expression.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ class Expression {
5656

5757
/// Return the desired result type of the function, or eResultTypeAny if
5858
/// indifferent.
59-
virtual ResultType DesiredResultType() { return eResultTypeAny; }
59+
virtual ResultType DesiredResultType() const { return eResultTypeAny; }
6060

6161
/// Flags
6262

lldb/include/lldb/Expression/UserExpression.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ class UserExpression : public Expression {
206206

207207
/// Return the desired result type of the function, or eResultTypeAny if
208208
/// indifferent.
209-
ResultType DesiredResultType() override { return m_desired_type; }
209+
ResultType DesiredResultType() const override { return m_desired_type; }
210210

211211
/// Return true if validation code should be inserted into the expression.
212212
bool NeedsValidation() override { return true; }

lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp

Lines changed: 123 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
#include "lldb/Host/HostInfo.h"
7878
#include "lldb/Symbol/SymbolVendor.h"
7979
#include "lldb/Target/ExecutionContext.h"
80+
#include "lldb/Target/ExecutionContextScope.h"
8081
#include "lldb/Target/Language.h"
8182
#include "lldb/Target/Process.h"
8283
#include "lldb/Target/Target.h"
@@ -425,99 +426,34 @@ static void SetupTargetOpts(CompilerInstance &compiler,
425426
compiler.getTargetOpts().ABI = std::move(abi);
426427
}
427428

428-
//===----------------------------------------------------------------------===//
429-
// Implementation of ClangExpressionParser
430-
//===----------------------------------------------------------------------===//
431-
432-
ClangExpressionParser::ClangExpressionParser(
433-
ExecutionContextScope *exe_scope, Expression &expr,
434-
bool generate_debug_info, std::vector<std::string> include_directories,
435-
std::string filename)
436-
: ExpressionParser(exe_scope, expr, generate_debug_info), m_compiler(),
437-
m_pp_callbacks(nullptr),
438-
m_include_directories(std::move(include_directories)),
439-
m_filename(std::move(filename)) {
429+
static void SetupLangOpts(CompilerInstance &compiler,
430+
ExecutionContextScope &exe_scope,
431+
const Expression &expr) {
440432
Log *log = GetLog(LLDBLog::Expressions);
441433

442-
// We can't compile expressions without a target. So if the exe_scope is
443-
// null or doesn't have a target, then we just need to get out of here. I'll
444-
// lldbassert and not make any of the compiler objects since
445-
// I can't return errors directly from the constructor. Further calls will
446-
// check if the compiler was made and
447-
// bag out if it wasn't.
448-
449-
if (!exe_scope) {
450-
lldbassert(exe_scope &&
451-
"Can't make an expression parser with a null scope.");
452-
return;
453-
}
454-
455-
lldb::TargetSP target_sp;
456-
target_sp = exe_scope->CalculateTarget();
457-
if (!target_sp) {
458-
lldbassert(target_sp.get() &&
459-
"Can't make an expression parser with a null target.");
460-
return;
461-
}
462-
463-
// 1. Create a new compiler instance.
464-
m_compiler = std::make_unique<CompilerInstance>();
434+
// If the expression is being evaluated in the context of an existing stack
435+
// frame, we introspect to see if the language runtime is available.
465436

466-
// Make sure clang uses the same VFS as LLDB.
467-
m_compiler->createFileManager(FileSystem::Instance().GetVirtualFileSystem());
437+
lldb::StackFrameSP frame_sp = exe_scope.CalculateStackFrame();
438+
lldb::ProcessSP process_sp = exe_scope.CalculateProcess();
468439

469440
// Defaults to lldb::eLanguageTypeUnknown.
470441
lldb::LanguageType frame_lang = expr.Language().AsLanguageType();
471442

472-
// If the expression is being evaluated in the context of an existing stack
473-
// frame, we introspect to see if the language runtime is available.
474-
475-
lldb::StackFrameSP frame_sp = exe_scope->CalculateStackFrame();
476-
lldb::ProcessSP process_sp = exe_scope->CalculateProcess();
477-
478443
// Make sure the user hasn't provided a preferred execution language with
479444
// `expression --language X -- ...`
480445
if (frame_sp && frame_lang == lldb::eLanguageTypeUnknown)
481446
frame_lang = frame_sp->GetLanguage().AsLanguageType();
482447

483448
if (process_sp && frame_lang != lldb::eLanguageTypeUnknown) {
484449
LLDB_LOGF(log, "Frame has language of type %s",
485-
Language::GetNameForLanguageType(frame_lang));
450+
lldb_private::Language::GetNameForLanguageType(frame_lang));
486451
}
487452

488-
// 2. Configure the compiler with a set of default options that are
489-
// appropriate for most situations.
490-
SetupTargetOpts(*m_compiler, *target_sp);
491-
492-
// 3. Create and install the target on the compiler.
493-
m_compiler->createDiagnostics();
494-
// Limit the number of error diagnostics we emit.
495-
// A value of 0 means no limit for both LLDB and Clang.
496-
m_compiler->getDiagnostics().setErrorLimit(target_sp->GetExprErrorLimit());
497-
498-
if (auto *target_info = TargetInfo::CreateTargetInfo(
499-
m_compiler->getDiagnostics(),
500-
m_compiler->getInvocation().TargetOpts)) {
501-
if (log) {
502-
LLDB_LOGF(log, "Target datalayout string: '%s'",
503-
target_info->getDataLayoutString());
504-
LLDB_LOGF(log, "Target ABI: '%s'", target_info->getABI().str().c_str());
505-
LLDB_LOGF(log, "Target vector alignment: %d",
506-
target_info->getMaxVectorAlign());
507-
}
508-
m_compiler->setTarget(target_info);
509-
} else {
510-
if (log)
511-
LLDB_LOGF(log, "Failed to create TargetInfo for '%s'",
512-
m_compiler->getTargetOpts().Triple.c_str());
513-
514-
lldbassert(false && "Failed to create TargetInfo.");
515-
}
516-
517-
// 4. Set language options.
518453
lldb::LanguageType language = expr.Language().AsLanguageType();
519-
LangOptions &lang_opts = m_compiler->getLangOpts();
454+
LangOptions &lang_opts = compiler.getLangOpts();
520455

456+
// FIXME: should this switch on frame_lang?
521457
switch (language) {
522458
case lldb::eLanguageTypeC:
523459
case lldb::eLanguageTypeC89:
@@ -558,7 +494,7 @@ ClangExpressionParser::ClangExpressionParser(
558494
case lldb::eLanguageTypeC_plus_plus_11:
559495
case lldb::eLanguageTypeC_plus_plus_14:
560496
lang_opts.CPlusPlus11 = true;
561-
m_compiler->getHeaderSearchOpts().UseLibcxx = true;
497+
compiler.getHeaderSearchOpts().UseLibcxx = true;
562498
[[fallthrough]];
563499
case lldb::eLanguageTypeC_plus_plus_03:
564500
lang_opts.CPlusPlus = true;
@@ -575,7 +511,7 @@ ClangExpressionParser::ClangExpressionParser(
575511
lang_opts.ObjC = true;
576512
lang_opts.CPlusPlus = true;
577513
lang_opts.CPlusPlus11 = true;
578-
m_compiler->getHeaderSearchOpts().UseLibcxx = true;
514+
compiler.getHeaderSearchOpts().UseLibcxx = true;
579515
break;
580516
}
581517

@@ -587,42 +523,14 @@ ClangExpressionParser::ClangExpressionParser(
587523
if (expr.DesiredResultType() == Expression::eResultTypeId)
588524
lang_opts.DebuggerCastResultToId = true;
589525

590-
lang_opts.CharIsSigned = ArchSpec(m_compiler->getTargetOpts().Triple.c_str())
591-
.CharIsSignedByDefault();
526+
lang_opts.CharIsSigned =
527+
ArchSpec(compiler.getTargetOpts().Triple.c_str()).CharIsSignedByDefault();
592528

593529
// Spell checking is a nice feature, but it ends up completing a lot of types
594530
// that we didn't strictly speaking need to complete. As a result, we spend a
595531
// long time parsing and importing debug information.
596532
lang_opts.SpellChecking = false;
597533

598-
auto *clang_expr = dyn_cast<ClangUserExpression>(&m_expr);
599-
if (clang_expr && clang_expr->DidImportCxxModules()) {
600-
LLDB_LOG(log, "Adding lang options for importing C++ modules");
601-
602-
lang_opts.Modules = true;
603-
// We want to implicitly build modules.
604-
lang_opts.ImplicitModules = true;
605-
// To automatically import all submodules when we import 'std'.
606-
lang_opts.ModulesLocalVisibility = false;
607-
608-
// We use the @import statements, so we need this:
609-
// FIXME: We could use the modules-ts, but that currently doesn't work.
610-
lang_opts.ObjC = true;
611-
612-
// Options we need to parse libc++ code successfully.
613-
// FIXME: We should ask the driver for the appropriate default flags.
614-
lang_opts.GNUMode = true;
615-
lang_opts.GNUKeywords = true;
616-
lang_opts.CPlusPlus11 = true;
617-
lang_opts.BuiltinHeadersInSystemModules = true;
618-
619-
// The Darwin libc expects this macro to be set.
620-
lang_opts.GNUCVersion = 40201;
621-
622-
SetupModuleHeaderPaths(m_compiler.get(), m_include_directories,
623-
target_sp);
624-
}
625-
626534
if (process_sp && lang_opts.ObjC) {
627535
if (auto *runtime = ObjCLanguageRuntime::Get(*process_sp)) {
628536
switch (runtime->GetRuntimeVersion()) {
@@ -651,6 +559,113 @@ ClangExpressionParser::ClangExpressionParser(
651559
// 'fopen'). Those libc functions are already correctly handled by LLDB, and
652560
// additionally enabling them as expandable builtins is breaking Clang.
653561
lang_opts.NoBuiltin = true;
562+
}
563+
564+
static void SetupImportStdModuleLangOpts(CompilerInstance &compiler) {
565+
LangOptions &lang_opts = compiler.getLangOpts();
566+
lang_opts.Modules = true;
567+
// We want to implicitly build modules.
568+
lang_opts.ImplicitModules = true;
569+
// To automatically import all submodules when we import 'std'.
570+
lang_opts.ModulesLocalVisibility = false;
571+
572+
// We use the @import statements, so we need this:
573+
// FIXME: We could use the modules-ts, but that currently doesn't work.
574+
lang_opts.ObjC = true;
575+
576+
// Options we need to parse libc++ code successfully.
577+
// FIXME: We should ask the driver for the appropriate default flags.
578+
lang_opts.GNUMode = true;
579+
lang_opts.GNUKeywords = true;
580+
lang_opts.CPlusPlus11 = true;
581+
lang_opts.BuiltinHeadersInSystemModules = true;
582+
583+
// The Darwin libc expects this macro to be set.
584+
lang_opts.GNUCVersion = 40201;
585+
}
586+
587+
//===----------------------------------------------------------------------===//
588+
// Implementation of ClangExpressionParser
589+
//===----------------------------------------------------------------------===//
590+
591+
ClangExpressionParser::ClangExpressionParser(
592+
ExecutionContextScope *exe_scope, Expression &expr,
593+
bool generate_debug_info, std::vector<std::string> include_directories,
594+
std::string filename)
595+
: ExpressionParser(exe_scope, expr, generate_debug_info), m_compiler(),
596+
m_pp_callbacks(nullptr),
597+
m_include_directories(std::move(include_directories)),
598+
m_filename(std::move(filename)) {
599+
Log *log = GetLog(LLDBLog::Expressions);
600+
601+
// We can't compile expressions without a target. So if the exe_scope is
602+
// null or doesn't have a target, then we just need to get out of here. I'll
603+
// lldbassert and not make any of the compiler objects since
604+
// I can't return errors directly from the constructor. Further calls will
605+
// check if the compiler was made and
606+
// bag out if it wasn't.
607+
608+
if (!exe_scope) {
609+
lldbassert(exe_scope &&
610+
"Can't make an expression parser with a null scope.");
611+
return;
612+
}
613+
614+
lldb::TargetSP target_sp;
615+
target_sp = exe_scope->CalculateTarget();
616+
if (!target_sp) {
617+
lldbassert(target_sp.get() &&
618+
"Can't make an expression parser with a null target.");
619+
return;
620+
}
621+
622+
// 1. Create a new compiler instance.
623+
m_compiler = std::make_unique<CompilerInstance>();
624+
625+
// Make sure clang uses the same VFS as LLDB.
626+
m_compiler->createFileManager(FileSystem::Instance().GetVirtualFileSystem());
627+
628+
std::string abi;
629+
ArchSpec target_arch;
630+
target_arch = target_sp->GetArchitecture();
631+
632+
// 2. Configure the compiler with a set of default options that are
633+
// appropriate for most situations.
634+
SetupTargetOpts(*m_compiler, *target_sp);
635+
636+
// 3. Create and install the target on the compiler.
637+
m_compiler->createDiagnostics();
638+
// Limit the number of error diagnostics we emit.
639+
// A value of 0 means no limit for both LLDB and Clang.
640+
m_compiler->getDiagnostics().setErrorLimit(target_sp->GetExprErrorLimit());
641+
642+
if (auto *target_info = TargetInfo::CreateTargetInfo(
643+
m_compiler->getDiagnostics(),
644+
m_compiler->getInvocation().TargetOpts)) {
645+
if (log) {
646+
LLDB_LOGF(log, "Target datalayout string: '%s'",
647+
target_info->getDataLayoutString());
648+
LLDB_LOGF(log, "Target ABI: '%s'", target_info->getABI().str().c_str());
649+
LLDB_LOGF(log, "Target vector alignment: %d",
650+
target_info->getMaxVectorAlign());
651+
}
652+
m_compiler->setTarget(target_info);
653+
} else {
654+
if (log)
655+
LLDB_LOGF(log, "Failed to create TargetInfo for '%s'",
656+
m_compiler->getTargetOpts().Triple.c_str());
657+
658+
lldbassert(false && "Failed to create TargetInfo.");
659+
}
660+
661+
// 4. Set language options.
662+
SetupLangOpts(*m_compiler, *exe_scope, expr);
663+
if (auto *clang_expr = dyn_cast<ClangUserExpression>(&m_expr);
664+
clang_expr && clang_expr->DidImportCxxModules()) {
665+
LLDB_LOG(log, "Adding lang options for importing C++ modules");
666+
SetupImportStdModuleLangOpts(*m_compiler);
667+
SetupModuleHeaderPaths(m_compiler.get(), m_include_directories, target_sp);
668+
}
654669

655670
// Set CodeGen options
656671
m_compiler->getCodeGenOpts().EmitDeclMetadata = true;
@@ -684,7 +699,7 @@ ClangExpressionParser::ClangExpressionParser(
684699
m_compiler->createSourceManager(m_compiler->getFileManager());
685700
m_compiler->createPreprocessor(TU_Complete);
686701

687-
switch (language) {
702+
switch (expr.Language().AsLanguageType()) {
688703
case lldb::eLanguageTypeC:
689704
case lldb::eLanguageTypeC89:
690705
case lldb::eLanguageTypeC99:

0 commit comments

Comments
 (0)