Skip to content

Commit 5bd7d3d

Browse files
committed
Add a new SBExpressionOptions::SetLanguage() API (NFCI)
that separates out language and version. To avoid reinventing the wheel and introducing subtle incompatibilities, this API uses the table of languages and versiond defined by the upcoming DWARF 6 standard (https://dwarfstd.org/languages-v6.html). While the DWARF 6 spec is not finialized, the list of languages is broadly considered stable. The primary motivation for this is to allow the Swift language plugin to switch between language dialects between, e.g., Swift 5.9 and 6.0 with out introducing a ton of new language codes. On the main branch this change is considered NFC.
1 parent 9e95951 commit 5bd7d3d

24 files changed

+187
-113
lines changed

lldb/include/lldb/API/SBExpressionOptions.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ class LLDB_API SBExpressionOptions {
6767
void SetTrapExceptions(bool trap_exceptions = true);
6868

6969
void SetLanguage(lldb::LanguageType language);
70+
/// Set the language using a pair of language code and version as
71+
/// defined by the DWARF 6 specification.
72+
/// WARNING: These codes may change until DWARF 6 is finalized.
73+
void SetLanguage(uint16_t dwarf_lname_code, uint32_t dwarf_lversion);
7074

7175
#ifndef SWIG
7276
void SetCancelCallback(lldb::ExpressionCancelCallback callback, void *baton);

lldb/include/lldb/Expression/Expression.h

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,8 @@ class Expression {
4747
/// expression. Text() should contain the definition of this function.
4848
virtual const char *FunctionName() = 0;
4949

50-
/// Return the language that should be used when parsing. To use the
51-
/// default, return eLanguageTypeUnknown.
52-
virtual lldb::LanguageType Language() const {
53-
return lldb::eLanguageTypeUnknown;
54-
}
50+
/// Return the language that should be used when parsing.
51+
virtual SourceLanguage Language() const { return {}; }
5552

5653
/// Return the Materializer that the parser should use when registering
5754
/// external values.

lldb/include/lldb/Expression/LLVMUserExpression.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ class LLVMUserExpression : public UserExpression {
5252
};
5353

5454
LLVMUserExpression(ExecutionContextScope &exe_scope, llvm::StringRef expr,
55-
llvm::StringRef prefix, lldb::LanguageType language,
55+
llvm::StringRef prefix, SourceLanguage language,
5656
ResultType desired_type,
5757
const EvaluateExpressionOptions &options);
5858
~LLVMUserExpression() override;

lldb/include/lldb/Expression/UserExpression.h

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ class UserExpression : public Expression {
5656
/// If not eResultTypeAny, the type to use for the expression
5757
/// result.
5858
UserExpression(ExecutionContextScope &exe_scope, llvm::StringRef expr,
59-
llvm::StringRef prefix, lldb::LanguageType language,
59+
llvm::StringRef prefix, SourceLanguage language,
6060
ResultType desired_type,
6161
const EvaluateExpressionOptions &options);
6262

@@ -202,7 +202,7 @@ class UserExpression : public Expression {
202202
virtual bool IsParseCacheable() { return true; }
203203
/// Return the language that should be used when parsing. To use the
204204
/// default, return eLanguageTypeUnknown.
205-
lldb::LanguageType Language() const override { return m_language; }
205+
SourceLanguage Language() const override { return m_language; }
206206

207207
/// Return the desired result type of the function, or eResultTypeAny if
208208
/// indifferent.
@@ -315,19 +315,22 @@ class UserExpression : public Expression {
315315
lldb::ProcessSP &process_sp,
316316
lldb::StackFrameSP &frame_sp);
317317

318-
Address m_address; ///< The address the process is stopped in.
319-
std::string m_expr_text; ///< The text of the expression, as typed by the user
320-
std::string m_expr_prefix; ///< The text of the translation-level definitions,
321-
///as provided by the user
322-
std::string m_fixed_text; ///< The text of the expression with fix-its applied
323-
///- this won't be set if the fixed text doesn't
324-
///parse.
325-
lldb::LanguageType m_language; ///< The language to use when parsing
326-
///(eLanguageTypeUnknown means use defaults)
327-
ResultType m_desired_type; ///< The type to coerce the expression's result to.
328-
///If eResultTypeAny, inferred from the expression.
329-
EvaluateExpressionOptions
330-
m_options; ///< Additional options provided by the user.
318+
/// The address the process is stopped in.
319+
Address m_address;
320+
/// The text of the expression, as typed by the user.
321+
std::string m_expr_text;
322+
/// The text of the translation-level definitions, as provided by the user.
323+
std::string m_expr_prefix;
324+
/// The text of the expression with fix-its applied this won't be set if the
325+
/// fixed text doesn't parse.
326+
std::string m_fixed_text;
327+
/// The language to use when parsing (unknown means use defaults).
328+
SourceLanguage m_language;
329+
/// The type to coerce the expression's result to. If eResultTypeAny, inferred
330+
/// from the expression.
331+
ResultType m_desired_type;
332+
/// Additional options provided by the user.
333+
EvaluateExpressionOptions m_options;
331334
};
332335

333336
} // namespace lldb_private

lldb/include/lldb/Symbol/TypeSystem.h

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -474,12 +474,10 @@ class TypeSystem : public PluginInterface,
474474
return IsPointerOrReferenceType(type, nullptr);
475475
}
476476

477-
virtual UserExpression *
478-
GetUserExpression(llvm::StringRef expr, llvm::StringRef prefix,
479-
lldb::LanguageType language,
480-
Expression::ResultType desired_type,
481-
const EvaluateExpressionOptions &options,
482-
ValueObject *ctx_obj) {
477+
virtual UserExpression *GetUserExpression(
478+
llvm::StringRef expr, llvm::StringRef prefix, SourceLanguage language,
479+
Expression::ResultType desired_type,
480+
const EvaluateExpressionOptions &options, ValueObject *ctx_obj) {
483481
return nullptr;
484482
}
485483

lldb/include/lldb/Target/StackFrame.h

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -446,13 +446,12 @@ class StackFrame : public ExecutionContextScope,
446446
/// Query this frame to determine what the default language should be when
447447
/// parsing expressions given the execution context.
448448
///
449-
/// \return
450-
/// The language of the frame if known, else lldb::eLanguageTypeUnknown.
451-
lldb::LanguageType GetLanguage();
449+
/// \return The language of the frame if known.
450+
SourceLanguage GetLanguage();
452451

453-
// similar to GetLanguage(), but is allowed to take a potentially incorrect
454-
// guess if exact information is not available
455-
lldb::LanguageType GuessLanguage();
452+
/// Similar to GetLanguage(), but is allowed to take a potentially incorrect
453+
/// guess if exact information is not available
454+
SourceLanguage GuessLanguage();
456455

457456
/// Attempt to econstruct the ValueObject for a given raw address touched by
458457
/// the current instruction. The ExpressionPath should indicate how to get

lldb/include/lldb/Target/Target.h

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ class TargetProperties : public Properties {
200200

201201
bool GetBreakpointsConsultPlatformAvoidList();
202202

203-
lldb::LanguageType GetLanguage() const;
203+
SourceLanguage GetLanguage() const;
204204

205205
llvm::StringRef GetExpressionPrefixContents();
206206

@@ -310,9 +310,18 @@ class EvaluateExpressionOptions {
310310
m_execution_policy = policy;
311311
}
312312

313-
lldb::LanguageType GetLanguage() const { return m_language; }
313+
SourceLanguage GetLanguage() const { return m_language; }
314314

315-
void SetLanguage(lldb::LanguageType language) { m_language = language; }
315+
void SetLanguage(lldb::LanguageType language_type) {
316+
m_language = SourceLanguage(language_type);
317+
}
318+
319+
/// Set the language using a pair of language code and version as
320+
/// defined by the DWARF 6 specification.
321+
/// WARNING: These codes may change until DWARF 6 is finalized.
322+
void SetLanguage(uint16_t dwarf_lname_code, uint32_t dwarf_lversion) {
323+
m_language = SourceLanguage(dwarf_lname_code, dwarf_lversion);
324+
}
316325

317326
bool DoesCoerceToId() const { return m_coerce_to_id; }
318327

@@ -445,7 +454,7 @@ class EvaluateExpressionOptions {
445454

446455
private:
447456
ExecutionPolicy m_execution_policy = default_execution_policy;
448-
lldb::LanguageType m_language = lldb::eLanguageTypeUnknown;
457+
SourceLanguage m_language;
449458
std::string m_prefix;
450459
bool m_coerce_to_id = false;
451460
bool m_unwind_on_error = true;
@@ -1160,7 +1169,7 @@ class Target : public std::enable_shared_from_this<Target>,
11601169

11611170
UserExpression *
11621171
GetUserExpressionForLanguage(llvm::StringRef expr, llvm::StringRef prefix,
1163-
lldb::LanguageType language,
1172+
SourceLanguage language,
11641173
Expression::ResultType desired_type,
11651174
const EvaluateExpressionOptions &options,
11661175
ValueObject *ctx_obj, Status &error);

lldb/include/lldb/lldb-private-types.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,25 @@ struct RegisterSet {
9696
const uint32_t *registers;
9797
};
9898

99+
/// A type-erased pair of llvm::dwarf::SourceLanguageName and version.
100+
struct SourceLanguage {
101+
SourceLanguage() = default;
102+
SourceLanguage(lldb::LanguageType language_type);
103+
SourceLanguage(uint32_t name, uint16_t version)
104+
: name(name), version(version) {}
105+
SourceLanguage(std::optional<std::pair<uint32_t, uint16_t>> name_vers)
106+
: name(name_vers ? name_vers->first : 0),
107+
version(name_vers ? name_vers->second : 0) {}
108+
operator bool() const { return name > 0; }
109+
lldb::LanguageType AsLanguageType() const;
110+
llvm::StringRef GetDescription() const;
111+
bool IsC() const;
112+
bool IsObjC() const;
113+
bool IsCPlusPlus() const;
114+
uint16_t name = 0;
115+
uint32_t version = 0;
116+
};
117+
99118
struct OptionEnumValueElement {
100119
int64_t value;
101120
const char *string_value;

lldb/source/API/SBExpressionOptions.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,13 @@ void SBExpressionOptions::SetLanguage(lldb::LanguageType language) {
156156
m_opaque_up->SetLanguage(language);
157157
}
158158

159+
void SBExpressionOptions::SetLanguage(uint16_t dwarf_lname_code,
160+
uint32_t dwarf_lversion) {
161+
LLDB_INSTRUMENT_VA(this, dwarf_lname_code, dwarf_lversion);
162+
163+
m_opaque_up->SetLanguage(dwarf_lname_code, dwarf_lversion);
164+
}
165+
159166
void SBExpressionOptions::SetCancelCallback(
160167
lldb::ExpressionCancelCallback callback, void *baton) {
161168
LLDB_INSTRUMENT_VA(this, callback, baton);

lldb/source/API/SBFrame.cpp

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1024,10 +1024,10 @@ SBValue SBFrame::EvaluateExpression(const char *expr) {
10241024
options.SetFetchDynamicValue(fetch_dynamic_value);
10251025
options.SetUnwindOnError(true);
10261026
options.SetIgnoreBreakpoints(true);
1027-
if (target->GetLanguage() != eLanguageTypeUnknown)
1028-
options.SetLanguage(target->GetLanguage());
1029-
else
1030-
options.SetLanguage(frame->GetLanguage());
1027+
SourceLanguage lang = target->GetLanguage();
1028+
if (!lang)
1029+
lang = frame->GetLanguage();
1030+
options.SetLanguage(lang.name, lang.version);
10311031
return EvaluateExpression(expr, options);
10321032
} else {
10331033
Status error;
@@ -1053,10 +1053,12 @@ SBFrame::EvaluateExpression(const char *expr,
10531053

10541054
StackFrame *frame = exe_ctx.GetFramePtr();
10551055
Target *target = exe_ctx.GetTargetPtr();
1056-
if (target && target->GetLanguage() != eLanguageTypeUnknown)
1057-
options.SetLanguage(target->GetLanguage());
1058-
else if (frame)
1059-
options.SetLanguage(frame->GetLanguage());
1056+
SourceLanguage language;
1057+
if (target)
1058+
language = target->GetLanguage();
1059+
if (!language && frame)
1060+
language = frame->GetLanguage();
1061+
options.SetLanguage(language.name, language.version);
10601062
return EvaluateExpression(expr, options);
10611063
}
10621064

@@ -1074,10 +1076,12 @@ SBValue SBFrame::EvaluateExpression(const char *expr,
10741076
options.SetIgnoreBreakpoints(true);
10751077
StackFrame *frame = exe_ctx.GetFramePtr();
10761078
Target *target = exe_ctx.GetTargetPtr();
1077-
if (target && target->GetLanguage() != eLanguageTypeUnknown)
1078-
options.SetLanguage(target->GetLanguage());
1079-
else if (frame)
1080-
options.SetLanguage(frame->GetLanguage());
1079+
SourceLanguage language;
1080+
if (target)
1081+
language = target->GetLanguage();
1082+
if (!language && frame)
1083+
language = frame->GetLanguage();
1084+
options.SetLanguage(language.name, language.version);
10811085
return EvaluateExpression(expr, options);
10821086
}
10831087

@@ -1218,7 +1222,7 @@ lldb::LanguageType SBFrame::GuessLanguage() const {
12181222
if (stop_locker.TryLock(&process->GetRunLock())) {
12191223
frame = exe_ctx.GetFramePtr();
12201224
if (frame) {
1221-
return frame->GuessLanguage();
1225+
return frame->GuessLanguage().AsLanguageType();
12221226
}
12231227
}
12241228
}

lldb/source/Breakpoint/Watchpoint.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -460,9 +460,8 @@ void Watchpoint::SetCondition(const char *condition) {
460460
// Pass nullptr for expr_prefix (no translation-unit level definitions).
461461
Status error;
462462
m_condition_up.reset(m_target.GetUserExpressionForLanguage(
463-
condition, llvm::StringRef(), lldb::eLanguageTypeUnknown,
464-
UserExpression::eResultTypeAny, EvaluateExpressionOptions(), nullptr,
465-
error));
463+
condition, {}, {}, UserExpression::eResultTypeAny,
464+
EvaluateExpressionOptions(), nullptr, error));
466465
if (error.Fail()) {
467466
// FIXME: Log something...
468467
m_condition_up.reset();

lldb/source/Commands/CommandObjectDWIMPrint.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ void CommandObjectDWIMPrint::DoExecute(StringRef command,
9696
// Either Swift was explicitly specified, or the frame is Swift.
9797
lldb::LanguageType language = m_expr_options.language;
9898
if (language == lldb::eLanguageTypeUnknown && frame)
99-
language = frame->GuessLanguage();
99+
language = frame->GuessLanguage().AsLanguageType();
100100

101101
// Add a hint if object description was requested, but no description
102102
// function was implemented.

lldb/source/Commands/CommandObjectType.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2509,7 +2509,7 @@ class CommandObjectTypeLookup : public CommandObjectRaw {
25092509
if (!frame)
25102510
return lang_type;
25112511

2512-
lang_type = frame->GuessLanguage();
2512+
lang_type = frame->GuessLanguage().AsLanguageType();
25132513
if (lang_type != lldb::eLanguageTypeUnknown)
25142514
return lang_type;
25152515

lldb/source/Expression/LLVMUserExpression.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ char LLVMUserExpression::ID;
4242
LLVMUserExpression::LLVMUserExpression(ExecutionContextScope &exe_scope,
4343
llvm::StringRef expr,
4444
llvm::StringRef prefix,
45-
lldb::LanguageType language,
45+
SourceLanguage language,
4646
ResultType desired_type,
4747
const EvaluateExpressionOptions &options)
4848
: UserExpression(exe_scope, expr, prefix, language, desired_type, options),

lldb/source/Expression/UserExpression.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,15 +39,15 @@
3939
#include "lldb/Utility/Log.h"
4040
#include "lldb/Utility/State.h"
4141
#include "lldb/Utility/StreamString.h"
42+
#include "llvm/BinaryFormat/Dwarf.h"
4243

4344
using namespace lldb_private;
4445

4546
char UserExpression::ID;
4647

4748
UserExpression::UserExpression(ExecutionContextScope &exe_scope,
4849
llvm::StringRef expr, llvm::StringRef prefix,
49-
lldb::LanguageType language,
50-
ResultType desired_type,
50+
SourceLanguage language, ResultType desired_type,
5151
const EvaluateExpressionOptions &options)
5252
: Expression(exe_scope), m_expr_text(std::string(expr)),
5353
m_expr_prefix(std::string(prefix)), m_language(language),
@@ -176,7 +176,7 @@ UserExpression::Evaluate(ExecutionContext &exe_ctx,
176176
}
177177

178178
lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy();
179-
lldb::LanguageType language = options.GetLanguage();
179+
SourceLanguage language = options.GetLanguage();
180180
const ResultType desired_type = options.DoesCoerceToId()
181181
? UserExpression::eResultTypeId
182182
: UserExpression::eResultTypeAny;
@@ -242,7 +242,7 @@ UserExpression::Evaluate(ExecutionContext &exe_ctx,
242242
// If the language was not specified in the expression command, set it to the
243243
// language in the target's properties if specified, else default to the
244244
// langage for the frame.
245-
if (language == lldb::eLanguageTypeUnknown) {
245+
if (!language.name) {
246246
if (target->GetLanguage() != lldb::eLanguageTypeUnknown)
247247
language = target->GetLanguage();
248248
else if (StackFrame *frame = exe_ctx.GetFramePtr())
@@ -384,7 +384,8 @@ UserExpression::Evaluate(ExecutionContext &exe_ctx,
384384
} else {
385385
if (expr_result) {
386386
result_valobj_sp = expr_result->GetValueObject();
387-
result_valobj_sp->SetPreferredDisplayLanguage(language);
387+
result_valobj_sp->SetPreferredDisplayLanguage(
388+
language.AsLanguageType());
388389

389390
LLDB_LOG(log,
390391
"== [UserExpression::Evaluate] Execution completed "
@@ -426,7 +427,8 @@ UserExpression::Execute(DiagnosticManager &diagnostic_manager,
426427
Target *target = exe_ctx.GetTargetPtr();
427428
if (options.GetSuppressPersistentResult() && result_var && target) {
428429
if (auto *persistent_state =
429-
target->GetPersistentExpressionStateForLanguage(m_language))
430+
target->GetPersistentExpressionStateForLanguage(
431+
m_language.AsLanguageType()))
430432
persistent_state->RemovePersistentVariable(result_var);
431433
}
432434
return expr_result;

lldb/source/Expression/UtilityFunction.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,8 @@ FunctionCaller *UtilityFunction::MakeFunctionCaller(
8080
name.append("-caller");
8181

8282
m_caller_up.reset(process_sp->GetTarget().GetFunctionCallerForLanguage(
83-
Language(), return_type, impl_code_address, arg_value_list, name.c_str(),
84-
error));
83+
Language().AsLanguageType(), return_type, impl_code_address,
84+
arg_value_list, name.c_str(), error));
8585
if (error.Fail()) {
8686

8787
return nullptr;

0 commit comments

Comments
 (0)