[Lldb-commits] [lldb] [LLDB] Add more helper functions to ValueObject class. (PR #87197)
via lldb-commits
lldb-commits at lists.llvm.org
Thu Jun 6 11:16:50 PDT 2024
================
@@ -2809,6 +2919,243 @@ 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;
+ lldb::TargetSP target_sp = GetTargetSP();
+ if (target_sp) {
+ 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 == eAddressTypeHost)
+ addr_value = LLDB_INVALID_ADDRESS;
+ }
+ return addr_value;
+}
+
+lldb::ValueObjectSP
+ValueObject::CastDerivedToBaseType(CompilerType type,
+ const std::vector<uint32_t> &idx) {
+
+ lldb::TargetSP target = GetTargetSP();
+ assert((type.IsPointerType() || type.IsReferenceType()) &&
+ "invalid ast: target type should be a pointer or a reference");
+ assert(!idx.empty() && "invalid ast: children sequence should be non-empty");
+
+ // The `value` can be a pointer, but GetChildAtIndex works for pointers too.
+ lldb::ValueObjectSP inner_value;
+
+ for (const uint32_t i : idx) {
+ // Force static value, otherwise we can end up with the "real" type.
+ inner_value = GetChildAtIndex(i, /*can_create_synthetic*/ false);
+ }
+
+ // At this point type of `inner_value` should be the dereferenced target type.
+ CompilerType inner_value_type = inner_value->GetCompilerType();
+ if (type.IsPointerType()) {
+ assert(inner_value_type.CompareTypes(type.GetPointeeType()) &&
+ "casted value doesn't match the desired type");
+
+ uintptr_t addr = inner_value->GetLoadAddress();
+ return ValueObject::CreateValueObjectFromPointer(target, addr, type);
+ }
+
+ // At this point the target type should be a reference.
+ assert(inner_value_type.CompareTypes(type.GetNonReferenceType()) &&
+ "casted value doesn't match the desired type");
+
+ return lldb::ValueObjectSP(inner_value->Cast(type.GetNonReferenceType()));
+}
+
+lldb::ValueObjectSP ValueObject::CastBaseToDerivedType(CompilerType type,
+ uint64_t offset) {
+ lldb::TargetSP target = GetTargetSP();
+
+ assert((type.IsPointerType() || type.IsReferenceType()) &&
+ "invalid ast: target type should be a pointer or a reference");
+
+ auto pointer_type =
+ type.IsPointerType() ? type : type.GetNonReferenceType().GetPointerType();
+
+ uintptr_t addr =
+ type.IsPointerType() ? GetValueAsUnsigned(0) : GetLoadAddress();
+
+ lldb::ValueObjectSP value = ValueObject::CreateValueObjectFromPointer(
+ target, addr - offset, pointer_type);
+
+ 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::CastScalarToBasicType(CompilerType type,
+ Status &error) {
+ assert(type.IsScalarType() && "target type must be an scalar");
+ assert(GetCompilerType().IsScalarType() && "argument must be a scalar");
+
+ lldb::TargetSP target = GetTargetSP();
+ if (type.IsBoolean()) {
+ if (GetCompilerType().IsInteger()) {
+ return ValueObject::CreateValueObjectFromBool(target,
+ GetValueAsUnsigned(0) != 0);
+ }
+ if (GetCompilerType().IsFloat()) {
+ return ValueObject::CreateValueObjectFromBool(
+ target, !GetValueAsFloat().isZero());
+ }
+ }
+ if (type.IsInteger()) {
+ if (GetCompilerType().IsInteger()) {
+ uint64_t byte_size = 0;
+ if (auto temp = type.GetByteSize(target.get()))
+ byte_size = temp.value();
+ llvm::APSInt ext = GetValueAsAPSInt().extOrTrunc(byte_size * CHAR_BIT);
+ return ValueObject::CreateValueObjectFromAPInt(target, ext, type);
+ }
+ if (GetCompilerType().IsFloat()) {
+ uint64_t byte_size = 0;
+ if (auto temp = type.GetByteSize(target.get()))
+ byte_size = temp.value();
+ llvm::APSInt integer(byte_size * CHAR_BIT, !type.IsSigned());
+ bool is_exact;
+ llvm::APFloatBase::opStatus status = GetValueAsFloat().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) {
+ error.SetErrorString("invalid type cast detected");
+ }
+
+ return ValueObject::CreateValueObjectFromAPInt(target, integer, type);
+ }
+ }
+ if (type.IsFloat()) {
+ if (GetCompilerType().IsInteger()) {
+ Scalar scalar_int(GetValueAsAPSInt());
+ llvm::APFloat f = scalar_int.CreateAPFloatFromAPSInt(
+ type.GetCanonicalType().GetBasicTypeEnumeration());
+ return ValueObject::CreateValueObjectFromAPFloat(target, f, type);
+ }
+ if (GetCompilerType().IsFloat()) {
+ Scalar scalar_float(GetValueAsFloat());
+ llvm::APFloat f = scalar_float.CreateAPFloatFromAPFloat(
+ type.GetCanonicalType().GetBasicTypeEnumeration());
+ return ValueObject::CreateValueObjectFromAPFloat(target, f, type);
+ }
+ }
+ assert(false && "invalid target type: must be a scalar");
+ return lldb::ValueObjectSP();
+}
+
+lldb::ValueObjectSP ValueObject::CastEnumToBasicType(CompilerType type) {
+ lldb::TargetSP target = GetTargetSP();
+
+ assert(type.IsScalarType() && "target type must be a scalar");
+ assert(GetCompilerType().IsEnumerationType() && "argument must be an enum");
+
+ if (type.IsBoolean()) {
+ return ValueObject::CreateValueObjectFromBool(target,
+ GetValueAsUnsigned(0) != 0);
+ }
+
+ uint64_t byte_size = 0;
+ if (auto temp = type.GetByteSize(target.get()))
+ byte_size = temp.value();
+ // Get the value as APSInt and extend or truncate it to the requested size.
+ llvm::APSInt ext = GetValueAsAPSInt().extOrTrunc(byte_size * CHAR_BIT);
+
+ if (type.IsInteger()) {
+ return ValueObject::CreateValueObjectFromAPInt(target, ext, type);
+ }
+ if (type.IsFloat()) {
+ Scalar scalar_int(ext);
+ llvm::APFloat f = scalar_int.CreateAPFloatFromAPSInt(
+ type.GetCanonicalType().GetBasicTypeEnumeration());
+ return ValueObject::CreateValueObjectFromAPFloat(target, f, type);
+ }
+ assert(false && "invalid target type: must be a scalar");
+ return lldb::ValueObjectSP();
+}
+
+lldb::ValueObjectSP ValueObject::CastPointerToBasicType(CompilerType type) {
+ 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();
+ assert(type.IsInteger() && "target type must be an integer");
+ assert((type.IsBoolean() || type_byte_size >= val_byte_size) &&
+ "target type cannot be smaller than the pointer type");
+
+ if (type.IsBoolean()) {
+ return ValueObject::CreateValueObjectFromBool(target,
+ GetValueAsUnsigned(0) != 0);
+ }
+
+ // Get the value as APSInt and extend or truncate it to the requested size.
+ llvm::APSInt ext = GetValueAsAPSInt().extOrTrunc(type_byte_size * CHAR_BIT);
+ return ValueObject::CreateValueObjectFromAPInt(target, ext, type);
+}
+
+lldb::ValueObjectSP
+ValueObject::CastIntegerOrEnumToEnumType(CompilerType type) {
+ lldb::TargetSP target = GetTargetSP();
+
+ assert(type.IsEnumerationType() && "target type must be an enum");
+ assert((GetCompilerType().IsInteger() ||
+ GetCompilerType().IsEnumerationType()) &&
+ "argument must be an integer or an enum");
+ uint64_t byte_size = 0;
+ if (auto temp = type.GetByteSize(target.get()))
+ byte_size = temp.value();
+
+ // Get the value as APSInt and extend or truncate it to the requested size.
+ llvm::APSInt ext = GetValueAsAPSInt().extOrTrunc(byte_size * CHAR_BIT);
+ return ValueObject::CreateValueObjectFromAPInt(target, ext, type);
+}
+
+lldb::ValueObjectSP ValueObject::CastFloatToEnumType(CompilerType type,
+ Status &error) {
+ lldb::TargetSP target = GetTargetSP();
+
+ assert(type.IsEnumerationType() && "target type must be an enum");
+ assert(GetCompilerType().IsFloat() && "argument must be a float");
----------------
cmtice wrote:
Whoops! Good catch. I've fixed that now.
https://github.com/llvm/llvm-project/pull/87197
More information about the lldb-commits
mailing list