This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PATCH: MS bitfield layout support for w32 targets - Take 2.


Hello

The attached patch adds -mms-bitfields as a new target switch for cygwin
and mingw32. This switch provides w32 targets with option to use
MS-compatable storage layout for bitfields in structures, as introduced
by Alexandre Oliva in SH5 port (refer
http://gcc.gnu.org/ml/gcc-patches/2002-02/msg00402.html). 

The patch provide documentation and testcases, as requested.

The documentation for this switch in invoke.texi is a shameless copy of
the documentation for the TARGET_MS_BITFIELD_LAYOUT_P hook in tm.texi.

The testcase bf-ms-layout.c succeeds on all 10 tests for offsets of
fields within structures but fails on four of the 10 tests for alignment
of the structure as a whole. This is because of a problem in
stor_layout.c handling of item (ii) of the documented behaviour of the
target hook, namely:"a zero-sized bit-field will affect the alignment of
the whole enclosing structure". 

Work on fixing these failures is in progress.

The testcase bf-no-ms-layout.c is the same code  but switched to test
whether the changes do not affect gcc default packing.  This test succeeds.

If this patch is acceptable, where should the testcases go? gcc.dg was
suggested earlier.

Bootstapped and tested on i586-pc-mingw32.

Okay for mainline?

Danny

ChangeLog

2002-04-05  Danny Smith  <dannysmith@users.sourceforge.net>

	* config/i386/cygwin.h (MASK_MS_BITFIELD_LAYOUT): New mask for
	target switch -mms-bitfields.
	(TARGET_USE_MS_BITFIELD_LAYOUT): New define, using mask.
	(SUBTARGET_SWITCHES): Set mask, document -mms-bitfield switch.
	* config/i386/i386.c (ix86_ms_bitfield_layout_p): Add new hook
	function for TARGET_MS_BITFIELD_LAYOUT_P returning ...
	(TARGET_USE_MS_BITFIELD_LAYOUT): Define to 0 if not defined
	by subtarget.
	* doc/invoke.texi (-mms-bitfields): Document target switch.
	* testsuite/gcc.dg/bf-ms-layout.c: New file.
	* testsuite/gcc.dg/bf-no-ms-layout.c: New file.



http://www.sold.com.au - SOLD.com.au Auctions
- 1,000s of Bargains!
Index: cygwin.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/cygwin.h,v
retrieving revision 1.66
diff -u -p -r1.66 cygwin.h
--- cygwin.h	2002/04/03 03:47:37	1.66
+++ cygwin.h	2002/04/05 00:54:50
@@ -36,9 +36,14 @@ Boston, MA 02111-1307, USA.  */
 
 /* Masks for subtarget switches used by other files.  */
 #define MASK_NOP_FUN_DLLIMPORT 0x08000000 /* Ignore dllimport for functions */
+#define MASK_MS_BITFIELD_LAYOUT 0x10000000 /* Use MS bitfield layout */
 
 /* Used in winnt.c.  */
 #define TARGET_NOP_FUN_DLLIMPORT (target_flags & MASK_NOP_FUN_DLLIMPORT)
+/* Tell i386.c to put a target-specific specialization of
+   ms_bitfield_layout_p in struct gcc_target targetm.  */
+#define TARGET_USE_MS_BITFIELD_LAYOUT  \
+  (target_flags & MASK_MS_BITFIELD_LAYOUT)	
 
 #undef  SUBTARGET_SWITCHES
 #define SUBTARGET_SWITCHES \
@@ -52,7 +57,11 @@ Boston, MA 02111-1307, USA.  */
 { "nop-fun-dllimport",	  MASK_NOP_FUN_DLLIMPORT,		\
   N_("Ignore dllimport for functions") }, 			\
 { "no-nop-fun-dllimport", -MASK_NOP_FUN_DLLIMPORT, "" },	\
-{ "threads",		  0, N_("Use Mingw-specific thread support") },
+{ "threads",		  0, N_("Use Mingw-specific thread support") },	\
+{ "ms-bitfields",	  MASK_MS_BITFIELD_LAYOUT, 		\
+  N_("Use MS bitfield layout") },				\
+{ "no-ms-bitfields",	  -MASK_MS_BITFIELD_LAYOUT,		\
+  N_("Don't use MS bitfield layout") },
 
 #undef CPP_PREDEFINES
 #define CPP_PREDEFINES "-D_X86_=1 -Asystem=winnt"

Index: i386.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.c,v
retrieving revision 1.383
diff -u -p -r1.383 i386.c
--- i386.c	2002/04/03 22:40:50	1.383
+++ i386.c	2002/04/05 00:55:11
@@ -725,6 +725,7 @@ static int ix86_comp_type_attributes PAR
 const struct attribute_spec ix86_attribute_table[];
 static tree ix86_handle_cdecl_attribute PARAMS ((tree *, tree, tree, int, bool *));
 static tree ix86_handle_regparm_attribute PARAMS ((tree *, tree, tree, int, bool *));
+static bool ix86_ms_bitfield_layout_p PARAMS ((tree));
 
 #ifdef DO_GLOBAL_CTORS_BODY
 static void ix86_svr3_asm_out_constructor PARAMS ((rtx, int));
@@ -821,6 +822,9 @@ static enum x86_64_reg_class merge_class
 #undef TARGET_SCHED_REORDER
 #define TARGET_SCHED_REORDER ix86_sched_reorder
 
+#undef TARGET_MS_BITFIELD_LAYOUT_P
+#define TARGET_MS_BITFIELD_LAYOUT_P ix86_ms_bitfield_layout_p
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 
 /* Sometimes certain combinations of command options do not make
@@ -12489,4 +12493,15 @@ x86_order_regs_for_local_alloc ()
       at all.  */
    while (pos < FIRST_PSEUDO_REGISTER)
      reg_alloc_order [pos++] = 0;
+}
+
+#ifndef TARGET_USE_MS_BITFIELD_LAYOUT
+#define TARGET_USE_MS_BITFIELD_LAYOUT 0
+#endif
+
+static bool
+ix86_ms_bitfield_layout_p (record_type)
+     tree record_type ATTRIBUTE_UNUSED;
+{
+  return TARGET_USE_MS_BITFIELD_LAYOUT;
 }

