C++ PATCH: very long bitfields

Mark Mitchell mark@codesourcery.com
Sat Mar 18 16:59:00 GMT 2000


In C++, things like:

  struct S { int i : 2057; };

are legal, even if an `int' has fewer than 2057 bits.  We used to be
`sorry' if the bitfield was wider than an `unsigned long long'; now,
we handle it appropriately.  This patch also implements appropriate
handling of bitfields that are longer than their types in the new ABI,
which has specific layout instructions about constructs we did handle
before, like:

  struct S { short s : 32; }

for targetrs where `short' has two bytes.

--
Mark Mitchell                   mark@codesourcery.com
CodeSourcery, LLC               http://www.codesourcery.com

2000-03-18  Mark Mitchell  <mark@codesourcery.com>

	* class.c (check_bitfield_decl): Remove restriction on really long
	bitfields.
	(layout_class_type): Implement new ABI handling of bitfields
	longer than their types.

Index: testsuite/g++.old-deja/g++.other/bitfld5.C
===================================================================
RCS file: bitfld5.C
diff -N bitfld5.C
*** /dev/null	Tue May  5 13:32:27 1998
--- bitfld5.C	Sat Mar 18 16:53:41 2000
***************
*** 0 ****
--- 1,7 ----
+ // Build don't link:
+ // Special g++ Options: -w
+ 
+ struct S
+ {
+   int i : 1756;
+ };
Index: cp/class.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/cp/class.c,v
retrieving revision 1.271
diff -c -p -r1.271 class.c
*** class.c	2000/03/18 10:28:02	1.271
--- class.c	2000/03/19 00:32:22
*************** check_bitfield_decl (field)
*** 3658,3674 ****
  	  DECL_INITIAL (field) = NULL;
  	  cp_error_at ("zero width for bit-field `%D'", field);
  	}
-       else if (0 < compare_tree_int (w,
- 				     TYPE_PRECISION
- 				     (long_long_unsigned_type_node)))
- 	{
- 	  /* The backend will dump if you try to use something too
- 	     big; avoid that.  */
- 	  DECL_INITIAL (field) = NULL;
- 	  sorry ("bit-fields larger than %d bits",
- 		 TYPE_PRECISION (long_long_unsigned_type_node));
- 	  cp_error_at ("  in declaration of `%D'", field);
- 	}
        else if (compare_tree_int (w, TYPE_PRECISION (type)) > 0
  	       && TREE_CODE (type) != ENUMERAL_TYPE
  	       && TREE_CODE (type) != BOOLEAN_TYPE)
--- 3658,3663 ----
*************** dfs_search_base_offsets (binfo, data)
*** 4168,4175 ****
     non-static data member of the type indicated by RLI.  BINFO is the
     binfo corresponding to the base subobject, or, if this is a
     non-static data-member, a dummy BINFO for the type of the data
!    member.  V maps offsets to types already located at those offsets.
!    This function determines the position of the DECL.  */
  
  static void
  layout_nonempty_base_or_field (rli, decl, binfo, v)
--- 4157,4166 ----
     non-static data member of the type indicated by RLI.  BINFO is the
     binfo corresponding to the base subobject, or, if this is a
     non-static data-member, a dummy BINFO for the type of the data
!    member.  BINFO may be NULL if checks to see if the field overlaps
!    an existing field with the same type are not required.  V maps
!    offsets to types already located at those offsets.  This function
!    determines the position of the DECL.  */
  
  static void
  layout_nonempty_base_or_field (rli, decl, binfo, v)
*************** layout_nonempty_base_or_field (rli, decl
*** 4192,4198 ****
  	 BINFO_OFFSET.  */
        offset = size_int (CEIL (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (decl)),
  			       BITS_PER_UNIT));
!       propagate_binfo_offsets (binfo, offset);
   
        /* We have to check to see whether or not there is already
  	 something of the same type at the offset we're about to use.
--- 4183,4190 ----
  	 BINFO_OFFSET.  */
        offset = size_int (CEIL (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (decl)),
  			       BITS_PER_UNIT));
!       if (binfo)
! 	propagate_binfo_offsets (binfo, offset);
   
        /* We have to check to see whether or not there is already
  	 something of the same type at the offset we're about to use.
*************** layout_nonempty_base_or_field (rli, decl
*** 4209,4218 ****
  	 empty class, have non-zero size, any overlap can happen only
  	 with a direct or indirect base-class -- it can't happen with
  	 a data member.  */
