[Lldb-commits] [lldb] r169449 - in /lldb/trunk: source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h test/lang/c/bitfields/TestBitfields.py test/lang/c/bitfields/main.c

Sean Callanan scallanan at apple.com
Wed Dec 5 15:37:15 PST 2012


Author: spyffe
Date: Wed Dec  5 17:37:14 2012
New Revision: 169449

URL: http://llvm.org/viewvc/llvm-project?rev=169449&view=rev
Log:
Rewrote the bitfield logic.  Major changes include:

- Removed the BitfieldMap class because it is unnecessary.
  We now just track the most recently added field.

- Moved the code that calculates bitfield widths so it
  can also be used to determine whether it's necessary
  to insert anonymous fields.

- Simplified the anonymous field calculation code into
  three cases (two of which are resolved identically).

- Beefed up the bitfield testcase.

Modified:
    lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
    lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
    lldb/trunk/test/lang/c/bitfields/TestBitfields.py
    lldb/trunk/test/lang/c/bitfields/main.c

Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp?rev=169449&r1=169448&r2=169449&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp Wed Dec  5 17:37:14 2012
@@ -1550,6 +1550,24 @@
     std::auto_ptr<ClangASTMetadata>        m_metadata_ap;
 };
 
+struct BitfieldInfo
+{
+    uint64_t bit_size;
+    uint64_t bit_offset;
+    
+    BitfieldInfo () :
+        bit_size (LLDB_INVALID_ADDRESS),
+        bit_offset (LLDB_INVALID_ADDRESS)
+    {
+    }
+    
+    bool IsValid ()
+    {
+        return (bit_size != LLDB_INVALID_ADDRESS) &&
+               (bit_offset != LLDB_INVALID_ADDRESS);
+    }
+};
+
 size_t
 SymbolFileDWARF::ParseChildMembers
 (
@@ -1561,7 +1579,6 @@
     std::vector<clang::CXXBaseSpecifier *>& base_classes,
     std::vector<int>& member_accessibilities,
     DWARFDIECollection& member_function_dies,
-    BitfieldMap &bitfield_map,
     DelayedPropertyList& delayed_properties,
     AccessType& default_accessibility,
     bool &is_a_class,
@@ -1575,6 +1592,7 @@
     const DWARFDebugInfoEntry *die;
     const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (dwarf_cu->GetAddressByteSize());
     uint32_t member_idx = 0;
+    BitfieldInfo last_field_info;
 
     for (die = parent_die->GetFirstChild(); die != NULL; die = die->GetSibling())
     {
@@ -1764,12 +1782,68 @@
                                 if (accessibility == eAccessNone)
                                     accessibility = default_accessibility;
                                 member_accessibilities.push_back(accessibility);
+                                
+                                BitfieldInfo this_field_info;
+                        
+                                this_field_info.bit_size = bit_size;
+                                
+                                if (member_byte_offset != UINT32_MAX || bit_size != 0)
+                                {
+                                    /////////////////////////////////////////////////////////////
+                                    // How to locate a field given the DWARF debug information
+                                    //
+                                    // AT_byte_size indicates the size of the word in which the
+                                    // bit offset must be interpreted.
+                                    //
+                                    // AT_data_member_location indicates the byte offset of the
+                                    // word from the base address of the structure.
+                                    //
+                                    // AT_bit_offset indicates how many bits into the word
+                                    // (according to the host endianness) the low-order bit of
+                                    // the field starts.  AT_bit_offset can be negative.
+                                    //
+                                    // AT_bit_size indicates the size of the field in bits.
+                                    /////////////////////////////////////////////////////////////
+                                    
+                                    this_field_info.bit_offset = 0;
+                                    
+                                    this_field_info.bit_offset += (member_byte_offset == UINT32_MAX ? 0 : (member_byte_offset * 8));
+                                    
+                                    if (GetObjectFile()->GetByteOrder() == eByteOrderLittle)
+                                    {
+                                        this_field_info.bit_offset += byte_size * 8;
+                                        this_field_info.bit_offset -= (bit_offset + bit_size);
+                                    }
+                                    else
+                                    {
+                                        this_field_info.bit_offset += bit_offset;
+                                    }
+                                }
 
-                                // Code to detect unnamed bitifields
-                                if (bit_size > 0 && member_byte_offset != UINT32_MAX)
+                                // If the member to be emitted did not start on a character boundary and there is
+                                // empty space between the last field and this one, then we need to emit an
+                                // anonymous member filling up the space up to its start.  There are three cases
+                                // here:
+                                //
+                                // 1 If the previous member ended on a character boundary, then we can emit an
+                                //   anonymous member starting at the most recent character boundary.
+                                //
+                                // 2 If the previous member did not end on a character boundary and the distance
+                                //   from the end of the previous member to the current member is less than a
+                                //   word width, then we can emit an anonymous member starting right after the
+                                //   previous member and right before this member.
+                                //
+                                // 3 If the previous member did not end on a character boundary and the distance
+                                //   from the end of the previous member to the current member is greater than
+                                //   or equal a word width, then we act as in Case 1.
+                                
+                                const uint64_t character_width = 8;
+                                const uint64_t word_width = 32;
+                                
+                                if (this_field_info.IsValid())
                                 {
-                                    // Objective C has invalid DW_AT_bit_offset values in older versions
-                                    // of clang, so we have to be careful and only detect unnammed bitfields
+                                    // Objective-C has invalid DW_AT_bit_offset values in older versions
+                                    // of clang, so we have to be careful and only insert unnammed bitfields
                                     // if we have a new enough clang.
                                     bool detect_unnamed_bitfields = true;
                                     
@@ -1778,73 +1852,44 @@
                                     
                                     if (detect_unnamed_bitfields)
                                     {
-                                        // We have a bitfield, we need to watch out for
-                                        // unnamed bitfields that we need to insert if
-                                        // there is a gap in the bytes as many compilers
-                                        // doesn't emit DWARF DW_TAG_member tags for
-                                        // unnammed bitfields.
-                                        BitfieldMap::iterator bit_pos = bitfield_map.find(member_byte_offset);
-                                        uint32_t unnamed_bit_size = 0;
-                                        uint32_t unnamed_bit_offset = 0;
-                                        if (bit_pos == bitfield_map.end())
+                                        BitfieldInfo anon_field_info;
+                                        
+                                        if ((this_field_info.bit_offset % character_width) != 0) // not char aligned
                                         {
-                                            // First bitfield in an integral type.
+                                            uint64_t last_field_end = 0;
                                             
-                                            // We might need to insert a leading unnamed bitfield
-                                            if (bit_offset < byte_size * 8)
-                                            {
-                                                unnamed_bit_size = byte_size * 8 - (bit_size + bit_offset);
-                                                unnamed_bit_offset = byte_size * 8 - unnamed_bit_size;
-                                            }
+                                            if (last_field_info.IsValid())
+                                                last_field_end = last_field_info.bit_offset + last_field_info.bit_size;
                                             
-                                            // Now put the current bitfield info into the map
-                                            bitfield_map[member_byte_offset].bit_size = bit_size;
-                                            bitfield_map[member_byte_offset].bit_offset = bit_offset;
-                                        }
-                                        else
-                                        {
-                                            // Subsequent bitfield in an integral type.
-
-                                            // We have a bitfield that isn't the first for this
-                                            // integral type, check to make sure there aren't any
-                                            // gaps.
-                                            assert (bit_pos->second.bit_size > 0);
-                                            if (bit_offset < bit_pos->second.bit_offset)
-                                            {
-                                                unnamed_bit_size = bit_pos->second.bit_offset - (bit_size + bit_offset);
-                                                unnamed_bit_offset = bit_pos->second.bit_offset - unnamed_bit_size;
+                                            if (this_field_info.bit_offset != last_field_end)
+                                            {                                                
+                                                if (((last_field_end % character_width) == 0) ||                    // case 1
+                                                    (this_field_info.bit_offset - last_field_end >= word_width))    // case 3
+                                                {
+                                                    anon_field_info.bit_size = this_field_info.bit_offset % character_width;
+                                                    anon_field_info.bit_offset = this_field_info.bit_offset - anon_field_info.bit_size;
+                                                }
+                                                else                                                                // case 2
+                                                {
+                                                    anon_field_info.bit_size = this_field_info.bit_offset - last_field_end;
+                                                    anon_field_info.bit_offset = last_field_end;
+                                                }
                                             }
-
-                                            // Now put the current bitfield info into the map
-                                            bit_pos->second.bit_size = bit_size;
-                                            bit_pos->second.bit_offset = bit_offset;
                                         }
                                         
-                                        if (unnamed_bit_size > 0)
+                                        if (anon_field_info.IsValid())
                                         {
                                             clang::FieldDecl *unnamed_bitfield_decl = GetClangASTContext().AddFieldToRecordType (class_clang_type,
                                                                                                                                  NULL,
-                                                                                                                                 member_type->GetClangLayoutType(),
+                                                                                                                                 GetClangASTContext().GetBuiltinTypeForEncodingAndBitSize(eEncodingSint, word_width),
                                                                                                                                  accessibility,
-                                                                                                                                 unnamed_bit_size);
-                                            uint64_t total_bit_offset = 0;
-                                            
-                                            total_bit_offset += (member_byte_offset == UINT32_MAX ? 0 : (member_byte_offset * 8));
+                                                                                                                                 anon_field_info.bit_size);
                                             
-                                            if (GetObjectFile()->GetByteOrder() == eByteOrderLittle)
-                                            {
-                                                total_bit_offset += byte_size * 8;
-                                                total_bit_offset -= (unnamed_bit_offset + unnamed_bit_size);
-                                            }
-                                            else
-                                            {
-                                                total_bit_offset += unnamed_bit_size;
-                                            }
-                                            
-                                            layout_info.field_offsets.insert(std::make_pair(unnamed_bitfield_decl, total_bit_offset));
+                                            layout_info.field_offsets.insert(std::make_pair(unnamed_bitfield_decl, anon_field_info.bit_offset));
                                         }
                                     }
                                 }
+                                
                                 field_decl = GetClangASTContext().AddFieldToRecordType (class_clang_type,
                                                                                         name, 
                                                                                         member_type->GetClangLayoutType(), 
@@ -1852,6 +1897,12 @@
                                                                                         bit_size);
                                 
                                 GetClangASTContext().SetMetadataAsUserID ((uintptr_t)field_decl, MakeUserID(die->GetOffset()));
+                                
+                                if (this_field_info.IsValid())
+                                {
+                                    layout_info.field_offsets.insert(std::make_pair(field_decl, this_field_info.bit_offset));
+                                    last_field_info = this_field_info;
+                                }
                             }
                             else
                             {
@@ -1865,41 +1916,6 @@
                                                                                MakeUserID(die->GetOffset()),
                                                                                encoding_uid);
                             }
