| //===-- 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/ConstString.h" |
| #include "lldb/Core/DataBufferHeap.h" |
| #include "lldb/Core/DataExtractor.h" |
| #include "lldb/Core/Debugger.h" |
| #include "lldb/Core/Scalar.h" |
| #include "lldb/Core/Stream.h" |
| #include "lldb/Core/StreamFile.h" |
| #include "lldb/Core/StreamString.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 <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::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; |
| } |
| |
| CompilerType |
| CompilerType::GetTemplateArgument (size_t idx, |
| lldb::TemplateArgumentKind &kind) const |
| { |
| if (IsValid()) |
| { |
| return m_type_system->GetTemplateArgument(m_type, idx, kind); |
| } |
| return CompilerType(); |
| } |
| |
| 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 lldb_private::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 lldb_private::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 lldb_private::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, (uint8_t*)nullptr + addr, byte_size); |
| return true; |
| } |
| else |
| { |
| Process *process = nullptr; |
| if (exe_ctx) |
| process = exe_ctx->GetProcessPtr(); |
| if (process) |
| { |
| Error 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) |
| { |
| Error 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(); |
| } |
| |
| |
| |