tinycc-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Tinycc-devel] Patch: add option -mms-bitfields


From: Michael B. Smith
Subject: Re: [Tinycc-devel] Patch: add option -mms-bitfields
Date: Tue, 22 Nov 2016 21:41:32 +0000

Speaking only to my personal opinion – if you are compiling on Windows, and the –mms-bitfields is not set and –no-ms-bitfields is not set, then you should issue a warning to that effect.

 

From: Tinycc-devel [mailto:tinycc-devel-bounces+address@hidden On Behalf Of David Mertens
Sent: Tuesday, November 22, 2016 4:32 PM
To: address@hidden
Subject: [Tinycc-devel] Patch: add option -mms-bitfields

 

Hello everyone,

Per previous discussion, here is a patch to implement a command-line option, -mms-bitfields. This would alter tcc's bitfield alignment algorithm in a backwards-incompatible way to be a bit more consistent with gcc's algorithm. The old behavior is traditionally attributed to MSVC, and so (consistent with gcc) the command-line option to use the old behavior is -mms-bitfields. If this patch gets applied, Windows users would be encouraged to add -mms-bitfields to their Makefiles.

I would appreciate comments, bug reports, etc. If you care, please give this a spin in the next 24 hours, or please tell me if you need more time. Any tests illustrating discrepancies between gcc and this algorithm would be especially appreciated!

 

Thanks!

David

diff --git a/libtcc.c b/libtcc.c
index f184502..b824c18 100644
--- a/libtcc.c
+++ b/libtcc.c
@@ -752,6 +752,7 @@ LIBTCCAPI TCCState *tcc_new(void)
     s->alacarte_link = 1;
     s->nocommon = 1;
     s->warn_implicit_function_declaration = 1;
+    s->ms_bitfields = 0;
 
 #ifdef CHAR_IS_UNSIGNED
     s->char_is_unsigned = 1;
@@ -1508,6 +1509,7 @@ enum {
     TCC_OPTION_Wl,
     TCC_OPTION_W,
     TCC_OPTION_O,
+    TCC_OPTION_mms_bitfields,
     TCC_OPTION_m,
     TCC_OPTION_f,
     TCC_OPTION_isystem,
@@ -1571,6 +1573,7 @@ static const TCCOption tcc_options[] = {
     { "Wl,", TCC_OPTION_Wl, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
     { "W", TCC_OPTION_W, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
     { "O", TCC_OPTION_O, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
+    { "mms-bitfields", TCC_OPTION_mms_bitfields, 0}, /* must go before option 'm' */
     { "m", TCC_OPTION_m, TCC_OPTION_HAS_ARG },
     { "f", TCC_OPTION_f, TCC_OPTION_HAS_ARG | TCC_OPTION_NOSEP },
     { "isystem", TCC_OPTION_isystem, TCC_OPTION_HAS_ARG },
@@ -1854,6 +1857,9 @@ PUB_FUNC int tcc_parse_args(TCCState *s, int argc, char **argv)
             if (x > 0)
                 tcc_define_symbol(s, "__OPTIMIZE__", NULL);
             break;
+        case TCC_OPTION_mms_bitfields:
+            s->ms_bitfields = 1;
+            break;
         case TCC_OPTION_traditional:
         case TCC_OPTION_pedantic:
         case TCC_OPTION_pipe:
diff --git a/tcc-doc.texi b/tcc-doc.texi
index 5aab13c..9f136ed 100644
--- a/tcc-doc.texi
+++ b/tcc-doc.texi
@@ -176,6 +176,10 @@ In a script, it gives the following header:
 #!/usr/local/bin/tcc -run -L/usr/X11R6/lib -lX11
 @end example
 
+@item -mms-bitfields
+Use an algorithm for bitfield alignment consistent with MSVC. Default is
+gcc's algorithm.
+
 @item -mfloat-abi (ARM only)
 Select the float ABI. Possible values: @code{softfp} and @code{hard}
 
diff --git a/tcc.c b/tcc.c
index 28f3ae9..fbfbffa 100644
--- a/tcc.c
+++ b/tcc.c
@@ -97,6 +97,7 @@ static void help(void)
            "  -o outfile  set output filename\n"
            "  -run        run compiled source\n"
            "  -fflag      set or reset (with 'no-' prefix) 'flag' (see man page)\n"
+           "  -mms-bitfields  use bitfield alignment consistent with MSVC\n"
            "  -Wwarning   set or reset (with 'no-' prefix) 'warning' (see man page)\n"
            "  -w          disable all warnings\n"
            "  -v          show version\n"
diff --git a/tcc.h b/tcc.h
index 180838d..cbdebd3 100644
--- a/tcc.h
+++ b/tcc.h
@@ -605,6 +605,7 @@ struct TCCState {
     int old_struct_init_code;    /* use old algorithm to init array in struct when there is no '{' used.
                    Liuux 2.4.26 can't find initrd when compiled with a new algorithm */
     int dollars_in_identifiers;    /* allows '$' char in indentifiers */
+    int ms_bitfields; /* if true, emulate MS algorithm for aligning bitfields */
 
     /* warning switches */
     int warn_write_strings;
diff --git a/tccgen.c b/tccgen.c
index ba1757e..d064024 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -3154,7 +3154,7 @@ static void parse_attribute(AttributeDef *ad)
 /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */
 static void struct_decl(CType *type, AttributeDef *ad, int u)
 {
-    int a, v, size, align, maxalign, c, offset, flexible;
+    int a, v, size, align, maxalign, c, offset, flexible, extra_bytes;
     int bit_size, bit_pos, bsize, bt, lbit_pos, prevbt;
     Sym *s, *ss, *ass, **ps;
     AttributeDef ad1;
@@ -3235,6 +3235,7 @@ static void struct_decl(CType *type, AttributeDef *ad, int u)
             while (tok != '}') {
                 parse_btype(&btype, &ad1);
                 while (1) {
+                extra_bytes = 0;
             if (flexible)
                 tcc_error("flexible array member '%s' not at the end of struct",
                               get_tok_str(v, NULL));
@@ -3310,9 +3311,9 @@ static void struct_decl(CType *type, AttributeDef *ad, int u)
                             /* zero size: means to pad */
                             bit_pos = 0;
                         } else {
-                            /* we do not have enough room ?
-                               did the type change?
-                               is it a union? */
+                            /* if type change, union, or will overrun
+                             * allignment slot, start at a newly
+                             * alligned slot */
                             if ((bit_pos + bit_size) > bsize ||
                                 bt != prevbt || a == TOK_UNION)
                                 bit_pos = 0;
@@ -3322,15 +3323,30 @@ static void struct_decl(CType *type, AttributeDef *ad, int u)
                                 (bit_pos << VT_STRUCT_SHIFT) |
                                 (bit_size << (VT_STRUCT_SHIFT + 6));
                             bit_pos += bit_size;
+                            /* without ms-bitfields, allocate the
+                             * minimum number of bytes necessary,
+                             * adding single bytes as needed */
+                            if (!tcc_state->ms_bitfields) {
+                                if (lbit_pos == 0)
+                                    /* minimum bytes for new bitfield */
+                                    size = (bit_size + 7) / 8;
+                                else {
+                                    /* enough spare bits already allocated? */
+                                    bit_size = (lbit_pos - 1) % 8 + 1 + bit_size;
+                                    if (bit_size > 8) /* doesn't fit */
+                                        extra_bytes = (bit_size - 1) / 8;
+                                }
+                            }
                         }
                         prevbt = bt;
                     } else {
                         bit_pos = 0;
                     }
                     if (v != 0 || (type1.t & VT_BTYPE) == VT_STRUCT) {
-                        /* add new memory data only if starting
-                           bit field */
-                        if (lbit_pos == 0) {
+                        /* add new memory data only if starting bit
+                           field or adding bytes to existing bit field */
+                        if (extra_bytes) c += extra_bytes;
+                        else if (lbit_pos == 0) {
                             if (a == TOK_STRUCT) {
                                 c = (c + align - 1) & -align;
                                 offset = c;
diff --git a/tests/tcctest.c b/tests/tcctest.c
index 5851fb4..b0fe8f3 100644
--- a/tests/tcctest.c
+++ b/tests/tcctest.c
@@ -1634,6 +1634,15 @@ void bitfield_test(void)
     st2.f3 = a;
     st2.f2++;
     printf("%lld %lld %lld\n", st2.f1, st2.f2, st2.f3);
+    struct sbf3 {
+        int f1 : 7;
+        int f2 : 1;
+        char f3;
+        int f4 : 8;
+        int f5 : 1;
+        int f6 : 16;
+    } st3;
+    printf("sizeof(st3) = %d\n", sizeof(st3));
 }
 
 #ifdef __x86_64__


reply via email to

[Prev in Thread] Current Thread [Next in Thread]