-
-                            if (member_byte_offset != UINT32_MAX || bit_size != 0)
-                            {
-                                /////////////////////////////////////////////////////////////
-                                // How to locate a field given the DWARF debug information
-                                //
-                                // AT_byte_size indicates the size of the word in which the
-                                // bit offset must be interpreted.
-                                //
-                                // AT_data_member_location indicates the byte offset of the
-                                // word from the base address of the structure.
-                                //
-                                // AT_bit_offset indicates how many bits into the word
-                                // (according to the host endianness) the low-order bit of
-                                // the field starts.  AT_bit_offset can be negative.
-                                //
-                                // AT_bit_size indicates the size of the field in bits.
-                                /////////////////////////////////////////////////////////////
-                                                        
-                                uint64_t total_bit_offset = 0;
-                                
-                                total_bit_offset += (member_byte_offset == UINT32_MAX ? 0 : (member_byte_offset * 8));
-                                
-                                if (GetObjectFile()->GetByteOrder() == eByteOrderLittle)
-                                {  
-                                    total_bit_offset += byte_size * 8;
-                                    total_bit_offset -= (bit_offset + bit_size);
-                                }
-                                else
-                                {
-                                    total_bit_offset += bit_offset;
-                                }
-                                                            
-                                layout_info.field_offsets.insert(std::make_pair(field_decl, total_bit_offset));
-                            }
                         }
                         
                         if (prop_name != NULL)
