From f7181903bbd897e9ed43c13fdeeff46aae972582 Mon Sep 17 00:00:00 2001 From: bellard Date: Thu, 20 Dec 2001 01:05:21 +0000 Subject: [PATCH] separated type and value on stack --- i386-gen.c | 92 ++++++----- tcc.c | 458 ++++++++++++++++++++++++++++------------------------- 2 files changed, 294 insertions(+), 256 deletions(-) diff --git a/i386-gen.c b/i386-gen.c index 11651d8..b52eec9 100644 --- a/i386-gen.c +++ b/i386-gen.c @@ -155,10 +155,10 @@ int oad(int c, int s) return s; } -/* output constant with relocation if 't & VT_FORWARD' is true */ -void gen_addr32(int c, int t) +/* output constant with relocation if 'r & VT_FORWARD' is true */ +void gen_addr32(int r, int c) { - if (!(t & VT_FORWARD)) { + if (!(r & VT_FORWARD)) { gen_le32(c); } else { greloc((Sym *)c, ind, RELOC_ADDR32); @@ -166,16 +166,23 @@ void gen_addr32(int c, int t) } } -/* XXX: generate correct pointer for forward references to functions */ -/* r = (ft, fc) */ -void load(int r, int ft, int fc) +/* load 'r' from value 'sv' */ +void load(int r, SValue *sv) { - int v, t; + int v, t, ft, fc, fr; + SValue v1; - v = ft & VT_VALMASK; - if (ft & VT_LVAL) { + fr = sv->r; + ft = sv->t; + fc = sv->c.ul; + + v = fr & VT_VALMASK; + if (fr & VT_LVAL) { if (v == VT_LLOCAL) { - load(r, VT_LOCAL | VT_LVAL, fc); + v1.t = VT_INT; + v1.r = VT_LOCAL | VT_LVAL; + v1.c.ul = fc; + load(r, &v1); v = r; } if ((ft & VT_BTYPE) == VT_FLOAT) { @@ -200,7 +207,7 @@ void load(int r, int ft, int fc) if (v == VT_CONST) { o(0x05 + r * 8); /* 0xXX, r */ - gen_addr32(fc, ft); + gen_addr32(fr, fc); } else if (v == VT_LOCAL) { oad(0x85 + r * 8, fc); /* xx(%ebp), r */ } else { @@ -209,7 +216,7 @@ void load(int r, int ft, int fc) } else { if (v == VT_CONST) { o(0xb8 + r); /* mov $xx, r */ - gen_addr32(fc, ft); + gen_addr32(fr, fc); } else if (v == VT_LOCAL) { o(0x8d); oad(0x85 + r * 8, fc); /* lea xxx(%ebp), r */ @@ -231,13 +238,14 @@ void load(int r, int ft, int fc) } } -/* (ft, fc) = r */ -/* WARNING: r must not be allocated on the stack */ -void store(r, ft, fc) +/* store register 'r' in lvalue 'v' */ +void store(int r, SValue *v) { - int fr, bt; + int fr, bt, ft, fc; - fr = ft & VT_VALMASK; + ft = v->t; + fc = v->c.ul; + fr = v->r & VT_VALMASK; bt = ft & VT_BTYPE; /* XXX: incorrect if reg to reg */ /* XXX: should not flush float stack */ @@ -261,10 +269,10 @@ void store(r, ft, fc) } if (fr == VT_CONST) { o(0x05 + r * 8); /* mov r,xxx */ - gen_addr32(fc, ft); + gen_addr32(v->r, fc); } else if (fr == VT_LOCAL) { oad(0x85 + r * 8, fc); /* mov r,xxx(%ebp) */ - } else if (ft & VT_LVAL) { + } else if (v->r & VT_LVAL) { g(fr + r * 8); /* mov r, (fr) */ } else if (fr != r) { o(0xc0 + fr + r * 8); /* mov r, fr */ @@ -283,7 +291,7 @@ void gfunc_param(GFuncContext *c) { int size, align, r; - if ((vtop->t & (VT_BTYPE | VT_LVAL)) == (VT_STRUCT | VT_LVAL)) { + if ((vtop->t & VT_BTYPE) == VT_STRUCT) { size = type_size(vtop->t, &align); /* align to stack align size */ size = (size + 3) & ~3; @@ -293,7 +301,7 @@ void gfunc_param(GFuncContext *c) r = get_reg(REG_CLASS_INT); o(0x89); /* mov %esp, r */ o(0xe0 + r); - vset(VT_INT | r, 0); + vset(VT_INT, r, 0); vswap(); vstore(); c->args_size += size; @@ -328,10 +336,10 @@ void gfunc_param(GFuncContext *c) void gfunc_call(GFuncContext *c) { int r; - if ((vtop->t & (VT_VALMASK | VT_LVAL)) == VT_CONST) { + if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) { /* constant case */ /* forward reference */ - if (vtop->t & VT_FORWARD) { + if (vtop->r & VT_FORWARD) { greloc(vtop->c.sym, ind + 1, RELOC_REL32); oad(0xe8, 0); } else { @@ -357,7 +365,7 @@ int gjmp(int t) int gtst(int inv, int t) { int v, *p; - v = vtop->t & VT_VALMASK; + v = vtop->r & VT_VALMASK; if (v == VT_CMP) { /* fast case : can jump directly since flags are set */ g(0x0f); @@ -375,7 +383,7 @@ int gtst(int inv, int t) t = gjmp(t); gsym(vtop->c.i); } - } else if ((vtop->t & (VT_VALMASK | VT_LVAL)) == VT_CONST) { + } else if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) { /* constant jmp optimization */ if ((vtop->c.i != 0) != inv) t = gjmp(t); @@ -438,7 +446,7 @@ void gen_opi(int op) o(0xe8 + r); else o(0xf8 + r); - vtop->t = (vtop->t & VT_TYPE) | r; + vtop->r = r; } else if (op == '/' | op == TOK_UDIV | op == TOK_PDIV | op == '%' | op == TOK_UMOD) { save_reg(2); /* save edx */ @@ -455,12 +463,12 @@ void gen_opi(int op) r = 2; else r = 0; - vtop->t = (vtop->t & VT_TYPE) | r; + vtop->r = r; } else { vtop--; o(0x39); o(0xc0 + r + fr * 8); /* cmp fr, r */ - vset(VT_CMP, op); + vset(VT_INT, VT_CMP, op); } } @@ -472,24 +480,24 @@ void gen_opf(int op) int a, ft, fc, swapped, r; /* convert constants to memory references */ - if ((vtop[-1].t & (VT_CONST | VT_LVAL)) == VT_CONST) { + if ((vtop[-1].r & (VT_CONST | VT_LVAL)) == VT_CONST) { vswap(); gv(); vswap(); } - if ((vtop[0].t & (VT_CONST | VT_LVAL)) == VT_CONST) + if ((vtop[0].r & (VT_CONST | VT_LVAL)) == VT_CONST) gv(); /* must put at least one value in the floating point register */ - if ((vtop[-1].t & VT_LVAL) && - (vtop[0].t & VT_LVAL)) { + if ((vtop[-1].r & VT_LVAL) && + (vtop[0].r & VT_LVAL)) { vswap(); gv(); vswap(); } if (op >= TOK_EQ && op <= TOK_GT) { /* load on stack second operand */ - load(REG_ST0, vtop->t, vtop->c.ul); + load(REG_ST0, vtop); if (op == TOK_GE || op == TOK_GT) o(0xc9d9); /* fxch %st(1) */ o(0xe9da); /* fucompp */ @@ -509,13 +517,13 @@ void gen_opf(int op) op = TOK_EQ; } vtop--; - vtop->t = (vtop->t & VT_TYPE) | VT_CMP; + vtop->r = VT_CMP; vtop->c.i = op; } else { /* swap the stack if needed so that t1 is the register and t2 is the memory reference */ swapped = 0; - if (vtop[-1].t & VT_LVAL) { + if (vtop[-1].r & VT_LVAL) { vswap(); swapped = 1; } @@ -546,10 +554,10 @@ void gen_opf(int op) else o(0xd8); - r = ft & VT_VALMASK; + r = vtop->r & VT_VALMASK; if (r == VT_CONST) { o(0x05 + a); - gen_addr32(fc, ft); + gen_addr32(vtop->r, fc); } else if (r == VT_LOCAL) { oad(0x85 + a, fc); } else { @@ -567,16 +575,16 @@ void gen_cvt_itof(int t) /* unsigned int to float/double/long double */ o(0x6a); /* push $0 */ g(0x00); - o(0x50 + (vtop->t & VT_VALMASK)); /* push r */ + o(0x50 + (vtop->r & VT_VALMASK)); /* push r */ o(0x242cdf); /* fildll (%esp) */ o(0x08c483); /* add $8, %esp */ } else { /* int to float/double/long double */ - o(0x50 + (vtop->t & VT_VALMASK)); /* push r */ + o(0x50 + (vtop->r & VT_VALMASK)); /* push r */ o(0x2404db); /* fildl (%esp) */ o(0x04c483); /* add $4, %esp */ } - vtop->t = t | REG_ST0; + vtop->r = REG_ST0; } /* FPU control word for rounding to nearest mode */ @@ -611,7 +619,7 @@ void gen_cvt_ftoi(int t) o(0x58 + r); /* pop r */ if (size == 8) o(0x04c483); /* add $4, %esp */ - vtop->t = t | r; + vtop->r = r; } /* convert from one floating point type to another */ @@ -625,7 +633,7 @@ void gen_cvt_ftof(int t) void vpop(void) { /* for x86, we need to pop the FP stack */ - if ((vtop->t & VT_VALMASK) == REG_ST0) { + if ((vtop->r & VT_VALMASK) == REG_ST0) { o(0xd9dd); /* fstp %st(1) */ } vtop--; diff --git a/tcc.c b/tcc.c index 91a70f3..aec3d47 100644 --- a/tcc.c +++ b/tcc.c @@ -64,14 +64,15 @@ typedef union CValue { long long ll; unsigned long long ull; struct TokenSym *ts; - int tab[1]; struct Sym *sym; + int tab[1]; } CValue; /* value on stack */ typedef struct SValue { - int t; - CValue c; + int t; /* type */ + int r; /* register + flags */ + CValue c; /* constant */ } SValue; /* symbol management */ @@ -360,7 +361,7 @@ int pointed_size(int t); int ist(void); int type_decl(int *v, int t, int td); void error(const char *fmt, ...); -void vset(int t, int v); +void vset(int t, int r, int v); /* true if float/double/long double type */ static inline int is_float(int t) @@ -485,7 +486,7 @@ void skip(int c) void test_lvalue(void) { - if (!(vtop->t & VT_LVAL)) + if (!(vtop->r & VT_LVAL)) expect("lvalue"); } @@ -1874,25 +1875,34 @@ void swap(int *p, int *q) *q = t; } -void vsetc(int t, CValue *vc) +void vsetc(int t, int r, CValue *vc) { if (vtop >= vstack + VSTACK_SIZE) error("memory full"); /* cannot let cpu flags if other instruction are generated */ /* XXX: VT_JMP test too ? */ - if ((vtop->t & VT_VALMASK) == VT_CMP) + if ((vtop->r & VT_VALMASK) == VT_CMP) gv(); vtop++; vtop->t = t; + vtop->r = r; vtop->c = *vc; } -void vset(int t, int v) +/* push integer constant */ +void vpushi(int v) +{ + CValue cval; + cval.i = v; + vsetc(VT_INT, VT_CONST, &cval); +} + +void vset(int t, int r, int v) { CValue cval; cval.i = v; - vsetc(t, &cval); + vsetc(t, r, &cval); } void vswap(void) @@ -1915,22 +1925,25 @@ void vdup(void) int save_reg_forced(int r) { int i, l, t; - SValue *p; + SValue *p, sv; /* store register */ loc = (loc - 4) & -3; - store(r, VT_LOCAL, loc); + sv.t = VT_INT; + sv.r = VT_LOCAL | VT_LVAL; + sv.c.ul = loc; + store(r, &sv); l = loc; /* modify all stack values */ for(p=vstack;p<=vtop;p++) { - i = p->t & VT_VALMASK; + i = p->r & VT_VALMASK; if (i == r) { - if (p->t & VT_LVAL) + if (p->r & VT_LVAL) t = VT_LLOCAL; else t = VT_LOCAL; - p->t = (p->t & VT_TYPE) | VT_LVAL | t; + p->r = VT_LVAL | t; p->c.ul = l; } } @@ -1945,7 +1958,7 @@ void save_reg(int r) /* modify all stack values */ for(p=vstack;p<=vtop;p++) { - i = p->t & VT_VALMASK; + i = p->r & VT_VALMASK; if (i == r) { save_reg_forced(r); break; @@ -1963,7 +1976,7 @@ int get_reg(int rc) for(r=0;rt & VT_VALMASK; + i = p->r & VT_VALMASK; if (i == r) goto notfound; } @@ -1976,7 +1989,7 @@ int get_reg(int rc) important to start from the bottom to ensure that we don't spill registers used in gen_op()) */ for(p=vstack;p<=vtop;p++) { - r = p->t & VT_VALMASK; + r = p->r & VT_VALMASK; if (r < VT_CONST && (reg_classes[r] & rc)) { save_reg(r); break; @@ -1985,13 +1998,13 @@ int get_reg(int rc) return r; } -void save_regs() +void save_regs(void) { int r; SValue *p; for(p=vstack;p<=vtop;p++) { - r = p->t & VT_VALMASK; + r = p->r & VT_VALMASK; if (r < VT_CONST) { save_reg(r); } @@ -2002,9 +2015,14 @@ void save_regs() if needed */ void move_reg(int r, int s) { + SValue sv; + if (r != s) { save_reg(r); - load(r, s, 0); + sv.t = VT_INT; + sv.r = s; + sv.c.ul = 0; + load(r, &sv); } } @@ -2022,14 +2040,15 @@ int gv(void) /* remove bit field info to avoid loops */ vtop->t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT)); /* generate shifts */ - vset(VT_CONST, 32 - (bit_pos + bit_size)); + vpushi(32 - (bit_pos + bit_size)); gen_op(TOK_SHL); - vset(VT_CONST, 32 - bit_size); + vpushi(32 - bit_size); /* NOTE: transformed to SHR if unsigned */ gen_op(TOK_SAR); r = gv(); } else { - if (is_float(vtop->t) && (vtop->t & (VT_CONST | VT_LVAL)) == VT_CONST) { + if (is_float(vtop->t) && + (vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) { /* CPUs usually cannot use float constants, so we store them generically in data segment */ size = type_size(vtop->t, &align); @@ -2038,20 +2057,20 @@ int gv(void) size = size >> 2; for(i=0;ic.tab[i]; - vtop->t |= VT_LVAL; + vtop->r |= VT_LVAL; vtop->c.ul = glo; glo += size << 2; } - r = vtop->t & VT_VALMASK; - if (r >= VT_CONST || (vtop->t & VT_LVAL)) { + r = vtop->r & VT_VALMASK; + if (r >= VT_CONST || (vtop->r & VT_LVAL)) { if (is_float(vtop->t)) rc = REG_CLASS_FLOAT; else rc = REG_CLASS_INT; r = get_reg(rc); } - load(r, vtop->t, vtop->c.ul); - vtop->t = (vtop->t & VT_TYPE) | r; + load(r, vtop); + vtop->r = r; } return r; } @@ -2065,8 +2084,8 @@ void gen_opc(int op) v1 = vtop - 1; v2 = vtop; /* currently, we cannot do computations with forward symbols */ - c1 = (v1->t & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST; - c2 = (v2->t & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST; + c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST; + c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST; if (c1 && c2) { fc = v2->c.i; switch(op) { @@ -2184,9 +2203,9 @@ void gen_op(int op) gen_opf(op); if (op >= TOK_EQ && op <= TOK_GT) { /* the result is an int */ - vtop->t = (vtop->t & ~VT_TYPE) | VT_INT; + vtop->t = VT_INT; } else { - vtop->t = (vtop->t & ~VT_TYPE) | t; + vtop->t = t; } } else if (op == '+' || op == '-') { if ((t1 & VT_BTYPE) == VT_PTR && @@ -2197,8 +2216,8 @@ void gen_op(int op) u = pointed_size(t1); gen_opc(op); /* set to integer type */ - vtop->t = (vtop->t & ~VT_TYPE) | VT_INT; - vset(VT_CONST, u); + vtop->t = VT_INT; + vpushi(u); gen_op(TOK_PDIV); } else if ((t1 & VT_BTYPE) == VT_PTR || (t2 & VT_BTYPE) == VT_PTR) { @@ -2207,11 +2226,11 @@ void gen_op(int op) swap(&t1, &t2); } /* stack-4 contains pointer, stack-2 value to add */ - vset(VT_CONST, pointed_size(vtop[-1].t)); + vpushi(pointed_size(vtop[-1].t)); gen_op('*'); gen_opc(op); /* put again type if gen_opc() swaped operands */ - vtop->t = (vtop->t & ~VT_TYPE) | (t1 & VT_TYPE); + vtop->t = t1; } else { gen_opc(op); } @@ -2242,128 +2261,128 @@ void gen_op(int op) /* cast 'vtop' to 't' type */ void gen_cast(int t) { - int r, bits, sbt, dbt, sf, df, c, st1, dt1; + int bits, sbt, dbt, sf, df, c, st1, dt1; - r = vtop->t & VT_VALMASK; - if (!(t & VT_LVAL)) { - /* if not lvalue, then we convert now */ - dbt = t & VT_BTYPE; - sbt = vtop->t & VT_BTYPE; - if (sbt != dbt) { - sf = is_float(sbt); - df = is_float(dbt); - c = (vtop->t & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == 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) - 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) - 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 { - /* non constant case: generate code */ - gen_cvt_ftof(dbt); - } - } else if (df) { - /* convert int to fp */ - /* XXX: add const cases */ - st1 = vtop->t & (VT_BTYPE | VT_UNSIGNED); - if (c) { - switch(st1) { - case VT_LLONG | VT_UNSIGNED: - case VT_LLONG: - /* well, currently not needed */ - 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 not lvalue, then we convert now */ + dbt = t & VT_BTYPE; + sbt = vtop->t & VT_BTYPE; + if (sbt != dbt) { + sf = is_float(sbt); + df = is_float(dbt); + c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == 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) + 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) + 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 { + /* non constant case: generate code */ + gen_cvt_ftof(dbt); + } + } else if (df) { + /* convert int to fp */ + /* XXX: add const cases */ + st1 = vtop->t & (VT_BTYPE | VT_UNSIGNED); + if (c) { + switch(st1) { + case VT_LLONG | VT_UNSIGNED: + case VT_LLONG: + /* well, currently not needed */ + 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; } - } else { - do_itof: - gen_cvt_itof(dbt); - } - } else if (sf) { - /* convert fp to int */ - dt1 = t & (VT_BTYPE | VT_UNSIGNED); - /* we handle char/short/etc... with generic code */ - if (dt1 != VT_INT | VT_UNSIGNED && - dt1 != VT_LLONG | VT_UNSIGNED && - dt1 != VT_LLONG) - dt1 = VT_INT; - if (c) { - switch(dt1) { - case VT_LLONG | VT_UNSIGNED: - case VT_LLONG: - /* well, currently not needed */ - 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; + 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; } - } else { - do_ftoi: - gen_cvt_ftoi(dt1); + break; } - if (dt1 == VT_INT && (t & (VT_TYPE | VT_UNSIGNED)) != dt1) { - /* additionnal cast for char/short/bool... */ - vtop->t = (vtop->t & ~VT_TYPE) | dt1; - gen_cast(t); - } - } else if (dbt == VT_BOOL) { - vset(VT_CONST, 0); - gen_op(TOK_NE); - } else if (dbt == VT_BYTE || dbt == VT_SHORT) { - if (dbt == VT_BYTE) - bits = 8; - else - bits = 16; - if (t & VT_UNSIGNED) { - vset(VT_CONST, (1 << bits) - 1); - gen_op('&'); - } else { - bits = 32 - bits; - vset(VT_CONST, bits); - gen_op(TOK_SHL); - vset(VT_CONST, bits); - gen_op(TOK_SAR); + } else { + do_itof: + gen_cvt_itof(dbt); + } + } else if (sf) { + /* convert fp to int */ + dt1 = t & (VT_BTYPE | VT_UNSIGNED); + /* we handle char/short/etc... with generic code */ + if (dt1 != VT_INT | VT_UNSIGNED && + dt1 != VT_LLONG | VT_UNSIGNED && + dt1 != VT_LLONG) + dt1 = VT_INT; + if (c) { + switch(dt1) { + case VT_LLONG | VT_UNSIGNED: + case VT_LLONG: + /* well, currently not needed */ + 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 { + do_ftoi: + gen_cvt_ftoi(dt1); + } + if (dt1 == VT_INT && (t & (VT_TYPE | VT_UNSIGNED)) != dt1) { + /* additionnal cast for char/short/bool... */ + vtop->t = (vtop->t & ~VT_TYPE) | dt1; + gen_cast(t); + } + } else if (dbt == VT_BOOL) { + vpushi(0); + gen_op(TOK_NE); + } else if ((dbt == VT_BYTE || dbt == VT_SHORT) && + !(vtop->r & VT_LVAL)) { + /* no need to apply if lvalue because we do it while + loading the value */ + if (dbt == VT_BYTE) + bits = 8; + else + bits = 16; + if (t & VT_UNSIGNED) { + vpushi((1 << bits) - 1); + gen_op('&'); + } else { + bits = 32 - bits; + vpushi(bits); + gen_op(TOK_SHL); + vpushi(bits); + gen_op(TOK_SAR); } } } - vtop->t = (vtop->t & ~VT_TYPE) | t; + vtop->t = t; } /* return type size. Put alignment at 'a' */ @@ -2599,7 +2618,7 @@ void gen_assign_cast(int dt) /* store vtop in lvalue pushed on stack */ void vstore(void) { - int ft, fc, r, t, size, align, bit_size, bit_pos; + int ft, r, t, size, align, bit_size, bit_pos; GFuncContext gf; ft = vtop[-1].t; @@ -2614,18 +2633,20 @@ void vstore(void) gfunc_start(&gf); /* type size */ size = type_size(vtop->t, &align); - vset(VT_CONST, size); + vpushi(size); gfunc_param(&gf); /* source */ - vtop->t &= ~VT_LVAL; + vtop->t = VT_INT; + vtop->r &= ~VT_LVAL; gfunc_param(&gf); /* destination */ vswap(); - vtop->t &= ~VT_LVAL; + vtop->t = VT_INT; + vtop->r &= ~VT_LVAL; gfunc_param(&gf); save_regs(); - vset(VT_CONST, (int)&memcpy); + vpushi((int)&memcpy); gfunc_call(&gf); /* leave source on stack */ } else if (ft & VT_BITFIELD) { @@ -2640,30 +2661,32 @@ void vstore(void) vtop[-1] = vtop[-2]; /* mask and shift source */ - vset(VT_CONST, (1 << bit_size) - 1); + vpushi((1 << bit_size) - 1); gen_op('&'); - vset(VT_CONST, bit_pos); + vpushi(bit_pos); gen_op(TOK_SHL); /* load destination, mask and or with source */ vswap(); - vset(VT_CONST, ~(((1 << bit_size) - 1) << bit_pos)); + vpushi(~(((1 << bit_size) - 1) << bit_pos)); gen_op('&'); gen_op('|'); /* store result */ vstore(); } else { r = gv(); /* generate value */ - ft = vtop[-1].t; - fc = vtop[-1].c.i; /* if lvalue was saved on stack, must read it */ - if ((ft & VT_VALMASK) == VT_LLOCAL) { + if ((vtop[-1].r & VT_VALMASK) == VT_LLOCAL) { + SValue sv; t = get_reg(REG_CLASS_INT); - load(t, VT_LOCAL | VT_LVAL, fc); - ft = (ft & ~VT_VALMASK) | t; + sv.t = VT_INT; + sv.r = VT_LOCAL | VT_LVAL; + sv.c.ul = vtop[-1].c.ul; + load(t, &sv); + vtop[-1].r = t | VT_LVAL; } - store(r, ft, fc); + store(r, vtop - 1); vtop--; - vtop->t = (ft & VT_TYPE) | r; + vtop->r = r; vtop->c.i = 0; } } @@ -2672,6 +2695,7 @@ void vstore(void) void inc(int post, int c) { int r, r1; + SValue sv; test_lvalue(); if (post) @@ -2682,13 +2706,16 @@ void inc(int post, int c) /* duplicate value */ /* XXX: handle floats */ r1 = get_reg(REG_CLASS_INT); - load(r1, r, 0); /* move r to r1 */ + sv.t = VT_INT; + sv.r = r; + sv.c.ul = 0; + load(r1, &sv); /* move r to r1 */ /* duplicates value */ - vtop[-2].t = (vtop->t & VT_TYPE) | r1; + vtop[-2].r = r1; vtop[-2].c.i = 0; } /* add constant */ - vset(VT_CONST, c - TOK_MID); + vpushi(c - TOK_MID); gen_op('+'); vstore(); /* store value */ if (post) @@ -3107,13 +3134,13 @@ Sym *external_sym(int v, int u) void indir(void) { - if (vtop->t & VT_LVAL) + if (vtop->r & VT_LVAL) gv(); if ((vtop->t & VT_BTYPE) != VT_PTR) expect("pointer"); vtop->t = pointed_type(vtop->t); if (!(vtop->t & VT_ARRAY)) /* an array is never an lvalue */ - vtop->t |= VT_LVAL; + vtop->r |= VT_LVAL; } /* pass a parameter to a function and do type checking and casting */ @@ -3141,21 +3168,21 @@ void unary(void) GFuncContext gf; if (tok == TOK_NUM || tok == TOK_CCHAR || tok == TOK_LCHAR) { - vset(VT_CONST | VT_INT, tokc.i); + vpushi(tokc.i); next(); } else if (tok == TOK_CFLOAT) { - vsetc(VT_CONST | VT_FLOAT, &tokc); + vsetc(VT_FLOAT, VT_CONST, &tokc); next(); } else if (tok == TOK_CDOUBLE) { - vsetc(VT_CONST | VT_DOUBLE, &tokc); + vsetc(VT_DOUBLE, VT_CONST, &tokc); next(); } else if (tok == TOK_CLDOUBLE) { - vsetc(VT_CONST | VT_LDOUBLE, &tokc); + vsetc(VT_LDOUBLE, VT_CONST, &tokc); next(); } else if (tok == TOK___FUNC__) { /* special function name identifier */ /* generate (char *) type */ - vset(VT_CONST | mk_pointer(VT_BYTE), glo); + vset(mk_pointer(VT_BYTE), VT_CONST, glo); strcpy((void *)glo, funcname); glo += strlen(funcname) + 1; next(); @@ -3174,7 +3201,7 @@ void unary(void) decl_initializer(t, glo, 1, 0); glo += type_size(t, &align); /* put it as pointer */ - vset(t & ~VT_ARRAY, fc); + vset(t & ~VT_ARRAY, VT_CONST, fc); } else { t = tok; next(); @@ -3194,7 +3221,7 @@ void unary(void) if (!(ft & VT_ARRAY)) ft |= VT_LVAL; fc = decl_initializer_alloc(ft, 1); - vset(ft, fc); + vset(ft & VT_TYPE, ft & (VT_VALMASK | VT_LVAL), fc); } else { unary(); gen_cast(ft); @@ -3214,20 +3241,21 @@ void unary(void) there and in function calls. */ if ((vtop->t & VT_BTYPE) != VT_FUNC) test_lvalue(); - vtop->t = mk_pointer(vtop->t & VT_LVALN); + vtop->t = mk_pointer(vtop->t); + vtop->r &= ~VT_LVAL; } else if (t == '!') { unary(); - if ((vtop->t & (VT_VALMASK | VT_LVAL)) == VT_CONST) + if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) vtop->c.i = !vtop->c.i; - else if ((vtop->t & VT_VALMASK) == VT_CMP) + else if ((vtop->r & VT_VALMASK) == VT_CMP) vtop->c.i = vtop->c.i ^ 1; else - vset(VT_JMP, gtst(1, 0)); + vset(VT_INT, VT_JMP, gtst(1, 0)); } else if (t == '~') { unary(); - vset(VT_CONST, -1); + vpushi(-1); gen_op('^'); } else if (t == '+') { @@ -3251,13 +3279,13 @@ void unary(void) t = vtop->t; vpop(); } - vset(VT_CONST, type_size(t, &t)); + vpushi(type_size(t, &t)); } else if (t == TOK_INC || t == TOK_DEC) { unary(); inc(0, t); } else if (t == '-') { - vset(VT_CONST, 0); + vpushi(0); unary(); gen_op('-'); } else @@ -3273,9 +3301,10 @@ void unary(void) /* int() function */ s = external_sym(t, VT_FUNC | (p << VT_STRUCT_SHIFT)); } - vset(s->t, s->c); + vset(s->t & VT_TYPE, + s->t & (VT_VALMASK | VT_LVAL | VT_FORWARD), s->c); /* if forward reference, we must point to s */ - if (vtop->t & VT_FORWARD) + if (vtop->r & VT_FORWARD) vtop->c.sym = s; } } @@ -3290,7 +3319,7 @@ void unary(void) if (tok == TOK_ARROW) indir(); test_lvalue(); - vtop->t &= VT_LVALN; + vtop->r &= ~VT_LVAL; next(); /* expect pointer on structure */ if ((vtop->t & VT_BTYPE) != VT_STRUCT) @@ -3305,14 +3334,14 @@ void unary(void) if (!s) error("field not found"); /* add field offset to pointer */ - vtop->t = (vtop->t & ~VT_TYPE) | VT_INT; /* change type to int */ - vset(VT_CONST, s->c); + vtop->t = VT_INT; /* change type to int */ + vpushi(s->c); gen_op('+'); /* change type to field type, and set to lvalue */ - vtop->t = (vtop->t & ~VT_TYPE) | s->t; + vtop->t = s->t; /* an array is never an lvalue */ if (!(vtop->t & VT_ARRAY)) - vtop->t |= VT_LVAL; + vtop->r |= VT_LVAL; next(); } else if (tok == '[') { next(); @@ -3321,8 +3350,7 @@ void unary(void) indir(); skip(']'); } else if (tok == '(') { - int rett; - CValue retc; + SValue ret; Sym *sa; /* function call */ @@ -3337,7 +3365,7 @@ void unary(void) expect("function pointer"); } } else { - vtop->t &= ~VT_LVAL; /* no lvalue */ + vtop->r &= ~VT_LVAL; /* no lvalue */ } /* get return type */ s = sym_find((unsigned)vtop->t >> VT_STRUCT_SHIFT); @@ -3403,15 +3431,17 @@ void unary(void) /* get some space for the returned structure */ size = type_size(s->t, &align); loc = (loc - size) & -align; - rett = s->t | VT_LOCAL | VT_LVAL; + ret.t = s->t; + ret.r = VT_LOCAL | VT_LVAL; /* pass it as 'int' to avoid structure arg passing problems */ - vset(VT_INT | VT_LOCAL, loc); - retc = vtop->c; + vset(VT_INT, VT_LOCAL, loc); + ret.c = vtop->c; gfunc_param(&gf); } else { - rett = s->t | FUNC_RET_REG; /* return in register */ - retc.i = 0; + ret.t = s->t; + ret.r = FUNC_RET_REG; /* return in register */ + ret.c.i = 0; } #ifndef INVERT_FUNC_PARAMS while (tok != ')') { @@ -3428,7 +3458,7 @@ void unary(void) skip(')'); gfunc_call(&gf); /* return value */ - vsetc(rett, &retc); + vsetc(ret.t, ret.r, &ret.c); } else { break; } @@ -3496,7 +3526,7 @@ void eand(void) if (tok != TOK_LAND) { if (t) { t = gtst(1, t); - vset(VT_JMPI, t); + vset(VT_INT, VT_JMPI, t); } break; } @@ -3516,7 +3546,7 @@ void eor(void) if (tok != TOK_LOR) { if (t) { t = gtst(0, t); - vset(VT_JMP, t); + vset(VT_INT, VT_JMP, t); } break; } @@ -3561,7 +3591,7 @@ void expr_eq(void) expr_eq(); r2 = gv(); move_reg(r1, r2); - vtop->t = (vtop->t & VT_TYPE) | r1; + vtop->r = r1; gsym(u); } } @@ -3585,7 +3615,7 @@ void expr_const1(void) a = const_wanted; const_wanted = 1; expr_eq(); - if ((vtop->t & (VT_CONST | VT_LVAL)) != VT_CONST) + if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST) expect("constant"); const_wanted = a; } @@ -3680,7 +3710,7 @@ void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_reg) if ((func_vt & VT_BTYPE) == VT_STRUCT) { /* if returning structure, must copy it to implicit first pointer arg location */ - vset(mk_pointer(func_vt) | VT_LOCAL | VT_LVAL, func_vc); + vset(mk_pointer(func_vt), VT_LOCAL | VT_LVAL, func_vc); indir(); vswap(); /* copy structure value to pointer */ @@ -3785,8 +3815,8 @@ void block(int *bsym, int *csym, int *case_sym, int *def_sym, int case_reg) /* since a case is like a label, we must skip it with a jmp */ b = gjmp(0); gsym(*case_sym); - vset(case_reg, 0); - vset(VT_CONST, a); + vset(VT_INT, case_reg, 0); + vpushi(a); gen_op(TOK_EQ); *case_sym = gtst(1, 0); gsym(b); @@ -3936,7 +3966,7 @@ void init_putv(int t, int c, int v, int is_expr) expr_const1(); global_expr = saved_global_expr; } else { - vset(VT_CONST | VT_INT, v); + vpushi(v); } /* XXX: do casting */ /* XXX: not portable */ @@ -3965,11 +3995,11 @@ void init_putv(int t, int c, int v, int is_expr) } vpop(); } else { - vset(t, c); + vset(t & VT_TYPE, t & (VT_VALMASK | VT_LVAL | VT_FORWARD), c); if (is_expr) expr_eq(); else - vset(VT_CONST | VT_INT, v); + vpushi(v); vstore(); vpop(); } @@ -3984,13 +4014,13 @@ void init_putz(int t, int c, int size) /* nothing to do because global are already set to zero */ } else { gfunc_start(&gf); - vset(VT_CONST, size); + vpushi(size); gfunc_param(&gf); - vset(VT_CONST, 0); + vpushi(0); gfunc_param(&gf); - vset(VT_LOCAL, c); + vset(VT_INT, VT_LOCAL, c); gfunc_param(&gf); - vset(VT_CONST, (int)&memset); + vpushi((int)&memset); gfunc_call(&gf); } }