Index: invoke.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/invoke.texi,v
retrieving revision 1.137
diff -u -p -r1.137 invoke.texi
--- invoke.texi	2002/03/31 03:11:19	1.137
+++ invoke.texi	2002/04/05 07:56:09
@@ -486,7 +486,7 @@ in the following sections.
 -mthreads  -mno-align-stringops  -minline-all-stringops @gol
 -mpush-args  -maccumulate-outgoing-args  -m128bit-long-double @gol
 -m96bit-long-double  -mregparm=@var{num}  -momit-leaf-frame-pointer @gol
--mno-red-zone@gol
+-mms-bitfields -mno-red-zone @gol
 -m32 -m64}
 
 @emph{HPPA Options}
@@ -7527,6 +7527,19 @@ avoids the instructions to save, set up 
 makes an extra register available in leaf functions.  The option
 @option{-fomit-frame-pointer} removes the frame pointer for all functions
 which might make debugging harder.
+
+@item -mms-bitfields
+@opindex mms-bitfields
+If set, @var{record_type} bit-fields are laid out following the rules of
+Microsoft Visual C/C++, namely: (i) a bit-field won't share the same
+storage unit with the previous bit-field if their underlying types have
+different sizes, and the bit-field will be aligned to the highest
+alignment of the underlying types of itself and of the previous
+bit-field; (ii) a zero-sized bit-field will affect the alignment of the
+whole enclosing structure, even if it is unnamed; except that (iii) a
+zero-sized bit-field will be disregarded unless it follows another
+bit-field of non-zero size. Currently, this option is supported on
+@samp{cygwin} and @samp{mingw32}.
 @end table
 
 These @samp{-m} switches are supported in addition to the above
/* bf-ms-layout.c */