@@ -2251,7 +2267,6 @@
                     DWARFDIECollection member_function_dies;
                                         
                     DelayedPropertyList delayed_properties;
-                    BitfieldMap bitfield_map;
                     ParseChildMembers (sc,
                                        dwarf_cu,
                                        die, 
@@ -2260,7 +2275,6 @@
                                        base_classes, 
                                        member_accessibilities,
                                        member_function_dies,
-                                       bitfield_map,
                                        delayed_properties,
                                        default_accessibility, 
                                        is_a_class,

Modified: lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h?rev=169449&r1=169448&r2=169449&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h (original)
+++ lldb/trunk/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h Wed Dec  5 17:37:14 2012
@@ -59,18 +59,10 @@
 class DWARFFormValue;
 class SymbolFileDWARFDebugMap;
 
-struct BitfieldInfo
-{
-    uint32_t bit_size;
-    uint32_t bit_offset;
-};
-
-typedef std::map<int64_t, BitfieldInfo> BitfieldMap;
-
 class SymbolFileDWARF : public lldb_private::SymbolFile, public lldb_private::UserID
 {
 public:
-    friend class SymbolFileDWARFDebugMap;    
+    friend class SymbolFileDWARFDebugMap;
     friend class DebugMapModule;
     //------------------------------------------------------------------
     // Static Functions
@@ -353,7 +345,6 @@
                                 std::vector<clang::CXXBaseSpecifier *>& base_classes,
                                 std::vector<int>& member_accessibilities,
                                 DWARFDIECollection& member_function_dies,
-                                BitfieldMap &bitfield_map,
                                 DelayedPropertyList& delayed_properties,
                                 lldb::AccessType &default_accessibility,
                                 bool &is_a_class,

Modified: lldb/trunk/test/lang/c/bitfields/TestBitfields.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/c/bitfields/TestBitfields.py?rev=169449&r1=169448&r2=169449&view=diff
==============================================================================
--- lldb/trunk/test/lang/c/bitfields/TestBitfields.py (original)
+++ lldb/trunk/test/lang/c/bitfields/TestBitfields.py Wed Dec  5 17:37:14 2012
@@ -86,6 +86,39 @@
                        '(uint32_t:7) b7 = 127',
                        '(uint32_t:4) four = 15'])
 
