diff options
Diffstat (limited to 'tccgen.c')
| -rw-r--r-- | tccgen.c | 86 |
1 files changed, 81 insertions, 5 deletions
@@ -525,7 +525,7 @@ ST_FUNC void vpushv(SValue *v) *vtop = *v; } -static void vdup(void) +ST_FUNC void vdup(void) { vpushv(vtop); } @@ -4200,6 +4200,7 @@ ST_FUNC void unary(void) SValue ret; Sym *sa; int nb_args, ret_nregs, ret_align, regsize, variadic; + RegArgs args; /* function call */ if ((vtop->type.t & VT_BTYPE) != VT_FUNC) { @@ -4224,8 +4225,10 @@ ST_FUNC void unary(void) /* compute first implicit argument if a structure is returned */ if ((s->type.t & VT_BTYPE) == VT_STRUCT) { variadic = (s->c == FUNC_ELLIPSIS); - ret_nregs = gfunc_sret(&s->type, variadic, &ret.type, - &ret_align, ®size); + gfunc_sret(&s->type, variadic, &ret.type, + &ret_align, ®size, &args); + ret_nregs = regargs_nregs(&args); + if (!ret_nregs) { /* get some space for the returned structure */ size = type_size(&s->type, &align); @@ -4303,6 +4306,10 @@ ST_FUNC void unary(void) /* handle packed struct return */ if (((s->type.t & VT_BTYPE) == VT_STRUCT) && ret_nregs) { int addr, offset; +#if defined(TCC_TARGET_X86_64) && !defined(TCC_TARGET_PE) + int i; +#endif + size = type_size(&s->type, &align); /* We're writing whole regs often, make sure there's enough @@ -4311,6 +4318,34 @@ ST_FUNC void unary(void) align = regsize; loc = (loc - size) & -align; addr = loc; +#if defined(TCC_TARGET_X86_64) && !defined(TCC_TARGET_PE) + for (i=0; i<REG_ARGS_MAX; i++) { + offset = args.ireg[i]; + + if (offset == -1) + break; + + ret.type.t = VT_LLONG; + vset(&ret.type, VT_LOCAL | VT_LVAL, addr + offset); + vsetc(&ret.type, i ? REG_LRET : REG_IRET, &ret.c); + vstore(); + vtop--; + vtop--; + } + for (i=0; i<REG_ARGS_MAX; i++) { + offset = args.freg[i]; + + if (offset == -1) + break; + + ret.type.t = VT_DOUBLE; + vset(&ret.type, VT_LOCAL | VT_LVAL, addr + offset); + vsetc(&ret.type, i ? REG_QRET : REG_FRET, &ret.c); + vstore(); + vtop--; + vtop--; + } +#else offset = 0; for (;;) { vset(&ret.type, VT_LOCAL | VT_LVAL, addr + offset); @@ -4321,6 +4356,7 @@ ST_FUNC void unary(void) break; offset += regsize; } +#endif vset(&s->type, VT_LOCAL | VT_LVAL, addr); } } else { @@ -4891,8 +4927,11 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, if ((func_vt.t & VT_BTYPE) == VT_STRUCT) { CType type, ret_type; int ret_align, ret_nregs, regsize; - ret_nregs = gfunc_sret(&func_vt, func_var, &ret_type, - &ret_align, ®size); + RegArgs args; + + gfunc_sret(&func_vt, func_var, &ret_type, + &ret_align, ®size, &args); + ret_nregs = regargs_nregs(&args); if (0 == ret_nregs) { /* if returning structure, must copy it to implicit first pointer arg location */ @@ -4906,6 +4945,9 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, } else { /* returning structure packed into registers */ int r, size, addr, align; +#if defined(TCC_TARGET_X86_64) && !defined(TCC_TARGET_PE) + int i; +#endif size = type_size(&func_vt,&align); if ((vtop->r != (VT_LOCAL | VT_LVAL) || (vtop->c.i & (ret_align-1))) && (align & (ret_align-1))) { @@ -4919,6 +4961,39 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, vset(&ret_type, VT_LOCAL | VT_LVAL, addr); } vtop->type = ret_type; +#if defined(TCC_TARGET_X86_64) && !defined(TCC_TARGET_PE) + for (i=0; i<REG_ARGS_MAX; i++) { + int off = args.ireg[i]; + + if (off == -1) + break; + + r = i ? RC_LRET : RC_IRET; + + vdup(); + vtop->c.i += off; + vtop->type.t = VT_LLONG; + gv(r); + vpop(); + } + for (i=0; i<REG_ARGS_MAX; i++) { + int off = args.freg[i]; + + if (off == -1) + break; + + /* We assume that when a structure is returned in multiple + registers, their classes are consecutive values of the + suite s(n) = 2^n */ + r = rc_fret(ret_type.t) << i; + + vdup(); + vtop->c.i += off; + vtop->type.t = VT_DOUBLE; + gv(r); + vpop(); + } +#else if (is_float(ret_type.t)) r = rc_fret(ret_type.t); else @@ -4935,6 +5010,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, vtop->c.i += regsize; vtop->r = VT_LOCAL | VT_LVAL; } +#endif } } else if (is_float(func_vt.t)) { gv(rc_fret(func_vt.t)); |
