summaryrefslogtreecommitdiff
path: root/lldb/source/Core/ValueObject.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Core/ValueObject.cpp')
-rw-r--r--lldb/source/Core/ValueObject.cpp640
1 files changed, 617 insertions, 23 deletions
diff --git a/lldb/source/Core/ValueObject.cpp b/lldb/source/Core/ValueObject.cpp
index f32cb82faa00..8f72efc2299b 100644
--- a/lldb/source/Core/ValueObject.cpp
+++ b/lldb/source/Core/ValueObject.cpp
@@ -989,41 +989,46 @@ ValueObject::ReadPointedString(lldb::WritableDataBufferSP &buffer_sp,
return {total_bytes_read, was_capped};
}
-const char *ValueObject::GetObjectDescription() {
+llvm::Expected<std::string> ValueObject::GetObjectDescription() {
if (!UpdateValueIfNeeded(true))
- return nullptr;
+ return llvm::createStringError("could not update value");
// Return cached value.
if (!m_object_desc_str.empty())
- return m_object_desc_str.c_str();
+ return m_object_desc_str;
ExecutionContext exe_ctx(GetExecutionContextRef());
Process *process = exe_ctx.GetProcessPtr();
if (!process)
- return nullptr;
+ return llvm::createStringError("no process");
// Returns the object description produced by one language runtime.
- auto get_object_description = [&](LanguageType language) -> const char * {
+ auto get_object_description =
+ [&](LanguageType language) -> llvm::Expected<std::string> {
if (LanguageRuntime *runtime = process->GetLanguageRuntime(language)) {
StreamString s;
- if (runtime->GetObjectDescription(s, *this)) {
- m_object_desc_str.append(std::string(s.GetString()));
- return m_object_desc_str.c_str();
- }
+ if (llvm::Error error = runtime->GetObjectDescription(s, *this))
+ return error;
+ m_object_desc_str = s.GetString();
+ return m_object_desc_str;
}
- return nullptr;
+ return llvm::createStringError("no native language runtime");
};
// Try the native language runtime first.
LanguageType native_language = GetObjectRuntimeLanguage();
- if (const char *desc = get_object_description(native_language))
+ llvm::Expected<std::string> desc = get_object_description(native_language);
+ if (desc)
return desc;
// Try the Objective-C language runtime. This fallback is necessary
// for Objective-C++ and mixed Objective-C / C++ programs.
- if (Language::LanguageIsCFamily(native_language))
+ if (Language::LanguageIsCFamily(native_language)) {
+ // We're going to try again, so let's drop the first error.
+ llvm::consumeError(desc.takeError());
return get_object_description(eLanguageTypeObjC);
- return nullptr;
+ }
+ return desc;
}
bool ValueObject::GetValueAsCString(const lldb_private::TypeFormatImpl &format,
@@ -1116,6 +1121,153 @@ int64_t ValueObject::GetValueAsSigned(int64_t fail_value, bool *success) {
return fail_value;
}
+llvm::Expected<llvm::APSInt> ValueObject::GetValueAsAPSInt() {
+ // Make sure the type can be converted to an APSInt.
+ if (!GetCompilerType().IsInteger() &&
+ !GetCompilerType().IsScopedEnumerationType() &&
+ !GetCompilerType().IsEnumerationType() &&
+ !GetCompilerType().IsPointerType() &&
+ !GetCompilerType().IsNullPtrType() &&
+ !GetCompilerType().IsReferenceType() && !GetCompilerType().IsBoolean())
+ return llvm::make_error<llvm::StringError>(
+ "type cannot be converted to APSInt", llvm::inconvertibleErrorCode());
+
+ if (CanProvideValue()) {
+ Scalar scalar;
+ if (ResolveValue(scalar))
+ return scalar.GetAPSInt();
+ }
+
+ return llvm::make_error<llvm::StringError>(
+ "error occurred; unable to convert to APSInt",
+ llvm::inconvertibleErrorCode());
+}
+
+llvm::Expected<llvm::APFloat> ValueObject::GetValueAsAPFloat() {
+ if (!GetCompilerType().IsFloat())
+ return llvm::make_error<llvm::StringError>(
+ "type cannot be converted to APFloat", llvm::inconvertibleErrorCode());
+
+ if (CanProvideValue()) {
+ Scalar scalar;
+ if (ResolveValue(scalar))
+ return scalar.GetAPFloat();
+ }
+
+ return llvm::make_error<llvm::StringError>(
+ "error occurred; unable to convert to APFloat",
+ llvm::inconvertibleErrorCode());
+}
+
+llvm::Expected<bool> ValueObject::GetValueAsBool() {
+ CompilerType val_type = GetCompilerType();
+ if (val_type.IsInteger() || val_type.IsUnscopedEnumerationType() ||
+ val_type.IsPointerType()) {
+ auto value_or_err = GetValueAsAPSInt();
+ if (value_or_err)
+ return value_or_err->getBoolValue();
+ }
+ if (val_type.IsFloat()) {
+ auto value_or_err = GetValueAsAPFloat();
+ if (value_or_err)
+ return value_or_err->isNonZero();
+ }
+ if (val_type.IsArrayType())
+ return GetAddressOf() != 0;
+
+ return llvm::make_error<llvm::StringError>("type cannot be converted to bool",
+ llvm::inconvertibleErrorCode());
+}
+
+void ValueObject::SetValueFromInteger(const llvm::APInt &value, Status &error) {
+ // Verify the current object is an integer object
+ CompilerType val_type = GetCompilerType();
+ if (!val_type.IsInteger() && !val_type.IsUnscopedEnumerationType() &&
+ !val_type.IsFloat() && !val_type.IsPointerType() &&
+ !val_type.IsScalarType()) {
+ error.SetErrorString("current value object is not an integer objet");
+ return;
+ }
+
+ // Verify the current object is not actually associated with any program
+ // variable.
+ if (GetVariable()) {
+ error.SetErrorString("current value object is not a temporary object");
+ return;
+ }
+
+ // Verify the proposed new value is the right size.
+ lldb::TargetSP target = GetTargetSP();
+ uint64_t byte_size = 0;
+ if (auto temp = GetCompilerType().GetByteSize(target.get()))
+ byte_size = temp.value();
+ if (value.getBitWidth() != byte_size * CHAR_BIT) {
+ error.SetErrorString(
+ "illegal argument: new value should be of the same size");
+ return;
+ }
+
+ lldb::DataExtractorSP data_sp;
+ data_sp->SetData(value.getRawData(), byte_size,
+ target->GetArchitecture().GetByteOrder());
+ data_sp->SetAddressByteSize(
+ static_cast<uint8_t>(target->GetArchitecture().GetAddressByteSize()));
+ SetData(*data_sp, error);
+}
+
+void ValueObject::SetValueFromInteger(lldb::ValueObjectSP new_val_sp,
+ Status &error) {
+ // Verify the current object is an integer object
+ CompilerType val_type = GetCompilerType();
+ if (!val_type.IsInteger() && !val_type.IsUnscopedEnumerationType() &&
+ !val_type.IsFloat() && !val_type.IsPointerType() &&
+ !val_type.IsScalarType()) {
+ error.SetErrorString("current value object is not an integer objet");
+ return;
+ }
+
+ // Verify the current object is not actually associated with any program
+ // variable.
+ if (GetVariable()) {
+ error.SetErrorString("current value object is not a temporary object");
+ return;
+ }
+
+ // Verify the proposed new value is the right type.
+ CompilerType new_val_type = new_val_sp->GetCompilerType();
+ if (!new_val_type.IsInteger() && !new_val_type.IsFloat() &&
+ !new_val_type.IsPointerType()) {
+ error.SetErrorString(
+ "illegal argument: new value should be of the same size");
+ return;
+ }
+
+ if (new_val_type.IsInteger()) {
+ auto value_or_err = new_val_sp->GetValueAsAPSInt();
+ if (value_or_err)
+ SetValueFromInteger(*value_or_err, error);
+ else
+ error.SetErrorString("error getting APSInt from new_val_sp");
+ } else if (new_val_type.IsFloat()) {
+ auto value_or_err = new_val_sp->GetValueAsAPFloat();
+ if (value_or_err)
+ SetValueFromInteger(value_or_err->bitcastToAPInt(), error);
+ else
+ error.SetErrorString("error getting APFloat from new_val_sp");
+ } else if (new_val_type.IsPointerType()) {
+ bool success = true;
+ uint64_t int_val = new_val_sp->GetValueAsUnsigned(0, &success);
+ if (success) {
+ lldb::TargetSP target = GetTargetSP();
+ uint64_t num_bits = 0;
+ if (auto temp = new_val_sp->GetCompilerType().GetBitSize(target.get()))
+ num_bits = temp.value();
+ SetValueFromInteger(llvm::APInt(num_bits, int_val), error);
+ } else
+ error.SetErrorString("error converting new_val_sp to integer");
+ }
+}
+
// if any more "special cases" are added to
// ValueObject::DumpPrintableRepresentation() please keep this call up to date
// by returning true for your new special cases. We will eventually move to
@@ -1325,9 +1477,16 @@ bool ValueObject::DumpPrintableRepresentation(
str = GetSummaryAsCString();
break;
- case eValueObjectRepresentationStyleLanguageSpecific:
- str = GetObjectDescription();
- break;
+ case eValueObjectRepresentationStyleLanguageSpecific: {
+ llvm::Expected<std::string> desc = GetObjectDescription();
+ if (!desc) {
+ strm << "error: " << toString(desc.takeError());
+ str = strm.GetString();
+ } else {
+ strm << *desc;
+ str = strm.GetString();
+ }
+ } break;
case eValueObjectRepresentationStyleLocation:
str = GetLocationAsCString();
@@ -2566,11 +2725,14 @@ ValueObjectSP ValueObject::GetValueForExpressionPath_Impl(
}
}
-void ValueObject::Dump(Stream &s) { Dump(s, DumpValueObjectOptions(*this)); }
+llvm::Error ValueObject::Dump(Stream &s) {
+ return Dump(s, DumpValueObjectOptions(*this));
+}
-void ValueObject::Dump(Stream &s, const DumpValueObjectOptions &options) {
+llvm::Error ValueObject::Dump(Stream &s,
+ const DumpValueObjectOptions &options) {
ValueObjectPrinter printer(*this, &s, options);
- printer.PrintValueObject();
+ return printer.PrintValueObject();
}
ValueObjectSP ValueObject::CreateConstantValue(ConstString name) {
@@ -2843,6 +3005,374 @@ ValueObjectSP ValueObject::CastPointerType(const char *name, TypeSP &type_sp) {
return valobj_sp;
}
+lldb::addr_t ValueObject::GetLoadAddress() {
+ lldb::addr_t addr_value = LLDB_INVALID_ADDRESS;
+ if (auto target_sp = GetTargetSP()) {
+ const bool scalar_is_load_address = true;
+ AddressType addr_type;
+ addr_value = GetAddressOf(scalar_is_load_address, &addr_type);
+ if (addr_type == eAddressTypeFile) {
+ lldb::ModuleSP module_sp(GetModule());
+ if (!module_sp)
+ addr_value = LLDB_INVALID_ADDRESS;
+ else {
+ Address tmp_addr;
+ module_sp->ResolveFileAddress(addr_value, tmp_addr);
+ addr_value = tmp_addr.GetLoadAddress(target_sp.get());
+ }
+ } else if (addr_type == eAddressTypeHost ||
+ addr_type == eAddressTypeInvalid)
+ addr_value = LLDB_INVALID_ADDRESS;
+ }
+ return addr_value;
+}
+
+llvm::Expected<lldb::ValueObjectSP> ValueObject::CastDerivedToBaseType(
+ CompilerType type, const llvm::ArrayRef<uint32_t> &base_type_indices) {
+ // Make sure the starting type and the target type are both valid for this
+ // type of cast; otherwise return the shared pointer to the original
+ // (unchanged) ValueObject.
+ if (!type.IsPointerType() && !type.IsReferenceType())
+ return llvm::make_error<llvm::StringError>(
+ "Invalid target type: should be a pointer or a reference",
+ llvm::inconvertibleErrorCode());
+
+ CompilerType start_type = GetCompilerType();
+ if (start_type.IsReferenceType())
+ start_type = start_type.GetNonReferenceType();
+
+ auto target_record_type =
+ type.IsPointerType() ? type.GetPointeeType() : type.GetNonReferenceType();
+ auto start_record_type =
+ start_type.IsPointerType() ? start_type.GetPointeeType() : start_type;
+
+ if (!target_record_type.IsRecordType() || !start_record_type.IsRecordType())
+ return llvm::make_error<llvm::StringError>(
+ "Underlying start & target types should be record types",
+ llvm::inconvertibleErrorCode());
+
+ if (target_record_type.CompareTypes(start_record_type))
+ return llvm::make_error<llvm::StringError>(
+ "Underlying start & target types should be different",
+ llvm::inconvertibleErrorCode());
+
+ if (base_type_indices.empty())
+ return llvm::make_error<llvm::StringError>(
+ "Children sequence must be non-empty", llvm::inconvertibleErrorCode());
+
+ // Both the starting & target types are valid for the cast, and the list of
+ // base class indices is non-empty, so we can proceed with the cast.
+
+ lldb::TargetSP target = GetTargetSP();
+ // The `value` can be a pointer, but GetChildAtIndex works for pointers too.
+ lldb::ValueObjectSP inner_value = GetSP();
+
+ for (const uint32_t i : base_type_indices)
+ // Create synthetic value if needed.
+ inner_value =
+ inner_value->GetChildAtIndex(i, /*can_create_synthetic*/ true);
+
+ // At this point type of `inner_value` should be the dereferenced target
+ // type.
+ CompilerType inner_value_type = inner_value->GetCompilerType();
+ if (type.IsPointerType()) {
+ if (!inner_value_type.CompareTypes(type.GetPointeeType()))
+ return llvm::make_error<llvm::StringError>(
+ "casted value doesn't match the desired type",
+ llvm::inconvertibleErrorCode());
+
+ uintptr_t addr = inner_value->GetLoadAddress();
+ llvm::StringRef name = "";
+ ExecutionContext exe_ctx(target.get(), false);
+ return ValueObject::CreateValueObjectFromAddress(name, addr, exe_ctx, type,
+ /* do deref */ false);
+ }
+
+ // At this point the target type should be a reference.
+ if (!inner_value_type.CompareTypes(type.GetNonReferenceType()))
+ return llvm::make_error<llvm::StringError>(
+ "casted value doesn't match the desired type",
+ llvm::inconvertibleErrorCode());
+
+ return lldb::ValueObjectSP(inner_value->Cast(type.GetNonReferenceType()));
+}
+
+llvm::Expected<lldb::ValueObjectSP>
+ValueObject::CastBaseToDerivedType(CompilerType type, uint64_t offset) {
+ // Make sure the starting type and the target type are both valid for this
+ // type of cast; otherwise return the shared pointer to the original
+ // (unchanged) ValueObject.
+ if (!type.IsPointerType() && !type.IsReferenceType())
+ return llvm::make_error<llvm::StringError>(
+ "Invalid target type: should be a pointer or a reference",
+ llvm::inconvertibleErrorCode());
+
+ CompilerType start_type = GetCompilerType();
+ if (start_type.IsReferenceType())
+ start_type = start_type.GetNonReferenceType();
+
+ auto target_record_type =
+ type.IsPointerType() ? type.GetPointeeType() : type.GetNonReferenceType();
+ auto start_record_type =
+ start_type.IsPointerType() ? start_type.GetPointeeType() : start_type;
+
+ if (!target_record_type.IsRecordType() || !start_record_type.IsRecordType())
+ return llvm::make_error<llvm::StringError>(
+ "Underlying start & target types should be record types",
+ llvm::inconvertibleErrorCode());
+
+ if (target_record_type.CompareTypes(start_record_type))
+ return llvm::make_error<llvm::StringError>(
+ "Underlying start & target types should be different",
+ llvm::inconvertibleErrorCode());
+
+ CompilerType virtual_base;
+ if (target_record_type.IsVirtualBase(start_record_type, &virtual_base)) {
+ if (!virtual_base.IsValid())
+ return llvm::make_error<llvm::StringError>(
+ "virtual base should be valid", llvm::inconvertibleErrorCode());
+ return llvm::make_error<llvm::StringError>(
+ llvm::Twine("cannot cast " + start_type.TypeDescription() + " to " +
+ type.TypeDescription() + " via virtual base " +
+ virtual_base.TypeDescription()),
+ llvm::inconvertibleErrorCode());
+ }
+
+ // Both the starting & target types are valid for the cast, so we can
+ // proceed with the cast.
+
+ lldb::TargetSP target = GetTargetSP();
+ auto pointer_type =
+ type.IsPointerType() ? type : type.GetNonReferenceType().GetPointerType();
+
+ uintptr_t addr =
+ type.IsPointerType() ? GetValueAsUnsigned(0) : GetLoadAddress();
+
+ llvm::StringRef name = "";
+ ExecutionContext exe_ctx(target.get(), false);
+ lldb::ValueObjectSP value = ValueObject::CreateValueObjectFromAddress(
+ name, addr - offset, exe_ctx, pointer_type, /* do_deref */ false);
+
+ if (type.IsPointerType())
+ return value;
+
+ // At this point the target type is a reference. Since `value` is a pointer,
+ // it has to be dereferenced.
+ Status error;
+ return value->Dereference(error);
+}
+
+lldb::ValueObjectSP ValueObject::CastToBasicType(CompilerType type) {
+ bool is_scalar = GetCompilerType().IsScalarType();
+ bool is_enum = GetCompilerType().IsEnumerationType();
+ bool is_pointer =
+ GetCompilerType().IsPointerType() || GetCompilerType().IsNullPtrType();
+ bool is_float = GetCompilerType().IsFloat();
+ bool is_integer = GetCompilerType().IsInteger();
+
+ if (!type.IsScalarType()) {
+ m_error.SetErrorString("target type must be a scalar");
+ return GetSP();
+ }
+
+ if (!is_scalar && !is_enum && !is_pointer) {
+ m_error.SetErrorString("argument must be a scalar, enum, or pointer");
+ return GetSP();
+ }
+
+ lldb::TargetSP target = GetTargetSP();
+ uint64_t type_byte_size = 0;
+ uint64_t val_byte_size = 0;
+ if (auto temp = type.GetByteSize(target.get()))
+ type_byte_size = temp.value();
+ if (auto temp = GetCompilerType().GetByteSize(target.get()))
+ val_byte_size = temp.value();
+
+ if (is_pointer) {
+ if (!type.IsInteger() && !type.IsBoolean()) {
+ m_error.SetErrorString("target type must be an integer or boolean");
+ return GetSP();
+ }
+ if (!type.IsBoolean() && type_byte_size < val_byte_size) {
+ m_error.SetErrorString(
+ "target type cannot be smaller than the pointer type");
+ return GetSP();
+ }
+ }
+
+ if (type.IsBoolean()) {
+ if (!is_scalar || is_integer)
+ return ValueObject::CreateValueObjectFromBool(
+ target, 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");
+ else {
+ m_error.SetErrorStringWithFormat(
+ "cannot get value as APFloat: %s",
+ llvm::toString(float_value_or_err.takeError()).c_str());
+ return GetSP();
+ }
+ }
+ }
+
+ if (type.IsInteger()) {
+ if (!is_scalar || is_integer) {
+ auto int_value_or_err = GetValueAsAPSInt();
+ if (int_value_or_err) {
+ // Get the value as APSInt and extend or truncate it to the requested
+ // size.
+ llvm::APSInt ext =
+ int_value_or_err->extOrTrunc(type_byte_size * CHAR_BIT);
+ return ValueObject::CreateValueObjectFromAPInt(target, ext, type,
+ "result");
+ } else {
+ m_error.SetErrorStringWithFormat(
+ "cannot get value as APSInt: %s",
+ llvm::toString(int_value_or_err.takeError()).c_str());
+ ;
+ return GetSP();
+ }
+ } else if (is_scalar && is_float) {
+ llvm::APSInt integer(type_byte_size * CHAR_BIT, !type.IsSigned());
+ bool is_exact;
+ auto float_value_or_err = GetValueAsAPFloat();
+ if (float_value_or_err) {
+ llvm::APFloatBase::opStatus status =
+ float_value_or_err->convertToInteger(
+ integer, llvm::APFloat::rmTowardZero, &is_exact);
+
+ // Casting floating point values that are out of bounds of the target
+ // type is undefined behaviour.
+ if (status & llvm::APFloatBase::opInvalidOp) {
+ m_error.SetErrorStringWithFormat(
+ "invalid type cast detected: %s",
+ llvm::toString(float_value_or_err.takeError()).c_str());
+ return GetSP();
+ }
+ return ValueObject::CreateValueObjectFromAPInt(target, integer, type,
+ "result");
+ }
+ }
+ }
+
+ if (type.IsFloat()) {
+ if (!is_scalar) {
+ auto int_value_or_err = GetValueAsAPSInt();
+ if (int_value_or_err) {
+ llvm::APSInt ext =
+ int_value_or_err->extOrTrunc(type_byte_size * CHAR_BIT);
+ Scalar scalar_int(ext);
+ llvm::APFloat f = scalar_int.CreateAPFloatFromAPSInt(
+ type.GetCanonicalType().GetBasicTypeEnumeration());
+ return ValueObject::CreateValueObjectFromAPFloat(target, f, type,
+ "result");
+ } else {
+ m_error.SetErrorStringWithFormat(
+ "cannot get value as APSInt: %s",
+ llvm::toString(int_value_or_err.takeError()).c_str());
+ return GetSP();
+ }
+ } else {
+ if (is_integer) {
+ auto int_value_or_err = GetValueAsAPSInt();
+ if (int_value_or_err) {
+ Scalar scalar_int(*int_value_or_err);
+ llvm::APFloat f = scalar_int.CreateAPFloatFromAPSInt(
+ type.GetCanonicalType().GetBasicTypeEnumeration());
+ return ValueObject::CreateValueObjectFromAPFloat(target, f, type,
+ "result");
+ } else {
+ m_error.SetErrorStringWithFormat(
+ "cannot get value as APSInt: %s",
+ llvm::toString(int_value_or_err.takeError()).c_str());
+ return GetSP();
+ }
+ }
+ if (is_float) {
+ auto float_value_or_err = GetValueAsAPFloat();
+ if (float_value_or_err) {
+ Scalar scalar_float(*float_value_or_err);
+ llvm::APFloat f = scalar_float.CreateAPFloatFromAPFloat(
+ type.GetCanonicalType().GetBasicTypeEnumeration());
+ return ValueObject::CreateValueObjectFromAPFloat(target, f, type,
+ "result");
+ } else {
+ m_error.SetErrorStringWithFormat(
+ "cannot get value as APFloat: %s",
+ llvm::toString(float_value_or_err.takeError()).c_str());
+ return GetSP();
+ }
+ }
+ }
+ }
+
+ m_error.SetErrorString("Unable to perform requested cast");
+ return GetSP();
+}
+
+lldb::ValueObjectSP ValueObject::CastToEnumType(CompilerType type) {
+ bool is_enum = GetCompilerType().IsEnumerationType();
+ bool is_integer = GetCompilerType().IsInteger();
+ bool is_float = GetCompilerType().IsFloat();
+
+ if (!is_enum && !is_integer && !is_float) {
+ m_error.SetErrorString("argument must be an integer, a float, or an enum");
+ return GetSP();
+ }
+
+ if (!type.IsEnumerationType()) {
+ m_error.SetErrorString("target type must be an enum");
+ return GetSP();
+ }
+
+ lldb::TargetSP target = GetTargetSP();
+ uint64_t byte_size = 0;
+ if (auto temp = type.GetByteSize(target.get()))
+ byte_size = temp.value();
+
+ if (is_float) {
+ llvm::APSInt integer(byte_size * CHAR_BIT, !type.IsSigned());
+ bool is_exact;
+ auto value_or_err = GetValueAsAPFloat();
+ if (value_or_err) {
+ llvm::APFloatBase::opStatus status = value_or_err->convertToInteger(
+ integer, llvm::APFloat::rmTowardZero, &is_exact);
+
+ // Casting floating point values that are out of bounds of the target
+ // type is undefined behaviour.
+ if (status & llvm::APFloatBase::opInvalidOp) {
+ m_error.SetErrorStringWithFormat(
+ "invalid type cast detected: %s",
+ llvm::toString(value_or_err.takeError()).c_str());
+ return GetSP();
+ }
+ return ValueObject::CreateValueObjectFromAPInt(target, integer, type,
+ "result");
+ } else {
+ m_error.SetErrorString("cannot get value as APFloat");
+ return GetSP();
+ }
+ } else {
+ // Get the value as APSInt and extend or truncate it to the requested size.
+ 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,
+ "result");
+ } else {
+ m_error.SetErrorStringWithFormat(
+ "cannot get value as APSInt: %s",
+ llvm::toString(value_or_err.takeError()).c_str());
+ return GetSP();
+ }
+ }
+ m_error.SetErrorString("Cannot perform requested cast");
+ return GetSP();
+}
+
ValueObject::EvaluationPoint::EvaluationPoint() : m_mod_id(), m_exe_ctx_ref() {}
ValueObject::EvaluationPoint::EvaluationPoint(ExecutionContextScope *exe_scope,
@@ -3028,9 +3558,11 @@ lldb::ValueObjectSP ValueObject::CreateValueObjectFromExpression(
lldb::ValueObjectSP ValueObject::CreateValueObjectFromAddress(
llvm::StringRef name, uint64_t address, const ExecutionContext &exe_ctx,
- CompilerType type) {
+ CompilerType type, bool do_deref) {
if (type) {
CompilerType pointer_type(type.GetPointerType());
+ if (!do_deref)
+ pointer_type = type;
if (pointer_type) {
lldb::DataBufferSP buffer(
new lldb_private::DataBufferHeap(&address, sizeof(lldb::addr_t)));
@@ -3039,10 +3571,12 @@ lldb::ValueObjectSP ValueObject::CreateValueObjectFromAddress(
ConstString(name), buffer, exe_ctx.GetByteOrder(),
exe_ctx.GetAddressByteSize()));
if (ptr_result_valobj_sp) {
- ptr_result_valobj_sp->GetValue().SetValueType(
- Value::ValueType::LoadAddress);
+ if (do_deref)
+ ptr_result_valobj_sp->GetValue().SetValueType(
+ Value::ValueType::LoadAddress);
Status err;
- ptr_result_valobj_sp = ptr_result_valobj_sp->Dereference(err);
+ if (do_deref)
+ ptr_result_valobj_sp = ptr_result_valobj_sp->Dereference(err);
if (ptr_result_valobj_sp && !name.empty())
ptr_result_valobj_sp->SetName(ConstString(name));
}
@@ -3065,6 +3599,66 @@ lldb::ValueObjectSP ValueObject::CreateValueObjectFromData(
return new_value_sp;
}
+lldb::ValueObjectSP
+ValueObject::CreateValueObjectFromAPInt(lldb::TargetSP target,
+ const llvm::APInt &v, CompilerType type,
+ llvm::StringRef name) {
+ ExecutionContext exe_ctx(target.get(), false);
+ uint64_t byte_size = 0;
+ if (auto temp = type.GetByteSize(target.get()))
+ byte_size = temp.value();
+ lldb::DataExtractorSP data_sp = std::make_shared<DataExtractor>(
+ reinterpret_cast<const void *>(v.getRawData()), byte_size,
+ exe_ctx.GetByteOrder(), exe_ctx.GetAddressByteSize());
+ return ValueObject::CreateValueObjectFromData(name, *data_sp, exe_ctx, type);
+}
+
+lldb::ValueObjectSP ValueObject::CreateValueObjectFromAPFloat(
+ lldb::TargetSP target, const llvm::APFloat &v, CompilerType type,
+ llvm::StringRef name) {
+ return CreateValueObjectFromAPInt(target, v.bitcastToAPInt(), type, name);
+}
+
+lldb::ValueObjectSP
+ValueObject::CreateValueObjectFromBool(lldb::TargetSP target, 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 = target_type.GetByteSize(target.get()))
+ byte_size = temp.value();
+ 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);
+}
+
+lldb::ValueObjectSP ValueObject::CreateValueObjectFromNullptr(
+ lldb::TargetSP target, 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 = type.GetByteSize(target.get()))
+ byte_size = temp.value();
+ lldb::DataExtractorSP data_sp = std::make_shared<DataExtractor>(
+ reinterpret_cast<const void *>(zero), byte_size, exe_ctx.GetByteOrder(),
+ exe_ctx.GetAddressByteSize());
+ return ValueObject::CreateValueObjectFromData(name, *data_sp, exe_ctx, type);
+}
+
ModuleSP ValueObject::GetModule() {
ValueObject *root(GetRoot());
if (root != this)