!       if (flag_new_abi && dfs_walk (binfo,
! 				    dfs_search_base_offsets,
! 				    dfs_skip_vbases,
! 				    v))
  	{
  	  /* Undo the propogate_binfo_offsets call.  */
  	  offset = convert (sizetype,
--- 4201,4210 ----
  	 empty class, have non-zero size, any overlap can happen only
  	 with a direct or indirect base-class -- it can't happen with
  	 a data member.  */
!       if (binfo && flag_new_abi && dfs_walk (binfo,
! 					     dfs_search_base_offsets,
! 					     dfs_skip_vbases,
! 					     v))
  	{
  	  /* Undo the propogate_binfo_offsets call.  */
  	  offset = convert (sizetype,
*************** layout_class_type (t, empty_p, has_virtu
*** 4930,4935 ****
--- 4922,4929 ----
         field = TREE_CHAIN (field))
      {
        tree binfo;
+       tree type;
+       tree padding;
  
        /* We still pass things that aren't non-static data members to
  	 the back-end, in case it wants to do something with them.  */
*************** layout_class_type (t, empty_p, has_virtu
*** 4939,4949 ****
  	  continue;
  	}
  
        /* Create a dummy BINFO corresponding to this field.  */
!       binfo = make_binfo (size_zero_node, TREE_TYPE (field),
! 			  NULL_TREE, NULL_TREE);
        unshare_base_binfos (binfo);
        layout_nonempty_base_or_field (rli, field, binfo, v);
      }
  
    /* Clean up.  */
--- 4933,4996 ----
  	  continue;
  	}
  
+       type = TREE_TYPE (field);
+ 
+       /* If this field is a bit-field whose width is greater than its
+ 	 type, then there are some special rules for allocating it
+ 	 under the new ABI.  Under the old ABI, there were no special
+ 	 rules, but the back-end can't handle bitfields longer than a
+ 	 `long long', so we use the same mechanism.  */
+       if (DECL_C_BIT_FIELD (field)
+ 	  && ((flag_new_abi 
+ 	       && INT_CST_LT (TYPE_SIZE (type), DECL_SIZE (field)))
+ 	      || (!flag_new_abi
+ 		  && compare_tree_int (DECL_SIZE (field),
+ 				       TYPE_PRECISION
+ 				       (long_long_unsigned_type_node)) > 0)))
+ 	{
+ 	  integer_type_kind itk;
+ 	  tree integer_type;
+ 
+ 	  /* We must allocate the bits as if suitably aligned for the
+ 	     longest integer type that fits in this many bits.  type
+ 	     of the field.  Then, we are supposed to use the left over
+ 	     bits as additional padding.  */
+ 	  for (itk = itk_char; itk != itk_none; ++itk)
+ 	    if (INT_CST_LT (DECL_SIZE (field), 
+ 			    TYPE_SIZE (integer_types[itk])))
+ 	      break;
+ 
+ 	  /* ITK now indicates a type that is too large for the
+ 	     field.  We have to back up by one to find the largest
+ 	     type that fits.  */
+ 	  integer_type = integer_types[itk - 1];
+ 	  padding = size_diffop (DECL_SIZE (field), 
+ 				 TYPE_SIZE (integer_type));
+ 	  DECL_SIZE (field) = TYPE_SIZE (integer_type);
+ 	  DECL_ALIGN (field) = TYPE_ALIGN (integer_type);
+ 	}
+       else
+ 	padding = NULL_TREE;
+ 
        /* Create a dummy BINFO corresponding to this field.  */
!       binfo = make_binfo (size_zero_node, type, NULL_TREE, NULL_TREE);
        unshare_base_binfos (binfo);
        layout_nonempty_base_or_field (rli, field, binfo, v);
+ 
+       /* If we needed additional padding after this field, add it
+ 	 now.  */
+       if (padding)
+ 	{
+ 	  tree padding_field;
+ 
+ 	  padding_field = build_decl (FIELD_DECL, 
+ 				      NULL_TREE,
+ 				      char_type_node); 
+ 	  DECL_BIT_FIELD (padding_field) = 1;
+ 	  DECL_SIZE (padding_field) = padding;
+ 	  DECL_ALIGN (padding_field) = 1;
+ 	  layout_nonempty_base_or_field (rli, padding_field, NULL_TREE, v);
+ 	}
      }
  
    /* Clean up.  */


More information about the Gcc-patches mailing list