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