/* Test for MS bitfield layout */
/* Adapted from Donn Terry <donnte@microsoft.com> testcase
   posted to GCC-patches
   http://gcc.gnu.org/ml/gcc-patches/2000-08/msg00577.html */ 

/* { dg-do run { target *-*-mingw* *-*-cygwin*  } } */
/* { dg-options "-mms-bitfields -D_TEST_MS_LAYOUT" } */

#include <stddef.h>
#include <string.h>

extern void abort();

#pragma pack(8)

struct one {
  int d;
  unsigned char a;
  unsigned short b:7;
  char c;	
};

struct two {
  int d;
  unsigned char a;
  unsigned int b:7;
  char c;	    	
};

struct three {
  short d;
  unsigned short a:3;
  unsigned short b:9;
  unsigned char c:7;
};


/* Bitfields of size 0 have some truly odd behaviors. */

struct four {
  unsigned short a:3;
  unsigned short b:9;
  unsigned int :0;  /* forces struct alignment to int */
  unsigned char c:7;
};

struct five {
  char a;	  	
  int :0;        /* ignored; prior field is not a bitfield. */
  char b;
  char c;
};

struct six { 
  char a :8;
  int :0;	/* not ignored; prior field IS a bitfield, causes
		   struct alignment as well. */
  char b;
  char c;
} ;

struct seven {
  char a:8;
  char :0;
  int  :0;	/* Ignored; prior field is zero size bitfield. */
  char b;
  char c;
};

struct eight { /* ms size 4 */
  short b:3;  
  char  c;
};

#ifdef _MSC_VER
#define LONGLONG __int64
#else
#define LONGLONG long long
#endif

union nine {   /* ms size 8 */
  LONGLONG a:3;
  char  c;
};

struct ten {   /* ms size 16 */
  LONGLONG a:3;
  LONGLONG b:3;
  char  c;
};


#define val(s,f) (s.f)