+        self.expect("expr (bits.b1)", VARIABLES_DISPLAYED_CORRECTLY,
+            substrs = ['uint32_t', '1'])
+        self.expect("expr (bits.b2)", VARIABLES_DISPLAYED_CORRECTLY,
+            substrs = ['uint32_t', '3'])
+        self.expect("expr (bits.b3)", VARIABLES_DISPLAYED_CORRECTLY,
+            substrs = ['uint32_t', '7'])
+        self.expect("expr (bits.b4)", VARIABLES_DISPLAYED_CORRECTLY,
+            substrs = ['uint32_t', '15'])
+        self.expect("expr (bits.b5)", VARIABLES_DISPLAYED_CORRECTLY,
+            substrs = ['uint32_t', '31'])
+        self.expect("expr (bits.b6)", VARIABLES_DISPLAYED_CORRECTLY,
+            substrs = ['uint32_t', '63'])
+        self.expect("expr (bits.b7)", VARIABLES_DISPLAYED_CORRECTLY,
+            substrs = ['uint32_t', '127'])
+        self.expect("expr (bits.four)", VARIABLES_DISPLAYED_CORRECTLY,
+            substrs = ['uint32_t', '15'])
+
+        self.expect("frame variable --show-types more_bits", VARIABLES_DISPLAYED_CORRECTLY,
+            substrs = ['(uint32_t:3) a = 3',
+                       '(int:1)  = 0',
+                       '(uint8_t:1) b = \'\\0\'',
+                       '(uint8_t:1) c = \'\\x01\'',
+                       '(uint8_t:1) d = \'\\0\''])
+
+        self.expect("expr (more_bits.a)", VARIABLES_DISPLAYED_CORRECTLY,
+            substrs = ['uint32_t', '3'])
+        self.expect("expr (more_bits.b)", VARIABLES_DISPLAYED_CORRECTLY,
+            substrs = ['uint8_t', '\\0'])
+        self.expect("expr (more_bits.c)", VARIABLES_DISPLAYED_CORRECTLY,
+            substrs = ['uint8_t', '\\x01'])
+        self.expect("expr (more_bits.d)", VARIABLES_DISPLAYED_CORRECTLY,
+            substrs = ['uint8_t', '\\0'])
+
     def bitfields_variable_python(self):
         """Use Python APIs to inspect a bitfields variable."""
         exe = os.path.join(os.getcwd(), "a.out")

Modified: lldb/trunk/test/lang/c/bitfields/main.c
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/test/lang/c/bitfields/main.c?rev=169449&r1=169448&r2=169449&view=diff
==============================================================================
--- lldb/trunk/test/lang/c/bitfields/main.c (original)
+++ lldb/trunk/test/lang/c/bitfields/main.c Wed Dec  5 17:37:14 2012
@@ -45,6 +45,23 @@
         bits.b7 = i;        //// break $source:$line
     for (i=0; i<(1<<4); i++)
         bits.four = i;      //// break $source:$line
+
+    struct MoreBits
+    {
+        uint32_t    a : 3;
+        uint8_t       : 1;
+        uint8_t     b : 1;
+        uint8_t     c : 1;
+        uint8_t     d : 1;
+    };
+
+    struct MoreBits more_bits;
+
+    more_bits.a = 3;
+    more_bits.b = 0;
+    more_bits.c = 1;
+    more_bits.d = 0;
+
     return 0;               //// Set break point at this line.
 
 }





More information about the lldb-commits mailing list