forked from Mirrors/tinycc
separated type and value on stack
parent
f50d0b4488
commit
f7181903bb
92
i386-gen.c
92
i386-gen.c
|
@ -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
458
tcc.c
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue