ValueObjectSP ABIMacOSX_i386::GetReturnValueObjectImpl (Thread &thread, CompilerType &compiler_type) const { Value value; ValueObjectSP return_valobj_sp; if (!compiler_type) return return_valobj_sp; //value.SetContext (Value::eContextTypeClangType, compiler_type.GetOpaqueQualType()); value.SetCompilerType (compiler_type); RegisterContext *reg_ctx = thread.GetRegisterContext().get(); if (!reg_ctx) return return_valobj_sp; bool is_signed; if (compiler_type.IsIntegerType (is_signed)) { size_t bit_width = compiler_type.GetBitSize(&thread); unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB]; unsigned edx_id = reg_ctx->GetRegisterInfoByName("edx", 0)->kinds[eRegisterKindLLDB]; switch (bit_width) { default: case 128: // Scalar can't hold 128-bit literals, so we don't handle this return return_valobj_sp; case 64: uint64_t raw_value; raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff; raw_value |= (thread.GetRegisterContext()->ReadRegisterAsUnsigned(edx_id, 0) & 0xffffffff) << 32; if (is_signed) value.GetScalar() = (int64_t)raw_value; else value.GetScalar() = (uint64_t)raw_value; break; case 32: if (is_signed) value.GetScalar() = (int32_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff); else value.GetScalar() = (uint32_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff); break; case 16: if (is_signed) value.GetScalar() = (int16_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffff); else value.GetScalar() = (uint16_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffff); break; case 8: if (is_signed) value.GetScalar() = (int8_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xff); else value.GetScalar() = (uint8_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xff); break; } } else if (compiler_type.IsPointerType ()) { unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB]; uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff; value.GetScalar() = ptr; } else { // not handled yet return return_valobj_sp; } // If we get here, we have a valid Value, so make our ValueObject out of it: return_valobj_sp = ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(), value, ConstString("")); return return_valobj_sp; }
ValueObjectSP ABISysV_mips::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_clang_type) const { ValueObjectSP return_valobj_sp; Value value; if (!return_clang_type) return return_valobj_sp; ExecutionContext exe_ctx (thread.shared_from_this()); if (exe_ctx.GetTargetPtr() == NULL || exe_ctx.GetProcessPtr() == NULL) return return_valobj_sp; value.SetCompilerType(return_clang_type); RegisterContext *reg_ctx = thread.GetRegisterContext().get(); if (!reg_ctx) return return_valobj_sp; bool is_signed = false; bool is_complex = false; uint32_t count = 0; // In MIPS register "r2" (v0) holds the integer function return values const RegisterInfo *r2_reg_info = reg_ctx->GetRegisterInfoByName("r2", 0); size_t bit_width = return_clang_type.GetBitSize(&thread); if (return_clang_type.IsIntegerType (is_signed)) { switch (bit_width) { default: return return_valobj_sp; case 64: { const RegisterInfo *r3_reg_info = reg_ctx->GetRegisterInfoByName("r3", 0); uint64_t raw_value; raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX; raw_value |= ((uint64_t)(reg_ctx->ReadRegisterAsUnsigned(r3_reg_info, 0) & UINT32_MAX)) << 32; if (is_signed) value.GetScalar() = (int64_t)raw_value; else value.GetScalar() = (uint64_t)raw_value; } break; case 32: if (is_signed) value.GetScalar() = (int32_t)(reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX); else value.GetScalar() = (uint32_t)(reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX); break; case 16: if (is_signed) value.GetScalar() = (int16_t)(reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT16_MAX); else value.GetScalar() = (uint16_t)(reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT16_MAX); break; case 8: if (is_signed) value.GetScalar() = (int8_t)(reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT8_MAX); else value.GetScalar() = (uint8_t)(reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT8_MAX); break; } } else if (return_clang_type.IsPointerType ()) { uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX; value.GetScalar() = ptr; } else if (return_clang_type.IsAggregateType ()) { // Structure/Vector is always passed in memory and pointer to that memory is passed in r2. uint64_t mem_address = reg_ctx->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r2", 0), 0); // We have got the address. Create a memory object out of it return_valobj_sp = ValueObjectMemory::Create (&thread, "", Address (mem_address, NULL), return_clang_type); return return_valobj_sp; } else if (return_clang_type.IsFloatingPointType (count, is_complex)) { const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0); const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0); if (count == 1 && !is_complex) { switch (bit_width) { default: return return_valobj_sp; case 64: { static_assert(sizeof(double) == sizeof(uint64_t), ""); uint64_t raw_value; raw_value = reg_ctx->ReadRegisterAsUnsigned(f0_info, 0) & UINT32_MAX; raw_value |= ((uint64_t)(reg_ctx->ReadRegisterAsUnsigned(f1_info, 0) & UINT32_MAX)) << 32; value.GetScalar() = *reinterpret_cast<double*>(&raw_value); break; } case 32: { static_assert(sizeof(float) == sizeof(uint32_t), ""); uint32_t raw_value = reg_ctx->ReadRegisterAsUnsigned(f0_info, 0) & UINT32_MAX; value.GetScalar() = *reinterpret_cast<float*>(&raw_value); break; } } } else { // not handled yet return return_valobj_sp; } } else { // not handled yet return return_valobj_sp; } // If we get here, we have a valid Value, so make our ValueObject out of it: return_valobj_sp = ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(), value, ConstString("")); return return_valobj_sp; }
void FormatManager::GetPossibleMatches( ValueObject &valobj, CompilerType compiler_type, uint32_t reason, lldb::DynamicValueType use_dynamic, FormattersMatchVector &entries, bool did_strip_ptr, bool did_strip_ref, bool did_strip_typedef, bool root_level) { compiler_type = compiler_type.GetTypeForFormatters(); ConstString type_name(compiler_type.GetConstTypeName()); if (valobj.GetBitfieldBitSize() > 0) { StreamString sstring; sstring.Printf("%s:%d", type_name.AsCString(), valobj.GetBitfieldBitSize()); ConstString bitfieldname(sstring.GetString()); entries.push_back( {bitfieldname, 0, did_strip_ptr, did_strip_ref, did_strip_typedef}); reason |= lldb_private::eFormatterChoiceCriterionStrippedBitField; } if (!compiler_type.IsMeaninglessWithoutDynamicResolution()) { entries.push_back( {type_name, reason, did_strip_ptr, did_strip_ref, did_strip_typedef}); ConstString display_type_name(compiler_type.GetDisplayTypeName()); if (display_type_name != type_name) entries.push_back({display_type_name, reason, did_strip_ptr, did_strip_ref, did_strip_typedef}); } for (bool is_rvalue_ref = true, j = true; j && compiler_type.IsReferenceType(nullptr, &is_rvalue_ref); j = false) { CompilerType non_ref_type = compiler_type.GetNonReferenceType(); GetPossibleMatches( valobj, non_ref_type, reason | lldb_private::eFormatterChoiceCriterionStrippedPointerReference, use_dynamic, entries, did_strip_ptr, true, did_strip_typedef); if (non_ref_type.IsTypedefType()) { CompilerType deffed_referenced_type = non_ref_type.GetTypedefedType(); deffed_referenced_type = is_rvalue_ref ? deffed_referenced_type.GetRValueReferenceType() : deffed_referenced_type.GetLValueReferenceType(); GetPossibleMatches( valobj, deffed_referenced_type, reason | lldb_private::eFormatterChoiceCriterionNavigatedTypedefs, use_dynamic, entries, did_strip_ptr, did_strip_ref, true); // this is not exactly the usual meaning of stripping typedefs } } if (compiler_type.IsPointerType()) { CompilerType non_ptr_type = compiler_type.GetPointeeType(); GetPossibleMatches( valobj, non_ptr_type, reason | lldb_private::eFormatterChoiceCriterionStrippedPointerReference, use_dynamic, entries, true, did_strip_ref, did_strip_typedef); if (non_ptr_type.IsTypedefType()) { CompilerType deffed_pointed_type = non_ptr_type.GetTypedefedType().GetPointerType(); GetPossibleMatches( valobj, deffed_pointed_type, reason | lldb_private::eFormatterChoiceCriterionNavigatedTypedefs, use_dynamic, entries, did_strip_ptr, did_strip_ref, true); // this is not exactly the usual meaning of stripping typedefs } } for (lldb::LanguageType language_type : GetCandidateLanguages(valobj)) { if (Language *language = Language::FindPlugin(language_type)) { for (ConstString candidate : language->GetPossibleFormattersMatches(valobj, use_dynamic)) { entries.push_back( {candidate, reason | lldb_private::eFormatterChoiceCriterionLanguagePlugin, did_strip_ptr, did_strip_ref, did_strip_typedef}); } } } // try to strip typedef chains if (compiler_type.IsTypedefType()) { CompilerType deffed_type = compiler_type.GetTypedefedType(); GetPossibleMatches( valobj, deffed_type, reason | lldb_private::eFormatterChoiceCriterionNavigatedTypedefs, use_dynamic, entries, did_strip_ptr, did_strip_ref, true); } if (root_level) { do { if (!compiler_type.IsValid()) break; CompilerType unqual_compiler_ast_type = compiler_type.GetFullyUnqualifiedType(); if (!unqual_compiler_ast_type.IsValid()) break; if (unqual_compiler_ast_type.GetOpaqueQualType() != compiler_type.GetOpaqueQualType()) GetPossibleMatches(valobj, unqual_compiler_ast_type, reason, use_dynamic, entries, did_strip_ptr, did_strip_ref, did_strip_typedef); } while (false); // if all else fails, go to static type if (valobj.IsDynamic()) { lldb::ValueObjectSP static_value_sp(valobj.GetStaticValue()); if (static_value_sp) GetPossibleMatches( *static_value_sp.get(), static_value_sp->GetCompilerType(), reason | lldb_private::eFormatterChoiceCriterionWentToStaticValue, use_dynamic, entries, did_strip_ptr, did_strip_ref, did_strip_typedef, true); } } }