eval function args in reverse order - added short and unsigned char support - added more messages

This commit is contained in:
bellard 2001-11-11 18:00:58 +00:00
parent d261452977
commit 605a028bf4

130
tcc.c
View File

@ -23,15 +23,21 @@
/* preprocessor debug */
//#define PP_DEBUG
#define TEXT_SIZE 50000
#define DATA_SIZE 50000
/* these sizes are dummy for unix, because malloc() does not use
memory when the pages are not used */
#define TEXT_SIZE (4*1024*1024)
#define DATA_SIZE (4*1024*1024)
#define INCLUDE_STACK_SIZE 32
#define IFDEF_STACK_SIZE 64
#define VSTACK_SIZE 64
#define STRING_MAX_SIZE 1024
#define INCLUDE_PATHS_MAX 32
/* number of available temporary registers */
#define NB_REGS 3
/* defined if function parameters must be evaluated in revert order */
#define INVERT_FUNC_PARAMS
/* token symbol management */
typedef struct TokenSym {
@ -107,8 +113,9 @@ int nb_include_paths;
#define VT_FORWARD 0x0020 /* value is forward reference
(only used for functions) */
/* types */
#define VT_VOID 0x00040
#define VT_BYTE 0x00080 /* byte type */
#define VT_BYTE 0x00080 /* signed byte type */
#define VT_PTR 0x00100 /* pointer increment */
#define VT_UNSIGNED 0x00200 /* unsigned type */
#define VT_ARRAY 0x00400 /* array type (only used in parsing) */
@ -116,17 +123,15 @@ int nb_include_paths;
#define VT_FUNC 0x01000 /* function type */
#define VT_STRUCT 0x002000 /* struct/union definition */
#define VT_TYPEDEF 0x004000 /* typedef definition */
#define VT_EXTERN 0x008000 /* extern definition */
#define VT_STATIC 0x010000 /* static variable */
#define VT_STRUCT_SHIFT 17 /* structure/enum name shift (12 bits lefts) */
#define VT_EXTERN 0x008000 /* extern definition */
#define VT_STATIC 0x010000 /* static variable */
#define VT_SHORT 0x020000 /* short type */
#define VT_STRUCT_SHIFT 18 /* structure/enum name shift (14 bits left) */
#define VT_TYPE 0xffffffc0 /* type mask */
#define VT_TYPEN 0x0000003f /* ~VT_TYPE */
#define VT_FUNCN -4097 /* ~VT_FUNC */
/* Special infos */
/* token values */
/* warning: the following compare tokens depend on i386 asm code */
@ -516,7 +521,6 @@ void minp()
}
/* same as minp, but also skip comments */
/* XXX: skip strings & chars */
void cinp()
{
int c;
@ -1196,6 +1200,12 @@ void macro_subst(int **tok_str, int *tok_len,
expect(")");
/* now subst each arg */
mstr = macro_arg_subst(nested_list, mstr, args);
/* free memory */
sa = args;
while (sa) {
free((int *)sa->c);
sa = sa->prev;
}
sym_pop(&args, NULL);
mstr_allocated = 1;
}
@ -1335,6 +1345,12 @@ void load(r, ft, fc)
}
if ((ft & VT_TYPE) == VT_BYTE)
o(0xbe0f); /* movsbl */
else if ((ft & VT_TYPE) == (VT_BYTE | VT_UNSIGNED))
o(0xb60f); /* movzbl */
else if ((ft & VT_TYPE) == VT_SHORT)
o(0xbf0f); /* movswl */
else if ((ft & VT_TYPE) == (VT_SHORT | VT_UNSIGNED))
o(0xb70f); /* movzwl */
else
o(0x8b); /* movl */
if (v == VT_CONST) {
@ -1376,6 +1392,9 @@ void store(r, ft, fc)
fr = ft & VT_VALMASK;
b = (ft & VT_TYPE) == VT_BYTE;
/* XXX: incorrect if reg to reg */
if (ft & VT_SHORT)
o(0x66);
o(0x89 - b);
if (fr == VT_CONST) {
oad(0x05 + r * 8, fc); /* mov r,xxx */
@ -1388,6 +1407,11 @@ void store(r, ft, fc)
}
}
void gfunc_param(void)
{
o(0x50 + gv()); /* push r */
}
int gjmp(t)
{
return psym(0xe9, t);
@ -1797,6 +1821,9 @@ int type_size(int t, int *a)
(t & VT_ENUM)) {
*a = 4;
return 4;
} else if (t & VT_SHORT) {
*a = 2;
return 2;
} else {
*a = 1;
return 1;
@ -1967,7 +1994,9 @@ int ist(void)
t |= VT_BYTE;
} else if (tok == TOK_VOID) {
t |= VT_VOID;
} else if (tok == TOK_INT | tok == TOK_SHORT |
} else if (tok == TOK_SHORT) {
t |= VT_SHORT;
} else if (tok == TOK_INT |
(tok >= TOK_CONST & tok <= TOK_INLINE)) {
/* ignored types */
} else if (tok == TOK_FLOAT || tok == TOK_DOUBLE) {
@ -2308,28 +2337,64 @@ void unary()
ft = vt;
fc = vc;
next();
#ifdef INVERT_FUNC_PARAMS
{
int *str, len, parlevel, *saved_macro_ptr;
Sym *args;
/* read each argument and store it on a stack */
/* XXX: merge it with macro args ? */
args = NULL;
while (tok != ')') {
len = 0;
str = NULL;
parlevel = 0;
while ((parlevel > 0 || (tok != ')' && tok != ',')) &&
tok != -1) {
if (tok == '(')
parlevel++;
else if (tok == ')')
parlevel--;
tok_add2(&str, &len, tok, tokc);
next();
}
tok_add(&str, &len, -1); /* end of file added */
tok_add(&str, &len, 0);
sym_push1(&args, 0, 0, (int)str);
if (tok != ',')
break;
next();
}
if (tok != ')')
expect(")");
/* now generate code in reverse order by reading the stack */
saved_macro_ptr = macro_ptr;
t = 0;
while (args) {
t += 4;
macro_ptr = (int *)args->c;
next();
expr_eq();
gfunc_param();
free((int *)args->c);
sym_pop(&args, args->prev);
}
macro_ptr = saved_macro_ptr;
/* restore token */
tok = ')';
}
#else
t = 0;
while (tok != ')') {
t = t + 4;
t += 4;
expr_eq();
r = gv();
o(0x50 + r); /* push r */
gfunc_param();
if (tok == ',')
next();
}
#endif
skip(')');
/* horrible, but needed : convert to native ordering (could
parse parameters in reverse order, but would cost more
code) */
n = 0;
p = t - 4;
while (n < p) {
oad(0x24848b, p); /* mov x(%esp,1), %eax */
oad(0x248487, n); /* xchg x(%esp,1), %eax */
oad(0x248489, p); /* mov %eax, x(%esp,1) */
n = n + 4;
p = p - 4;
}
if ((ft & VT_VALMASK) == VT_CONST) {
/* forward reference */
if (ft & VT_FORWARD) {
@ -2450,7 +2515,7 @@ void eor()
/* XXX: better constant handling */
void expr_eq()
{
int t, u, c;
int t, u, c, r1, r2;
if (const_wanted) {
sum(10);
@ -2470,12 +2535,14 @@ void expr_eq()
next();
t = gtst(1, 0);
expr();
gv();
r1 = gv();
skip(':');
u = gjmp(0);
gsym(t);
expr_eq();
gv();
r2 = gv();
move_reg(r1, r2);
vt = (vt & VT_TYPE) | r1;
gsym(u);
}
}
@ -2835,7 +2902,8 @@ int main(int argc, char **argv)
optind = 1;
while (1) {
if (optind >= argc) {
printf("usage: tcc [-Idir] [-Dsym] [-llib] infile [infile_arg...]\n");
printf("tcc version 0.9 - Tiny C Compiler - Copyright (C) 2001 Fabrice Bellard\n"
"usage: tcc [-Idir] [-Dsym] [-llib] infile [infile_arg...]\n");
return 1;
}
r = argv[optind];
@ -2890,7 +2958,7 @@ int main(int argc, char **argv)
s = sym_find(TOK_MAIN);
if (!s)
error("main() not defined");
t = s->c;
t = (int (*)())s->c;
#ifdef PROFILE
return 1;
#else