================ @@ -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 _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits