forked from OSchip/llvm-project
<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:
parent
d1c43cee24
commit
1811b4faad
|
@ -43,6 +43,12 @@ public:
|
|||
uint64_t
|
||||
GetOffsetInBits();
|
||||
|
||||
bool
|
||||
IsBitfield();
|
||||
|
||||
uint32_t
|
||||
GetBitfieldSizeInBits();
|
||||
|
||||
bool
|
||||
GetDescription (lldb::SBStream &description,
|
||||
lldb::DescriptionLevel description_level);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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.''')
|
||||
|
||||
%}
|
||||
|
||||
};
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue