https://github.com/cmtice updated https://github.com/llvm/llvm-project/pull/73467
>From 70957429780c31c8981198967af254a4232ad3bc Mon Sep 17 00:00:00 2001 From: Caroline Tice <cmt...@google.com> Date: Sun, 26 Nov 2023 16:14:46 -0800 Subject: [PATCH 1/2] [LLDB] Add more helper functions to CompilerType class. This adds 23 new helper functions to LLDB's CompilerType class, things like IsSmartPtrType, IsPromotableIntegerType, GetNumberofNonEmptyBaseClasses, and GetTemplateArgumentType (to name a few). These helper functions are needed as part of the implementation for the Data Inspection Language, (see https://discourse.llvm.org/t/rfc-data-inspection-language/69893). --- lldb/include/lldb/Symbol/CompilerType.h | 49 +++++ lldb/source/Symbol/CompilerType.cpp | 252 ++++++++++++++++++++++++ 2 files changed, 301 insertions(+) diff --git a/lldb/include/lldb/Symbol/CompilerType.h b/lldb/include/lldb/Symbol/CompilerType.h index 0a9533a1ac0efc1..e02dfeb08b1d063 100644 --- a/lldb/include/lldb/Symbol/CompilerType.h +++ b/lldb/include/lldb/Symbol/CompilerType.h @@ -194,6 +194,55 @@ class CompilerType { bool IsTypedefType() const; bool IsVoidType() const; + + bool IsSmartPtrType() const; + + bool IsInteger() const; + + bool IsFloat() const; + + bool IsEnumerationType() const; + + bool IsUnscopedEnumerationType() const; + + bool IsIntegerOrUnscopedEnumerationType() const; + + bool IsSigned() const; + + bool IsNullPtrType() const; + + bool IsBoolean() const; + + bool IsEnumerationIntegerTypeSigned() const; + + bool IsScalarOrUnscopedEnumerationType() const; + + bool IsPromotableIntegerType() const; + + bool IsPointerToVoid() const; + + bool IsRecordType() const; + + bool IsVirtualBase(CompilerType target_base, + CompilerType *virtual_base, + bool carry_virtual = false) const; + + bool IsContextuallyConvertibleToBool() const; + + bool IsBasicType() const; + + std::string TypeDescription(); + + bool CompareTypes(CompilerType rhs) const; + + const char * GetTypeTag(); + + uint32_t GetNumberOfNonEmptyBaseClasses(); + + CompilerType GetTemplateArgumentType(uint32_t idx); + + CompilerType GetSmartPtrPointeeType(); + /// \} /// Type Completion. diff --git a/lldb/source/Symbol/CompilerType.cpp b/lldb/source/Symbol/CompilerType.cpp index 78cc8dad94a9c5f..f5c38a6f92d4151 100644 --- a/lldb/source/Symbol/CompilerType.cpp +++ b/lldb/source/Symbol/CompilerType.cpp @@ -302,6 +302,258 @@ bool CompilerType::IsBeingDefined() const { return false; } +bool CompilerType::IsSmartPtrType() const { + // These regular expressions cover shared, unique and weak pointers both from + // stdlibc++ and libc+++. + + static llvm::Regex k_libcxx_std_unique_ptr_regex( + "^std::__[[:alnum:]]+::unique_ptr<.+>(( )?&)?$"); + static llvm::Regex k_libcxx_std_shared_ptr_regex( + "^std::__[[:alnum:]]+::shared_ptr<.+>(( )?&)?$"); + static llvm::Regex k_libcxx_std_weak_ptr_regex( + "^std::__[[:alnum:]]+::weak_ptr<.+>(( )?&)?$"); + // + static llvm::Regex k_libcxx_std_unique_ptr_regex_2( + "^std::unique_ptr<.+>(( )?&)?$"); + static llvm::Regex k_libcxx_std_shared_ptr_regex_2( + "^std::shared_ptr<.+>(( )?&)?$"); + static llvm::Regex k_libcxx_std_weak_ptr_regex_2( + "^std::weak_ptr<.+>(( )?&)?$"); + // + llvm::StringRef name = GetTypeName(); + return k_libcxx_std_unique_ptr_regex.match(name) || + k_libcxx_std_shared_ptr_regex.match(name) || + k_libcxx_std_weak_ptr_regex.match(name) || + k_libcxx_std_unique_ptr_regex_2.match(name) || + k_libcxx_std_shared_ptr_regex_2.match(name) || + k_libcxx_std_weak_ptr_regex_2.match(name); +} + +bool CompilerType::IsInteger() const { + // This is used when you don't care about the signedness of the integer. + bool is_signed; + return IsIntegerType(is_signed); +} + +bool CompilerType::IsFloat() const { + uint32_t count = 0; + bool is_complex = false; + return IsFloatingPointType(count, is_complex); +} + +bool CompilerType::IsEnumerationType() const { + // This is used when you don't care about the signedness of the enum. + bool is_signed; + return IsEnumerationType(is_signed); +} + +bool CompilerType::IsUnscopedEnumerationType() const { + return IsEnumerationType() && !IsScopedEnumerationType(); +} + +bool CompilerType::IsIntegerOrUnscopedEnumerationType() const { + return IsInteger() || IsUnscopedEnumerationType(); +} + +bool CompilerType::IsSigned() const { + if (IsEnumerationType()) { + return IsEnumerationIntegerTypeSigned(); + } + return GetTypeInfo() & lldb::eTypeIsSigned; +} + +bool CompilerType::IsNullPtrType() const { + return GetCanonicalType().GetBasicTypeEnumeration() == + lldb::eBasicTypeNullPtr; +} + +bool CompilerType::IsBoolean() const { + return GetCanonicalType().GetBasicTypeEnumeration() == + lldb::eBasicTypeBool; +} + +bool CompilerType::IsEnumerationIntegerTypeSigned() const { + if (IsValid()) { + return GetEnumerationIntegerType().GetTypeInfo() + & lldb::eTypeIsSigned; + } + return false; +} + +bool CompilerType::IsScalarOrUnscopedEnumerationType() const { + return IsScalarType() || IsUnscopedEnumerationType(); +} + +bool CompilerType::IsPromotableIntegerType() const { + // Unscoped enums are always considered as promotable, even if their + // underlying type does not need to be promoted (e.g. "int"). + if (IsUnscopedEnumerationType()) { + return true; + } + + switch (GetCanonicalType().GetBasicTypeEnumeration()) { + case lldb::eBasicTypeBool: + case lldb::eBasicTypeChar: + case lldb::eBasicTypeSignedChar: + case lldb::eBasicTypeUnsignedChar: + case lldb::eBasicTypeShort: + case lldb::eBasicTypeUnsignedShort: + case lldb::eBasicTypeWChar: + case lldb::eBasicTypeSignedWChar: + case lldb::eBasicTypeUnsignedWChar: + case lldb::eBasicTypeChar16: + case lldb::eBasicTypeChar32: + return true; + + default: + return false; + } +} + +bool CompilerType::IsPointerToVoid() const { + if (!IsValid()) + return false; + + return IsPointerType() && + GetPointeeType().GetBasicTypeEnumeration() == lldb::eBasicTypeVoid; +} + +bool CompilerType::IsRecordType() const { + if (!IsValid()) + return false; + + return GetCanonicalType().GetTypeClass() & + (lldb::eTypeClassClass | lldb::eTypeClassStruct | lldb::eTypeClassUnion); +} + +// Checks whether `target_base` is a virtual base of `type` (direct or +// indirect). If it is, stores the first virtual base type on the path from +// `type` to `target_type`. +bool CompilerType::IsVirtualBase(CompilerType target_base, + CompilerType *virtual_base, + bool carry_virtual) const { + if (CompareTypes(target_base)) { + return carry_virtual; + } + + if (!carry_virtual) { + uint32_t num_virtual_bases = GetNumVirtualBaseClasses(); + for (uint32_t i = 0; i < num_virtual_bases; ++i) { + uint32_t bit_offset; + auto base = GetVirtualBaseClassAtIndex(i, &bit_offset); + if (base.IsVirtualBase(target_base, virtual_base, + /*carry_virtual*/ true)) { + if (virtual_base) { + *virtual_base = base; + } + return true; + } + } + } + + uint32_t num_direct_bases = GetNumDirectBaseClasses(); + for (uint32_t i = 0; i < num_direct_bases; ++i) { + uint32_t bit_offset; + auto base = GetDirectBaseClassAtIndex(i, &bit_offset); + if (base.IsVirtualBase(target_base, virtual_base, carry_virtual)) { + return true; + } + } + + return false; +} + +bool CompilerType::IsContextuallyConvertibleToBool() const { + return IsScalarType() || IsUnscopedEnumerationType() || IsPointerType() || + IsNullPtrType() || IsArrayType(); +} + +bool CompilerType::IsBasicType() const { + return GetCanonicalType().GetBasicTypeEnumeration() + != lldb::eBasicTypeInvalid; +} + +std::string CompilerType::TypeDescription() { + auto name = GetTypeName(); + auto canonical_name = GetCanonicalType().GetTypeName(); + if (name.IsEmpty() || canonical_name.IsEmpty()) { + return "''"; // should not happen + } + if (name == canonical_name) { + return llvm::formatv("'{0}'", name); + } + return llvm::formatv("'{0}' (aka '{1}')", name, canonical_name); +} + +bool CompilerType::CompareTypes(CompilerType rhs) const { + if (*this == rhs) + return true; + + const ConstString name = GetFullyUnqualifiedType().GetTypeName(); + const ConstString rhs_name = rhs.GetFullyUnqualifiedType().GetTypeName(); + return name == rhs_name; +} + +const char * CompilerType::GetTypeTag() { + switch (GetTypeClass()) { + // clang-format off + case lldb::eTypeClassClass: return "class"; + case lldb::eTypeClassEnumeration: return "enum"; + case lldb::eTypeClassStruct: return "struct"; + case lldb::eTypeClassUnion: return "union"; + // clang-format on + default: + return "unknown"; + } +} + +uint32_t CompilerType::GetNumberOfNonEmptyBaseClasses() { + // Go through the base classes and count non-empty ones. + uint32_t ret = 0; + uint32_t num_direct_bases = GetNumDirectBaseClasses(); + + for (uint32_t i = 0; i < num_direct_bases; ++i) { + uint32_t bit_offset; + CompilerType base_type = GetDirectBaseClassAtIndex(i, &bit_offset); + if (base_type.GetNumFields() > 0 || + base_type.GetNumberOfNonEmptyBaseClasses() > 0) { + ret += 1; + } + } + return ret; +} + +CompilerType CompilerType::GetTemplateArgumentType(uint32_t idx) +{ + CompilerType empty_type; + if (!IsValid()) + return empty_type; + + CompilerType type; + const bool expand_pack = true; + switch(GetTemplateArgumentKind(idx, true)) { + case lldb::eTemplateArgumentKindType: + type = GetTypeTemplateArgument(idx, expand_pack); + break; + case lldb::eTemplateArgumentKindIntegral: + type = GetIntegralTemplateArgument(idx, expand_pack)->type; + break; + default: + break; + } + if (type.IsValid()) + return type; + return empty_type; +} + +CompilerType CompilerType::GetSmartPtrPointeeType() { + assert(IsSmartPtrType() && + "the type should be a smart pointer (std::unique_ptr, std::shared_ptr " + "or std::weak_ptr"); + + return GetTemplateArgumentType(0); +} + // Type Completion bool CompilerType::GetCompleteType() const { >From a429d50cf4e586fdbbb5403d2b60fb80269873d0 Mon Sep 17 00:00:00 2001 From: Caroline Tice <cmt...@google.com> Date: Sun, 26 Nov 2023 16:32:59 -0800 Subject: [PATCH 2/2] [LLDB] Add more helper functions to CompilerType class. Fix clang format issues. --- lldb/include/lldb/Symbol/CompilerType.h | 13 +-- lldb/source/Symbol/CompilerType.cpp | 117 ++++++++++++------------ 2 files changed, 64 insertions(+), 66 deletions(-) diff --git a/lldb/include/lldb/Symbol/CompilerType.h b/lldb/include/lldb/Symbol/CompilerType.h index e02dfeb08b1d063..a3331ad3269c01d 100644 --- a/lldb/include/lldb/Symbol/CompilerType.h +++ b/lldb/include/lldb/Symbol/CompilerType.h @@ -112,9 +112,7 @@ class CompilerType { /// Tests. /// \{ - explicit operator bool() const { - return m_type_system.lock() && m_type; - } + explicit operator bool() const { return m_type_system.lock() && m_type; } bool IsValid() const { return (bool)*this; } @@ -223,8 +221,7 @@ class CompilerType { bool IsRecordType() const; - bool IsVirtualBase(CompilerType target_base, - CompilerType *virtual_base, + bool IsVirtualBase(CompilerType target_base, CompilerType *virtual_base, bool carry_virtual = false) const; bool IsContextuallyConvertibleToBool() const; @@ -235,7 +232,7 @@ class CompilerType { bool CompareTypes(CompilerType rhs) const; - const char * GetTypeTag(); + const char *GetTypeTag(); uint32_t GetNumberOfNonEmptyBaseClasses(); @@ -485,8 +482,8 @@ class CompilerType { ExecutionContextScope *exe_scope); /// Dump to stdout. - void DumpTypeDescription(lldb::DescriptionLevel level = - lldb::eDescriptionLevelFull) const; + void DumpTypeDescription( + lldb::DescriptionLevel level = lldb::eDescriptionLevelFull) const; /// Print a description of the type to a stream. The exact implementation /// varies, but the expectation is that eDescriptionLevelFull returns a diff --git a/lldb/source/Symbol/CompilerType.cpp b/lldb/source/Symbol/CompilerType.cpp index f5c38a6f92d4151..854d6cab01b508e 100644 --- a/lldb/source/Symbol/CompilerType.cpp +++ b/lldb/source/Symbol/CompilerType.cpp @@ -54,7 +54,7 @@ bool CompilerType::IsArrayType(CompilerType *element_type_ptr, uint64_t *size, if (IsValid()) if (auto type_system_sp = GetTypeSystem()) return type_system_sp->IsArrayType(m_type, element_type_ptr, size, - is_incomplete); + is_incomplete); if (element_type_ptr) element_type_ptr->Clear(); @@ -157,7 +157,8 @@ bool CompilerType::IsBlockPointerType( CompilerType *function_pointer_type_ptr) const { if (IsValid()) if (auto type_system_sp = GetTypeSystem()) - return type_system_sp->IsBlockPointerType(m_type, function_pointer_type_ptr); + return type_system_sp->IsBlockPointerType(m_type, + function_pointer_type_ptr); return false; } @@ -249,7 +250,7 @@ bool CompilerType::IsPossibleDynamicType(CompilerType *dynamic_pointee_type, if (IsValid()) if (auto type_system_sp = GetTypeSystem()) return type_system_sp->IsPossibleDynamicType(m_type, dynamic_pointee_type, - check_cplusplus, check_objc); + check_cplusplus, check_objc); return false; } @@ -323,7 +324,7 @@ bool CompilerType::IsSmartPtrType() const { llvm::StringRef name = GetTypeName(); return k_libcxx_std_unique_ptr_regex.match(name) || k_libcxx_std_shared_ptr_regex.match(name) || - k_libcxx_std_weak_ptr_regex.match(name) || + k_libcxx_std_weak_ptr_regex.match(name) || k_libcxx_std_unique_ptr_regex_2.match(name) || k_libcxx_std_shared_ptr_regex_2.match(name) || k_libcxx_std_weak_ptr_regex_2.match(name); @@ -364,18 +365,16 @@ bool CompilerType::IsSigned() const { bool CompilerType::IsNullPtrType() const { return GetCanonicalType().GetBasicTypeEnumeration() == - lldb::eBasicTypeNullPtr; + lldb::eBasicTypeNullPtr; } bool CompilerType::IsBoolean() const { - return GetCanonicalType().GetBasicTypeEnumeration() == - lldb::eBasicTypeBool; + return GetCanonicalType().GetBasicTypeEnumeration() == lldb::eBasicTypeBool; } bool CompilerType::IsEnumerationIntegerTypeSigned() const { if (IsValid()) { - return GetEnumerationIntegerType().GetTypeInfo() - & lldb::eTypeIsSigned; + return GetEnumerationIntegerType().GetTypeInfo() & lldb::eTypeIsSigned; } return false; } @@ -392,21 +391,21 @@ bool CompilerType::IsPromotableIntegerType() const { } switch (GetCanonicalType().GetBasicTypeEnumeration()) { - case lldb::eBasicTypeBool: - case lldb::eBasicTypeChar: - case lldb::eBasicTypeSignedChar: - case lldb::eBasicTypeUnsignedChar: - case lldb::eBasicTypeShort: - case lldb::eBasicTypeUnsignedShort: - case lldb::eBasicTypeWChar: - case lldb::eBasicTypeSignedWChar: - case lldb::eBasicTypeUnsignedWChar: - case lldb::eBasicTypeChar16: - case lldb::eBasicTypeChar32: - return true; + case lldb::eBasicTypeBool: + case lldb::eBasicTypeChar: + case lldb::eBasicTypeSignedChar: + case lldb::eBasicTypeUnsignedChar: + case lldb::eBasicTypeShort: + case lldb::eBasicTypeUnsignedShort: + case lldb::eBasicTypeWChar: + case lldb::eBasicTypeSignedWChar: + case lldb::eBasicTypeUnsignedWChar: + case lldb::eBasicTypeChar16: + case lldb::eBasicTypeChar32: + return true; - default: - return false; + default: + return false; } } @@ -415,7 +414,7 @@ bool CompilerType::IsPointerToVoid() const { return false; return IsPointerType() && - GetPointeeType().GetBasicTypeEnumeration() == lldb::eBasicTypeVoid; + GetPointeeType().GetBasicTypeEnumeration() == lldb::eBasicTypeVoid; } bool CompilerType::IsRecordType() const { @@ -423,7 +422,8 @@ bool CompilerType::IsRecordType() const { return false; return GetCanonicalType().GetTypeClass() & - (lldb::eTypeClassClass | lldb::eTypeClassStruct | lldb::eTypeClassUnion); + (lldb::eTypeClassClass | lldb::eTypeClassStruct | + lldb::eTypeClassUnion); } // Checks whether `target_base` is a virtual base of `type` (direct or @@ -465,19 +465,19 @@ bool CompilerType::IsVirtualBase(CompilerType target_base, bool CompilerType::IsContextuallyConvertibleToBool() const { return IsScalarType() || IsUnscopedEnumerationType() || IsPointerType() || - IsNullPtrType() || IsArrayType(); + IsNullPtrType() || IsArrayType(); } bool CompilerType::IsBasicType() const { - return GetCanonicalType().GetBasicTypeEnumeration() - != lldb::eBasicTypeInvalid; + return GetCanonicalType().GetBasicTypeEnumeration() != + lldb::eBasicTypeInvalid; } std::string CompilerType::TypeDescription() { auto name = GetTypeName(); auto canonical_name = GetCanonicalType().GetTypeName(); if (name.IsEmpty() || canonical_name.IsEmpty()) { - return "''"; // should not happen + return "''"; // should not happen } if (name == canonical_name) { return llvm::formatv("'{0}'", name); @@ -494,16 +494,16 @@ bool CompilerType::CompareTypes(CompilerType rhs) const { return name == rhs_name; } -const char * CompilerType::GetTypeTag() { +const char *CompilerType::GetTypeTag() { switch (GetTypeClass()) { - // clang-format off + // clang-format off case lldb::eTypeClassClass: return "class"; case lldb::eTypeClassEnumeration: return "enum"; case lldb::eTypeClassStruct: return "struct"; case lldb::eTypeClassUnion: return "union"; - // clang-format on - default: - return "unknown"; + // clang-format on + default: + return "unknown"; } } @@ -523,23 +523,22 @@ uint32_t CompilerType::GetNumberOfNonEmptyBaseClasses() { return ret; } -CompilerType CompilerType::GetTemplateArgumentType(uint32_t idx) -{ +CompilerType CompilerType::GetTemplateArgumentType(uint32_t idx) { CompilerType empty_type; if (!IsValid()) return empty_type; CompilerType type; const bool expand_pack = true; - switch(GetTemplateArgumentKind(idx, true)) { - case lldb::eTemplateArgumentKindType: - type = GetTypeTemplateArgument(idx, expand_pack); - break; - case lldb::eTemplateArgumentKindIntegral: - type = GetIntegralTemplateArgument(idx, expand_pack)->type; - break; - default: - break; + switch (GetTemplateArgumentKind(idx, true)) { + case lldb::eTemplateArgumentKindType: + type = GetTypeTemplateArgument(idx, expand_pack); + break; + case lldb::eTemplateArgumentKindIntegral: + type = GetIntegralTemplateArgument(idx, expand_pack)->type; + break; + default: + break; } if (type.IsValid()) return type; @@ -588,9 +587,9 @@ ConstString CompilerType::GetDisplayTypeName() const { uint32_t CompilerType::GetTypeInfo( CompilerType *pointee_or_element_compiler_type) const { if (IsValid()) - if (auto type_system_sp = GetTypeSystem()) - return type_system_sp->GetTypeInfo(m_type, - pointee_or_element_compiler_type); + if (auto type_system_sp = GetTypeSystem()) + return type_system_sp->GetTypeInfo(m_type, + pointee_or_element_compiler_type); return 0; } @@ -614,8 +613,9 @@ void CompilerType::SetCompilerType(lldb::TypeSystemWP type_system, m_type = type; } -void CompilerType::SetCompilerType(CompilerType::TypeSystemSPWrapper type_system, - lldb::opaque_compiler_type_t type) { +void CompilerType::SetCompilerType( + CompilerType::TypeSystemSPWrapper type_system, + lldb::opaque_compiler_type_t type) { m_type_system = type_system.GetSharedPointer(); m_type = type; } @@ -841,7 +841,7 @@ uint32_t CompilerType::GetNumChildren(bool omit_empty_base_classes, if (IsValid()) if (auto type_system_sp = GetTypeSystem()) return type_system_sp->GetNumChildren(m_type, omit_empty_base_classes, - exe_ctx); + exe_ctx); return 0; } @@ -853,8 +853,7 @@ lldb::BasicType CompilerType::GetBasicTypeEnumeration() const { } void CompilerType::ForEachEnumerator( - std::function<bool(const CompilerType &integer_type, - ConstString name, + std::function<bool(const CompilerType &integer_type, ConstString name, const llvm::APSInt &value)> const &callback) const { if (IsValid()) if (auto type_system_sp = GetTypeSystem()) @@ -875,7 +874,8 @@ CompilerType CompilerType::GetFieldAtIndex(size_t idx, std::string &name, if (IsValid()) if (auto type_system_sp = GetTypeSystem()) return type_system_sp->GetFieldAtIndex(m_type, idx, name, bit_offset_ptr, - bitfield_bit_size_ptr, is_bitfield_ptr); + bitfield_bit_size_ptr, + is_bitfield_ptr); return CompilerType(); } @@ -899,7 +899,7 @@ CompilerType::GetDirectBaseClassAtIndex(size_t idx, if (IsValid()) if (auto type_system_sp = GetTypeSystem()) return type_system_sp->GetDirectBaseClassAtIndex(m_type, idx, - bit_offset_ptr); + bit_offset_ptr); return CompilerType(); } @@ -909,7 +909,7 @@ CompilerType::GetVirtualBaseClassAtIndex(size_t idx, if (IsValid()) if (auto type_system_sp = GetTypeSystem()) return type_system_sp->GetVirtualBaseClassAtIndex(m_type, idx, - bit_offset_ptr); + bit_offset_ptr); return CompilerType(); } @@ -990,7 +990,7 @@ size_t CompilerType::GetIndexOfChildMemberWithName( if (IsValid() && !name.empty()) { if (auto type_system_sp = GetTypeSystem()) return type_system_sp->GetIndexOfChildMemberWithName( - m_type, name, omit_empty_base_classes, child_indexes); + m_type, name, omit_empty_base_classes, child_indexes); } return 0; } @@ -1024,7 +1024,8 @@ std::optional<CompilerType::IntegralTemplateArgument> CompilerType::GetIntegralTemplateArgument(size_t idx, bool expand_pack) const { if (IsValid()) if (auto type_system_sp = GetTypeSystem()) - return type_system_sp->GetIntegralTemplateArgument(m_type, idx, expand_pack); + return type_system_sp->GetIntegralTemplateArgument(m_type, idx, + expand_pack); return std::nullopt; } _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits