| //===-- CompilerType.cpp ----------------------------------------*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #include "lldb/Symbol/CompilerType.h" |
| |
| #include "lldb/Core/Debugger.h" |
| #include "lldb/Core/Scalar.h" |
| #include "lldb/Core/StreamFile.h" |
| #include "lldb/Symbol/ClangASTContext.h" |
| #include "lldb/Symbol/ClangExternalASTSourceCommon.h" |
| #include "lldb/Symbol/Type.h" |
| #include "lldb/Target/ExecutionContext.h" |
| #include "lldb/Target/Process.h" |
| #include "lldb/Utility/ConstString.h" |
| #include "lldb/Utility/DataBufferHeap.h" |
| #include "lldb/Utility/DataExtractor.h" |
| #include "lldb/Utility/Stream.h" |
| #include "lldb/Utility/StreamString.h" |
| |
| #include <iterator> |
| #include <mutex> |
| |
| using namespace lldb; |
| using namespace lldb_private; |
| |
| CompilerType::CompilerType(TypeSystem *type_system, |
| lldb::opaque_compiler_type_t type) |
| : m_type(type), m_type_system(type_system) {} |
| |
| CompilerType::CompilerType(clang::ASTContext *ast, clang::QualType qual_type) |
| : m_type(qual_type.getAsOpaquePtr()), |
| m_type_system(ClangASTContext::GetASTContext(ast)) { |
| #ifdef LLDB_CONFIGURATION_DEBUG |
| if (m_type) |
| assert(m_type_system != nullptr); |
| #endif |
| } |
| |
| CompilerType::~CompilerType() {} |
| |
| //---------------------------------------------------------------------- |
| // Tests |
| //---------------------------------------------------------------------- |
| |
| bool CompilerType::IsAggregateType() const { |
| if (IsValid()) |
| return m_type_system->IsAggregateType(m_type); |
| return false; |
| } |
| |
| bool CompilerType::IsAnonymousType() const { |
| if (IsValid()) |
| return m_type_system->IsAnonymousType(m_type); |
| return false; |
| } |
| |
| bool CompilerType::IsArrayType(CompilerType *element_type_ptr, uint64_t *size, |
| bool *is_incomplete) const { |
| if (IsValid()) |
| return m_type_system->IsArrayType(m_type, element_type_ptr, size, |
| is_incomplete); |
| |
| if (element_type_ptr) |
| element_type_ptr->Clear(); |
| if (size) |
| *size = 0; |
| if (is_incomplete) |
| *is_incomplete = false; |
| return false; |
| } |
| |
| bool CompilerType::IsVectorType(CompilerType *element_type, |
| uint64_t *size) const { |
| if (IsValid()) |
| return m_type_system->IsVectorType(m_type, element_type, size); |
| return false; |
| } |
| |
| bool CompilerType::IsRuntimeGeneratedType() const { |
| if (IsValid()) |
| return m_type_system->IsRuntimeGeneratedType(m_type); |
| return false; |
| } |
| |
| bool CompilerType::IsCharType() const { |
| if (IsValid()) |
| return m_type_system->IsCharType(m_type); |
| return false; |
| } |
| |
| bool CompilerType::IsCompleteType() const { |
| if (IsValid()) |
| return m_type_system->IsCompleteType(m_type); |
| return false; |
| } |
| |
| bool CompilerType::IsConst() const { |
| if (IsValid()) |
| return m_type_system->IsConst(m_type); |
| return false; |
| } |
| |
| bool CompilerType::IsCStringType(uint32_t &length) const { |
| if (IsValid()) |
| return m_type_system->IsCStringType(m_type, length); |
| return false; |
| } |
| |
| bool CompilerType::IsFunctionType(bool *is_variadic_ptr) const { |
| if (IsValid()) |
| return m_type_system->IsFunctionType(m_type, is_variadic_ptr); |
| return false; |
| } |
| |
| // Used to detect "Homogeneous Floating-point Aggregates" |
| uint32_t |
| CompilerType::IsHomogeneousAggregate(CompilerType *base_type_ptr) const { |
| if (IsValid()) |
| return m_type_system->IsHomogeneousAggregate(m_type, base_type_ptr); |
| return 0; |
| } |
| |
| size_t CompilerType::GetNumberOfFunctionArguments() const { |
| if (IsValid()) |
| return m_type_system->GetNumberOfFunctionArguments(m_type); |
| return 0; |
| } |
| |
| CompilerType |
| CompilerType::GetFunctionArgumentAtIndex(const size_t index) const { |
| if (IsValid()) |
| return m_type_system->GetFunctionArgumentAtIndex(m_type, index); |
| return CompilerType(); |
| } |
| |
| bool CompilerType::IsFunctionPointerType() const { |
| if (IsValid()) |
| return m_type_system->IsFunctionPointerType(m_type); |
| return false; |
| } |
| |
| bool CompilerType::IsBlockPointerType( |
| CompilerType *function_pointer_type_ptr) const { |
| if (IsValid()) |
| return m_type_system->IsBlockPointerType(m_type, function_pointer_type_ptr); |
| return 0; |
| } |
| |
| bool CompilerType::IsIntegerType(bool &is_signed) const { |
| if (IsValid()) |
| return m_type_system->IsIntegerType(m_type, is_signed); |
| return false; |
| } |
| |
| bool CompilerType::IsEnumerationType(bool &is_signed) const { |
| if (IsValid()) |
| return m_type_system->IsEnumerationType(m_type, is_signed); |
| return false; |
| } |
| |
| bool CompilerType::IsIntegerOrEnumerationType(bool &is_signed) const { |
| return IsIntegerType(is_signed) || IsEnumerationType(is_signed); |
| } |
| |
| bool CompilerType::IsPointerType(CompilerType *pointee_type) const { |
| if (IsValid()) { |
| return m_type_system->IsPointerType(m_type, pointee_type); |
| } |
| if (pointee_type) |
| pointee_type->Clear(); |
| return false; |
| } |
| |
| bool CompilerType::IsPointerOrReferenceType(CompilerType *pointee_type) const { |
| if (IsValid()) { |
| return m_type_system->IsPointerOrReferenceType(m_type, pointee_type); |
| } |
| if (pointee_type) |
| pointee_type->Clear(); |
| return false; |
| } |
| |
| bool CompilerType::IsReferenceType(CompilerType *pointee_type, |
| bool *is_rvalue) const { |
| if (IsValid()) { |
| return m_type_system->IsReferenceType(m_type, pointee_type, is_rvalue); |
| } |
| if (pointee_type) |
| pointee_type->Clear(); |
| return false; |
| } |
| |
| bool CompilerType::ShouldTreatScalarValueAsAddress() const { |
| if (IsValid()) |
| return m_type_system->ShouldTreatScalarValueAsAddress(m_type); |
| return false; |
| } |
| |
| bool CompilerType::IsFloatingPointType(uint32_t &count, |
| bool &is_complex) const { |
| if (IsValid()) { |
| return m_type_system->IsFloatingPointType(m_type, count, is_complex); |
| } |
| count = 0; |
| is_complex = false; |
| return false; |
| } |
| |
| bool CompilerType::IsDefined() const { |
| if (IsValid()) |
| return m_type_system->IsDefined(m_type); |
| return true; |
| } |
| |
| bool CompilerType::IsPolymorphicClass() const { |
| if (IsValid()) { |
| return m_type_system->IsPolymorphicClass(m_type); |
| } |
| return false; |
| } |
| |
| bool CompilerType::IsPossibleDynamicType(CompilerType *dynamic_pointee_type, |
| bool check_cplusplus, |
| bool check_objc) const { |
| if (IsValid()) |
| return m_type_system->IsPossibleDynamicType(m_type, dynamic_pointee_type, |
| check_cplusplus, check_objc); |
| return false; |
| } |
| |
| bool CompilerType::IsScalarType() const { |
| if (!IsValid()) |
| return false; |
| |
| return m_type_system->IsScalarType(m_type); |
| } |
| |
| bool CompilerType::IsTypedefType() const { |
| if (!IsValid()) |
| return false; |
| return m_type_system->IsTypedefType(m_type); |
| } |
| |
| bool CompilerType::IsVoidType() const { |
| if (!IsValid()) |
| return false; |
| return m_type_system->IsVoidType(m_type); |
| } |
| |
| bool CompilerType::IsPointerToScalarType() const { |
| if (!IsValid()) |
| return false; |
| |
| return IsPointerType() && GetPointeeType().IsScalarType(); |
| } |
| |
| bool CompilerType::IsArrayOfScalarType() const { |
| CompilerType element_type; |
| if (IsArrayType(&element_type, nullptr, nullptr)) |
| return element_type.IsScalarType(); |
| return false; |
| } |
| |
| bool CompilerType::IsBeingDefined() const { |
| if (!IsValid()) |
| return false; |
| return m_type_system->IsBeingDefined(m_type); |
| } |
| |
| //---------------------------------------------------------------------- |
| // Type Completion |
| //---------------------------------------------------------------------- |
| |
| bool CompilerType::GetCompleteType() const { |
| if (!IsValid()) |
| return false; |
| return m_type_system->GetCompleteType(m_type); |
| } |
| |
| //---------------------------------------------------------------------- |
| // AST related queries |
| //---------------------------------------------------------------------- |
| size_t CompilerType::GetPointerByteSize() const { |
| if (m_type_system) |
| return m_type_system->GetPointerByteSize(); |
| return 0; |
| } |
| |
| ConstString CompilerType::GetConstQualifiedTypeName() const { |
| return GetConstTypeName(); |
| } |
| |
| ConstString CompilerType::GetConstTypeName() const { |
| if (IsValid()) { |
| ConstString type_name(GetTypeName()); |
| if (type_name) |
| return type_name; |
| } |
| return ConstString("<invalid>"); |
| } |
| |
| ConstString CompilerType::GetTypeName() const { |
| if (IsValid()) { |
| return m_type_system->GetTypeName(m_type); |
| } |
| return ConstString("<invalid>"); |
| } |
| |
| ConstString CompilerType::GetDisplayTypeName() const { return GetTypeName(); } |
| |
| uint32_t CompilerType::GetTypeInfo( |
| CompilerType *pointee_or_element_compiler_type) const { |
| if (!IsValid()) |
| return 0; |
| |
| return m_type_system->GetTypeInfo(m_type, pointee_or_element_compiler_type); |
| } |
| |
| lldb::LanguageType CompilerType::GetMinimumLanguage() { |
| if (!IsValid()) |
| return lldb::eLanguageTypeC; |
| |
| return m_type_system->GetMinimumLanguage(m_type); |
| } |
| |
| lldb::TypeClass CompilerType::GetTypeClass() const { |
| if (!IsValid()) |
| return lldb::eTypeClassInvalid; |
| |
| return m_type_system->GetTypeClass(m_type); |
| } |
| |
| void CompilerType::SetCompilerType(TypeSystem *type_system, |
| lldb::opaque_compiler_type_t type) { |
| m_type_system = type_system; |
| m_type = type; |
| } |
| |
| void CompilerType::SetCompilerType(clang::ASTContext *ast, |
| clang::QualType qual_type) { |
| m_type_system = ClangASTContext::GetASTContext(ast); |
| m_type = qual_type.getAsOpaquePtr(); |
| } |
| |
| unsigned CompilerType::GetTypeQualifiers() const { |
| if (IsValid()) |
| return m_type_system->GetTypeQualifiers(m_type); |
| return 0; |
| } |
| |
| //---------------------------------------------------------------------- |
| // Creating related types |
| //---------------------------------------------------------------------- |
| |
| CompilerType CompilerType::GetArrayElementType(uint64_t *stride) const { |
| if (IsValid()) { |
| return m_type_system->GetArrayElementType(m_type, stride); |
| } |
| return CompilerType(); |
| } |
| |
| CompilerType CompilerType::GetArrayType(uint64_t size) const { |
| if (IsValid()) { |
| return m_type_system->GetArrayType(m_type, size); |
| } |
| return CompilerType(); |
| } |
| |
| CompilerType CompilerType::GetCanonicalType() const { |
| if (IsValid()) |
| return m_type_system->GetCanonicalType(m_type); |
| return CompilerType(); |
| } |
| |
| CompilerType CompilerType::GetFullyUnqualifiedType() const { |
| if (IsValid()) |
| return m_type_system->GetFullyUnqualifiedType(m_type); |
| return CompilerType(); |
| } |
| |
| int CompilerType::GetFunctionArgumentCount() const { |
| if (IsValid()) { |
| return m_type_system->GetFunctionArgumentCount(m_type); |
| } |
| return -1; |
| } |
| |
| CompilerType CompilerType::GetFunctionArgumentTypeAtIndex(size_t idx) const { |
| if (IsValid()) { |
| return m_type_system->GetFunctionArgumentTypeAtIndex(m_type, idx); |
| } |
| return CompilerType(); |
| } |
| |
| CompilerType CompilerType::GetFunctionReturnType() const { |
| if (IsValid()) { |
| return m_type_system->GetFunctionReturnType(m_type); |
| } |
| return CompilerType(); |
| } |
| |
| size_t CompilerType::GetNumMemberFunctions() const { |
| if (IsValid()) { |
| return m_type_system->GetNumMemberFunctions(m_type); |
| } |
| return 0; |
| } |
| |
| TypeMemberFunctionImpl CompilerType::GetMemberFunctionAtIndex(size_t idx) { |
| if (IsValid()) { |
| return m_type_system->GetMemberFunctionAtIndex(m_type, idx); |
| } |
| return TypeMemberFunctionImpl(); |
| } |
| |
| CompilerType CompilerType::GetNonReferenceType() const { |
| if (IsValid()) |
| return m_type_system->GetNonReferenceType(m_type); |
| return CompilerType(); |
| } |
| |
| CompilerType CompilerType::GetPointeeType() const { |
| if (IsValid()) { |
| return m_type_system->GetPointeeType(m_type); |
| } |
| return CompilerType(); |
| } |
| |
| CompilerType CompilerType::GetPointerType() const { |
| if (IsValid()) { |
| return m_type_system->GetPointerType(m_type); |
| } |
| return CompilerType(); |
| } |
| |
| CompilerType CompilerType::GetLValueReferenceType() const { |
| if (IsValid()) |
| return m_type_system->GetLValueReferenceType(m_type); |
| else |
| return CompilerType(); |
| } |
| |
| CompilerType CompilerType::GetRValueReferenceType() const { |
| if (IsValid()) |
| return m_type_system->GetRValueReferenceType(m_type); |
| else |
| return CompilerType(); |
| } |
| |
| CompilerType CompilerType::AddConstModifier() const { |
| if (IsValid()) |
| return m_type_system->AddConstModifier(m_type); |
| else |
| return CompilerType(); |
| } |
| |
| CompilerType CompilerType::AddVolatileModifier() const { |
| if (IsValid()) |
| return m_type_system->AddVolatileModifier(m_type); |
| else |
| return CompilerType(); |
| } |
| |
| CompilerType CompilerType::AddRestrictModifier() const { |
| if (IsValid()) |
| return m_type_system->AddRestrictModifier(m_type); |
| else |
| return CompilerType(); |
| } |
| |
| CompilerType |
| CompilerType::CreateTypedef(const char *name, |
| const CompilerDeclContext &decl_ctx) const { |
| if (IsValid()) |
| return m_type_system->CreateTypedef(m_type, name, decl_ctx); |
| else |
| return CompilerType(); |
| } |
| |
| CompilerType CompilerType::GetTypedefedType() const { |
| if (IsValid()) |
| return m_type_system->GetTypedefedType(m_type); |
| else |
| return CompilerType(); |
| } |
| |
| //---------------------------------------------------------------------- |
| // Create related types using the current type's AST |
| //---------------------------------------------------------------------- |
| |
| CompilerType |
| CompilerType::GetBasicTypeFromAST(lldb::BasicType basic_type) const { |
| if (IsValid()) |
| return m_type_system->GetBasicTypeFromAST(basic_type); |
| return CompilerType(); |
| } |
| //---------------------------------------------------------------------- |
| // Exploring the type |
| //---------------------------------------------------------------------- |
| |
| uint64_t CompilerType::GetBitSize(ExecutionContextScope *exe_scope) const { |
| if (IsValid()) { |
| return m_type_system->GetBitSize(m_type, exe_scope); |
| } |
| return 0; |
| } |
| |
| uint64_t CompilerType::GetByteSize(ExecutionContextScope *exe_scope) const { |
| return (GetBitSize(exe_scope) + 7) / 8; |
| } |
| |
| size_t CompilerType::GetTypeBitAlign() const { |
| if (IsValid()) |
| return m_type_system->GetTypeBitAlign(m_type); |
| return 0; |
| } |
| |
| lldb::Encoding CompilerType::GetEncoding(uint64_t &count) const { |
| if (!IsValid()) |
| return lldb::eEncodingInvalid; |
| |
| return m_type_system->GetEncoding(m_type, count); |
| } |
| |
| lldb::Format CompilerType::GetFormat() const { |
| if (!IsValid()) |
| return lldb::eFormatDefault; |
| |
| return m_type_system->GetFormat(m_type); |
| } |
| |
| uint32_t CompilerType::GetNumChildren(bool omit_empty_base_classes) const { |
| if (!IsValid()) |
| return 0; |
| return m_type_system->GetNumChildren(m_type, omit_empty_base_classes); |
| } |
| |
| lldb::BasicType CompilerType::GetBasicTypeEnumeration() const { |
| if (IsValid()) |
| return m_type_system->GetBasicTypeEnumeration(m_type); |
| return eBasicTypeInvalid; |
| } |
| |
| void CompilerType::ForEachEnumerator( |
| std::function<bool(const CompilerType &integer_type, |
| const ConstString &name, |
| const llvm::APSInt &value)> const &callback) const { |
| if (IsValid()) |
| return m_type_system->ForEachEnumerator(m_type, callback); |
| } |
| |
| uint32_t CompilerType::GetNumFields() const { |
| if (!IsValid()) |
| return 0; |
| return m_type_system->GetNumFields(m_type); |
| } |
| |
| CompilerType CompilerType::GetFieldAtIndex(size_t idx, std::string &name, |
| uint64_t *bit_offset_ptr, |
| uint32_t *bitfield_bit_size_ptr, |
| bool *is_bitfield_ptr) const { |
| if (!IsValid()) |
| return CompilerType(); |
| return m_type_system->GetFieldAtIndex(m_type, idx, name, bit_offset_ptr, |
| bitfield_bit_size_ptr, is_bitfield_ptr); |
| } |
| |
| uint32_t CompilerType::GetNumDirectBaseClasses() const { |
| if (IsValid()) |
| return m_type_system->GetNumDirectBaseClasses(m_type); |
| return 0; |
| } |
| |
| uint32_t CompilerType::GetNumVirtualBaseClasses() const { |
| if (IsValid()) |
| return m_type_system->GetNumVirtualBaseClasses(m_type); |
| return 0; |
| } |
| |
| CompilerType |
| CompilerType::GetDirectBaseClassAtIndex(size_t idx, |
| uint32_t *bit_offset_ptr) const { |
| if (IsValid()) |
| return m_type_system->GetDirectBaseClassAtIndex(m_type, idx, |
| bit_offset_ptr); |
| return CompilerType(); |
| } |
| |
| CompilerType |
| CompilerType::GetVirtualBaseClassAtIndex(size_t idx, |
| uint32_t *bit_offset_ptr) const { |
| if (IsValid()) |
| return m_type_system->GetVirtualBaseClassAtIndex(m_type, idx, |
| bit_offset_ptr); |
| return CompilerType(); |
| } |
| |
| uint32_t CompilerType::GetIndexOfFieldWithName( |
| const char *name, CompilerType *field_compiler_type_ptr, |
| uint64_t *bit_offset_ptr, uint32_t *bitfield_bit_size_ptr, |
| bool *is_bitfield_ptr) const { |
| unsigned count = GetNumFields(); |
| std::string field_name; |
| for (unsigned index = 0; index < count; index++) { |
| CompilerType field_compiler_type( |
| GetFieldAtIndex(index, field_name, bit_offset_ptr, |
| bitfield_bit_size_ptr, is_bitfield_ptr)); |
| if (strcmp(field_name.c_str(), name) == 0) { |
| if (field_compiler_type_ptr) |
| *field_compiler_type_ptr = field_compiler_type; |
| return index; |
| } |
| } |
| return UINT32_MAX; |
| } |
| |
| CompilerType CompilerType::GetChildCompilerTypeAtIndex( |
| ExecutionContext *exe_ctx, size_t idx, bool transparent_pointers, |
| bool omit_empty_base_classes, bool ignore_array_bounds, |
| std::string &child_name, uint32_t &child_byte_size, |
| int32_t &child_byte_offset, uint32_t &child_bitfield_bit_size, |
| uint32_t &child_bitfield_bit_offset, bool &child_is_base_class, |
| bool &child_is_deref_of_parent, ValueObject *valobj, |
| uint64_t &language_flags) const { |
| if (!IsValid()) |
| return CompilerType(); |
| return m_type_system->GetChildCompilerTypeAtIndex( |
| m_type, exe_ctx, idx, transparent_pointers, omit_empty_base_classes, |
| ignore_array_bounds, child_name, child_byte_size, child_byte_offset, |
| child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class, |
| child_is_deref_of_parent, valobj, language_flags); |
| } |
| |
| // Look for a child member (doesn't include base classes, but it does include |
| // their members) in the type hierarchy. Returns an index path into |
| // "clang_type" on how to reach the appropriate member. |
| // |
| // class A |
| // { |
| // public: |
| // int m_a; |
| // int m_b; |
| // }; |
| // |
| // class B |
| // { |
| // }; |
| // |
| // class C : |
| // public B, |
| // public A |
| // { |
| // }; |
| // |
| // If we have a clang type that describes "class C", and we wanted to looked |
| // "m_b" in it: |
| // |
| // With omit_empty_base_classes == false we would get an integer array back |
| // with: { 1, 1 } The first index 1 is the child index for "class A" within |
| // class C The second index 1 is the child index for "m_b" within class A |
| // |
| // With omit_empty_base_classes == true we would get an integer array back |
| // with: { 0, 1 } The first index 0 is the child index for "class A" within |
| // class C (since class B doesn't have any members it doesn't count) The second |
| // index 1 is the child index for "m_b" within class A |
| |
| size_t CompilerType::GetIndexOfChildMemberWithName( |
| const char *name, bool omit_empty_base_classes, |
| std::vector<uint32_t> &child_indexes) const { |
| if (IsValid() && name && name[0]) { |
| return m_type_system->GetIndexOfChildMemberWithName( |
| m_type, name, omit_empty_base_classes, child_indexes); |
| } |
| return 0; |
| } |
| |
| size_t CompilerType::GetNumTemplateArguments() const { |
| if (IsValid()) { |
| return m_type_system->GetNumTemplateArguments(m_type); |
| } |
| return 0; |
| } |
| |
| TemplateArgumentKind CompilerType::GetTemplateArgumentKind(size_t idx) const { |
| if (IsValid()) |
| return m_type_system->GetTemplateArgumentKind(m_type, idx); |
| return eTemplateArgumentKindNull; |
| } |
| |
| CompilerType CompilerType::GetTypeTemplateArgument(size_t idx) const { |
| if (IsValid()) { |
| return m_type_system->GetTypeTemplateArgument(m_type, idx); |
| } |
| return CompilerType(); |
| } |
| |
| llvm::Optional<CompilerType::IntegralTemplateArgument> |
| CompilerType::GetIntegralTemplateArgument(size_t idx) const { |
| if (IsValid()) |
| return m_type_system->GetIntegralTemplateArgument(m_type, idx); |
| return llvm::None; |
| } |
| |
| CompilerType CompilerType::GetTypeForFormatters() const { |
| if (IsValid()) |
| return m_type_system->GetTypeForFormatters(m_type); |
| return CompilerType(); |
| } |
| |
| LazyBool CompilerType::ShouldPrintAsOneLiner(ValueObject *valobj) const { |
| if (IsValid()) |
| return m_type_system->ShouldPrintAsOneLiner(m_type, valobj); |
| return eLazyBoolCalculate; |
| } |
| |
| bool CompilerType::IsMeaninglessWithoutDynamicResolution() const { |
| if (IsValid()) |
| return m_type_system->IsMeaninglessWithoutDynamicResolution(m_type); |
| return false; |
| } |
| |
| // Get the index of the child of "clang_type" whose name matches. This function |
| // doesn't descend into the children, but only looks one level deep and name |
| // matches can include base class names. |
| |
| uint32_t |
| CompilerType::GetIndexOfChildWithName(const char *name, |
| bool omit_empty_base_classes) const { |
| if (IsValid() && name && name[0]) { |
| return m_type_system->GetIndexOfChildWithName(m_type, name, |
| omit_empty_base_classes); |
| } |
| return UINT32_MAX; |
| } |
| |
| size_t CompilerType::ConvertStringToFloatValue(const char *s, uint8_t *dst, |
| size_t dst_size) const { |
| if (IsValid()) |
| return m_type_system->ConvertStringToFloatValue(m_type, s, dst, dst_size); |
| return 0; |
| } |
| |
| //---------------------------------------------------------------------- |
| // Dumping types |
| //---------------------------------------------------------------------- |
| #define DEPTH_INCREMENT 2 |
| |
| void CompilerType::DumpValue(ExecutionContext *exe_ctx, Stream *s, |
| lldb::Format format, const DataExtractor &data, |
| lldb::offset_t data_byte_offset, |
| size_t data_byte_size, uint32_t bitfield_bit_size, |
| uint32_t bitfield_bit_offset, bool show_types, |
| bool show_summary, bool verbose, uint32_t depth) { |
| if (!IsValid()) |
| return; |
| m_type_system->DumpValue(m_type, exe_ctx, s, format, data, data_byte_offset, |
| data_byte_size, bitfield_bit_size, |
| bitfield_bit_offset, show_types, show_summary, |
| verbose, depth); |
| } |
| |
| bool CompilerType::DumpTypeValue(Stream *s, lldb::Format format, |
| const DataExtractor &data, |
| lldb::offset_t byte_offset, size_t byte_size, |
| uint32_t bitfield_bit_size, |
| uint32_t bitfield_bit_offset, |
| ExecutionContextScope *exe_scope) { |
| if (!IsValid()) |
| return false; |
| return m_type_system->DumpTypeValue(m_type, s, format, data, byte_offset, |
| byte_size, bitfield_bit_size, |
| bitfield_bit_offset, exe_scope); |
| } |
| |
| void CompilerType::DumpSummary(ExecutionContext *exe_ctx, Stream *s, |
| const DataExtractor &data, |
| lldb::offset_t data_byte_offset, |
| size_t data_byte_size) { |
| if (IsValid()) |
| m_type_system->DumpSummary(m_type, exe_ctx, s, data, data_byte_offset, |
| data_byte_size); |
| } |
| |
| void CompilerType::DumpTypeDescription() const { |
| if (IsValid()) |
| m_type_system->DumpTypeDescription(m_type); |
| } |
| |
| void CompilerType::DumpTypeDescription(Stream *s) const { |
| if (IsValid()) { |
| m_type_system->DumpTypeDescription(m_type, s); |
| } |
| } |
| |
| bool CompilerType::GetValueAsScalar(const lldb_private::DataExtractor &data, |
| lldb::offset_t data_byte_offset, |
| size_t data_byte_size, |
| Scalar &value) const { |
| if (!IsValid()) |
| return false; |
| |
| if (IsAggregateType()) { |
| return false; // Aggregate types don't have scalar values |
| } else { |
| uint64_t count = 0; |
| lldb::Encoding encoding = GetEncoding(count); |
| |
| if (encoding == lldb::eEncodingInvalid || count != 1) |
| return false; |
| |
| const uint64_t byte_size = GetByteSize(nullptr); |
| lldb::offset_t offset = data_byte_offset; |
| switch (encoding) { |
| case lldb::eEncodingInvalid: |
| break; |
| case lldb::eEncodingVector: |
| break; |
| case lldb::eEncodingUint: |
| if (byte_size <= sizeof(unsigned long long)) { |
| uint64_t uval64 = data.GetMaxU64(&offset, byte_size); |
| if (byte_size <= sizeof(unsigned int)) { |
| value = (unsigned int)uval64; |
| return true; |
| } else if (byte_size <= sizeof(unsigned long)) { |
| value = (unsigned long)uval64; |
| return true; |
| } else if (byte_size <= sizeof(unsigned long long)) { |
| value = (unsigned long long)uval64; |
| return true; |
| } else |
| value.Clear(); |
| } |
| break; |
| |
| case lldb::eEncodingSint: |
| if (byte_size <= sizeof(long long)) { |
| int64_t sval64 = data.GetMaxS64(&offset, byte_size); |
| if (byte_size <= sizeof(int)) { |
| value = (int)sval64; |
| return true; |
| } else if (byte_size <= sizeof(long)) { |
| value = (long)sval64; |
| return true; |
| } else if (byte_size <= sizeof(long long)) { |
| value = (long long)sval64; |
| return true; |
| } else |
| value.Clear(); |
| } |
| break; |
| |
| case lldb::eEncodingIEEE754: |
| if (byte_size <= sizeof(long double)) { |
| uint32_t u32; |
| uint64_t u64; |
| if (byte_size == sizeof(float)) { |
| if (sizeof(float) == sizeof(uint32_t)) { |
| u32 = data.GetU32(&offset); |
| value = *((float *)&u32); |
| return true; |
| } else if (sizeof(float) == sizeof(uint64_t)) { |
| u64 = data.GetU64(&offset); |
| value = *((float *)&u64); |
| return true; |
| } |
| } else if (byte_size == sizeof(double)) { |
| if (sizeof(double) == sizeof(uint32_t)) { |
| u32 = data.GetU32(&offset); |
| value = *((double *)&u32); |
| return true; |
| } else if (sizeof(double) == sizeof(uint64_t)) { |
| u64 = data.GetU64(&offset); |
| value = *((double *)&u64); |
| return true; |
| } |
| } else if (byte_size == sizeof(long double)) { |
| if (sizeof(long double) == sizeof(uint32_t)) { |
| u32 = data.GetU32(&offset); |
| value = *((long double *)&u32); |
| return true; |
| } else if (sizeof(long double) == sizeof(uint64_t)) { |
| u64 = data.GetU64(&offset); |
| value = *((long double *)&u64); |
| return true; |
| } |
| } |
| } |
| break; |
| } |
| } |
| return false; |
| } |
| |
| bool CompilerType::SetValueFromScalar(const Scalar &value, Stream &strm) { |
| if (!IsValid()) |
| return false; |
| |
| // Aggregate types don't have scalar values |
| if (!IsAggregateType()) { |
| strm.GetFlags().Set(Stream::eBinary); |
| uint64_t count = 0; |
| lldb::Encoding encoding = GetEncoding(count); |
| |
| if (encoding == lldb::eEncodingInvalid || count != 1) |
| return false; |
| |
| const uint64_t bit_width = GetBitSize(nullptr); |
| // This function doesn't currently handle non-byte aligned assignments |
| if ((bit_width % 8) != 0) |
| return false; |
| |
| const uint64_t byte_size = (bit_width + 7) / 8; |
| switch (encoding) { |
| case lldb::eEncodingInvalid: |
| break; |
| case lldb::eEncodingVector: |
| break; |
| case lldb::eEncodingUint: |
| switch (byte_size) { |
| case 1: |
| strm.PutHex8(value.UInt()); |
| return true; |
| case 2: |
| strm.PutHex16(value.UInt()); |
| return true; |
| case 4: |
| strm.PutHex32(value.UInt()); |
| return true; |
| case 8: |
| strm.PutHex64(value.ULongLong()); |
| return true; |
| default: |
| break; |
| } |
| break; |
| |
| case lldb::eEncodingSint: |
| switch (byte_size) { |
| case 1: |
| strm.PutHex8(value.SInt()); |
| return true; |
| case 2: |
| strm.PutHex16(value.SInt()); |
| return true; |
| case 4: |
| strm.PutHex32(value.SInt()); |
| return true; |
| case 8: |
| strm.PutHex64(value.SLongLong()); |
| return true; |
| default: |
| break; |
| } |
| break; |
| |
| case lldb::eEncodingIEEE754: |
| if (byte_size <= sizeof(long double)) { |
| if (byte_size == sizeof(float)) { |
| strm.PutFloat(value.Float()); |
| return true; |
| } else if (byte_size == sizeof(double)) { |
| strm.PutDouble(value.Double()); |
| return true; |
| } else if (byte_size == sizeof(long double)) { |
| strm.PutDouble(value.LongDouble()); |
| return true; |
| } |
| } |
| break; |
| } |
| } |
| return false; |
| } |
| |
| bool CompilerType::ReadFromMemory(lldb_private::ExecutionContext *exe_ctx, |
| lldb::addr_t addr, AddressType address_type, |
| lldb_private::DataExtractor &data) { |
| if (!IsValid()) |
| return false; |
| |
| // Can't convert a file address to anything valid without more context (which |
| // Module it came from) |
| if (address_type == eAddressTypeFile) |
| return false; |
| |
| if (!GetCompleteType()) |
| return false; |
| |
| const uint64_t byte_size = |
| GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); |
| if (data.GetByteSize() < byte_size) { |
| lldb::DataBufferSP data_sp(new DataBufferHeap(byte_size, '\0')); |
| data.SetData(data_sp); |
| } |
| |
| uint8_t *dst = const_cast<uint8_t *>(data.PeekData(0, byte_size)); |
| if (dst != nullptr) { |
| if (address_type == eAddressTypeHost) { |
| if (addr == 0) |
| return false; |
| // The address is an address in this process, so just copy it |
| memcpy(dst, reinterpret_cast<uint8_t *>(addr), byte_size); |
| return true; |
| } else { |
| Process *process = nullptr; |
| if (exe_ctx) |
| process = exe_ctx->GetProcessPtr(); |
| if (process) { |
| Status error; |
| return process->ReadMemory(addr, dst, byte_size, error) == byte_size; |
| } |
| } |
| } |
| return false; |
| } |
| |
| bool CompilerType::WriteToMemory(lldb_private::ExecutionContext *exe_ctx, |
| lldb::addr_t addr, AddressType address_type, |
| StreamString &new_value) { |
| if (!IsValid()) |
| return false; |
| |
| // Can't convert a file address to anything valid without more context (which |
| // Module it came from) |
| if (address_type == eAddressTypeFile) |
| return false; |
| |
| if (!GetCompleteType()) |
| return false; |
| |
| const uint64_t byte_size = |
| GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); |
| |
| if (byte_size > 0) { |
| if (address_type == eAddressTypeHost) { |
| // The address is an address in this process, so just copy it |
| memcpy((void *)addr, new_value.GetData(), byte_size); |
| return true; |
| } else { |
| Process *process = nullptr; |
| if (exe_ctx) |
| process = exe_ctx->GetProcessPtr(); |
| if (process) { |
| Status error; |
| return process->WriteMemory(addr, new_value.GetData(), byte_size, |
| error) == byte_size; |
| } |
| } |
| } |
| return false; |
| } |
| |
| // clang::CXXRecordDecl * |
| // CompilerType::GetAsCXXRecordDecl (lldb::opaque_compiler_type_t |
| // opaque_compiler_qual_type) |
| //{ |
| // if (opaque_compiler_qual_type) |
| // return |
| // clang::QualType::getFromOpaquePtr(opaque_compiler_qual_type)->getAsCXXRecordDecl(); |
| // return NULL; |
| //} |
| |
| bool lldb_private::operator==(const lldb_private::CompilerType &lhs, |
| const lldb_private::CompilerType &rhs) { |
| return lhs.GetTypeSystem() == rhs.GetTypeSystem() && |
| lhs.GetOpaqueQualType() == rhs.GetOpaqueQualType(); |
| } |
| |
| bool lldb_private::operator!=(const lldb_private::CompilerType &lhs, |
| const lldb_private::CompilerType &rhs) { |
| return lhs.GetTypeSystem() != rhs.GetTypeSystem() || |
| lhs.GetOpaqueQualType() != rhs.GetOpaqueQualType(); |
| } |