# HG changeset patch # User bellard # Date 1050527780 0 # Node ID 5559494e740e09ba86b0f4cdc932c193355768b4 # Parent 47e87383dd2b017ff999f412309cbc5290546e61 [project @ 2003-04-16 21:16:20 by bellard] simpler function call API diff -r 47e87383dd2b -r 5559494e740e i386-gen.c --- a/i386-gen.c Sat Oct 07 14:41:24 2006 -0400 +++ b/i386-gen.c Wed Apr 16 21:16:20 2003 +0000 @@ -73,12 +73,6 @@ /* 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 @@ } } -/* 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 @@ } } -/* 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 -r 47e87383dd2b -r 5559494e740e tcc.c --- a/tcc.c Sat Oct 07 14:41:24 2006 -0400 +++ b/tcc.c Wed Apr 16 21:16:20 2003 +0000 @@ -4589,7 +4589,9 @@ 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 @@ 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 @@ { int t, a, b, op1, c, i; int func; - GFuncContext gf; SValue tmp; switch(op) { @@ -4683,11 +4698,9 @@ 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 @@ /* 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 @@ /* 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 @@ 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 @@ /* 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 @@ } /* 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 @@ } 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 @@ 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 @@ } else if (tok == '(') { SValue ret; Sym *sa; + int nb_args; /* function call */ if ((vtop->type.t & VT_BTYPE) != VT_FUNC) { @@ -6781,63 +6782,9 @@ } /* 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 @@ 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 @@ } 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 @@ 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 @@ /* 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); + vpush_global_sym(&func_old_type, TOK_memset); + vseti(VT_LOCAL, c); vpushi(0); - gfunc_param(&gf); - vseti(VT_LOCAL, c); - gfunc_param(&gf); - vpush_global_sym(&func_old_type, TOK_memset); - gfunc_call(&gf); + vpushi(size); + gfunc_call(3); } }