separated type and value on stack

tcc-xref
bellard 2001-12-20 01:05:21 +00:00
parent f50d0b4488
commit f7181903bb
2 changed files with 294 additions and 256 deletions

View File

@ -155,10 +155,10 @@ int oad(int c, int s)
return s; return s;
} }
/* output constant with relocation if 't & VT_FORWARD' is true */ /* output constant with relocation if 'r & VT_FORWARD' is true */
void gen_addr32(int c, int t) void gen_addr32(int r, int c)
{ {
if (!(t & VT_FORWARD)) { if (!(r & VT_FORWARD)) {
gen_le32(c); gen_le32(c);
} else { } else {
greloc((Sym *)c, ind, RELOC_ADDR32); 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 */ /* load 'r' from value 'sv' */
/* r = (ft, fc) */ void load(int r, SValue *sv)
void load(int r, int ft, int fc)
{ {
int v, t; int v, t, ft, fc, fr;
SValue v1;
v = ft & VT_VALMASK; fr = sv->r;
if (ft & VT_LVAL) { ft = sv->t;
fc = sv->c.ul;
v = fr & VT_VALMASK;
if (fr & VT_LVAL) {
if (v == VT_LLOCAL) { 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; v = r;
} }
if ((ft & VT_BTYPE) == VT_FLOAT) { if ((ft & VT_BTYPE) == VT_FLOAT) {
@ -200,7 +207,7 @@ void load(int r, int ft, int fc)
if (v == VT_CONST) { if (v == VT_CONST) {
o(0x05 + r * 8); /* 0xXX, r */ o(0x05 + r * 8); /* 0xXX, r */
gen_addr32(fc, ft); gen_addr32(fr, fc);
} else if (v == VT_LOCAL) { } else if (v == VT_LOCAL) {
oad(0x85 + r * 8, fc); /* xx(%ebp), r */ oad(0x85 + r * 8, fc); /* xx(%ebp), r */
} else { } else {
@ -209,7 +216,7 @@ void load(int r, int ft, int fc)
} else { } else {
if (v == VT_CONST) { if (v == VT_CONST) {
o(0xb8 + r); /* mov $xx, r */ o(0xb8 + r); /* mov $xx, r */
gen_addr32(fc, ft); gen_addr32(fr, fc);
} else if (v == VT_LOCAL) { } else if (v == VT_LOCAL) {
o(0x8d); o(0x8d);
oad(0x85 + r * 8, fc); /* lea xxx(%ebp), r */ oad(0x85 + r * 8, fc); /* lea xxx(%ebp), r */
@ -231,13 +238,14 @@ void load(int r, int ft, int fc)
} }
} }
/* (ft, fc) = r */ /* store register 'r' in lvalue 'v' */
/* WARNING: r must not be allocated on the stack */ void store(int r, SValue *v)
void store(r, ft, fc)
{ {
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; bt = ft & VT_BTYPE;
/* XXX: incorrect if reg to reg */ /* XXX: incorrect if reg to reg */
/* XXX: should not flush float stack */ /* XXX: should not flush float stack */
@ -261,10 +269,10 @@ void store(r, ft, fc)
} }
if (fr == VT_CONST) { if (fr == VT_CONST) {
o(0x05 + r * 8); /* mov r,xxx */ o(0x05 + r * 8); /* mov r,xxx */
gen_addr32(fc, ft); gen_addr32(v->r, fc);
} else if (fr == VT_LOCAL) { } else if (fr == VT_LOCAL) {
oad(0x85 + r * 8, fc); /* mov r,xxx(%ebp) */ 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) */ g(fr + r * 8); /* mov r, (fr) */
} else if (fr != r) { } else if (fr != r) {
o(0xc0 + fr + r * 8); /* mov r, fr */ o(0xc0 + fr + r * 8); /* mov r, fr */
@ -283,7 +291,7 @@ void gfunc_param(GFuncContext *c)
{ {
int size, align, r; 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); size = type_size(vtop->t, &align);
/* align to stack align size */ /* align to stack align size */
size = (size + 3) & ~3; size = (size + 3) & ~3;
@ -293,7 +301,7 @@ void gfunc_param(GFuncContext *c)
r = get_reg(REG_CLASS_INT); r = get_reg(REG_CLASS_INT);
o(0x89); /* mov %esp, r */ o(0x89); /* mov %esp, r */
o(0xe0 + r); o(0xe0 + r);
vset(VT_INT | r, 0); vset(VT_INT, r, 0);
vswap(); vswap();
vstore(); vstore();
c->args_size += size; c->args_size += size;
@ -328,10 +336,10 @@ void gfunc_param(GFuncContext *c)
void gfunc_call(GFuncContext *c) void gfunc_call(GFuncContext *c)
{ {
int r; int r;
if ((vtop->t & (VT_VALMASK | VT_LVAL)) == VT_CONST) { if ((vtop->r & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
/* constant case */ /* constant case */
/* forward reference */ /* forward reference */
if (vtop->t & VT_FORWARD) { if (vtop->r & VT_FORWARD) {
greloc(vtop->c.sym, ind + 1, RELOC_REL32); greloc(vtop->c.sym, ind + 1, RELOC_REL32);
oad(0xe8, 0); oad(0xe8, 0);
} else { } else {
@ -357,7 +365,7 @@ int gjmp(int t)
int gtst(int inv, int t) int gtst(int inv, int t)
{ {
int v, *p; int v, *p;
v = vtop->t & VT_VALMASK; v = vtop->r & VT_VALMASK;
if (v == VT_CMP) { if (v == VT_CMP) {
/* fast case : can jump directly since flags are set */ /* fast case : can jump directly since flags are set */
g(0x0f); g(0x0f);
@ -375,7 +383,7 @@ int gtst(int inv, int t)
t = gjmp(t); t = gjmp(t);
gsym(vtop->c.i); 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 */ /* constant jmp optimization */
if ((vtop->c.i != 0) != inv) if ((vtop->c.i != 0) != inv)
t = gjmp(t); t = gjmp(t);
@ -438,7 +446,7 @@ void gen_opi(int op)
o(0xe8 + r); o(0xe8 + r);
else else
o(0xf8 + r); o(0xf8 + r);
vtop->t = (vtop->t & VT_TYPE) | r; vtop->r = r;
} else if (op == '/' | op == TOK_UDIV | op == TOK_PDIV | } else if (op == '/' | op == TOK_UDIV | op == TOK_PDIV |
op == '%' | op == TOK_UMOD) { op == '%' | op == TOK_UMOD) {
save_reg(2); /* save edx */ save_reg(2); /* save edx */
@ -455,12 +463,12 @@ void gen_opi(int op)
r = 2; r = 2;
else else
r = 0; r = 0;
vtop->t = (vtop->t & VT_TYPE) | r; vtop->r = r;
} else { } else {
vtop--; vtop--;
o(0x39); o(0x39);
o(0xc0 + r + fr * 8); /* cmp fr, r */ 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; int a, ft, fc, swapped, r;
/* convert constants to memory references */ /* 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(); vswap();
gv(); gv();
vswap(); vswap();
} }
if ((vtop[0].t & (VT_CONST | VT_LVAL)) == VT_CONST) if ((vtop[0].r & (VT_CONST | VT_LVAL)) == VT_CONST)
gv(); gv();
/* must put at least one value in the floating point register */ /* must put at least one value in the floating point register */
if ((vtop[-1].t & VT_LVAL) && if ((vtop[-1].r & VT_LVAL) &&
(vtop[0].t & VT_LVAL)) { (vtop[0].r & VT_LVAL)) {
vswap(); vswap();
gv(); gv();
vswap(); vswap();
} }
if (op >= TOK_EQ && op <= TOK_GT) { if (op >= TOK_EQ && op <= TOK_GT) {
/* load on stack second operand */ /* load on stack second operand */
load(REG_ST0, vtop->t, vtop->c.ul); load(REG_ST0, vtop);
if (op == TOK_GE || op == TOK_GT) if (op == TOK_GE || op == TOK_GT)
o(0xc9d9); /* fxch %st(1) */ o(0xc9d9); /* fxch %st(1) */
o(0xe9da); /* fucompp */ o(0xe9da); /* fucompp */
@ -509,13 +517,13 @@ void gen_opf(int op)
op = TOK_EQ; op = TOK_EQ;
} }
vtop--; vtop--;
vtop->t = (vtop->t & VT_TYPE) | VT_CMP; vtop->r = VT_CMP;
vtop->c.i = op; vtop->c.i = op;
} else { } else {
/* swap the stack if needed so that t1 is the register and t2 is /* swap the stack if needed so that t1 is the register and t2 is
the memory reference */ the memory reference */
swapped = 0; swapped = 0;
if (vtop[-1].t & VT_LVAL) { if (vtop[-1].r & VT_LVAL) {
vswap(); vswap();
swapped = 1; swapped = 1;
} }
@ -546,10 +554,10 @@ void gen_opf(int op)
else else
o(0xd8); o(0xd8);
r = ft & VT_VALMASK; r = vtop->r & VT_VALMASK;
if (r == VT_CONST) { if (r == VT_CONST) {
o(0x05 + a); o(0x05 + a);
gen_addr32(fc, ft); gen_addr32(vtop->r, fc);
} else if (r == VT_LOCAL) { } else if (r == VT_LOCAL) {
oad(0x85 + a, fc); oad(0x85 + a, fc);
} else { } else {
@ -567,16 +575,16 @@ void gen_cvt_itof(int t)
/* unsigned int to float/double/long double */ /* unsigned int to float/double/long double */
o(0x6a); /* push $0 */ o(0x6a); /* push $0 */
g(0x00); g(0x00);
o(0x50 + (vtop->t & VT_VALMASK)); /* push r */ o(0x50 + (vtop->r & VT_VALMASK)); /* push r */
o(0x242cdf); /* fildll (%esp) */ o(0x242cdf); /* fildll (%esp) */
o(0x08c483); /* add $8, %esp */ o(0x08c483); /* add $8, %esp */
} else { } else {
/* int to float/double/long double */ /* 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(0x2404db); /* fildl (%esp) */
o(0x04c483); /* add $4, %esp */ o(0x04c483); /* add $4, %esp */
} }
vtop->t = t | REG_ST0; vtop->r = REG_ST0;
} }
/* FPU control word for rounding to nearest mode */ /* FPU control word for rounding to nearest mode */
@ -611,7 +619,7 @@ void gen_cvt_ftoi(int t)
o(0x58 + r); /* pop r */ o(0x58 + r); /* pop r */
if (size == 8) if (size == 8)
o(0x04c483); /* add $4, %esp */ o(0x04c483); /* add $4, %esp */
vtop->t = t | r; vtop->r = r;
} }
/* convert from one floating point type to another */ /* convert from one floating point type to another */
@ -625,7 +633,7 @@ void gen_cvt_ftof(int t)
void vpop(void) void vpop(void)
{ {
/* for x86, we need to pop the FP stack */ /* 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) */ o(0xd9dd); /* fstp %st(1) */
} }
vtop--; vtop--;

458
tcc.c
View File

@ -64,14 +64,15 @@ typedef union CValue {
long long ll; long long ll;
unsigned long long ull; unsigned long long ull;
struct TokenSym *ts; struct TokenSym *ts;
int tab[1];
struct Sym *sym; struct Sym *sym;
int tab[1];
} CValue; } CValue;
/* value on stack */ /* value on stack */
typedef struct SValue { typedef struct SValue {
int t; int t; /* type */
CValue c; int r; /* register + flags */
CValue c; /* constant */
} SValue; } SValue;
/* symbol management */ /* symbol management */
@ -360,7 +361,7 @@ int pointed_size(int t);
int ist(void); int ist(void);
int type_decl(int *v, int t, int td); int type_decl(int *v, int t, int td);
void error(const char *fmt, ...); 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 */ /* true if float/double/long double type */
static inline int is_float(int t) static inline int is_float(int t)
@ -485,7 +486,7 @@ void skip(int c)
void test_lvalue(void) void test_lvalue(void)
{ {
if (!(vtop->t & VT_LVAL)) if (!(vtop->r & VT_LVAL))
expect("lvalue"); expect("lvalue");
} }
@ -1874,25 +1875,34 @@ void swap(int *p, int *q)
*q = t; *q = t;
} }
void vsetc(int t, CValue *vc) void vsetc(int t, int r, CValue *vc)
{ {
if (vtop >= vstack + VSTACK_SIZE) if (vtop >= vstack + VSTACK_SIZE)
error("memory full"); error("memory full");
/* cannot let cpu flags if other instruction are generated */ /* cannot let cpu flags if other instruction are generated */
/* XXX: VT_JMP test too ? */ /* XXX: VT_JMP test too ? */
if ((vtop->t & VT_VALMASK) == VT_CMP) if ((vtop->r & VT_VALMASK) == VT_CMP)
gv(); gv();
vtop++; vtop++;
vtop->t = t; vtop->t = t;
vtop->r = r;
vtop->c = *vc; 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; CValue cval;
cval.i = v; cval.i = v;
vsetc(t, &cval); vsetc(t, r, &cval);
} }
void vswap(void) void vswap(void)
@ -1915,22 +1925,25 @@ void vdup(void)
int save_reg_forced(int r) int save_reg_forced(int r)
{ {
int i, l, t; int i, l, t;
SValue *p; SValue *p, sv;
/* store register */ /* store register */
loc = (loc - 4) & -3; 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; l = loc;
/* modify all stack values */ /* modify all stack values */
for(p=vstack;p<=vtop;p++) { for(p=vstack;p<=vtop;p++) {
i = p->t & VT_VALMASK; i = p->r & VT_VALMASK;
if (i == r) { if (i == r) {
if (p->t & VT_LVAL) if (p->r & VT_LVAL)
t = VT_LLOCAL; t = VT_LLOCAL;
else else
t = VT_LOCAL; t = VT_LOCAL;
p->t = (p->t & VT_TYPE) | VT_LVAL | t; p->r = VT_LVAL | t;
p->c.ul = l; p->c.ul = l;
} }
} }
@ -1945,7 +1958,7 @@ void save_reg(int r)
/* modify all stack values */ /* modify all stack values */
for(p=vstack;p<=vtop;p++) { for(p=vstack;p<=vtop;p++) {
i = p->t & VT_VALMASK; i = p->r & VT_VALMASK;
if (i == r) { if (i == r) {
save_reg_forced(r); save_reg_forced(r);
break; break;
@ -1963,7 +1976,7 @@ int get_reg(int rc)
for(r=0;r<NB_REGS;r++) { for(r=0;r<NB_REGS;r++) {
if (reg_classes[r] & rc) { if (reg_classes[r] & rc) {
for(p=vstack;p<=vtop;p++) { for(p=vstack;p<=vtop;p++) {
i = p->t & VT_VALMASK; i = p->r & VT_VALMASK;
if (i == r) if (i == r)
goto notfound; goto notfound;
} }
@ -1976,7 +1989,7 @@ int get_reg(int rc)
important to start from the bottom to ensure that we don't important to start from the bottom to ensure that we don't
spill registers used in gen_op()) */ spill registers used in gen_op()) */
for(p=vstack;p<=vtop;p++) { for(p=vstack;p<=vtop;p++) {
r = p->t & VT_VALMASK; r = p->r & VT_VALMASK;
if (r < VT_CONST && (reg_classes[r] & rc)) { if (r < VT_CONST && (reg_classes[r] & rc)) {
save_reg(r); save_reg(r);
break; break;
@ -1985,13 +1998,13 @@ int get_reg(int rc)
return r; return r;
} }
void save_regs() void save_regs(void)
{ {
int r; int r;
SValue *p; SValue *p;
for(p=vstack;p<=vtop;p++) { for(p=vstack;p<=vtop;p++) {
r = p->t & VT_VALMASK; r = p->r & VT_VALMASK;
if (r < VT_CONST) { if (r < VT_CONST) {
save_reg(r); save_reg(r);
} }
@ -2002,9 +2015,14 @@ void save_regs()
if needed */ if needed */
void move_reg(int r, int s) void move_reg(int r, int s)
{ {
SValue sv;
if (r != s) { if (r != s) {
save_reg(r); 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 */ /* remove bit field info to avoid loops */
vtop->t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT)); vtop->t &= ~(VT_BITFIELD | (-1 << VT_STRUCT_SHIFT));
/* generate shifts */ /* generate shifts */
vset(VT_CONST, 32 - (bit_pos + bit_size)); vpushi(32 - (bit_pos + bit_size));
gen_op(TOK_SHL); gen_op(TOK_SHL);
vset(VT_CONST, 32 - bit_size); vpushi(32 - bit_size);
/* NOTE: transformed to SHR if unsigned */ /* NOTE: transformed to SHR if unsigned */
gen_op(TOK_SAR); gen_op(TOK_SAR);
r = gv(); r = gv();
} else { } 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 /* CPUs usually cannot use float constants, so we store them
generically in data segment */ generically in data segment */
size = type_size(vtop->t, &align); size = type_size(vtop->t, &align);
@ -2038,20 +2057,20 @@ int gv(void)
size = size >> 2; size = size >> 2;
for(i=0;i<size;i++) for(i=0;i<size;i++)
((int *)glo)[i] = vtop->c.tab[i]; ((int *)glo)[i] = vtop->c.tab[i];
vtop->t |= VT_LVAL; vtop->r |= VT_LVAL;
vtop->c.ul = glo; vtop->c.ul = glo;
glo += size << 2; glo += size << 2;
} }
r = vtop->t & VT_VALMASK; r = vtop->r & VT_VALMASK;
if (r >= VT_CONST || (vtop->t & VT_LVAL)) { if (r >= VT_CONST || (vtop->r & VT_LVAL)) {
if (is_float(vtop->t)) if (is_float(vtop->t))
rc = REG_CLASS_FLOAT; rc = REG_CLASS_FLOAT;
else else
rc = REG_CLASS_INT; rc = REG_CLASS_INT;
r = get_reg(rc); r = get_reg(rc);
} }
load(r, vtop->t, vtop->c.ul); load(r, vtop);
vtop->t = (vtop->t & VT_TYPE) | r; vtop->r = r;
} }
return r; return r;
} }
@ -2065,8 +2084,8 @@ void gen_opc(int op)
v1 = vtop - 1; v1 = vtop - 1;
v2 = vtop; v2 = vtop;
/* currently, we cannot do computations with forward symbols */ /* currently, we cannot do computations with forward symbols */
c1 = (v1->t & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST; c1 = (v1->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST;
c2 = (v2->t & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST; c2 = (v2->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST;
if (c1 && c2) { if (c1 && c2) {
fc = v2->c.i; fc = v2->c.i;
switch(op) { switch(op) {
@ -2184,9 +2203,9 @@ void gen_op(int op)
gen_opf(op); gen_opf(op);
if (op >= TOK_EQ && op <= TOK_GT) { if (op >= TOK_EQ && op <= TOK_GT) {
/* the result is an int */ /* the result is an int */
vtop->t = (vtop->t & ~VT_TYPE) | VT_INT; vtop->t = VT_INT;
} else { } else {
vtop->t = (vtop->t & ~VT_TYPE) | t; vtop->t = t;
} }
} else if (op == '+' || op == '-') { } else if (op == '+' || op == '-') {
if ((t1 & VT_BTYPE) == VT_PTR && if ((t1 & VT_BTYPE) == VT_PTR &&
@ -2197,8 +2216,8 @@ void gen_op(int op)
u = pointed_size(t1); u = pointed_size(t1);
gen_opc(op); gen_opc(op);
/* set to integer type */ /* set to integer type */
vtop->t = (vtop->t & ~VT_TYPE) | VT_INT; vtop->t = VT_INT;
vset(VT_CONST, u); vpushi(u);
gen_op(TOK_PDIV); gen_op(TOK_PDIV);
} else if ((t1 & VT_BTYPE) == VT_PTR || } else if ((t1 & VT_BTYPE) == VT_PTR ||
(t2 & VT_BTYPE) == VT_PTR) { (t2 & VT_BTYPE) == VT_PTR) {
@ -2207,11 +2226,11 @@ void gen_op(int op)
swap(&t1, &t2); swap(&t1, &t2);
} }
/* stack-4 contains pointer, stack-2 value to add */ /* 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_op('*');
gen_opc(op); gen_opc(op);
/* put again type if gen_opc() swaped operands */ /* put again type if gen_opc() swaped operands */
vtop->t = (vtop->t & ~VT_TYPE) | (t1 & VT_TYPE); vtop->t = t1;
} else { } else {
gen_opc(op); gen_opc(op);
} }
@ -2242,128 +2261,128 @@ void gen_op(int op)
/* cast 'vtop' to 't' type */ /* cast 'vtop' to 't' type */
void gen_cast(int t) 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 not lvalue, then we convert now */
if (!(t & VT_LVAL)) { dbt = t & VT_BTYPE;
/* if not lvalue, then we convert now */ sbt = vtop->t & VT_BTYPE;
dbt = t & VT_BTYPE; if (sbt != dbt) {
sbt = vtop->t & VT_BTYPE; sf = is_float(sbt);
if (sbt != dbt) { df = is_float(dbt);
sf = is_float(sbt); c = (vtop->r & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST;
df = is_float(dbt); if (sf && df) {
c = (vtop->t & (VT_VALMASK | VT_LVAL | VT_FORWARD)) == VT_CONST; /* convert from fp to fp */
if (sf && df) { if (c) {
/* convert from fp to fp */ /* constant case: we can do it now */
if (c) { /* XXX: in ISOC, cannot do it if error in convert */
/* constant case: we can do it now */ if (dbt == VT_FLOAT && sbt == VT_DOUBLE)
/* XXX: in ISOC, cannot do it if error in convert */ vtop->c.f = (float)vtop->c.d;
if (dbt == VT_FLOAT && sbt == VT_DOUBLE) else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE)
vtop->c.f = (float)vtop->c.d; vtop->c.f = (float)vtop->c.ld;
else if (dbt == VT_FLOAT && sbt == VT_LDOUBLE) else if (dbt == VT_DOUBLE && sbt == VT_FLOAT)
vtop->c.f = (float)vtop->c.ld; vtop->c.d = (double)vtop->c.f;
else if (dbt == VT_DOUBLE && sbt == VT_FLOAT) else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE)
vtop->c.d = (double)vtop->c.f; vtop->c.d = (double)vtop->c.ld;
else if (dbt == VT_DOUBLE && sbt == VT_LDOUBLE) else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT)
vtop->c.d = (double)vtop->c.ld; vtop->c.ld = (long double)vtop->c.f;
else if (dbt == VT_LDOUBLE && sbt == VT_FLOAT) else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE)
vtop->c.ld = (long double)vtop->c.f; vtop->c.ld = (long double)vtop->c.d;
else if (dbt == VT_LDOUBLE && sbt == VT_DOUBLE) } else {
vtop->c.ld = (long double)vtop->c.d; /* non constant case: generate code */
} else { gen_cvt_ftof(dbt);
/* non constant case: generate code */ }
gen_cvt_ftof(dbt); } else if (df) {
} /* convert int to fp */
} else if (df) { /* XXX: add const cases */
/* convert int to fp */ st1 = vtop->t & (VT_BTYPE | VT_UNSIGNED);
/* XXX: add const cases */ if (c) {
st1 = vtop->t & (VT_BTYPE | VT_UNSIGNED); switch(st1) {
if (c) { case VT_LLONG | VT_UNSIGNED:
switch(st1) { case VT_LLONG:
case VT_LLONG | VT_UNSIGNED: /* well, currently not needed */
case VT_LLONG: goto do_itof;
/* well, currently not needed */ case VT_INT | VT_UNSIGNED:
goto do_itof; switch(dbt) {
case VT_INT | VT_UNSIGNED: case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break;
switch(dbt) { case VT_DOUBLE: vtop->c.d = (double)vtop->c.ui; break;
case VT_FLOAT: vtop->c.f = (float)vtop->c.ui; break; case VT_LDOUBLE: vtop->c.ld = (long double)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;
} }
} else { break;
do_itof: default:
gen_cvt_itof(dbt); switch(dbt) {
} case VT_FLOAT: vtop->c.f = (float)vtop->c.i; break;
} else if (sf) { case VT_DOUBLE: vtop->c.d = (double)vtop->c.i; break;
/* convert fp to int */ case VT_LDOUBLE: vtop->c.ld = (long double)vtop->c.i; break;
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 { break;
do_ftoi:
gen_cvt_ftoi(dt1);
} }
if (dt1 == VT_INT && (t & (VT_TYPE | VT_UNSIGNED)) != dt1) { } else {
/* additionnal cast for char/short/bool... */ do_itof:
vtop->t = (vtop->t & ~VT_TYPE) | dt1; gen_cvt_itof(dbt);
gen_cast(t); }
} } else if (sf) {
} else if (dbt == VT_BOOL) { /* convert fp to int */
vset(VT_CONST, 0); dt1 = t & (VT_BTYPE | VT_UNSIGNED);
gen_op(TOK_NE); /* we handle char/short/etc... with generic code */
} else if (dbt == VT_BYTE || dbt == VT_SHORT) { if (dt1 != VT_INT | VT_UNSIGNED &&
if (dbt == VT_BYTE) dt1 != VT_LLONG | VT_UNSIGNED &&
bits = 8; dt1 != VT_LLONG)
else dt1 = VT_INT;
bits = 16; if (c) {
if (t & VT_UNSIGNED) { switch(dt1) {
vset(VT_CONST, (1 << bits) - 1); case VT_LLONG | VT_UNSIGNED:
gen_op('&'); case VT_LLONG:
} else { /* well, currently not needed */
bits = 32 - bits; goto do_ftoi;
vset(VT_CONST, bits); case VT_INT | VT_UNSIGNED:
gen_op(TOK_SHL); switch(sbt) {
vset(VT_CONST, bits); case VT_FLOAT: vtop->c.ui = (unsigned int)vtop->c.d; break;
gen_op(TOK_SAR); 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' */ /* return type size. Put alignment at 'a' */
@ -2599,7 +2618,7 @@ void gen_assign_cast(int dt)
/* store vtop in lvalue pushed on stack */ /* store vtop in lvalue pushed on stack */
void vstore(void) 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; GFuncContext gf;
ft = vtop[-1].t; ft = vtop[-1].t;
@ -2614,18 +2633,20 @@ void vstore(void)
gfunc_start(&gf); gfunc_start(&gf);
/* type size */ /* type size */
size = type_size(vtop->t, &align); size = type_size(vtop->t, &align);
vset(VT_CONST, size); vpushi(size);
gfunc_param(&gf); gfunc_param(&gf);
/* source */ /* source */
vtop->t &= ~VT_LVAL; vtop->t = VT_INT;
vtop->r &= ~VT_LVAL;
gfunc_param(&gf); gfunc_param(&gf);
/* destination */ /* destination */
vswap(); vswap();
vtop->t &= ~VT_LVAL; vtop->t = VT_INT;
vtop->r &= ~VT_LVAL;
gfunc_param(&gf); gfunc_param(&gf);
save_regs(); save_regs();
vset(VT_CONST, (int)&memcpy); vpushi((int)&memcpy);
gfunc_call(&gf); gfunc_call(&gf);
/* leave source on stack */ /* leave source on stack */
} else if (ft & VT_BITFIELD) { } else if (ft & VT_BITFIELD) {
@ -2640,30 +2661,32 @@ void vstore(void)
vtop[-1] = vtop[-2]; vtop[-1] = vtop[-2];
/* mask and shift source */ /* mask and shift source */
vset(VT_CONST, (1 << bit_size) - 1); vpushi((1 << bit_size) - 1);
gen_op('&'); gen_op('&');
vset(VT_CONST, bit_pos); vpushi(bit_pos);
gen_op(TOK_SHL); gen_op(TOK_SHL);
/* load destination, mask and or with source */ /* load destination, mask and or with source */
vswap(); vswap();
vset(VT_CONST, ~(((1 << bit_size) - 1) << bit_pos)); vpushi(~(((1 << bit_size) - 1) << bit_pos));
gen_op('&'); gen_op('&');
gen_op('|'); gen_op('|');
/* store result */ /* store result */
vstore(); vstore();
} else { } else {
r = gv(); /* generate value */ r = gv(); /* generate value */
ft = vtop[-1].t;
fc = vtop[-1].c.i;
/* if lvalue was saved on stack, must read it */ /* 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); t = get_reg(REG_CLASS_INT);
load(t, VT_LOCAL | VT_LVAL, fc); sv.t = VT_INT;
ft = (ft & ~VT_VALMASK) | t; 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--;
vtop->t = (ft & VT_TYPE) | r; vtop->r = r;
vtop->c.i = 0; vtop->c.i = 0;
} }
} }
@ -2672,6 +2695,7 @@ void vstore(void)
void inc(int post, int c) void inc(int post, int c)
{ {
int r, r1; int r, r1;
SValue sv;
test_lvalue(); test_lvalue();
if (post) if (post)
@ -2682,13 +2706,16 @@ void inc(int post, int c)
/* duplicate value */ /* duplicate value */
/* XXX: handle floats */ /* XXX: handle floats */
r1 = get_reg(REG_CLASS_INT); 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 */ /* duplicates value */
vtop[-2].t = (vtop->t & VT_TYPE) | r1; vtop[-2].r = r1;
vtop[-2].c.i = 0; vtop[-2].c.i = 0;
} }
/* add constant */ /* add constant */
vset(VT_CONST, c - TOK_MID); vpushi(c - TOK_MID);
gen_op('+'); gen_op('+');
vstore(); /* store value */ vstore(); /* store value */
if (post) if (post)
@ -3107,13 +3134,13 @@ Sym *external_sym(int v, int u)
void indir(void) void indir(void)
{ {
if (vtop->t & VT_LVAL) if (vtop->r & VT_LVAL)
gv(); gv();
if ((vtop->t & VT_BTYPE) != VT_PTR) if ((vtop->t & VT_BTYPE) != VT_PTR)
expect("pointer"); expect("pointer");
vtop->t = pointed_type(vtop->t); vtop->t = pointed_type(vtop->t);
if (!(vtop->t & VT_ARRAY)) /* an array is never an lvalue */ 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 */ /* pass a parameter to a function and do type checking and casting */
@ -3141,21 +3168,21 @@ void unary(void)
GFuncContext gf; GFuncContext gf;
if (tok == TOK_NUM || tok == TOK_CCHAR || tok == TOK_LCHAR) { if (tok == TOK_NUM || tok == TOK_CCHAR || tok == TOK_LCHAR) {
vset(VT_CONST | VT_INT, tokc.i); vpushi(tokc.i);
next(); next();
} else if (tok == TOK_CFLOAT) { } else if (tok == TOK_CFLOAT) {
vsetc(VT_CONST | VT_FLOAT, &tokc); vsetc(VT_FLOAT, VT_CONST, &tokc);
next(); next();
} else if (tok == TOK_CDOUBLE) { } else if (tok == TOK_CDOUBLE) {
vsetc(VT_CONST | VT_DOUBLE, &tokc); vsetc(VT_DOUBLE, VT_CONST, &tokc);
next(); next();
} else if (tok == TOK_CLDOUBLE) { } else if (tok == TOK_CLDOUBLE) {
vsetc(VT_CONST | VT_LDOUBLE, &tokc); vsetc(VT_LDOUBLE, VT_CONST, &tokc);
next(); next();
} else if (tok == TOK___FUNC__) { } else if (tok == TOK___FUNC__) {
/* special function name identifier */ /* special function name identifier */
/* generate (char *) type */ /* generate (char *) type */
vset(VT_CONST | mk_pointer(VT_BYTE), glo); vset(mk_pointer(VT_BYTE), VT_CONST, glo);
strcpy((void *)glo, funcname); strcpy((void *)glo, funcname);
glo += strlen(funcname) + 1; glo += strlen(funcname) + 1;
next(); next();
@ -3174,7 +3201,7 @@ void unary(void)
decl_initializer(t, glo, 1, 0); decl_initializer(t, glo, 1, 0);
glo += type_size(t, &align); glo += type_size(t, &align);
/* put it as pointer */ /* put it as pointer */
vset(t & ~VT_ARRAY, fc); vset(t & ~VT_ARRAY, VT_CONST, fc);
} else { } else {
t = tok; t = tok;
next(); next();
@ -3194,7 +3221,7 @@ void unary(void)
if (!(ft & VT_ARRAY)) if (!(ft & VT_ARRAY))
ft |= VT_LVAL; ft |= VT_LVAL;
fc = decl_initializer_alloc(ft, 1); fc = decl_initializer_alloc(ft, 1);
vset(ft, fc); vset(ft & VT_TYPE, ft & (VT_VALMASK | VT_LVAL), fc);
} else { } else {
unary(); unary();
gen_cast(ft); gen_cast(ft);
@ -3214,20 +3241,21 @@ void unary(void)
there and in function calls. */ there and in function calls. */
if ((vtop->t & VT_BTYPE) != VT_FUNC) if ((vtop->t & VT_BTYPE) != VT_FUNC)
test_lvalue(); test_lvalue();
vtop->t = mk_pointer(vtop->t & VT_LVALN); vtop->t = mk_pointer(vtop->t);
vtop->r &= ~VT_LVAL;
} else } else
if (t == '!') { if (t == '!') {
unary(); 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; 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; vtop->c.i = vtop->c.i ^ 1;
else else
vset(VT_JMP, gtst(1, 0)); vset(VT_INT, VT_JMP, gtst(1, 0));
} else } else
if (t == '~') { if (t == '~') {
unary(); unary();
vset(VT_CONST, -1); vpushi(-1);
gen_op('^'); gen_op('^');
} else } else
if (t == '+') { if (t == '+') {
@ -3251,13 +3279,13 @@ void unary(void)
t = vtop->t; t = vtop->t;
vpop(); vpop();
} }
vset(VT_CONST, type_size(t, &t)); vpushi(type_size(t, &t));
} else } else
if (t == TOK_INC || t == TOK_DEC) { if (t == TOK_INC || t == TOK_DEC) {
unary(); unary();
inc(0, t); inc(0, t);
} else if (t == '-') { } else if (t == '-') {
vset(VT_CONST, 0); vpushi(0);
unary(); unary();
gen_op('-'); gen_op('-');
} else } else
@ -3273,9 +3301,10 @@ void unary(void)
/* int() function */ /* int() function */
s = external_sym(t, VT_FUNC | (p << VT_STRUCT_SHIFT)); 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 forward reference, we must point to s */
if (vtop->t & VT_FORWARD) if (vtop->r & VT_FORWARD)
vtop->c.sym = s; vtop->c.sym = s;
} }
} }
@ -3290,7 +3319,7 @@ void unary(void)
if (tok == TOK_ARROW) if (tok == TOK_ARROW)
indir(); indir();
test_lvalue(); test_lvalue();
vtop->t &= VT_LVALN; vtop->r &= ~VT_LVAL;
next(); next();
/* expect pointer on structure */ /* expect pointer on structure */
if ((vtop->t & VT_BTYPE) != VT_STRUCT) if ((vtop->t & VT_BTYPE) != VT_STRUCT)
@ -3305,14 +3334,14 @@ void unary(void)
if (!s) if (!s)
error("field not found"); error("field not found");
/* add field offset to pointer */ /* add field offset to pointer */
vtop->t = (vtop->t & ~VT_TYPE) | VT_INT; /* change type to int */ vtop->t = VT_INT; /* change type to int */
vset(VT_CONST, s->c); vpushi(s->c);
gen_op('+'); gen_op('+');
/* change type to field type, and set to lvalue */ /* 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 */ /* an array is never an lvalue */
if (!(vtop->t & VT_ARRAY)) if (!(vtop->t & VT_ARRAY))
vtop->t |= VT_LVAL; vtop->r |= VT_LVAL;
next(); next();
} else if (tok == '[') { } else if (tok == '[') {
next(); next();
@ -3321,8 +3350,7 @@ void unary(void)
indir(); indir();
skip(']'); skip(']');
} else if (tok == '(') { } else if (tok == '(') {
int rett; SValue ret;
CValue retc;
Sym *sa; Sym *sa;
/* function call */ /* function call */
@ -3337,7 +3365,7 @@ void unary(void)
expect("function pointer"); expect("function pointer");
} }
} else { } else {
vtop->t &= ~VT_LVAL; /* no lvalue */ vtop->r &= ~VT_LVAL; /* no lvalue */
} }
/* get return type */ /* get return type */
s = sym_find((unsigned)vtop->t >> VT_STRUCT_SHIFT); s = sym_find((unsigned)vtop->t >> VT_STRUCT_SHIFT);
@ -3403,15 +3431,17 @@ void unary(void)
/* get some space for the returned structure */ /* get some space for the returned structure */
size = type_size(s->t, &align); size = type_size(s->t, &align);
loc = (loc - size) & -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 /* pass it as 'int' to avoid structure arg passing
problems */ problems */
vset(VT_INT | VT_LOCAL, loc); vset(VT_INT, VT_LOCAL, loc);
retc = vtop->c; ret.c = vtop->c;
gfunc_param(&gf); gfunc_param(&gf);
} else { } else {
rett = s->t | FUNC_RET_REG; /* return in register */ ret.t = s->t;
retc.i = 0; ret.r = FUNC_RET_REG; /* return in register */
ret.c.i = 0;
} }
#ifndef INVERT_FUNC_PARAMS #ifndef INVERT_FUNC_PARAMS
while (tok != ')') { while (tok != ')') {
@ -3428,7 +3458,7 @@ void unary(void)
skip(')'); skip(')');
gfunc_call(&gf); gfunc_call(&gf);
/* return value */ /* return value */
vsetc(rett, &retc); vsetc(ret.t, ret.r, &ret.c);
} else { } else {
break; break;
} }
@ -3496,7 +3526,7 @@ void eand(void)
if (tok != TOK_LAND) { if (tok != TOK_LAND) {
if (t) { if (t) {
t = gtst(1, t); t = gtst(1, t);
vset(VT_JMPI, t); vset(VT_INT, VT_JMPI, t);
} }
break; break;
} }
@ -3516,7 +3546,7 @@ void eor(void)
if (tok != TOK_LOR) { if (tok != TOK_LOR) {
if (t) { if (t) {
t = gtst(0, t); t = gtst(0, t);
vset(VT_JMP, t); vset(VT_INT, VT_JMP, t);
} }
break; break;
} }
@ -3561,7 +3591,7 @@ void expr_eq(void)
expr_eq(); expr_eq();
r2 = gv(); r2 = gv();
move_reg(r1, r2); move_reg(r1, r2);
vtop->t = (vtop->t & VT_TYPE) | r1; vtop->r = r1;
gsym(u); gsym(u);
} }
} }
@ -3585,7 +3615,7 @@ void expr_const1(void)
a = const_wanted; a = const_wanted;
const_wanted = 1; const_wanted = 1;
expr_eq(); expr_eq();
if ((vtop->t & (VT_CONST | VT_LVAL)) != VT_CONST) if ((vtop->r & (VT_VALMASK | VT_LVAL)) != VT_CONST)
expect("constant"); expect("constant");
const_wanted = a; 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 ((func_vt & VT_BTYPE) == VT_STRUCT) {
/* if returning structure, must copy it to implicit /* if returning structure, must copy it to implicit
first pointer arg location */ 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(); indir();
vswap(); vswap();
/* copy structure value to pointer */ /* 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 */ /* since a case is like a label, we must skip it with a jmp */
b = gjmp(0); b = gjmp(0);
gsym(*case_sym); gsym(*case_sym);
vset(case_reg, 0); vset(VT_INT, case_reg, 0);
vset(VT_CONST, a); vpushi(a);
gen_op(TOK_EQ); gen_op(TOK_EQ);
*case_sym = gtst(1, 0); *case_sym = gtst(1, 0);
gsym(b); gsym(b);
@ -3936,7 +3966,7 @@ void init_putv(int t, int c, int v, int is_expr)
expr_const1(); expr_const1();
global_expr = saved_global_expr; global_expr = saved_global_expr;
} else { } else {
vset(VT_CONST | VT_INT, v); vpushi(v);
} }
/* XXX: do casting */ /* XXX: do casting */
/* XXX: not portable */ /* XXX: not portable */
@ -3965,11 +3995,11 @@ void init_putv(int t, int c, int v, int is_expr)
} }
vpop(); vpop();
} else { } else {
vset(t, c); vset(t & VT_TYPE, t & (VT_VALMASK | VT_LVAL | VT_FORWARD), c);
if (is_expr) if (is_expr)
expr_eq(); expr_eq();
else else
vset(VT_CONST | VT_INT, v); vpushi(v);
vstore(); vstore();
vpop(); vpop();
} }
@ -3984,13 +4014,13 @@ void init_putz(int t, int c, int size)
/* nothing to do because global are already set to zero */ /* nothing to do because global are already set to zero */
} else { } else {
gfunc_start(&gf); gfunc_start(&gf);
vset(VT_CONST, size); vpushi(size);
gfunc_param(&gf); gfunc_param(&gf);
vset(VT_CONST, 0); vpushi(0);
gfunc_param(&gf); gfunc_param(&gf);
vset(VT_LOCAL, c); vset(VT_INT, VT_LOCAL, c);
gfunc_param(&gf); gfunc_param(&gf);
vset(VT_CONST, (int)&memset); vpushi((int)&memset);
gfunc_call(&gf); gfunc_call(&gf);
} }
} }