my patch:See Attachment
You look at, if no problem, I'll push mob

Jiang

在 2014年07月30日 00:00, tinycc-devel-requ...@nongnu.org 写道:
Gcc and msvc are correct.

-----Original Message-----
From:tinycc-devel-bounces+michael=theessentialexchange....@nongnu.org  
[mailto:tinycc-devel-bounces+michael=theessentialexchange....@nongnu.org] On 
Behalf Of jiang
Sent: Monday, July 28, 2014 9:37 PM
To: Thomas Preud'homme
Cc:tinycc-devel@nongnu.org
Subject: [Tinycc-devel] 回复: tcc grammar problems

I am sorry, I do not have expressed good I mean. I want you sure, is tcc 
correct or gcc msvc correctly. If the gcc msvc correct, I want to fix it.

Best regards
Jiang

Thomas Preud'homme<robo...@celest.fr>编写:

>Le dimanche 13 juillet 2014, 22:12:39 jiang a écrit :
>>Hello everyone!
>>
>>(s->a = (s->b = (s->c = n + 4)));
>>
>>
>>gcc & msvc:
>>--> 30 / 30 / 126 // Because the return value is left
>>
>>
>>tcc
>>--> 254 / 30 / 126 // Because the return is the right value
>
>Since it works for the last two values I don't think it's that. It
>simply looks like tcc compute n + 4 (254) and then tries to store it in
>each field independently. It's a folding issue. Tcc records 254 in a
>CValue associated with the SValue for n + 4. The problem is how this is
>propagated (folded) to the three field access.
>
>>
>>Shall tcc assignment modify what? Same with gcc&msvc.
>
>Yes, gcc and msvc are definitely right here.
>
>Best regards,
>
>Thomas
_______________________________________________
Tinycc-devel mailing list
Tinycc-devel@nongnu.org
https://lists.nongnu.org/mailman/listinfo/tinycc-devel

commit 1988c974137f3042d9c38000fda3e00779fecab3
Author: Jiang <30155...@qq.com>
Date:   Fri Aug 1 16:27:58 2014 +0800

    fix bitfields
    
    see:
    http://lists.nongnu.org/archive/html/tinycc-devel/2014-07/msg00023.html

diff --git a/tcc.h b/tcc.h
index c93cedf..a8cabb6 100644
--- a/tcc.h
+++ b/tcc.h
@@ -1192,6 +1192,17 @@ ST_DATA int func_var; /* true if current function is 
variadic */
 ST_DATA int func_vc;
 ST_DATA int last_line_num, last_ind, func_ind; /* debug last line number and 
pc */
 ST_DATA char *funcname;
+/* gen_ctrl */
+enum {
+    CTRL_NONE,
+    CTRL_CALL,
+    CTRL_FOCE,
+    CTRL_ARGS,
+    CTRL_RETS,
+    CTRL_INIT,
+    CTRL_USED,
+};
+ST_DATA int gen_ctrl;
 
 ST_INLN int is_float(int t);
 ST_FUNC int ieee_finite(double d);
diff --git a/tccgen.c b/tccgen.c
index 1a89d4a..73b759f 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -70,6 +70,7 @@ ST_DATA int func_var; /* true if current function is variadic 
(used by return in
 ST_DATA int func_vc;
 ST_DATA int last_line_num, last_ind, func_ind; /* debug last line number and 
pc */
 ST_DATA char *funcname;
+ST_DATA int gen_ctrl;
 
 ST_DATA CType char_pointer_type, func_old_type, int_type, size_type;
 
@@ -1909,8 +1910,9 @@ static void force_charshort_cast(int t)
 /* cast 'vtop' to 'type'. Casting to bitfields is forbidden. */
 static void gen_cast(CType *type)
 {
-    int sbt, dbt, sf, df, c, p;
+    int sbt, dbt, dt, sf, df, c, p, bb;
 
+    bb = type->t & VT_BITFIELD;
     /* special delayed cast for char/short */
     /* XXX: in some cases (multiple cascaded casts), it may still
        be incorrect */
@@ -1925,9 +1927,10 @@ static void gen_cast(CType *type)
     }
 
     dbt = type->t & (VT_BTYPE | VT_UNSIGNED);
+    dt = dbt & VT_BTYPE;
     sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED);
 