#define check_struct(_X) \
{ \
  if (sizeof (struct _X) != exp_sizeof_##_X )	\
    abort();					\
  memcpy(&test_##_X, filler, sizeof(test_##_X));\
  if (val(test_##_X,c) != exp_##_X##_c) 	\
    abort();
}

#define check_union(_X) \
{ \
  if (sizeof (union _X) != exp_sizeof_##_X )	\
    abort();                                    \
  memcpy(&test_##_X, filler, sizeof(test_##_X));\
  if (val(test_##_X,c) != exp_##_X##_c) 	\
     abort();					\
}

#define check_struct_size(_X) \
{ \
  if (sizeof (struct _X) != exp_sizeof_##_X )	\
    abort();                                    \
}

#define check_struct_off(_X) \
{ \
  memcpy(&test_##_X, filler, sizeof(test_##_X));\
  if (val(test_##_X,c) != exp_##_X##_c) 	\
    abort();                                    \
}

#define check_union_size(_X) \
{ \
  if (sizeof (union _X) != exp_sizeof_##_X )	\
    abort();                                    \
}

#define check_union_off(_X) \
{ \
  memcpy(&test_##_X, filler, sizeof(test_##_X));\
  if (val(test_##_X,c) != exp_##_X##_c) 	\
    abort();                                    \
}

int main(){

  unsigned char filler[16];
  struct one test_one;
  struct two test_two;
  struct three test_three;
  struct four test_four;
  struct five test_five;
  struct six test_six;
  struct seven test_seven;
  struct eight test_eight;
  union nine test_nine;
  struct ten test_ten;
 
#if defined (_TEST_MS_LAYOUT) || defined (_MSC_VER)
  size_t exp_sizeof_one = 12;
  size_t exp_sizeof_two = 16;
  size_t exp_sizeof_three =6;
  size_t exp_sizeof_four = 8;
  size_t exp_sizeof_five = 3;
  size_t exp_sizeof_six = 8;
  size_t exp_sizeof_seven = 3;
  size_t exp_sizeof_eight = 4;
  size_t exp_sizeof_nine = 8;
  size_t exp_sizeof_ten = 16;

  unsigned char exp_one_c = 8;
  unsigned char exp_two_c  = 12;
  unsigned char exp_three_c = 4;
  unsigned char exp_four_c = 4;
  char exp_five_c = 2;
  char exp_six_c = 5;
  char exp_seven_c = 2;
  char exp_eight_c = 2;
  char exp_nine_c = 0;
  char exp_ten_c = 8;

#else /* testing -mno-ms-bitfields */

  size_t exp_sizeof_one = 8;
  size_t exp_sizeof_two = 8;
  size_t exp_sizeof_three = 6;
  size_t exp_sizeof_four = 6;  
  size_t exp_sizeof_five = 6;
  size_t exp_sizeof_six = 6;
  size_t exp_sizeof_seven = 6;
  size_t exp_sizeof_eight = 2;
  size_t exp_sizeof_nine = 8;
  size_t exp_sizeof_ten = 8;

  unsigned short exp_one_c = 6;
  unsigned int exp_two_c  = 6;
  unsigned char exp_three_c = 64;
  unsigned char exp_four_c = 4;
  char exp_five_c = 5;
  char exp_six_c = 5;
  char exp_seven_c = 5;
  char exp_eight_c = 1;
  char exp_nine_c = 0;
  char exp_ten_c = 1;

#endif

  unsigned char i; 
  for ( i = 0; i < 16; i++ )
    filler[i] = i;

  check_struct_off (one);
  check_struct_off (two);  
  check_struct_off (three);
  check_struct_off (four);
  check_struct_off (five);
  check_struct_off (six);
  check_struct_off (seven);
  check_struct_off (eight);
  check_union_off (nine);
  check_struct_off (ten);

  check_struct_size (one);
  check_struct_size (two);  
  check_struct_size (three);
  check_struct_size (four);
  check_struct_size (five);
  check_struct_size (six);
  check_struct_size (seven);
  check_struct_size (eight);
  check_union_size (nine);
  check_struct_size (ten);

  return 0;
};

/* bf-no-ms-layout.c */

/* Test for gcc bitfield layout, with -mno-ms-bitfields */
/* Adapted from Donn Terry <donnte@microsoft.com> testcase
   posted to GCC-patches
   http://gcc.gnu.org/ml/gcc-patches/2000-08/msg00577.html */ 

/* { dg-do run { target *-*-mingw* *-*-cygwin*  } } */
/* { dg-options "-mno-ms-bitfields" } */

#include <stddef.h>
#include <string.h>

extern void abort();

#pragma pack(8)

struct one {
  int d;
  unsigned char a;
  unsigned short b:7;
  char c;	
};

struct two {
  int d;
  unsigned char a;
  unsigned int b:7;
  char c;	    	
};

struct three {
  short d;
  unsigned short a:3;
  unsigned short b:9;
  unsigned char c:7;
};


/* Bitfields of size 0 have some truly odd behaviors. */

struct four {
  unsigned short a:3;
  unsigned short b:9;
  unsigned int :0;  /* forces struct alignment to int */
  unsigned char c:7;
};

struct five {
  char a;	  	
  int :0;        /* ignored; prior field is not a bitfield. */
  char b;
  char c;
};

struct six { 
  char a :8;
  int :0;	/* not ignored; prior field IS a bitfield, causes
		   struct alignment as well. */
  char b;
  char c;
} ;

struct seven {
  char a:8;
  char :0;
  int  :0;	/* Ignored; prior field is zero size bitfield. */
  char b;
  char c;
};

struct eight { /* ms size 4 */
  short b:3;  
  char  c;
};

#ifdef _MSC_VER
#define LONGLONG __int64
#else
#define LONGLONG long long
#endif

union nine {   /* ms size 8 */
  LONGLONG a:3;
  char  c;
};

struct ten {   /* ms size 16 */
  LONGLONG a:3;
  LONGLONG b:3;
  char  c;
};


#define val(s,f) (s.f)

#define check_struct(_X) \
{ \
  if (sizeof (struct _X) != exp_sizeof_##_X )	\
    abort();					\
  memcpy(&test_##_X, filler, sizeof(test_##_X));\
  if (val(test_##_X,c) != exp_##_X##_c) 	\
    abort();
}

#define check_union(_X) \
{ \
  if (sizeof (union _X) != exp_sizeof_##_X )	\
    abort();                                    \
  memcpy(&test_##_X, filler, sizeof(test_##_X));\
  if (val(test_##_X,c) != exp_##_X##_c) 	\
     abort();					\
}

#define check_struct_size(_X) \
{ \
  if (sizeof (struct _X) != exp_sizeof_##_X )	\
    abort();                                    \
}

#define check_struct_off(_X) \
{ \
  memcpy(&test_##_X, filler, sizeof(test_##_X));\
  if (val(test_##_X,c) != exp_##_X##_c) 	\
    abort();                                    \
}

#define check_union_size(_X) \
{ \
  if (sizeof (union _X) != exp_sizeof_##_X )	\
    abort();                                    \
}

#define check_union_off(_X) \
{ \
  memcpy(&test_##_X, filler, sizeof(test_##_X));\
  if (val(test_##_X,c) != exp_##_X##_c) 	\
    abort();                                    \
}

int main(){

  unsigned char filler[16];
  struct one test_one;
  struct two test_two;
  struct three test_three;
  struct four test_four;
  struct five test_five;
  struct six test_six;
  struct seven test_seven;
  struct eight test_eight;
  union nine test_nine;
  struct ten test_ten;
 
#if defined (_TEST_MS_LAYOUT) || defined (_MSC_VER)
  size_t exp_sizeof_one = 12;
  size_t exp_sizeof_two = 16;
  size_t exp_sizeof_three =6;
  size_t exp_sizeof_four = 8;
  size_t exp_sizeof_five = 3;
  size_t exp_sizeof_six = 8;
  size_t exp_sizeof_seven = 3;
  size_t exp_sizeof_eight = 4;
  size_t exp_sizeof_nine = 8;
  size_t exp_sizeof_ten = 16;

  unsigned char exp_one_c = 8;
  unsigned char exp_two_c  = 12;
  unsigned char exp_three_c = 4;
  unsigned char exp_four_c = 4;
  char exp_five_c = 2;
  char exp_six_c = 5;
  char exp_seven_c = 2;
  char exp_eight_c = 2;
  char exp_nine_c = 0;
  char exp_ten_c = 8;

#else /* testing -mno-ms-bitfields */

  size_t exp_sizeof_one = 8;
  size_t exp_sizeof_two = 8;
  size_t exp_sizeof_three = 6;
  size_t exp_sizeof_four = 6;  
  size_t exp_sizeof_five = 6;
  size_t exp_sizeof_six = 6;
  size_t exp_sizeof_seven = 6;
  size_t exp_sizeof_eight = 2;
  size_t exp_sizeof_nine = 8;
  size_t exp_sizeof_ten = 8;

  unsigned short exp_one_c = 6;
  unsigned int exp_two_c  = 6;
  unsigned char exp_three_c = 64;
  unsigned char exp_four_c = 4;
  char exp_five_c = 5;
  char exp_six_c = 5;
  char exp_seven_c = 5;
  char exp_eight_c = 1;
  char exp_nine_c = 0;
  char exp_ten_c = 1;

#endif

  unsigned char i; 
  for ( i = 0; i < 16; i++ )
    filler[i] = i;

  check_struct_off (one);
  check_struct_off (two);  
  check_struct_off (three);
  check_struct_off (four);
  check_struct_off (five);
  check_struct_off (six);
  check_struct_off (seven);
  check_struct_off (eight);
  check_union_off (nine);
  check_struct_off (ten);

  check_struct_size (one);
  check_struct_size (two);  
  check_struct_size (three);
  check_struct_size (four);
  check_struct_size (five);
  check_struct_size (six);
  check_struct_size (seven);
  check_struct_size (eight);
  check_union_size (nine);
  check_struct_size (ten);

  return 0;
};


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]