diff options
author | Greg Clayton <gclayton@apple.com> | 2012-07-31 23:39:10 +0000 |
---|---|---|
committer | Greg Clayton <gclayton@apple.com> | 2012-07-31 23:39:10 +0000 |
commit | 1811b4faad9fd1496bde1d09bd336f9d9902dd78 (patch) | |
tree | a706d8b48c714fe427e6fb1320064796a73c3afc | |
parent | d1c43cee245b56f34849821228e12b9437d97329 (diff) | |
download | bcm5719-llvm-1811b4faad9fd1496bde1d09bd336f9d9902dd78.tar.gz bcm5719-llvm-1811b4faad9fd1496bde1d09bd336f9d9902dd78.zip |
<rdar://problem/11275622>
Added new API to lldb::SBTypeMember for bitfields:
bool SBTypeMember::IsBitfield();
uint32_t SBTypeMember::GetBitfieldSizeInBits();
Also added new properties for easy access. Now SBTypeMember objects in python have a "fields" property for all type fields, "bases" for all direct bases, "vbases" for all virtual base classes and "members" for a combo of all three organized by bit offset. They all return a python list() of SBTypeMember objects. Usage:
(lldb) script
>>> t = lldb.target.FindFirstType("my_type")
>>> for field in t.fields:
... print field
>>> for vbase in t.vbases:
... print vbase
>>> for base in t.bases:
... print base
>>> for member in t.members:
... print member
Also added new "is_bitfield" property to the SBTypeMember objects that will return the result of SBTypeMember::IsBitfield(), and "bitfield_bit_size" which will return the result of SBTypeMember::GetBitfieldSizeInBits();
I also fixed "SBTypeMember::GetOffsetInBytes()" to return the correct byte offset.
llvm-svn: 161091
-rw-r--r-- | lldb/include/lldb/API/SBType.h | 6 | ||||
-rw-r--r-- | lldb/include/lldb/Symbol/ClangASTContext.h | 4 | ||||
-rw-r--r-- | lldb/include/lldb/Symbol/Type.h | 43 | ||||
-rw-r--r-- | lldb/scripts/Python/interface/SBType.i | 87 | ||||
-rw-r--r-- | lldb/source/API/SBType.cpp | 41 | ||||
-rw-r--r-- | lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp | 18 | ||||
-rw-r--r-- | lldb/source/Symbol/ClangASTContext.cpp | 50 |
7 files changed, 227 insertions, 22 deletions
diff --git a/lldb/include/lldb/API/SBType.h b/lldb/include/lldb/API/SBType.h index 9ad2e062a1b..cc582c1129f 100644 --- a/lldb/include/lldb/API/SBType.h +++ b/lldb/include/lldb/API/SBType.h @@ -44,6 +44,12 @@ public: GetOffsetInBits(); bool + IsBitfield(); + + uint32_t + GetBitfieldSizeInBits(); + + bool GetDescription (lldb::SBStream &description, lldb::DescriptionLevel description_level); diff --git a/lldb/include/lldb/Symbol/ClangASTContext.h b/lldb/include/lldb/Symbol/ClangASTContext.h index c88043b6803..67e907ee27d 100644 --- a/lldb/include/lldb/Symbol/ClangASTContext.h +++ b/lldb/include/lldb/Symbol/ClangASTContext.h @@ -603,7 +603,9 @@ public: lldb::clang_type_t clang_type, uint32_t idx, std::string& name, - uint32_t *bit_offset_ptr); + uint64_t *bit_offset_ptr, + uint32_t *bitfield_bit_size_ptr, + bool *is_bitfield_ptr); static uint32_t GetNumPointeeChildren (lldb::clang_type_t clang_type); diff --git a/lldb/include/lldb/Symbol/Type.h b/lldb/include/lldb/Symbol/Type.h index ba4b2ad6801..85940c61f7f 100644 --- a/lldb/include/lldb/Symbol/Type.h +++ b/lldb/include/lldb/Symbol/Type.h @@ -477,16 +477,23 @@ public: TypeMemberImpl () : m_type_impl_sp (), m_bit_offset (0), - m_name () + m_name (), + m_bitfield_bit_size (0), + m_is_bitfield (false) + { } TypeMemberImpl (const lldb::TypeImplSP &type_impl_sp, uint64_t bit_offset, - const ConstString &name) : + const ConstString &name, + uint32_t bitfield_bit_size = 0, + bool is_bitfield = false) : m_type_impl_sp (type_impl_sp), m_bit_offset (bit_offset), - m_name (name) + m_name (name), + m_bitfield_bit_size (bitfield_bit_size), + m_is_bitfield (is_bitfield) { } @@ -494,7 +501,9 @@ public: uint64_t bit_offset): m_type_impl_sp (type_impl_sp), m_bit_offset (bit_offset), - m_name () + m_name (), + m_bitfield_bit_size (0), + m_is_bitfield (false) { } @@ -516,10 +525,36 @@ public: return m_bit_offset; } + uint32_t + GetBitfieldBitSize () const + { + return m_bitfield_bit_size; + } + + void + SetBitfieldBitSize (uint32_t bitfield_bit_size) + { + m_bitfield_bit_size = bitfield_bit_size; + } + + bool + GetIsBitfield () const + { + return m_is_bitfield; + } + + void + SetIsBitfield (bool is_bitfield) + { + m_is_bitfield = is_bitfield; + } + protected: lldb::TypeImplSP m_type_impl_sp; uint64_t m_bit_offset; ConstString m_name; + uint32_t m_bitfield_bit_size; // Bit size for bitfield members only + bool m_is_bitfield; }; diff --git a/lldb/scripts/Python/interface/SBType.i b/lldb/scripts/Python/interface/SBType.i index c77788e678f..e2904f85a23 100644 --- a/lldb/scripts/Python/interface/SBType.i +++ b/lldb/scripts/Python/interface/SBType.i @@ -37,6 +37,12 @@ public: uint64_t GetOffsetInBits(); + bool + IsBitfield(); + + uint32_t + GetBitfieldSizeInBits(); + %pythoncode %{ __swig_getmethods__["name"] = GetName if _newclass: name = property(GetName, None, doc='''A read only property that returns the name for this member as a string.''') @@ -49,7 +55,14 @@ public: __swig_getmethods__["bit_offset"] = GetOffsetInBits if _newclass: bit_offset = property(GetOffsetInBits, None, doc='''A read only property that returns offset in bits for this member as an integer.''') - %} + + __swig_getmethods__["is_bitfield"] = IsBitfield + if _newclass: is_bitfield = property(IsBitfield, None, doc='''A read only property that returns true if this member is a bitfield.''') + + __swig_getmethods__["bitfield_bit_size"] = GetBitfieldSizeInBits + if _newclass: bitfield_bit_size = property(GetBitfieldSizeInBits, None, doc='''A read only property that returns the bitfield size in bits for this member as an integer, or zero if this member is not a bitfield.''') + + %} protected: std::auto_ptr<lldb_private::TypeMemberImpl> m_opaque_ap; @@ -245,6 +258,78 @@ public: __swig_getmethods__["is_complete"] = IsTypeComplete if _newclass: is_complete = property(IsTypeComplete, None, doc='''A read only property that returns a boolean value that indicates if this type is a complete type (True) or a forward declaration (False).''') + + def get_bases_array(self): + '''An accessor function that returns a list() that contains all direct base classes in a lldb.SBType object.''' + bases = [] + for idx in range(self.GetNumberOfDirectBaseClasses()): + bases.append(self.GetDirectBaseClassAtIndex(idx)) + return bases + + def get_vbases_array(self): + '''An accessor function that returns a list() that contains all fields in a lldb.SBType object.''' + vbases = [] + for idx in range(self.GetNumberOfVirtualBaseClasses()): + vbases.append(self.GetVirtualBaseClassAtIndex(idx)) + return vbases + + def get_fields_array(self): + '''An accessor function that returns a list() that contains all fields in a lldb.SBType object.''' + fields = [] + for idx in range(self.GetNumberOfFields()): + fields.append(self.GetFieldAtIndex(idx)) + return fields + + def get_members_array(self): + '''An accessor function that returns a list() that contains all members (base classes and fields) in a lldb.SBType object in ascending bit offset order.''' + members = [] + bases = self.get_bases_array() + fields = self.get_fields_array() + vbases = self.get_vbases_array() + for base in bases: + bit_offset = base.bit_offset + added = False + for idx, member in enumerate(members): + if member.bit_offset > bit_offset: + members.insert(idx, base) + added = True + break + if not added: + members.append(base) + for vbase in vbases: + bit_offset = vbase.bit_offset + added = False + for idx, member in enumerate(members): + if member.bit_offset > bit_offset: + members.insert(idx, vbase) + added = True + break + if not added: + members.append(vbase) + for field in fields: + bit_offset = field.bit_offset + added = False + for idx, member in enumerate(members): + if member.bit_offset > bit_offset: + members.insert(idx, field) + added = True + break + if not added: + members.append(field) + return members + + __swig_getmethods__["bases"] = get_bases_array + if _newclass: bases = property(get_bases_array, None, doc='''A read only property that returns a list() of lldb.SBTypeMember objects that represent all of the direct base classes for this type.''') + + __swig_getmethods__["vbases"] = get_vbases_array + if _newclass: vbases = property(get_vbases_array, None, doc='''A read only property that returns a list() of lldb.SBTypeMember objects that represent all of the virtual base classes for this type.''') + + __swig_getmethods__["fields"] = get_fields_array + if _newclass: fields = property(get_fields_array, None, doc='''A read only property that returns a list() of lldb.SBTypeMember objects that represent all of the fields for this type.''') + + __swig_getmethods__["members"] = get_members_array + if _newclass: members = property(get_members_array, None, doc='''A read only property that returns a list() of all lldb.SBTypeMember objects that represent all of the base classes, virtual base classes and fields for this type in ascending bit offset order.''') + %} }; diff --git a/lldb/source/API/SBType.cpp b/lldb/source/API/SBType.cpp index fa9d6b7b2f9..a65f29b779e 100644 --- a/lldb/source/API/SBType.cpp +++ b/lldb/source/API/SBType.cpp @@ -410,17 +410,19 @@ SBType::GetFieldAtIndex (uint32_t idx) SBTypeMember sb_type_member; if (IsValid()) { - uint32_t bit_offset = 0; + uint64_t bit_offset = 0; + uint32_t bitfield_bit_size = 0; + bool is_bitfield = false; clang::ASTContext* ast = m_opaque_sp->GetASTContext(); std::string name_sstr; - clang_type_t clang_type = ClangASTContext::GetFieldAtIndex (ast, m_opaque_sp->GetOpaqueQualType(), idx, name_sstr, &bit_offset); + clang_type_t clang_type = ClangASTContext::GetFieldAtIndex (ast, m_opaque_sp->GetOpaqueQualType(), idx, name_sstr, &bit_offset, &bitfield_bit_size, &is_bitfield); if (clang_type) { ConstString name; if (!name_sstr.empty()) name.SetCString(name_sstr.c_str()); TypeImplSP type_impl_sp (new TypeImpl(ClangASTType (ast, clang_type))); - sb_type_member.reset (new TypeMemberImpl (type_impl_sp, bit_offset, name)); + sb_type_member.reset (new TypeMemberImpl (type_impl_sp, bit_offset, name, bitfield_bit_size, is_bitfield)); } } return sb_type_member; @@ -627,7 +629,7 @@ uint64_t SBTypeMember::GetOffsetInBytes() { if (m_opaque_ap.get()) - return (m_opaque_ap->GetBitOffset() + 7) / 8u; + return m_opaque_ap->GetBitOffset() / 8u; return 0; } @@ -640,21 +642,48 @@ SBTypeMember::GetOffsetInBits() } bool +SBTypeMember::IsBitfield() +{ + if (m_opaque_ap.get()) + return m_opaque_ap->GetIsBitfield(); + return false; +} + +uint32_t +SBTypeMember::GetBitfieldSizeInBits() +{ + if (m_opaque_ap.get()) + return m_opaque_ap->GetBitfieldBitSize(); + return 0; +} + + +bool SBTypeMember::GetDescription (lldb::SBStream &description, lldb::DescriptionLevel description_level) { Stream &strm = description.ref(); if (m_opaque_ap.get()) { - const uint32_t byte_offset = (m_opaque_ap->GetBitOffset() + 7) / 8u; + const uint32_t bit_offset = m_opaque_ap->GetBitOffset(); + const uint32_t byte_offset = bit_offset / 8u; + const uint32_t byte_bit_offset = bit_offset % 8u; const char *name = m_opaque_ap->GetName().GetCString(); - strm.Printf ("+%u: (", byte_offset); + if (byte_bit_offset) + strm.Printf ("+%u + %u bits: (", byte_offset, byte_bit_offset); + else + strm.Printf ("+%u: (", byte_offset); TypeImplSP type_impl_sp (m_opaque_ap->GetTypeImpl()); if (type_impl_sp) type_impl_sp->GetDescription(strm, description_level); strm.Printf (") %s", name); + if (m_opaque_ap->GetIsBitfield()) + { + const uint32_t bitfield_bit_size = m_opaque_ap->GetBitfieldBitSize(); + strm.Printf (" : %u", bitfield_bit_size); + } } else { diff --git a/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp b/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp index 7b5631c1bca..677a4afede0 100644 --- a/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp +++ b/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp @@ -753,12 +753,12 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &ast_type for (uint32_t idx = 0; idx < num_children; idx++) { std::string name; - uint32_t field_bit_offset; + uint64_t field_bit_offset = 0; bool is_signed; bool is_complex; uint32_t count; - clang_type_t field_clang_type = ClangASTContext::GetFieldAtIndex (ast_context, ret_value_type, idx, name, &field_bit_offset); + clang_type_t field_clang_type = ClangASTContext::GetFieldAtIndex (ast_context, ret_value_type, idx, name, &field_bit_offset, NULL, NULL); size_t field_bit_width = ClangASTType::GetClangTypeBitWidth(ast_context, field_clang_type); // If there are any unaligned fields, this is stored in memory. @@ -840,12 +840,14 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &ast_type in_gpr = false; else { - uint32_t next_field_bit_offset; - clang_type_t next_field_clang_type = ClangASTContext::GetFieldAtIndex (ast_context, + uint64_t next_field_bit_offset = 0; + clang_type_t next_field_clang_type = ClangASTContext::GetFieldAtIndex (ast_context, ret_value_type, idx + 1, name, - &next_field_bit_offset); + &next_field_bit_offset, + NULL, + NULL); if (ClangASTContext::IsIntegerType (next_field_clang_type, is_signed)) in_gpr = true; else @@ -864,12 +866,14 @@ ABISysV_x86_64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &ast_type in_gpr = false; else { - uint32_t prev_field_bit_offset; + uint64_t prev_field_bit_offset = 0; clang_type_t prev_field_clang_type = ClangASTContext::GetFieldAtIndex (ast_context, ret_value_type, idx - 1, name, - &prev_field_bit_offset); + &prev_field_bit_offset, + NULL, + NULL); if (ClangASTContext::IsIntegerType (prev_field_clang_type, is_signed)) in_gpr = true; else diff --git a/lldb/source/Symbol/ClangASTContext.cpp b/lldb/source/Symbol/ClangASTContext.cpp index ca516c90d98..132ab60b34a 100644 --- a/lldb/source/Symbol/ClangASTContext.cpp +++ b/lldb/source/Symbol/ClangASTContext.cpp @@ -3499,7 +3499,9 @@ ClangASTContext::GetFieldAtIndex (clang::ASTContext *ast, clang_type_t clang_type, uint32_t idx, std::string& name, - uint32_t *bit_offset_ptr) + uint64_t *bit_offset_ptr, + uint32_t *bitfield_bit_size_ptr, + bool *is_bitfield_ptr) { if (clang_type == NULL) return 0; @@ -3531,6 +3533,25 @@ ClangASTContext::GetFieldAtIndex (clang::ASTContext *ast, *bit_offset_ptr = record_layout.getFieldOffset (field_idx); } + const bool is_bitfield = field->isBitField(); + + if (bitfield_bit_size_ptr) + { + *bitfield_bit_size_ptr = 0; + + if (is_bitfield && ast) + { + Expr *bitfield_bit_size_expr = field->getBitWidth(); + llvm::APSInt bitfield_apsint; + if (bitfield_bit_size_expr && bitfield_bit_size_expr->EvaluateAsInt(bitfield_apsint, *ast)) + { + *bitfield_bit_size_ptr = bitfield_apsint.getLimitedValue(); + } + } + } + if (is_bitfield_ptr) + *is_bitfield_ptr = is_bitfield; + return field->getType().getAsOpaquePtr(); } } @@ -3570,6 +3591,25 @@ ClangASTContext::GetFieldAtIndex (clang::ASTContext *ast, *bit_offset_ptr = interface_layout.getFieldOffset (ivar_idx); } + const bool is_bitfield = ivar_pos->isBitField(); + + if (bitfield_bit_size_ptr) + { + *bitfield_bit_size_ptr = 0; + + if (is_bitfield && ast) + { + Expr *bitfield_bit_size_expr = ivar_pos->getBitWidth(); + llvm::APSInt bitfield_apsint; + if (bitfield_bit_size_expr && bitfield_bit_size_expr->EvaluateAsInt(bitfield_apsint, *ast)) + { + *bitfield_bit_size_ptr = bitfield_apsint.getLimitedValue(); + } + } + } + if (is_bitfield_ptr) + *is_bitfield_ptr = is_bitfield; + return ivar_qual_type.getAsOpaquePtr(); } } @@ -3585,14 +3625,18 @@ ClangASTContext::GetFieldAtIndex (clang::ASTContext *ast, cast<TypedefType>(qual_type)->getDecl()->getUnderlyingType().getAsOpaquePtr(), idx, name, - bit_offset_ptr); + bit_offset_ptr, + bitfield_bit_size_ptr, + is_bitfield_ptr); case clang::Type::Elaborated: return ClangASTContext::GetFieldAtIndex (ast, cast<ElaboratedType>(qual_type)->getNamedType().getAsOpaquePtr(), idx, name, - bit_offset_ptr); + bit_offset_ptr, + bitfield_bit_size_ptr, + is_bitfield_ptr); default: break; |