[Lldb-commits] [lldb] [LLDB] Modify CreateValueObjectFrom* to take an ExecutionContext (PR #185547)
Adrian Prantl via lldb-commits
lldb-commits at lists.llvm.org
Thu Mar 12 15:49:14 PDT 2026
https://github.com/adrian-prantl updated https://github.com/llvm/llvm-project/pull/185547
>From 5fe1ef9d3b577b5db85915451a7939ece5e8bc86 Mon Sep 17 00:00:00 2001
From: Adrian Prantl <aprantl at apple.com>
Date: Mon, 9 Mar 2026 17:09:31 -0700
Subject: [PATCH] [LLDB] Modify CreateValueObjectFrom* to take an
ExecutionContext
Currently these functions take a target pointer. In Cross-language
projects this means it's down to change what typesystem the resulting
value will be in, since the implementation returns the first scratch
type system in the target, which depends on the order of images and
their implementation language.
By passing in an execution context the selected frame is used to
determine the typesystem, which is usually the expected outcome when
using DIL.
---
lldb/include/lldb/ValueObject/ValueObject.h | 33 ++++-----
lldb/source/API/SBValue.cpp | 31 ++++++--
lldb/source/ValueObject/DILEval.cpp | 21 +++---
lldb/source/ValueObject/ValueObject.cpp | 71 +++++++++----------
.../DataFormatter/FormatterSectionTest.cpp | 5 +-
5 files changed, 89 insertions(+), 72 deletions(-)
diff --git a/lldb/include/lldb/ValueObject/ValueObject.h b/lldb/include/lldb/ValueObject/ValueObject.h
index 020b4a97cfc92..392c69a4f4bda 100644
--- a/lldb/include/lldb/ValueObject/ValueObject.h
+++ b/lldb/include/lldb/ValueObject/ValueObject.h
@@ -727,32 +727,33 @@ class ValueObject {
const ExecutionContext &exe_ctx, CompilerType type);
/// Create a value object containing the given APInt value.
- static lldb::ValueObjectSP CreateValueObjectFromAPInt(lldb::TargetSP target,
- const llvm::APInt &v,
- CompilerType type,
- llvm::StringRef name);
+ static lldb::ValueObjectSP
+ CreateValueObjectFromAPInt(const ExecutionContext &exe_ctx,
+ const llvm::APInt &v, CompilerType type,
+ llvm::StringRef name);
/// Create a value object containing the given APFloat value.
static lldb::ValueObjectSP
- CreateValueObjectFromAPFloat(lldb::TargetSP target, const llvm::APFloat &v,
- CompilerType type, llvm::StringRef name);
+ CreateValueObjectFromAPFloat(const ExecutionContext &exe_ctx,
+ const llvm::APFloat &v, CompilerType type,
+ llvm::StringRef name);
/// Create a value object containing the given Scalar value.
- static lldb::ValueObjectSP CreateValueObjectFromScalar(lldb::TargetSP target,
- Scalar &s,
- CompilerType type,
- llvm::StringRef name);
+ static lldb::ValueObjectSP
+ CreateValueObjectFromScalar(const ExecutionContext &exe_ctx, Scalar &s,
+ CompilerType type, llvm::StringRef name);
/// Create a value object containing the given boolean value.
- static lldb::ValueObjectSP CreateValueObjectFromBool(lldb::TargetSP target,
- bool value,
- llvm::StringRef name);
+ static lldb::ValueObjectSP
+ CreateValueObjectFromBool(const ExecutionContext &exe_ctx,
+ lldb::TypeSystemSP typesystem, bool value,
+ llvm::StringRef name);
/// Create a nullptr value object with the specified type (must be a
/// nullptr type).
- static lldb::ValueObjectSP CreateValueObjectFromNullptr(lldb::TargetSP target,
- CompilerType type,
- llvm::StringRef name);
+ static lldb::ValueObjectSP
+ CreateValueObjectFromNullptr(const ExecutionContext &exe_ctx,
+ CompilerType type, llvm::StringRef name);
lldb::ValueObjectSP Persist();
diff --git a/lldb/source/API/SBValue.cpp b/lldb/source/API/SBValue.cpp
index adc03785602e1..6b7a2edc616f0 100644
--- a/lldb/source/API/SBValue.cpp
+++ b/lldb/source/API/SBValue.cpp
@@ -486,15 +486,32 @@ lldb::SBValue SBValue::CreateBoolValue(const char *name, bool value) {
LLDB_INSTRUMENT_VA(this, name);
lldb::SBValue sb_value;
- lldb::ValueObjectSP new_value_sp;
ValueLocker locker;
lldb::ValueObjectSP value_sp(GetSP(locker));
- lldb::TargetSP target_sp = m_opaque_sp->GetTargetSP();
- if (value_sp && target_sp) {
- new_value_sp =
- ValueObject::CreateValueObjectFromBool(target_sp, value, name);
- }
- sb_value.SetSP(new_value_sp);
+
+ auto get_new_value = [&]() -> lldb::ValueObjectSP {
+ if (!value_sp)
+ return {};
+
+ lldb::TargetSP target_sp = value_sp->GetTargetSP();
+ if (!target_sp)
+ return {};
+
+ lldb::LanguageType language = lldb::eLanguageTypeC;
+ ExecutionContext exe_ctx(value_sp->GetExecutionContextRef());
+ if (StackFrame *frame = exe_ctx.GetFramePtr())
+ language = frame->GuessLanguage().AsLanguageType();
+ auto type_system_or_err =
+ target_sp->GetScratchTypeSystemForLanguage(language);
+ if (!type_system_or_err) {
+ LLDB_LOG_ERROR(GetLog(LLDBLog::Types), type_system_or_err.takeError(),
+ "cannot get a type system: {0}");
+ return {};
+ }
+ return ValueObject::CreateValueObjectFromBool(exe_ctx, *type_system_or_err,
+ value, name);
+ };
+ sb_value.SetSP(get_new_value());
return sb_value;
}
diff --git a/lldb/source/ValueObject/DILEval.cpp b/lldb/source/ValueObject/DILEval.cpp
index 1b841d39a034e..ec9ea8b9618fc 100644
--- a/lldb/source/ValueObject/DILEval.cpp
+++ b/lldb/source/ValueObject/DILEval.cpp
@@ -105,8 +105,8 @@ Interpreter::UnaryConversion(lldb::ValueObjectSP valobj, uint32_t location) {
bool resolved = valobj->ResolveValue(scalar);
if (!resolved)
return llvm::createStringError("invalid scalar value");
- return ValueObject::CreateValueObjectFromScalar(m_target, scalar, in_type,
- "result");
+ return ValueObject::CreateValueObjectFromScalar(m_exe_ctx_scope, scalar,
+ in_type, "result");
}
}
@@ -507,7 +507,7 @@ Interpreter::Visit(const UnaryOpNode &node) {
bool negated = scalar.UnaryNegate();
if (negated)
return ValueObject::CreateValueObjectFromScalar(
- m_target, scalar, operand->GetCompilerType(), "result");
+ m_exe_ctx_scope, scalar, operand->GetCompilerType(), "result");
break;
}
case UnaryOpKind::Plus: {
@@ -551,7 +551,7 @@ Interpreter::EvaluateScalarOp(BinaryOpKind kind, lldb::ValueObjectSP lhs,
location);
auto value_object = [this, result_type](Scalar scalar) {
- return ValueObject::CreateValueObjectFromScalar(m_target, scalar,
+ return ValueObject::CreateValueObjectFromScalar(m_exe_ctx_scope, scalar,
result_type, "result");
};
@@ -1010,8 +1010,8 @@ Interpreter::Visit(const IntegerLiteralNode &node) {
if (!type_bitsize)
return type_bitsize.takeError();
scalar.TruncOrExtendTo(*type_bitsize, false);
- return ValueObject::CreateValueObjectFromScalar(m_target, scalar, *type,
- "result");
+ return ValueObject::CreateValueObjectFromScalar(m_exe_ctx_scope, scalar,
+ *type, "result");
}
llvm::Expected<lldb::ValueObjectSP>
@@ -1032,14 +1032,19 @@ Interpreter::Visit(const FloatLiteralNode &node) {
m_expr, "unable to create a const literal", node.GetLocation());
Scalar scalar = node.GetValue();
- return ValueObject::CreateValueObjectFromScalar(m_target, scalar, type,
+ return ValueObject::CreateValueObjectFromScalar(m_exe_ctx_scope, scalar, type,
"result");
}
llvm::Expected<lldb::ValueObjectSP>
Interpreter::Visit(const BooleanLiteralNode &node) {
bool value = node.GetValue();
- return ValueObject::CreateValueObjectFromBool(m_target, value, "result");
+ llvm::Expected<lldb::TypeSystemSP> type_system =
+ GetTypeSystemFromCU(m_exe_ctx_scope);
+ if (!type_system)
+ return type_system.takeError();
+ return ValueObject::CreateValueObjectFromBool(m_exe_ctx_scope, *type_system,
+ value, "result");
}
llvm::Expected<CastKind>
diff --git a/lldb/source/ValueObject/ValueObject.cpp b/lldb/source/ValueObject/ValueObject.cpp
index da9c84a4fa221..d44ee79d59d5e 100644
--- a/lldb/source/ValueObject/ValueObject.cpp
+++ b/lldb/source/ValueObject/ValueObject.cpp
@@ -3188,12 +3188,14 @@ lldb::ValueObjectSP ValueObject::CastToBasicType(CompilerType type) {
if (type.IsBoolean()) {
if (!is_scalar || is_integer)
return ValueObject::CreateValueObjectFromBool(
- target, GetValueAsUnsigned(0) != 0, "result");
+ exe_ctx, type.GetTypeSystem().GetSharedPointer(),
+ GetValueAsUnsigned(0) != 0, "result");
else if (is_scalar && is_float) {
auto float_value_or_err = GetValueAsAPFloat();
if (float_value_or_err)
return ValueObject::CreateValueObjectFromBool(
- target, !float_value_or_err->isZero(), "result");
+ exe_ctx, type.GetTypeSystem().GetSharedPointer(),
+ !float_value_or_err->isZero(), "result");
else
return ValueObjectConstResult::Create(
exe_ctx.GetBestExecutionContextScope(),
@@ -3211,7 +3213,7 @@ lldb::ValueObjectSP ValueObject::CastToBasicType(CompilerType type) {
// size.
llvm::APSInt ext =
int_value_or_err->extOrTrunc(type_byte_size * CHAR_BIT);
- return ValueObject::CreateValueObjectFromAPInt(target, ext, type,
+ return ValueObject::CreateValueObjectFromAPInt(exe_ctx, ext, type,
"result");
} else
return ValueObjectConstResult::Create(
@@ -3236,7 +3238,7 @@ lldb::ValueObjectSP ValueObject::CastToBasicType(CompilerType type) {
Status::FromErrorStringWithFormat(
"invalid type cast detected: %s",
llvm::toString(float_value_or_err.takeError()).c_str()));
- return ValueObject::CreateValueObjectFromAPInt(target, integer, type,
+ return ValueObject::CreateValueObjectFromAPInt(exe_ctx, integer, type,
"result");
}
}
@@ -3251,7 +3253,7 @@ lldb::ValueObjectSP ValueObject::CastToBasicType(CompilerType type) {
Scalar scalar_int(ext);
llvm::APFloat f =
scalar_int.CreateAPFloatFromAPSInt(type.GetBasicTypeEnumeration());
- return ValueObject::CreateValueObjectFromAPFloat(target, f, type,
+ return ValueObject::CreateValueObjectFromAPFloat(exe_ctx, f, type,
"result");
} else {
return ValueObjectConstResult::Create(
@@ -3267,7 +3269,7 @@ lldb::ValueObjectSP ValueObject::CastToBasicType(CompilerType type) {
Scalar scalar_int(*int_value_or_err);
llvm::APFloat f = scalar_int.CreateAPFloatFromAPSInt(
type.GetBasicTypeEnumeration());
- return ValueObject::CreateValueObjectFromAPFloat(target, f, type,
+ return ValueObject::CreateValueObjectFromAPFloat(exe_ctx, f, type,
"result");
} else {
return ValueObjectConstResult::Create(
@@ -3283,7 +3285,7 @@ lldb::ValueObjectSP ValueObject::CastToBasicType(CompilerType type) {
Scalar scalar_float(*float_value_or_err);
llvm::APFloat f = scalar_float.CreateAPFloatFromAPFloat(
type.GetBasicTypeEnumeration());
- return ValueObject::CreateValueObjectFromAPFloat(target, f, type,
+ return ValueObject::CreateValueObjectFromAPFloat(exe_ctx, f, type,
"result");
} else {
return ValueObjectConstResult::Create(
@@ -3339,7 +3341,7 @@ lldb::ValueObjectSP ValueObject::CastToEnumType(CompilerType type) {
Status::FromErrorStringWithFormat(
"invalid type cast detected: %s",
llvm::toString(value_or_err.takeError()).c_str()));
- return ValueObject::CreateValueObjectFromAPInt(target, integer, type,
+ return ValueObject::CreateValueObjectFromAPInt(exe_ctx, integer, type,
"result");
} else
return ValueObjectConstResult::Create(
@@ -3350,7 +3352,7 @@ lldb::ValueObjectSP ValueObject::CastToEnumType(CompilerType type) {
auto value_or_err = GetValueAsAPSInt();
if (value_or_err) {
llvm::APSInt ext = value_or_err->extOrTrunc(byte_size * CHAR_BIT);
- return ValueObject::CreateValueObjectFromAPInt(target, ext, type,
+ return ValueObject::CreateValueObjectFromAPInt(exe_ctx, ext, type,
"result");
} else
return ValueObjectConstResult::Create(
@@ -3591,13 +3593,13 @@ lldb::ValueObjectSP ValueObject::CreateValueObjectFromData(
}
lldb::ValueObjectSP
-ValueObject::CreateValueObjectFromAPInt(lldb::TargetSP target,
+ValueObject::CreateValueObjectFromAPInt(const ExecutionContext &exe_ctx,
const llvm::APInt &v, CompilerType type,
llvm::StringRef name) {
- ExecutionContext exe_ctx(target.get(), false);
- uint64_t byte_size = 0;
- if (auto temp = llvm::expectedToOptional(type.GetByteSize(target.get())))
- byte_size = temp.value();
+ uint64_t byte_size =
+ llvm::expectedToOptional(
+ type.GetByteSize(exe_ctx.GetBestExecutionContextScope()))
+ .value_or(0);
lldb::DataExtractorSP data_sp = std::make_shared<DataExtractor>(
reinterpret_cast<const void *>(v.getRawData()), byte_size,
exe_ctx.GetByteOrder(), exe_ctx.GetAddressByteSize());
@@ -3605,52 +3607,43 @@ ValueObject::CreateValueObjectFromAPInt(lldb::TargetSP target,
}
lldb::ValueObjectSP ValueObject::CreateValueObjectFromAPFloat(
- lldb::TargetSP target, const llvm::APFloat &v, CompilerType type,
+ const ExecutionContext &exe_ctx, const llvm::APFloat &v, CompilerType type,
llvm::StringRef name) {
- return CreateValueObjectFromAPInt(target, v.bitcastToAPInt(), type, name);
+ return CreateValueObjectFromAPInt(exe_ctx, v.bitcastToAPInt(), type, name);
}
-lldb::ValueObjectSP ValueObject::CreateValueObjectFromScalar(
- lldb::TargetSP target, Scalar &s, CompilerType type, llvm::StringRef name) {
- ExecutionContext exe_ctx(target.get(), false);
+lldb::ValueObjectSP
+ValueObject::CreateValueObjectFromScalar(const ExecutionContext &exe_ctx,
+ Scalar &s, CompilerType type,
+ llvm::StringRef name) {
return ValueObjectConstResult::Create(exe_ctx.GetBestExecutionContextScope(),
type, s, ConstString(name));
}
lldb::ValueObjectSP
-ValueObject::CreateValueObjectFromBool(lldb::TargetSP target, bool value,
+ValueObject::CreateValueObjectFromBool(const ExecutionContext &exe_ctx,
+ TypeSystemSP typesystem_sp, bool value,
llvm::StringRef name) {
- CompilerType target_type;
- if (target) {
- for (auto type_system_sp : target->GetScratchTypeSystems())
- if (auto compiler_type =
- type_system_sp->GetBasicTypeFromAST(lldb::eBasicTypeBool)) {
- target_type = compiler_type;
- break;
- }
- }
- ExecutionContext exe_ctx(target.get(), false);
- uint64_t byte_size = 0;
- if (auto temp =
- llvm::expectedToOptional(target_type.GetByteSize(target.get())))
- byte_size = temp.value();
+ CompilerType type = typesystem_sp->GetBasicTypeFromAST(lldb::eBasicTypeBool);
+ ExecutionContextScope *exe_scope = exe_ctx.GetBestExecutionContextScope();
+ uint64_t byte_size =
+ llvm::expectedToOptional(type.GetByteSize(exe_scope)).value_or(0);
lldb::DataExtractorSP data_sp = std::make_shared<DataExtractor>(
reinterpret_cast<const void *>(&value), byte_size, exe_ctx.GetByteOrder(),
exe_ctx.GetAddressByteSize());
- return ValueObject::CreateValueObjectFromData(name, *data_sp, exe_ctx,
- target_type);
+ return ValueObject::CreateValueObjectFromData(name, *data_sp, exe_ctx, type);
}
lldb::ValueObjectSP ValueObject::CreateValueObjectFromNullptr(
- lldb::TargetSP target, CompilerType type, llvm::StringRef name) {
+ const ExecutionContext &exe_ctx, CompilerType type, llvm::StringRef name) {
if (!type.IsNullPtrType()) {
lldb::ValueObjectSP ret_val;
return ret_val;
}
uintptr_t zero = 0;
- ExecutionContext exe_ctx(target.get(), false);
uint64_t byte_size = 0;
- if (auto temp = llvm::expectedToOptional(type.GetByteSize(target.get())))
+ if (auto temp = llvm::expectedToOptional(
+ type.GetByteSize(exe_ctx.GetBestExecutionContextScope())))
byte_size = temp.value();
lldb::DataExtractorSP data_sp = std::make_shared<DataExtractor>(
reinterpret_cast<const void *>(zero), byte_size, exe_ctx.GetByteOrder(),
diff --git a/lldb/unittests/DataFormatter/FormatterSectionTest.cpp b/lldb/unittests/DataFormatter/FormatterSectionTest.cpp
index 344b299023d03..7da7a34d84ef9 100644
--- a/lldb/unittests/DataFormatter/FormatterSectionTest.cpp
+++ b/lldb/unittests/DataFormatter/FormatterSectionTest.cpp
@@ -131,8 +131,9 @@ TEST_F(FormatterSectionTest, LoadFormattersForModule) {
ASSERT_TRUE(rect_summary_sp != nullptr);
std::string dest;
- ValueObjectSP valobj = ValueObjectConstResult::CreateValueObjectFromBool(
- m_target_sp, false, "mock");
+ Scalar val;
+ ValueObjectSP valobj = ValueObjectConstResult::CreateValueObjectFromScalar(
+ ExecutionContext(m_target_sp.get(), false), val, CompilerType(), "mock");
ASSERT_TRUE(
point_summary_sp->FormatObject(valobj.get(), dest, TypeSummaryOptions()));
ASSERT_EQ(dest, "AAAAA");
More information about the lldb-commits
mailing list