* config/i386/i386-interix.h (TARGET_SUBTARGET_DEFAULT): Or MASK_MS_BITFIELD_LAYOUT (SUBTARGET_OVERRIDE_OPTIONS): Warn about and turn off MS bitfields for Objective-C. (PCC_BIT_FIELD_TYPE_TEST, GROUP_BITFIELDS_BY_ALIGN): Remove defines. * config/i386/i386.c (ix86_ms_bitfield_layout): New function. (TARGET_MS_BITFIELD_LAYOUT_P): Define to above function. (TARGET_USE_MS_BITFIELD_LAYOUT): Define. * config/i386/i386.h (MASK_MS_BITFIELD_LAYOUT: New mask. TARGET_USE_MS_BITFIELD_LAYOUT): New macro. (TARGET_SWITCHES): Add above mask. * testsuite/gcc.dg/bf-ms-layout.c: New test case. * testsuite/gcc.dg/bf-no-ms-layout.c: New test case. * testsuite/gcc.dg/i386-bitfield1.c (dg-options): Add appropriate flags for interix. Index: gcc/config/i386/i386-interix.h =================================================================== RCS file: /cvs/gcc/gcc/gcc/config/i386/i386-interix.h,v retrieving revision 1.36.4.1 diff -u -p -r1.36.4.1 i386-interix.h --- gcc/config/i386/i386-interix.h 5 Sep 2002 17:47:07 -0000 1.36.4.1 +++ gcc/config/i386/i386-interix.h 1 Nov 2002 17:09:28 -0000 @@ -35,11 +35,12 @@ Boston, MA 02111-1307, USA. */ /* By default, target has a 80387, uses IEEE compatible arithmetic, and returns float values in the 387 and needs stack probes - We also align doubles to 64-bits for MSVC default compatibility */ + We also align doubles to 64-bits for MSVC default compatibility + We do bitfields MSVC-compatably by default, too. */ #undef TARGET_SUBTARGET_DEFAULT #define TARGET_SUBTARGET_DEFAULT \ (MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS | MASK_STACK_PROBE | \ - MASK_ALIGN_DOUBLE) + MASK_ALIGN_DOUBLE | MASK_MS_BITFIELD_LAYOUT) #undef TARGET_CPU_DEFAULT #define TARGET_CPU_DEFAULT 2 /* 486 */ @@ -243,6 +244,28 @@ Boston, MA 02111-1307, USA. */ #define TARGET_NOP_FUN_DLLIMPORT 1 #define drectve_section() /* nothing */ +/* Objective C has its own packing rules... + Objc tries to parallel the code in stor-layout.c at runtime + (see libobjc/encoding.c). This (compile-time) packing info isn't + available at runtime, so it's hopeless to try. + + And if the user tries to set the flag for objc, give an error + so he has some clue. */ + +#undef SUBTARGET_OVERRIDE_OPTIONS +#define SUBTARGET_OVERRIDE_OPTIONS \ +do { \ + if (strcmp (lang_hooks.name, "GNU Objective-C") == 0) \ + { \ + if ((target_flags & MASK_MS_BITFIELD_LAYOUT) != 0 \ + && (target_flags_explicit & MASK_MS_BITFIELD_LAYOUT) != 0) \ + { \ + error ("ms-bitfields not supported for objc"); \ + } \ + target_flags &= ~MASK_MS_BITFIELD_LAYOUT; \ + } \ +} while (0) + #define EH_FRAME_IN_DATA_SECTION #define READONLY_DATA_SECTION_ASM_OP "\t.section\t.rdata,\"r\"" @@ -273,8 +296,6 @@ while (0) #define HOST_PTR_AS_INT unsigned long #define PCC_BITFIELD_TYPE_MATTERS 1 -#define PCC_BITFIELD_TYPE_TEST TYPE_NATIVE(rec) -#define GROUP_BITFIELDS_BY_ALIGN TYPE_NATIVE(rec) /* The following two flags are usually "off" for i386, because some non-gnu tools (for the i386) don't handle them. However, we don't have that Index: gcc/config/i386/i386.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.c,v retrieving revision 1.447.2.18 diff -u -p -r1.447.2.18 i386.c --- gcc/config/i386/i386.c 29 Oct 2002 19:49:58 -0000 1.447.2.18 +++ gcc/config/i386/i386.c 1 Nov 2002 17:09:57 -0000 @@ -814,6 +814,7 @@ static bool ix86_function_ok_for_sibcall 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 int ix86_value_regno PARAMS ((enum machine_mode)); +static bool ix86_ms_bitfield_layout_p PARAMS ((tree)); #if defined (DO_GLOBAL_CTORS_BODY) && defined (HAS_INIT_SECTION) static void ix86_svr3_asm_out_constructor PARAMS ((rtx, int)); @@ -920,6 +921,9 @@ static enum x86_64_reg_class merge_class #define TARGET_HAVE_TLS true #endif +#undef TARGET_MS_BITFIELD_LAYOUT_P +#define TARGET_MS_BITFIELD_LAYOUT_P ix86_ms_bitfield_layout_p + #undef TARGET_ASM_OUTPUT_MI_THUNK #define TARGET_ASM_OUTPUT_MI_THUNK x86_output_mi_thunk #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK @@ -14191,6 +14195,17 @@ 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; } /* Returns an expression indicating where the this parameter is Index: gcc/config/i386/i386.h =================================================================== RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.h,v retrieving revision 1.280.4.14 diff -u -p -r1.280.4.14 i386.h --- gcc/config/i386/i386.h 29 Oct 2002 19:49:59 -0000 1.280.4.14 +++ gcc/config/i386/i386.h 1 Nov 2002 17:10:08 -0000 @@ -119,8 +119,9 @@ extern int target_flags; #define MASK_3DNOW_A 0x00020000 /* Support Athlon 3Dnow builtins */ #define MASK_128BIT_LONG_DOUBLE 0x00040000 /* long double size is 128bit */ #define MASK_64BIT 0x00080000 /* Produce 64bit code */ +#define MASK_MS_BITFIELD_LAYOUT 0x00100000 /* Use native (MS) bitfield layout */ -/* Unused: 0x03f0000 */ +/* Unused: 0x03e0000 */ /* ... overlap with subtarget options starts by 0x04000000. */ #define MASK_NO_RED_ZONE 0x04000000 /* Do not use red zone */ @@ -291,6 +292,8 @@ extern int x86_prefetch_sse; #define TARGET_RED_ZONE (!(target_flags & MASK_NO_RED_ZONE)) +#define TARGET_USE_MS_BITFIELD_LAYOUT (target_flags & MASK_MS_BITFIELD_LAYOUT) + #define TARGET_GNU_TLS (ix86_tls_dialect == TLS_DIALECT_GNU) #define TARGET_SUN_TLS (ix86_tls_dialect == TLS_DIALECT_SUN) @@ -383,6 +386,10 @@ extern int x86_prefetch_sse; N_("Generate 64bit x86-64 code") }, \ { "32", -MASK_64BIT, \ N_("Generate 32bit i386 code") }, \ + { "ms-bitfields", MASK_MS_BITFIELD_LAYOUT, \ + N_("Use native (MS) bitfield layout") }, \ + { "no-ms-bitfields", -MASK_MS_BITFIELD_LAYOUT, \ + N_("Use gcc default bitfield layout") }, \ { "red-zone", -MASK_NO_RED_ZONE, \ N_("Use red-zone in the x86-64 code") }, \ { "no-red-zone", MASK_NO_RED_ZONE, \ Index: gcc/testsuite/gcc.dg/i386-bitfield1.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.dg/i386-bitfield1.c,v retrieving revision 1.2 diff -u -p -r1.2 i386-bitfield1.c --- gcc/testsuite/gcc.dg/i386-bitfield1.c 7 Aug 2002 21:05:16 -0000 1.2 +++ gcc/testsuite/gcc.dg/i386-bitfield1.c 1 Nov 2002 17:10:25 -0000 @@ -1,6 +1,7 @@ // Test for bitfield alignment in structs on IA-32 // { dg-do run { target i?86-*-* } } // { dg-options "-O2" } +// { dg-options "-mno-align-double -mno-ms-bitfields" { target *-*-interix* } } extern void abort (void); extern void exit (int); --- /dev/null Fri Nov 1 09:04:36 2002 +++ gcc/testsuite/gcc.dg/bf-ms-layout.c Tue Oct 29 19:00:18 2002 @@ -0,0 +1,232 @@ +/* bf-ms-layout.c */ + +/* Test for MS bitfield layout */ +/* Adapted from Donn Terry testcase + posted to GCC-patches + http://gcc.gnu.org/ml/gcc-patches/2000-08/msg00577.html */ + +/* { dg-do run { target *-*-interix* } } */ +/* { dg-options "-mms-bitfields -D_TEST_MS_LAYOUT" } */ + +#include +#include + +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; +}; + --- /dev/null Fri Nov 1 09:04:36 2002 +++ gcc/testsuite/gcc.dg/bf-no-ms-layout.c Tue Oct 29 19:00:24 2002 @@ -0,0 +1,232 @@ +/* bf-no-ms-layout.c */ + +/* Test for gcc bitfield layout, with -mno-ms-bitfields */ +/* Adapted from Donn Terry testcase + posted to GCC-patches + http://gcc.gnu.org/ml/gcc-patches/2000-08/msg00577.html */ + +/* { dg-do run { target *-*-interix* } } */ +/* { dg-options "-mno-ms-bitfields" } */ + +#include +#include + +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; +}; +