-    if (sbt != dbt) {
+    if (sbt != dbt || bb) {
         sf = is_float(sbt);
         df = is_float(dbt);
         c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
@@ -1959,6 +1962,8 @@ static void gen_cast(CType *type)
                     vtop->c.d = (double)vtop->c.ld;
             } else if (sf && dbt == (VT_LLONG|VT_UNSIGNED)) {
                 vtop->c.ull = (unsigned long long)vtop->c.ld;
+                if(bb)
+                    goto to_min;
             } else if (sf && dbt == VT_BOOL) {
                 vtop->c.i = (vtop->c.ld != 0);
             } else {
@@ -1975,24 +1980,53 @@ static void gen_cast(CType *type)
                 else if (sbt != VT_LLONG)
                     vtop->c.ll = vtop->c.i;
 
-                if (dbt == (VT_LLONG|VT_UNSIGNED))
+                if (dbt == (VT_LLONG|VT_UNSIGNED)){
                     vtop->c.ull = vtop->c.ll;
-                else if (dbt == VT_BOOL)
+                    if(bb)
+                        goto to_min;
+                }else if (dbt == VT_BOOL)
                     vtop->c.i = (vtop->c.ll != 0);
 #ifdef TCC_TARGET_X86_64
                 else if (dbt == VT_PTR)
                     ;
 #endif
                 else if (dbt != VT_LLONG) {
-                    int s = 0;
-                    if ((dbt & VT_BTYPE) == VT_BYTE)
-                        s = 24;
-                    else if ((dbt & VT_BTYPE) == VT_SHORT)
-                        s = 16;
-                    if(dbt & VT_UNSIGNED)
-                        vtop->c.ui = ((unsigned int)vtop->c.ll << s) >> s;
-                    else
-                        vtop->c.i = ((int)vtop->c.ll << s) >> s;
+                    unsigned long long ull;
+                    long long ll;
+                    int s, warr;
+to_min:
+                    warr = 0;
+                    if(bb){
+                        s = 64 - ((type->t >> (VT_STRUCT_SHIFT + 6)) & 0x3f);
+                        type->t  = type->t  & ~(VT_BITFIELD | (-1 << 
VT_STRUCT_SHIFT));
+                    }else if (dt == VT_BYTE){
+                        s = 56;
+                    }else if (dt == VT_SHORT){
+                        s = 48;
+                    }else{
+                        s = 32;
+                    }
+
+                    ull = (vtop->c.ull << s) >> s;
+                    ll = (vtop->c.ll << s) >> s;
+                    if(ull != vtop->c.ull && ll != vtop->c.ll){
+                        warr = 1;
+                    }
+                    if(warr){
+                        if(dt == VT_ENUM)
+                            dbt |= VT_UNSIGNED;
+                        if(gen_ctrl != CTRL_FOCE){
+                            if(dt == VT_ENUM)
+                                tcc_warning("large integer implicitly 
truncated to unsigned type");
+                            else
+                                tcc_warning("overflow in implicit constant 
conversion");
+                        }
+                    }
+                    if(dbt & VT_UNSIGNED){
+                        vtop->c.ull = ull;
+                    }else{
+                        vtop->c.ll = ll;
+                    }
                 }
             }
         } else if (p && dbt == VT_BOOL) {
@@ -2024,67 +2058,78 @@ static void gen_cast(CType *type)
                         gen_cast(type);
                     }
                 }
+            } else {
+
 #ifndef TCC_TARGET_X86_64
-            } else if ((dbt & VT_BTYPE) == VT_LLONG) {
-                if ((sbt & VT_BTYPE) != VT_LLONG) {
-                    /* scalar to long long */
-                    /* machine independent conversion */
-                    gv(RC_INT);
-                    /* generate high word */
-                    if (sbt == (VT_INT | VT_UNSIGNED)) {
-                        vpushi(0);
+                if ((dbt & VT_BTYPE) == VT_LLONG) {
+                    if ((sbt & VT_BTYPE) != VT_LLONG) {
+                        /* scalar to long long */
+                        /* machine independent conversion */
                         gv(RC_INT);
-                    } else {
-                        if (sbt == VT_PTR) {
-                            /* cast from pointer to int before we apply
-                               shift operation, which pointers don't support*/
-                            gen_cast(&int_type);
+                        /* generate high word */
+                        if (sbt == (VT_INT | VT_UNSIGNED)) {
+                            vpushi(0);
+                            gv(RC_INT);
+                        } else {
+                            if (sbt == VT_PTR) {
+                                /* cast from pointer to int before we apply
+                                   shift operation, which pointers don't 
support*/
+                                gen_cast(&int_type);
+                            }
+                            gv_dup();
+                            vpushi(31);
+                            gen_op(TOK_SAR);
                         }
-                        gv_dup();
-                        vpushi(31);
-                        gen_op(TOK_SAR);
+                        /* patch second register */
+                        vtop[-1].r2 = vtop->r;
+                        vpop();
                     }
-                    /* patch second register */
-                    vtop[-1].r2 = vtop->r;
-                    vpop();
                 }
 #else
-            } else if ((dbt & VT_BTYPE) == VT_LLONG ||
-                       (dbt & VT_BTYPE) == VT_PTR ||
-                       (dbt & VT_BTYPE) == VT_FUNC) {
-                if ((sbt & VT_BTYPE) != VT_LLONG &&
-                    (sbt & VT_BTYPE) != VT_PTR &&
-                    (sbt & VT_BTYPE) != VT_FUNC) {
-                    /* need to convert from 32bit to 64bit */
-                    int r = gv(RC_INT);
-                    if (sbt != (VT_INT | VT_UNSIGNED)) {
-                        /* x86_64 specific: movslq */
-                        o(0x6348);
-                        o(0xc0 + (REG_VALUE(r) << 3) + REG_VALUE(r));
+                if((dbt & VT_BTYPE) == VT_LLONG || (dbt & VT_BTYPE) == VT_PTR 
||
+                            (dbt & VT_BTYPE) == VT_FUNC) {
+                    if ((sbt & VT_BTYPE) != VT_LLONG && (sbt & VT_BTYPE) != 
VT_PTR &&
+                        (sbt & VT_BTYPE) != VT_FUNC) {
+                        /* need to convert from 32bit to 64bit */
+                        int r = gv(RC_INT);
+                        if (sbt != (VT_INT | VT_UNSIGNED)) {
+                            /* x86_64 specific: movslq */
+                            o(0x6348);
+                            o(0xc0 + (REG_VALUE(r) << 3) + REG_VALUE(r));
+                        }
                     }
                 }
 #endif
-            } else if (dbt == VT_BOOL) {
-                /* scalar to bool */
-                vpushi(0);
-                gen_op(TOK_NE);
-            } else if ((dbt & VT_BTYPE) == VT_BYTE || 
-                       (dbt & VT_BTYPE) == VT_SHORT) {
-                if (sbt == VT_PTR) {
-                    vtop->type.t = VT_INT;
-                    tcc_warning("nonportable conversion from pointer to 
char/short");
+                else if (dbt == VT_BOOL) {
+                    /* scalar to bool */
+                    vpushi(0);
+                    gen_op(TOK_NE);
+                } else if ((dbt & VT_BTYPE) == VT_BYTE || (dbt & VT_BTYPE) == 
VT_SHORT) {
+                    if (sbt == VT_PTR) {
+                        vtop->type.t = VT_INT;
+                        tcc_warning("nonportable conversion from pointer to 
char/short");
+                    }
+                    force_charshort_cast(dbt);
+                } else if ((dbt & VT_BTYPE) == VT_INT) {
+                    /* scalar to int */
+                    if (sbt == VT_LLONG) {
+                        /* from long long: just take low order word */
+                        lexpand();
+                        vpop();
+                    }
+                    /* if lvalue and single word type, nothing to do because
+                       the lvalue already contains the real type size (see
+                       VT_LVAL_xxx constants) */
+                }
+                if(bb){
+                    int bit_size = (type->t >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
+                    type->t  = type->t  & ~(VT_BITFIELD | (-1 << 
VT_STRUCT_SHIFT));
+                    if(dt == VT_LLONG)
+                        vpushll((1ULL << bit_size) - 1ULL);
+                    else
+                        vpushi((1 << bit_size) - 1);
+                    gen_op('&');
                 }
-                force_charshort_cast(dbt);
-            } else if ((dbt & VT_BTYPE) == VT_INT) {
-                /* scalar to int */
-                if (sbt == VT_LLONG) {
-                    /* from long long: just take low order word */
-                    lexpand();
-                    vpop();
-                } 
-                /* if lvalue and single word type, nothing to do because
-                   the lvalue already contains the real type size (see
-                   VT_LVAL_xxx constants) */
             }
         }
     } else if ((dbt & VT_BTYPE) == VT_PTR && !(vtop->r & VT_LVAL)) {
@@ -2463,24 +2508,36 @@ static void gen_assign_cast(CType *dt)
 /* store vtop in lvalue pushed on stack */
 ST_FUNC void vstore(void)
 {
-    int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
+    int sbt, dbt, ft, cc, r, t, size, align, bit_size, bit_pos, rc, 
delayed_cast, ret;
 
     ft = vtop[-1].type.t;
     sbt = vtop->type.t & VT_BTYPE;
     dbt = ft & VT_BTYPE;
+    ret = delayed_cast = 0;
+    cc = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST;
     if ((((sbt == VT_INT || sbt == VT_SHORT) && dbt == VT_BYTE) ||
-         (sbt == VT_INT && dbt == VT_SHORT))
-       && !(vtop->type.t & VT_BITFIELD)) {
+        (sbt == VT_INT && dbt == VT_SHORT)) && !(vtop->type.t & VT_BITFIELD) 
&& !cc) {
         /* optimize char/short casts */
         delayed_cast = VT_MUSTCAST;
         vtop->type.t = ft & (VT_TYPE & ~(VT_BITFIELD | (-1 << 
VT_STRUCT_SHIFT)));
         /* XXX: factorize */
         if (ft & VT_CONSTANT)
             tcc_warning("assignment of read-only location");
+    }else if(ft & VT_BITFIELD){
+        ret = (vtop > (vstack + 1) || gen_ctrl == CTRL_INIT);
+        if(dbt == VT_BOOL)
+            vtop[-1].type.t = (vtop[-1].type.t & ~VT_BTYPE) | (VT_BYTE | 
VT_UNSIGNED);
+        gen_assign_cast(&vtop[-1].type);
+        if(ret){
+            if((vtop->r & (VT_VALMASK|VT_LVAL|VT_SYM)) < VT_CONST){
+                gv_dup();
+            }else{
+                vpushv(&vtop[0]);
+            }
+            vrott(3);
+        }
     } else {
-        delayed_cast = 0;
-        if (!(ft & VT_BITFIELD))
-            gen_assign_cast(&vtop[-1].type);
+        gen_assign_cast(&vtop[-1].type);
     }
 
     if (sbt == VT_STRUCT) {
@@ -2522,37 +2579,18 @@ ST_FUNC void vstore(void)
         /* bitfield store handling */
         bit_pos = (ft >> VT_STRUCT_SHIFT) & 0x3f;
         bit_size = (ft >> (VT_STRUCT_SHIFT + 6)) & 0x3f;
+
         /* remove bit field info to avoid loops */
         vtop[-1].type.t = ft & ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
 
-        /* duplicate source into other register */
-        gv_dup();
-        vswap();
-        vrott(3);
-
-        if((ft & VT_BTYPE) == VT_BOOL) {
-            gen_cast(&vtop[-1].type);
-            vtop[-1].type.t = (vtop[-1].type.t & ~VT_BTYPE) | (VT_BYTE | 
VT_UNSIGNED);
-        }
+        vpushi(bit_pos);
+        gen_op(TOK_SHL);
 
         /* duplicate destination */
-        vdup();
-        vtop[-1] = vtop[-2];
+        vpushv(&vtop[-1]);
 
-        /* mask and shift source */
-        if((ft & VT_BTYPE) != VT_BOOL) {
-            if((ft & VT_BTYPE) == VT_LLONG) {
-                vpushll((1ULL << bit_size) - 1ULL);
-            } else {
-                vpushi((1 << bit_size) - 1);
-            }
-            gen_op('&');
-        }
-        vpushi(bit_pos);
-        gen_op(TOK_SHL);
         /* load destination, mask and or with source */
-        vswap();
-        if((ft & VT_BTYPE) == VT_LLONG) {
+        if(dbt == VT_LLONG) {
             vpushll(~(((1ULL << bit_size) - 1ULL) << bit_pos));
         } else {
             vpushi(~(((1 << bit_size) - 1) << bit_pos));
@@ -2563,8 +2601,8 @@ ST_FUNC void vstore(void)
         vstore();
 
         /* pop off shifted source from "duplicate source..." above */
-        vpop();
-
+        if(ret)
+            vtop--;
     } else {
 #ifdef CONFIG_TCC_BCHECK
         /* bound check case */
@@ -3605,7 +3643,7 @@ static void vpush_tokc(int t)
 
 ST_FUNC void unary(void)
 {
-    int n, t, align, size, r, sizeof_caller;
+    int n, t, align, size, r, sizeof_caller, save_ctrl;
     CType type;
     Sym *s;
     AttributeDef ad;
@@ -3714,7 +3752,10 @@ ST_FUNC void unary(void)
                     return;
                 }
                 unary();
+                save_ctrl = gen_ctrl;
+                gen_ctrl = CTRL_FOCE;
                 gen_cast(&type);
+                gen_ctrl = save_ctrl;
             }
         } else if (tok == '{') {
             /* save all registers */
@@ -5127,7 +5168,7 @@ static void decl_designator(CType *type, Section *sec, 
unsigned long c,
 static void init_putv(CType *type, Section *sec, unsigned long c, 
                       int v, int expr_type)
 {
-    int saved_global_expr, bt, bit_pos, bit_size;
+    int saved_global_expr, bt, bit_pos, bit_size, save_ctrl;
     void *ptr;
     unsigned long long bit_mask;
     CType dtype;
@@ -5147,7 +5188,10 @@ static void init_putv(CType *type, Section *sec, 
unsigned long c,
             tcc_error("initializer element is not constant");
         break;
     case EXPR_ANY:
+        save_ctrl = gen_ctrl;
+        gen_ctrl = CTRL_INIT;
         expr_eq();
+        gen_ctrl = save_ctrl;
         break;
     }
     
diff --git a/tests/tests2/03_struct.c b/tests/tests2/03_struct.c
index c5d48c5..e06d20d 100644
--- a/tests/tests2/03_struct.c
+++ b/tests/tests2/03_struct.c
@@ -27,5 +27,36 @@ int main()
    printf("%d\n", jones[1].boris);
    printf("%d\n", jones[1].natasha);
 
+   struct sbf1 {
+        int f1 : 3;
+        int : 2;
+        int f2 : 1;
+        int : 0;
+        int f3 : 5;
+        int f4 : 7;
+        unsigned int f5 : 7;
+   } st1;
+   st1.f1 = st1.f2 = st1.f3 = st1.f4 = st1.f5 = 3;
+   printf("%d %d %d %d %d\n",
+         st1.f1, st1.f2, st1.f3, st1.f4, st1.f5);
+
+   struct { unsigned a:9, b:7, c:5; } s1;
+            s1.a = s1.b = s1.c = 3;
+   printf("%d / %d / %d\n", s1.a, s1.b, s1.c);
+
+   struct {
+        unsigned a:9, b:5, c:7;
+   } s2, *ps = &s2;
+   int n = 250;
+
+   int ii = ps->a = ps->b = ps->c = n + 4;
+   printf("%d / %d / %d\n", ps->a, ps->b, ps->c);
+   printf("%d\n", ii);
+   
+   ps->a = n + 4;
+   ps->b = n + 4;
+   ps->c = n + 4;
+   printf("%d / %d / %d\n", ps->a, ps->b, ps->c);
+
    return 0;
 }
diff --git a/tests/tests2/03_struct.expect b/tests/tests2/03_struct.expect
index ecbf589..6b90186 100644
--- a/tests/tests2/03_struct.expect
+++ b/tests/tests2/03_struct.expect
@@ -1,6 +1,12 @@
+03_struct.c:39: warning: overflow in implicit constant conversion
 12
 34
 12
 34
 56
 78
+-1 -1 3 3 3
+3 / 3 / 3
+30 / 30 / 126
+30
+254 / 30 / 126
_______________________________________________
Tinycc-devel mailing list
Tinycc-devel@nongnu.org
https://lists.nongnu.org/mailman/listinfo/tinycc-devel

Reply via email to