Skip to content

Commit

Permalink
Add a new SBExpressionOptions::SetLanguage() API (NFCI) (#89981)
Browse files Browse the repository at this point in the history
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.

Depends on #89980
  • Loading branch information
adrian-prantl committed Apr 29, 2024
1 parent 8ba880b commit 975eca0
Show file tree
Hide file tree
Showing 35 changed files with 306 additions and 123 deletions.
5 changes: 5 additions & 0 deletions lldb/include/lldb/API/SBExpressionOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#define LLDB_API_SBEXPRESSIONOPTIONS_H

#include "lldb/API/SBDefines.h"
#include "lldb/API/SBLanguages.h"

This comment has been minimized.

Copy link
@nico

nico Apr 30, 2024

Contributor

Also, since this is a generated file, maybe it makes sense to forward-declare the enum in public headers and include the header only in source files so clients don't have to have to have the generated header at hand?

(Might even make sense if the generation part goes away.)


#include <vector>

Expand Down Expand Up @@ -67,6 +68,10 @@ class LLDB_API SBExpressionOptions {
void SetTrapExceptions(bool trap_exceptions = true);

void SetLanguage(lldb::LanguageType language);
/// Set the language using a pair of language code and version as
/// defined by the DWARF 6 specification.
/// WARNING: These codes may change until DWARF 6 is finalized.
void SetLanguage(SBSourceLanguageName name, uint32_t version);

#ifndef SWIG
void SetCancelCallback(lldb::ExpressionCancelCallback callback, void *baton);
Expand Down
7 changes: 2 additions & 5 deletions lldb/include/lldb/Expression/Expression.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,8 @@ class Expression {
/// expression. Text() should contain the definition of this function.
virtual const char *FunctionName() = 0;

/// Return the language that should be used when parsing. To use the
/// default, return eLanguageTypeUnknown.
virtual lldb::LanguageType Language() const {
return lldb::eLanguageTypeUnknown;
}
/// Return the language that should be used when parsing.
virtual SourceLanguage Language() const { return {}; }

/// Return the Materializer that the parser should use when registering
/// external values.
Expand Down
2 changes: 1 addition & 1 deletion lldb/include/lldb/Expression/LLVMUserExpression.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class LLVMUserExpression : public UserExpression {
};

LLVMUserExpression(ExecutionContextScope &exe_scope, llvm::StringRef expr,
llvm::StringRef prefix, lldb::LanguageType language,
llvm::StringRef prefix, SourceLanguage language,
ResultType desired_type,
const EvaluateExpressionOptions &options);
~LLVMUserExpression() override;
Expand Down
33 changes: 18 additions & 15 deletions lldb/include/lldb/Expression/UserExpression.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ class UserExpression : public Expression {
/// If not eResultTypeAny, the type to use for the expression
/// result.
UserExpression(ExecutionContextScope &exe_scope, llvm::StringRef expr,
llvm::StringRef prefix, lldb::LanguageType language,
llvm::StringRef prefix, SourceLanguage language,
ResultType desired_type,
const EvaluateExpressionOptions &options);

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

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

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

} // namespace lldb_private
Expand Down
10 changes: 4 additions & 6 deletions lldb/include/lldb/Symbol/TypeSystem.h
Original file line number Diff line number Diff line change
Expand Up @@ -483,12 +483,10 @@ class TypeSystem : public PluginInterface,
return IsPointerOrReferenceType(type, nullptr);
}

virtual UserExpression *
GetUserExpression(llvm::StringRef expr, llvm::StringRef prefix,
lldb::LanguageType language,
Expression::ResultType desired_type,
const EvaluateExpressionOptions &options,
ValueObject *ctx_obj) {
virtual UserExpression *GetUserExpression(
llvm::StringRef expr, llvm::StringRef prefix, SourceLanguage language,
Expression::ResultType desired_type,
const EvaluateExpressionOptions &options, ValueObject *ctx_obj) {
return nullptr;
}

Expand Down
12 changes: 6 additions & 6 deletions lldb/include/lldb/Target/StackFrame.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@

//===-- StackFrame.h --------------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
Expand Down Expand Up @@ -446,13 +447,12 @@ class StackFrame : public ExecutionContextScope,
/// Query this frame to determine what the default language should be when
/// parsing expressions given the execution context.
///
/// \return
/// The language of the frame if known, else lldb::eLanguageTypeUnknown.
lldb::LanguageType GetLanguage();
/// \return The language of the frame if known.
SourceLanguage GetLanguage();

// similar to GetLanguage(), but is allowed to take a potentially incorrect
// guess if exact information is not available
lldb::LanguageType GuessLanguage();
/// Similar to GetLanguage(), but is allowed to take a potentially incorrect
/// guess if exact information is not available.
SourceLanguage GuessLanguage();

/// Attempt to econstruct the ValueObject for a given raw address touched by
/// the current instruction. The ExpressionPath should indicate how to get
Expand Down
19 changes: 14 additions & 5 deletions lldb/include/lldb/Target/Target.h
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ class TargetProperties : public Properties {

bool GetBreakpointsConsultPlatformAvoidList();

lldb::LanguageType GetLanguage() const;
SourceLanguage GetLanguage() const;

llvm::StringRef GetExpressionPrefixContents();

Expand Down Expand Up @@ -310,9 +310,18 @@ class EvaluateExpressionOptions {
m_execution_policy = policy;
}

lldb::LanguageType GetLanguage() const { return m_language; }
SourceLanguage GetLanguage() const { return m_language; }

void SetLanguage(lldb::LanguageType language) { m_language = language; }
void SetLanguage(lldb::LanguageType language_type) {
m_language = SourceLanguage(language_type);
}

/// Set the language using a pair of language code and version as
/// defined by the DWARF 6 specification.
/// WARNING: These codes may change until DWARF 6 is finalized.
void SetLanguage(uint16_t name, uint32_t version) {
m_language = SourceLanguage(name, version);
}

bool DoesCoerceToId() const { return m_coerce_to_id; }

Expand Down Expand Up @@ -445,7 +454,7 @@ class EvaluateExpressionOptions {

private:
ExecutionPolicy m_execution_policy = default_execution_policy;
lldb::LanguageType m_language = lldb::eLanguageTypeUnknown;
SourceLanguage m_language;
std::string m_prefix;
bool m_coerce_to_id = false;
bool m_unwind_on_error = true;
Expand Down Expand Up @@ -1160,7 +1169,7 @@ class Target : public std::enable_shared_from_this<Target>,

UserExpression *
GetUserExpressionForLanguage(llvm::StringRef expr, llvm::StringRef prefix,
lldb::LanguageType language,
SourceLanguage language,
Expression::ResultType desired_type,
const EvaluateExpressionOptions &options,
ValueObject *ctx_obj, Status &error);
Expand Down
19 changes: 19 additions & 0 deletions lldb/include/lldb/lldb-private-types.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,25 @@ struct RegisterSet {
const uint32_t *registers;
};

/// A type-erased pair of llvm::dwarf::SourceLanguageName and version.
struct SourceLanguage {
SourceLanguage() = default;
SourceLanguage(lldb::LanguageType language_type);
SourceLanguage(uint16_t name, uint32_t version)
: name(name), version(version) {}
SourceLanguage(std::optional<std::pair<uint16_t, uint32_t>> name_vers)
: name(name_vers ? name_vers->first : 0),
version(name_vers ? name_vers->second : 0) {}
operator bool() const { return name > 0; }
lldb::LanguageType AsLanguageType() const;
llvm::StringRef GetDescription() const;
bool IsC() const;
bool IsObjC() const;
bool IsCPlusPlus() const;
uint16_t name = 0;
uint32_t version = 0;
};

struct OptionEnumValueElement {
int64_t value;
const char *string_value;
Expand Down
1 change: 1 addition & 0 deletions lldb/packages/Python/lldbsuite/test/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@

# LLDB library directory.
lldb_libs_dir = None
lldb_obj_root = None

libcxx_include_dir = None
libcxx_include_target_dir = None
Expand Down
3 changes: 3 additions & 0 deletions lldb/packages/Python/lldbsuite/test/dotest.py
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,7 @@ def parseOptionsAndInitTestdirs():
configuration.lldb_module_cache_dir = os.path.join(
configuration.test_build_dir, "module-cache-lldb"
)

if args.clang_module_cache_dir:
configuration.clang_module_cache_dir = args.clang_module_cache_dir
else:
Expand All @@ -432,6 +433,8 @@ def parseOptionsAndInitTestdirs():

if args.lldb_libs_dir:
configuration.lldb_libs_dir = args.lldb_libs_dir
if args.lldb_obj_root:
configuration.lldb_obj_root = args.lldb_obj_root

if args.enabled_plugins:
configuration.enabled_plugins = args.enabled_plugins
Expand Down
8 changes: 7 additions & 1 deletion lldb/packages/Python/lldbsuite/test/dotest_args.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,11 +236,17 @@ def create_parser():
metavar="The clang module cache directory used by Clang",
help="The clang module cache directory used in the Make files by Clang while building tests. Defaults to <test build directory>/module-cache-clang.",
)
group.add_argument(
"--lldb-obj-root",
dest="lldb_obj_root",
metavar="path",
help="The path to the LLDB object files.",
)
group.add_argument(
"--lldb-libs-dir",
dest="lldb_libs_dir",
metavar="path",
help="The path to LLDB library directory (containing liblldb)",
help="The path to LLDB library directory (containing liblldb).",
)
group.add_argument(
"--enable-plugin",
Expand Down
25 changes: 18 additions & 7 deletions lldb/packages/Python/lldbsuite/test/lldbtest.py
Original file line number Diff line number Diff line change
Expand Up @@ -1473,23 +1473,25 @@ def buildDriver(self, sources, exe_name):
d = {
"CXX_SOURCES": sources,
"EXE": exe_name,
"CFLAGS_EXTRAS": "%s %s -I%s"
"CFLAGS_EXTRAS": "%s %s -I%s -I%s"
% (
stdflag,
stdlibflag,
os.path.join(os.environ["LLDB_SRC"], "include"),
os.path.join(configuration.lldb_obj_root, "include"),
),
"LD_EXTRAS": "-L%s -lliblldb" % lib_dir,
}
else:
d = {
"CXX_SOURCES": sources,
"EXE": exe_name,
"CFLAGS_EXTRAS": "%s %s -I%s"
"CFLAGS_EXTRAS": "%s %s -I%s -I%s"
% (
stdflag,
stdlibflag,
os.path.join(os.environ["LLDB_SRC"], "include"),
os.path.join(configuration.lldb_obj_root, "include"),
),
"LD_EXTRAS": "-L%s -llldb -Wl,-rpath,%s" % (lib_dir, lib_dir),
}
Expand All @@ -1508,7 +1510,8 @@ def buildLibrary(self, sources, lib_name):
d = {
"DYLIB_CXX_SOURCES": sources,
"DYLIB_NAME": lib_name,
"CFLAGS_EXTRAS": "%s -stdlib=libc++" % stdflag,
"CFLAGS_EXTRAS": "%s -stdlib=libc++ -I%s"
% (stdflag, os.path.join(configuration.lldb_obj_root, "include")),
"FRAMEWORK_INCLUDES": "-F%s" % self.framework_dir,
"LD_EXTRAS": "%s -Wl,-rpath,%s -dynamiclib"
% (self.lib_lldb, self.framework_dir),
Expand All @@ -1517,16 +1520,24 @@ def buildLibrary(self, sources, lib_name):
d = {
"DYLIB_CXX_SOURCES": sources,
"DYLIB_NAME": lib_name,
"CFLAGS_EXTRAS": "%s -I%s "
% (stdflag, os.path.join(os.environ["LLDB_SRC"], "include")),
"CFLAGS_EXTRAS": "%s -I%s -I%s"
% (
stdflag,
os.path.join(os.environ["LLDB_SRC"], "include"),
os.path.join(configuration.lldb_obj_root, "include"),
),
"LD_EXTRAS": "-shared -l%s\liblldb.lib" % lib_dir,
}
else:
d = {
"DYLIB_CXX_SOURCES": sources,
"DYLIB_NAME": lib_name,
"CFLAGS_EXTRAS": "%s -I%s -fPIC"
% (stdflag, os.path.join(os.environ["LLDB_SRC"], "include")),
"CFLAGS_EXTRAS": "%s -I%s -I%s -fPIC"
% (
stdflag,
os.path.join(os.environ["LLDB_SRC"], "include"),
os.path.join(configuration.lldb_obj_root, "include"),
),
"LD_EXTRAS": "-shared -L%s -llldb -Wl,-rpath,%s" % (lib_dir, lib_dir),
}
if self.TraceOn():
Expand Down
7 changes: 7 additions & 0 deletions lldb/source/API/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ if(LLDB_ENABLE_LUA)
set(lldb_lua_wrapper ${lua_bindings_dir}/LLDBWrapLua.cpp)
endif()

lldb_tablegen(../../include/lldb/API/SBLanguages.h -gen-lldb-sbapi-dwarf-enum
SOURCE ${LLVM_MAIN_INCLUDE_DIR}/llvm/BinaryFormat/Dwarf.def
TARGET lldb-sbapi-dwarf-enums)

add_lldb_library(liblldb SHARED ${option_framework}
SBAddress.cpp
SBAttachInfo.cpp
Expand Down Expand Up @@ -100,6 +104,9 @@ add_lldb_library(liblldb SHARED ${option_framework}
${lldb_python_wrapper}
${lldb_lua_wrapper}

DEPENDS
lldb-sbapi-dwarf-enums

LINK_LIBS
lldbBreakpoint
lldbCore
Expand Down
7 changes: 7 additions & 0 deletions lldb/source/API/SBExpressionOptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,13 @@ void SBExpressionOptions::SetLanguage(lldb::LanguageType language) {
m_opaque_up->SetLanguage(language);
}

void SBExpressionOptions::SetLanguage(SBSourceLanguageName name,
uint32_t version) {
LLDB_INSTRUMENT_VA(this, name, version);

m_opaque_up->SetLanguage(name, version);
}

void SBExpressionOptions::SetCancelCallback(
lldb::ExpressionCancelCallback callback, void *baton) {
LLDB_INSTRUMENT_VA(this, callback, baton);
Expand Down
Loading

0 comments on commit 975eca0

Please sign in to comment.