fix function call and ! operator

This commit is contained in:
bellard 2001-12-08 20:24:33 +00:00
parent 3c9ab729ae
commit 52ca29cd4f

63
tcc.c
View file

@ -128,7 +128,7 @@ int func_vt, func_vc; /* current function return type (used by
return instruction) */ return instruction) */
int tok_ident; int tok_ident;
TokenSym **table_ident; TokenSym **table_ident;
TokenSym *hash_ident[521]; TokenSym *hash_ident[TOK_HASH_SIZE];
char token_buf[STRING_MAX_SIZE + 1]; char token_buf[STRING_MAX_SIZE + 1];
char *filename, *funcname; char *filename, *funcname;
/* contains global symbols which remain between each translation unit */ /* contains global symbols which remain between each translation unit */
@ -451,7 +451,7 @@ TokenSym *tok_alloc(char *str, int len)
table_ident = ptable; table_ident = ptable;
} }
ts = malloc(sizeof(TokenSym) + len); ts = malloc(sizeof(TokenSym) + len);
if (!ts) if (!ts || tok_ident >= SYM_FIRST_ANOM)
error("memory full"); error("memory full");
table_ident[i] = ts; table_ident[i] = ts;
ts->tok = tok_ident++; ts->tok = tok_ident++;
@ -1118,8 +1118,6 @@ void next_nomacro1()
*q++ = ch; *q++ = ch;
cinp(); cinp();
if (q[-1] == 'L') { if (q[-1] == 'L') {
/* XXX: not supported entirely (needs different
preprocessor architecture) */
if (ch == '\'') { if (ch == '\'') {
tok = TOK_LCHAR; tok = TOK_LCHAR;
goto char_const; goto char_const;
@ -1746,23 +1744,23 @@ void gfunc_param(GFuncContext *c)
} }
} }
/* generate function call with address in (ft, fc) and free function */ /* generate function call with address in (vt, vc) and free function
void gfunc_call(GFuncContext *c, int ft, int fc) context */
void gfunc_call(GFuncContext *c)
{ {
int r; int r;
r = ft & VT_VALMASK; if ((vt & (VT_VALMASK | VT_LVAL)) == VT_CONST) {
if (r == VT_CONST) { /* constant case */
/* forward reference */ /* forward reference */
if (ft & VT_FORWARD) { if (vt & VT_FORWARD) {
greloc((Sym *)fc, ind + 1, RELOC_REL32); greloc((Sym *)vc, ind + 1, RELOC_REL32);
oad(0xe8, 0); oad(0xe8, 0);
} else { } else {
oad(0xe8, fc - ind - 5); oad(0xe8, vc - ind - 5);
} }
} else if (r == VT_LOCAL) {
oad(0x95ff, fc); /* call *xxx(%ebp) */
} else { } else {
/* not actually used */ /* otherwise, indirect call */
r = gv();
o(0xff); /* call *r */ o(0xff); /* call *r */
o(0xd0 + r); o(0xd0 + r);
} }
@ -1776,7 +1774,7 @@ int gjmp(int t)
} }
/* generate a test. set 'inv' to invert test */ /* generate a test. set 'inv' to invert test */
int gtst(inv, t) int gtst(int inv, int t)
{ {
int v, *p; int v, *p;
v = vt & VT_VALMASK; v = vt & VT_VALMASK;
@ -1813,7 +1811,7 @@ int gtst(inv, t)
/* generate a binary operation 'v = r op fr' instruction and modifies /* generate a binary operation 'v = r op fr' instruction and modifies
(vt,vc) if needed */ (vt,vc) if needed */
void gen_op1(op, r, fr) void gen_op1(int op, int r, int fr)
{ {
int t; int t;
if (op == '+') { if (op == '+') {
@ -1990,6 +1988,7 @@ void vpush(void)
*vstack_ptr++ = vt; *vstack_ptr++ = vt;
*vstack_ptr++ = vc; *vstack_ptr++ = vc;
/* cannot let cpu flags if other instruction are generated */ /* cannot let cpu flags if other instruction are generated */
/* XXX: VT_JMP test too ? */
if ((vt & VT_VALMASK) == VT_CMP) if ((vt & VT_VALMASK) == VT_CMP)
gvp(vstack_ptr - 2); gvp(vstack_ptr - 2);
} }
@ -2207,8 +2206,8 @@ int type_size(int t, int *a)
} else if (t & VT_ARRAY) { } else if (t & VT_ARRAY) {
s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT)); s = sym_find(((unsigned)t >> VT_STRUCT_SHIFT));
return type_size(s->t, a) * s->c; return type_size(s->t, a) * s->c;
} else if ((t & VT_PTR) | } else if ((t & VT_PTR) ||
(t & VT_TYPE) == 0 | (t & VT_TYPE & ~VT_UNSIGNED) == VT_INT ||
(t & VT_ENUM)) { (t & VT_ENUM)) {
*a = 4; *a = 4;
return 4; return 4;
@ -2265,7 +2264,8 @@ void vstore(void)
gfunc_param(&gf); gfunc_param(&gf);
save_regs(); save_regs();
gfunc_call(&gf, VT_CONST, (int)&memcpy); vset(VT_CONST, (int)&memcpy);
gfunc_call(&gf);
/* generate again current type */ /* generate again current type */
vt = ft; vt = ft;
@ -2510,13 +2510,14 @@ int post_type(int t)
} }
skip(']'); skip(']');
/* parse next post type */ /* parse next post type */
t = post_type(t); t1 = t & (VT_TYPEDEF | VT_STATIC | VT_EXTERN);
t = post_type(t & ~(VT_TYPEDEF | VT_STATIC | VT_EXTERN));
/* we push a anonymous symbol which will contain the array /* we push a anonymous symbol which will contain the array
element type */ element type */
p = anon_sym++; p = anon_sym++;
sym_push(p, t, n); sym_push(p, t, n);
t = VT_ARRAY | VT_PTR | (p << VT_STRUCT_SHIFT); t = t1 | VT_ARRAY | VT_PTR | (p << VT_STRUCT_SHIFT);
} }
return t; return t;
} }
@ -2669,7 +2670,7 @@ void unary(void)
} else } else
if (t == '!') { if (t == '!') {
unary(); unary();
if ((vt & (VT_CONST | VT_LVAL)) == VT_CONST) if ((vt & (VT_VALMASK | VT_LVAL)) == VT_CONST)
vc = !vc; vc = !vc;
else if ((vt & VT_VALMASK) == VT_CMP) else if ((vt & VT_VALMASK) == VT_CMP)
vc = vc ^ 1; vc = vc ^ 1;
@ -2780,13 +2781,14 @@ void unary(void)
goto error_func; goto error_func;
} else { } else {
error_func: error_func:
expect("function type"); expect("function pointer");
} }
} else {
vt &= ~VT_LVAL; /* no lvalue */
} }
/* get return type */ /* get return type */
s = sym_find((unsigned)vt >> VT_STRUCT_SHIFT); s = sym_find((unsigned)vt >> VT_STRUCT_SHIFT);
vt &= ~VT_LVAL; /* no lvalue */
vpush(); /* push function address */ vpush(); /* push function address */
save_regs(); /* save used temporary registers */ save_regs(); /* save used temporary registers */
gfunc_start(&gf); gfunc_start(&gf);
@ -2865,8 +2867,8 @@ void unary(void)
} }
#endif #endif
skip(')'); skip(')');
vpop(&ft, &fc); vpop(&vt, &vc);
gfunc_call(&gf, ft, fc); gfunc_call(&gf);
/* return value */ /* return value */
vt = rett; vt = rett;
vc = retc; vc = retc;
@ -2994,7 +2996,7 @@ void sum(l)
} }
/* only used if non constant */ /* only used if non constant */
void eand() void eand(void)
{ {
int t; int t;
@ -3014,7 +3016,7 @@ void eand()
} }
} }
void eor() void eor(void)
{ {
int t; int t;
@ -3450,7 +3452,8 @@ void init_putz(int t, int c, int size)
gfunc_param(&gf); gfunc_param(&gf);
vset(VT_LOCAL, c); vset(VT_LOCAL, c);
gfunc_param(&gf); gfunc_param(&gf);
gfunc_call(&gf, VT_CONST, (int)&memset); vset(VT_CONST, (int)&memset);
gfunc_call(&gf);
} }
} }