From 18352327b7033149636acba6af13ce47e5f38059 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Daniel=20Gl=C3=B6ckner?= Date: Thu, 20 Nov 2008 11:30:35 +0100 Subject: [PATCH] Rewrote casts Casting of constants was done only inside functions. I restructured the code and used intermediate types (long double/long long) for most conversions to have less ifs. Please review. There are lots of cases to take care of and lots of mistakes to make. --- tcc.c | 216 +++++++++++++++++++++++++++++++----------------------------------- 1 file changed, 101 insertions(+), 115 deletions(-) diff --git a/tcc.c b/tcc.c index 4560b3f5..6a0f0da2 100644 --- a/tcc.c +++ b/tcc.c @@ -5991,110 +5991,95 @@ static void gen_cast(CType *type) dbt = type->t & (VT_BTYPE | VT_UNSIGNED); sbt = vtop->type.t & (VT_BTYPE | VT_UNSIGNED); - if (sbt != dbt && !nocode_wanted) { + if (sbt != dbt) { sf = is_float(sbt); df = is_float(dbt); c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_SYM)) == VT_CONST; - if (sf && df) { - /* convert from fp to fp */ - if (c) { - /* constant case: we can do it now */ - /* XXX: in ISOC, cannot do it if error in convert */ - if (dbt == VT_FLOAT && sbt == VT_DOUBLE) - vtop->c.f = (float)vtop->c.d; - else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE) + if (c) { + /* constant case: we can do it now */ + /* XXX: in ISOC, cannot do it if error in convert */ + if (sbt == VT_FLOAT) + vtop->c.ld = vtop->c.f; + else if (sbt == VT_DOUBLE) + vtop->c.ld = vtop->c.d; + + if (df) { + if ((sbt & VT_BTYPE) == VT_LLONG) { + if (sbt & VT_UNSIGNED) + vtop->c.ld = vtop->c.ull; + else + vtop->c.ld = vtop->c.ll; + } else if(!sf) { + if (sbt & VT_UNSIGNED) + vtop->c.ld = vtop->c.ui; + else + vtop->c.ld = vtop->c.i; + } + + if (dbt == VT_FLOAT) vtop->c.f = (float)vtop->c.ld; - else if (dbt == VT_DOUBLE && sbt == VT_FLOAT) - vtop->c.d = (double)vtop->c.f; - else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE) + else if (dbt == VT_DOUBLE) vtop->c.d = (double)vtop->c.ld; - else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT) - vtop->c.ld = (long double)vtop->c.f; - else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE) - vtop->c.ld = (long double)vtop->c.d; + } else if (sf && dbt == (VT_LLONG|VT_UNSIGNED)) { + vtop->c.ull = (unsigned long long)vtop->c.ld; + } else if (sf && dbt == VT_BOOL) { + vtop->c.i = (vtop->c.ld != 0); } else { - /* non constant case: generate code */ - gen_cvt_ftof(dbt); - } - } else if (df) { - /* convert int to fp */ - if (c) { - switch(sbt) { - case VT_LLONG | VT_UNSIGNED: - case VT_LLONG: - /* XXX: add const cases for long long */ - goto do_itof; - case VT_INT | VT_UNSIGNED: - switch(dbt) { - case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break; - case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break; - case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.ui; break; - } - break; - default: - switch(dbt) { - case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break; - case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break; - case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break; - } - break; + if(sf) + vtop->c.ll = (long long)vtop->c.ld; + else if (sbt == (VT_LLONG|VT_UNSIGNED)) + vtop->c.ll = vtop->c.ull; + else if (sbt & VT_UNSIGNED) + vtop->c.ll = vtop->c.ui; + else if (sbt != VT_LLONG) + vtop->c.ll = vtop->c.i; + + if (dbt == (VT_LLONG|VT_UNSIGNED)) + vtop->c.ull = vtop->c.ll; + else if (dbt == VT_BOOL) + vtop->c.i = (vtop->c.ll != 0); + 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; } - } else { - do_itof: - gen_cvt_itof1(dbt); } - } else if (sf) { - /* convert fp to int */ - if (dbt == VT_BOOL) { - vpushi(0); - gen_op(TOK_NE); - } else { - /* we handle char/short/etc... with generic code */ - if (dbt != (VT_INT | VT_UNSIGNED) && - dbt != (VT_LLONG | VT_UNSIGNED) && - dbt != VT_LLONG) - dbt = VT_INT; - if (c) { - switch(dbt) { - case VT_LLONG | VT_UNSIGNED: - case VT_LLONG: - /* XXX: add const cases for long long */ - goto do_ftoi; - case VT_INT | VT_UNSIGNED: - switch(sbt) { - case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break; - case VT_DOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break; - case VT_LDOUBLE: vtop->c.ui = (unsigned int)vtop->c.d; break; - } - break; - default: - /* int case */ - switch(sbt) { - case VT_FLOAT: vtop->c.i = (int)vtop->c.d; break; - case VT_DOUBLE: vtop->c.i = (int)vtop->c.d; break; - case VT_LDOUBLE: vtop->c.i = (int)vtop->c.d; break; - } - break; - } + } else if (!nocode_wanted) { + /* non constant case: generate code */ + if (sf && df) { + /* convert from fp to fp */ + gen_cvt_ftof(dbt); + } else if (df) { + /* convert int to fp */ + gen_cvt_itof1(dbt); + } else if (sf) { + /* convert fp to int */ + if (dbt == VT_BOOL) { + vpushi(0); + gen_op(TOK_NE); } else { - do_ftoi: + /* we handle char/short/etc... with generic code */ + if (dbt != (VT_INT | VT_UNSIGNED) && + dbt != (VT_LLONG | VT_UNSIGNED) && + dbt != VT_LLONG) + dbt = VT_INT; gen_cvt_ftoi1(dbt); + if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) { + /* additional cast for char/short... */ + vtop->type.t = dbt; + gen_cast(type); + } } - if (dbt == VT_INT && (type->t & (VT_BTYPE | VT_UNSIGNED)) != dbt) { - /* additional cast for char/short... */ - vtop->type.t = dbt; - gen_cast(type); - } - } - } else if ((dbt & VT_BTYPE) == VT_LLONG) { - if ((sbt & VT_BTYPE) != VT_LLONG) { - /* scalar to long long */ - if (c) { - if (sbt == (VT_INT | VT_UNSIGNED)) - vtop->c.ll = vtop->c.ui; - else - vtop->c.ll = vtop->c.i; - } else { + } 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 */ @@ -6110,29 +6095,30 @@ static void gen_cast(CType *type) vtop[-1].r2 = vtop->r; vpop(); } + } 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; + 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) */ } - } 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; - 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) */ - } + } else + expect("constant expression"); } else if ((dbt & VT_BTYPE) == VT_PTR && !(vtop->r & VT_LVAL)) { /* if we are casting between pointer types, we must update the VT_LVAL_xxx size */ -- 2.11.4.GIT