<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
This commit is contained in:
Greg Clayton 2012-07-31 23:39:10 +00:00
parent d1c43cee24
commit 1811b4faad
7 changed files with 227 additions and 22 deletions

View File

@ -43,6 +43,12 @@ public:
uint64_t
GetOffsetInBits();
bool
IsBitfield();
uint32_t
GetBitfieldSizeInBits();
bool
GetDescription (lldb::SBStream &description,
lldb::DescriptionLevel description_level);

View File

@ -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);

View File

@ -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;
};

View File

@ -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.''')
%}
};

View File

@ -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;
}
@ -639,6 +641,23 @@ SBTypeMember::GetOffsetInBits()
return 0;
}
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)
{
@ -646,15 +665,25 @@ SBTypeMember::GetDescription (lldb::SBStream &description, lldb::DescriptionLeve
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
{

View File

@ -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

View File

@ -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;