summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGreg Clayton <gclayton@apple.com>2012-07-31 23:39:10 +0000
committerGreg Clayton <gclayton@apple.com>2012-07-31 23:39:10 +0000
commit1811b4faad9fd1496bde1d09bd336f9d9902dd78 (patch)
treea706d8b48c714fe427e6fb1320064796a73c3afc
parentd1c43cee245b56f34849821228e12b9437d97329 (diff)
downloadbcm5719-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.h6
-rw-r--r--lldb/include/lldb/Symbol/ClangASTContext.h4
-rw-r--r--lldb/include/lldb/Symbol/Type.h43
-rw-r--r--lldb/scripts/Python/interface/SBType.i87
-rw-r--r--lldb/source/API/SBType.cpp41
-rw-r--r--lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp18
-rw-r--r--lldb/source/Symbol/ClangASTContext.cpp50
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;
OpenPOWER on IntegriCloud