aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbellard <bellard>2003-04-16 21:16:20 +0000
committerbellard <bellard>2003-04-16 21:16:20 +0000
commit214ccccea7f9645e3f0249642174a3d650e6a000 (patch)
treee779aa169452a4731b9e13c1a758fc9a8296f40d
parent0d6f8021ee8874f4537e92a3621321086b268e24 (diff)
downloadtinycc-214ccccea7f9645e3f0249642174a3d650e6a000.tar.gz
tinycc-214ccccea7f9645e3f0249642174a3d650e6a000.tar.bz2
simpler function call API
-rw-r--r--i386-gen.c128
-rw-r--r--tcc.c162
2 files changed, 108 insertions, 182 deletions
diff --git a/i386-gen.c b/i386-gen.c
index 88e75b5..fef32e5 100644
--- a/i386-gen.c
+++ b/i386-gen.c
@@ -73,12 +73,6 @@ int reg_classes[NB_REGS] = {
/* relocation type for 32 bit data relocation */
#define R_DATA_32 R_386_32
-/* function call context */
-typedef struct GFuncContext {
- int args_size;
- int func_call; /* func call type (FUNC_STDCALL or FUNC_CDECL) */
-} GFuncContext;
-
/******************************************************/
static unsigned long func_sub_sp_offset;
@@ -282,65 +276,6 @@ void store(int r, SValue *v)
}
}
-/* start function call and return function call context */
-void gfunc_start(GFuncContext *c, int func_call)
-{
- c->args_size = 0;
- c->func_call = func_call;
-}
-
-/* push function parameter which is in (vtop->t, vtop->c). Stack entry
- is then popped. */
-void gfunc_param(GFuncContext *c)
-{
- int size, align, r;
-
- if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
- size = type_size(&vtop->type, &align);
- /* align to stack align size */
- size = (size + 3) & ~3;
- /* allocate the necessary size on stack */
- oad(0xec81, size); /* sub $xxx, %esp */
- /* generate structure store */
- r = get_reg(RC_INT);
- o(0x89); /* mov %esp, r */
- o(0xe0 + r);
- vset(&vtop->type, r | VT_LVAL, 0);
- vswap();
- vstore();
- c->args_size += size;
- } else if (is_float(vtop->type.t)) {
- gv(RC_FLOAT); /* only one float register */
- if ((vtop->type.t & VT_BTYPE) == VT_FLOAT)
- size = 4;
- else if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
- size = 8;
- else
- size = 12;
- oad(0xec81, size); /* sub $xxx, %esp */
- if (size == 12)
- o(0x7cdb);
- else
- o(0x5cd9 + size - 4); /* fstp[s|l] 0(%esp) */
- g(0x24);
- g(0x00);
- c->args_size += size;
- } else {
- /* simple type (currently always same size) */
- /* XXX: implicit cast ? */
- r = gv(RC_INT);
- if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
- size = 8;
- o(0x50 + vtop->r2); /* push r */
- } else {
- size = 4;
- }
- o(0x50 + r); /* push r */
- c->args_size += size;
- }
- vtop--;
-}
-
static void gadd_sp(int val)
{
if (val == (char)val) {
@@ -375,13 +310,66 @@ static void gcall_or_jmp(int is_jmp)
}
}
-/* generate function call with address in (vtop->t, vtop->c) and free function
- context. Stack entry is popped */
-void gfunc_call(GFuncContext *c)
+/* Generate function call. The function address is pushed first, then
+ all the parameters in call order. This functions pops all the
+ parameters and the function address. */
+void gfunc_call(int nb_args)
{
+ int size, align, r, args_size, i;
+ Sym *func_sym;
+
+ args_size = 0;
+ for(i = 0;i < nb_args; i++) {
+ if ((vtop->type.t & VT_BTYPE) == VT_STRUCT) {
+ size = type_size(&vtop->type, &align);
+ /* align to stack align size */
+ size = (size + 3) & ~3;
+ /* allocate the necessary size on stack */
+ oad(0xec81, size); /* sub $xxx, %esp */
+ /* generate structure store */
+ r = get_reg(RC_INT);
+ o(0x89); /* mov %esp, r */
+ o(0xe0 + r);
+ vset(&vtop->type, r | VT_LVAL, 0);
+ vswap();
+ vstore();
+ args_size += size;
+ } else if (is_float(vtop->type.t)) {
+ gv(RC_FLOAT); /* only one float register */
+ if ((vtop->type.t & VT_BTYPE) == VT_FLOAT)
+ size = 4;
+ else if ((vtop->type.t & VT_BTYPE) == VT_DOUBLE)
+ size = 8;
+ else
+ size = 12;
+ oad(0xec81, size); /* sub $xxx, %esp */
+ if (size == 12)
+ o(0x7cdb);
+ else
+ o(0x5cd9 + size - 4); /* fstp[s|l] 0(%esp) */
+ g(0x24);
+ g(0x00);
+ args_size += size;
+ } else {
+ /* simple type (currently always same size) */
+ /* XXX: implicit cast ? */
+ r = gv(RC_INT);
+ if ((vtop->type.t & VT_BTYPE) == VT_LLONG) {
+ size = 8;
+ o(0x50 + vtop->r2); /* push r */
+ } else {
+ size = 4;
+ }
+ o(0x50 + r); /* push r */
+ args_size += size;
+ }
+ vtop--;
+ }
+ save_regs(0); /* save used temporary registers */
+ func_sym = vtop->type.ref;
gcall_or_jmp(0);
- if (c->args_size && c->func_call == FUNC_CDECL)
- gadd_sp(c->args_size);
+ if (args_size && func_sym->r == FUNC_CDECL)
+ gadd_sp(args_size);
vtop--;
}
diff --git a/tcc.c b/tcc.c
index 81cac4e..8e4dcb1 100644
--- a/tcc.c
+++ b/tcc.c
@@ -4589,7 +4589,9 @@ void lbuild(int t)
vpop();
}
-/* rotate n first stack elements to the bottom */
+/* rotate n first stack elements to the bottom
+ I1 ... In -> I2 ... In I1 [top is right]
+*/
void vrotb(int n)
{
int i;
@@ -4601,6 +4603,20 @@ void vrotb(int n)
vtop[0] = tmp;
}
+/* rotate n first stack elements to the top
+ I1 ... In -> In I1 ... I(n-1) [top is right]
+ */
+void vrott(int n)
+{
+ int i;
+ SValue tmp;
+
+ tmp = vtop[0];
+ for(i = 0;i < n - 1; i++)
+ vtop[-i] = vtop[-i - 1];
+ vtop[-n + 1] = tmp;
+}
+
/* pop stack value */
void vpop(void)
{
@@ -4665,7 +4681,6 @@ void gen_opl(int op)
{
int t, a, b, op1, c, i;
int func;
- GFuncContext gf;
SValue tmp;
switch(op) {
@@ -4683,11 +4698,9 @@ void gen_opl(int op)
func = TOK___umoddi3;
gen_func:
/* call generic long long function */
- gfunc_start(&gf, FUNC_CDECL);
- gfunc_param(&gf);
- gfunc_param(&gf);
vpush_global_sym(&func_old_type, func);
- gfunc_call(&gf);
+ vrott(3);
+ gfunc_call(2);
vpushi(0);
vtop->r = REG_IRET;
vtop->r2 = REG_LRET;
@@ -5227,20 +5240,17 @@ void gen_op(int op)
/* generic itof for unsigned long long case */
void gen_cvt_itof1(int t)
{
- GFuncContext gf;
-
if ((vtop->type.t & (VT_BTYPE | VT_UNSIGNED)) ==
(VT_LLONG | VT_UNSIGNED)) {
- gfunc_start(&gf, FUNC_CDECL);
- gfunc_param(&gf);
if (t == VT_FLOAT)
vpush_global_sym(&func_old_type, TOK___ulltof);
else if (t == VT_DOUBLE)
vpush_global_sym(&func_old_type, TOK___ulltod);
else
vpush_global_sym(&func_old_type, TOK___ulltold);
- gfunc_call(&gf);
+ vrott(2);
+ gfunc_call(1);
vpushi(0);
vtop->r = REG_FRET;
} else {
@@ -5251,21 +5261,19 @@ void gen_cvt_itof1(int t)
/* generic ftoi for unsigned long long case */
void gen_cvt_ftoi1(int t)
{
- GFuncContext gf;
int st;
if (t == (VT_LLONG | VT_UNSIGNED)) {
/* not handled natively */
- gfunc_start(&gf, FUNC_CDECL);
st = vtop->type.t & VT_BTYPE;
- gfunc_param(&gf);
if (st == VT_FLOAT)
vpush_global_sym(&func_old_type, TOK___fixunssfdi);
else if (st == VT_DOUBLE)
vpush_global_sym(&func_old_type, TOK___fixunsdfdi);
else
vpush_global_sym(&func_old_type, TOK___fixunsxfdi);
- gfunc_call(&gf);
+ vrott(2);
+ gfunc_call(1);
vpushi(0);
vtop->r = REG_IRET;
vtop->r2 = REG_LRET;
@@ -5700,7 +5708,6 @@ static void gen_assign_cast(CType *dt)
void vstore(void)
{
int sbt, dbt, ft, r, t, size, align, bit_size, bit_pos, rc, delayed_cast;
- GFuncContext gf;
ft = vtop[-1].type.t;
sbt = vtop->type.t & VT_BTYPE;
@@ -5720,25 +5727,24 @@ void vstore(void)
/* structure assignment : generate memcpy */
/* XXX: optimize if small size */
if (!nocode_wanted) {
- vdup();
- gfunc_start(&gf, FUNC_CDECL);
- /* type size */
size = type_size(&vtop->type, &align);
- vpushi(size);
- gfunc_param(&gf);
- /* source */
+
+ vpush_global_sym(&func_old_type, TOK_memcpy);
+
+ /* destination */
+ vpushv(vtop - 2);
vtop->type.t = VT_INT;
gaddrof();
- gfunc_param(&gf);
- /* destination */
- vswap();
+ /* source */
+ vpushv(vtop - 2);
vtop->type.t = VT_INT;
gaddrof();
- gfunc_param(&gf);
+ /* type size */
+ vpushi(size);
+ gfunc_call(3);
- save_regs(0);
- vpush_global_sym(&func_old_type, TOK_memcpy);
- gfunc_call(&gf);
+ vswap();
+ vpop();
} else {
vswap();
vpop();
@@ -6436,7 +6442,7 @@ static void indir(void)
}
/* pass a parameter to a function and do type checking and casting */
-void gfunc_param_typed(GFuncContext *gf, Sym *func, Sym *arg)
+static void gfunc_param_typed(Sym *func, Sym *arg)
{
int func_type;
CType type;
@@ -6454,11 +6460,6 @@ void gfunc_param_typed(GFuncContext *gf, Sym *func, Sym *arg)
} else {
gen_assign_cast(&arg->type);
}
- if (!nocode_wanted) {
- gfunc_param(gf);
- } else {
- vpop();
- }
}
/* parse an expression of the form '(type)' or '(expr)' and return its
@@ -6489,7 +6490,6 @@ static void unary(void)
int n, t, align, size, r;
CType type;
Sym *s;
- GFuncContext gf;
AttributeDef ad;
/* XXX: GCC 2.95.3 does not generate a table although it should be
@@ -6764,6 +6764,7 @@ static void unary(void)
} else if (tok == '(') {
SValue ret;
Sym *sa;
+ int nb_args;
/* function call */
if ((vtop->type.t & VT_BTYPE) != VT_FUNC) {
@@ -6781,63 +6782,9 @@ static void unary(void)
}
/* get return type */
s = vtop->type.ref;
- if (!nocode_wanted) {
- save_regs(0); /* save used temporary registers */
- gfunc_start(&gf, s->r);
- }
next();
sa = s->next; /* first parameter */
-#ifdef INVERT_FUNC_PARAMS
- {
- int parlevel;
- Sym *args, *s1;
- ParseState saved_parse_state;
- TokenString str;
-
- /* read each argument and store it on a stack */
- args = NULL;
- if (tok != ')') {
- for(;;) {
- tok_str_new(&str);
- parlevel = 0;
- while ((parlevel > 0 || (tok != ')' && tok != ',')) &&
- tok != TOK_EOF) {
- if (tok == '(')
- parlevel++;
- else if (tok == ')')
- parlevel--;
- tok_str_add_tok(&str);
- next();
- }
- tok_str_add(&str, -1); /* end of file added */
- tok_str_add(&str, 0);
- s1 = sym_push2(&args, 0, 0, (int)str.str);
- s1->next = sa; /* add reference to argument */
- if (sa)
- sa = sa->next;
- if (tok == ')')
- break;
- skip(',');
- }
- }
-
- /* now generate code in reverse order by reading the stack */
- save_parse_state(&saved_parse_state);
- while (args) {
- macro_ptr = (int *)args->c;
- next();
- expr_eq();
- if (tok != -1)
- expect("',' or ')'");
- gfunc_param_typed(&gf, s, args->next);
- s1 = args->prev;
- tok_str_free((int *)args->c);
- tcc_free(args);
- args = s1;
- }
- restore_parse_state(&saved_parse_state);
- }
-#endif
+ nb_args = 0;
/* compute first implicit argument if a structure is returned */
if ((s->type.t & VT_BTYPE) == VT_STRUCT) {
/* get some space for the returned structure */
@@ -6849,10 +6796,7 @@ static void unary(void)
problems */
vseti(VT_LOCAL, loc);
ret.c = vtop->c;
- if (!nocode_wanted)
- gfunc_param(&gf);
- else
- vtop--;
+ nb_args++;
} else {
ret.type = s->type;
ret.r2 = VT_CONST;
@@ -6866,11 +6810,11 @@ static void unary(void)
}
ret.c.i = 0;
}
-#ifndef INVERT_FUNC_PARAMS
if (tok != ')') {
for(;;) {
expr_eq();
- gfunc_param_typed(&gf, s, sa);
+ gfunc_param_typed(s, sa);
+ nb_args++;
if (sa)
sa = sa->next;
if (tok == ')')
@@ -6878,14 +6822,14 @@ static void unary(void)
skip(',');
}
}
-#endif
if (sa)
error("too few arguments to function");
skip(')');
- if (!nocode_wanted)
- gfunc_call(&gf);
- else
- vtop--;
+ if (!nocode_wanted) {
+ gfunc_call(nb_args);
+ } else {
+ vtop -= (nb_args + 1);
+ }
/* return value */
vsetc(&ret.type, ret.r, &ret.c);
vtop->r2 = ret.r2;
@@ -7793,20 +7737,14 @@ static void init_putv(CType *type, Section *sec, unsigned long c,
/* put zeros for variable based init */
static void init_putz(CType *t, Section *sec, unsigned long c, int size)
{
- GFuncContext gf;
-
if (sec) {
/* nothing to do because globals are already set to zero */
} else {
- gfunc_start(&gf, FUNC_CDECL);
- vpushi(size);
- gfunc_param(&gf);
- vpushi(0);
- gfunc_param(&gf);
- vseti(VT_LOCAL, c);
- gfunc_param(&gf);
vpush_global_sym(&func_old_type, TOK_memset);
- gfunc_call(&gf);
+ vseti(VT_LOCAL, c);
+ vpushi(0);
+ vpushi(size);
+ gfunc_call(3);
}
}