| @@ -3927,7 +3927,7 @@ ST_FUNC void unary(void) · 3926 unmodified lines |
| 3927 | 3927 | } else if (tok == '(') { |
| 3928 | 3928 | SValue ret; |
| 3929 | 3929 | Sym *sa; |
| 3930 | | − int nb_args, sret, ret_align; |
| 3930 | + int nb_args, ret_nregs, ret_align; |
| 3931 | 3931 | |
| 3932 | 3932 | /* function call */ |
| 3933 | 3933 | if ((vtop->type.t & VT_BTYPE) != VT_FUNC) { |
| @@ -3951,8 +3951,8 @@ ST_FUNC void unary(void) · 17 unmodified lines |
| 3951 | 3951 | ret.r2 = VT_CONST; |
| 3952 | 3952 | /* compute first implicit argument if a structure is returned */ |
| 3953 | 3953 | if ((s->type.t & VT_BTYPE) == VT_STRUCT) { |
| 3954 | | − sret = gfunc_sret(&s->type, &ret.type, &ret_align); |
| 3955 | | − if (!sret) { |
| 3954 | + ret_nregs = gfunc_sret(&s->type, &ret.type, &ret_align); |
| 3955 | + if (!ret_nregs) { |
| 3956 | 3956 | /* get some space for the returned structure */ |
| 3957 | 3957 | size = type_size(&s->type, &align); |
| 3958 | 3958 | loc = (loc - size) & -align; |
| @@ -3965,11 +3965,11 @@ ST_FUNC void unary(void) · 6 unmodified lines |
| 3965 | 3965 | nb_args++; |
| 3966 | 3966 | } |
| 3967 | 3967 | } else { |
| 3968 | | − sret = 1; |
| 3968 | + ret_nregs = 1; |
| 3969 | 3969 | ret.type = s->type; |
| 3970 | 3970 | } |
| 3971 | 3971 | |
| 3972 | | − if (sret) { |
| 3972 | + if (ret_nregs) { |
| 3973 | 3973 | /* return in register */ |
| 3974 | 3974 | if (is_float(ret.type.t)) { |
| 3975 | 3975 | ret.r = reg_fret(ret.type.t); |
| @@ -4008,23 +4008,30 @@ ST_FUNC void unary(void) · 32 unmodified lines |
| 4008 | 4008 | } else { |
| 4009 | 4009 | vtop -= (nb_args + 1); |
| 4010 | 4010 | } |
| 4011 | + |
| 4011 | 4012 | /* return value */ |
| 4012 | | − for (r = ret.r + sret + !sret; r-- > ret.r;) { |
| 4013 | + for (r = ret.r + ret_nregs + !ret_nregs; r-- > ret.r;) { |
| 4013 | 4014 | vsetc(&ret.type, r, &ret.c); |
| 4014 | 4015 | vtop->r2 = ret.r2; /* Loop only happens when r2 is VT_CONST */ |
| 4015 | 4016 | } |
| 4017 | + |
| 4016 | 4018 | /* handle packed struct return */ |
| 4017 | | − if (((s->type.t & VT_BTYPE) == VT_STRUCT) && sret) { |
| 4019 | + if (((s->type.t & VT_BTYPE) == VT_STRUCT) && ret_nregs) { |
| 4018 | 4020 | int addr, offset; |
| 4019 | 4021 | |
| 4020 | 4022 | size = type_size(&s->type, &align); |
| 4021 | 4023 | loc = (loc - size) & -align; |
| 4022 | 4024 | addr = loc; |
| 4023 | | − for(offset = 0; offset < size; offset += ret_align) { |
| 4025 | + offset = 0; |
| 4026 | + for (;;) { |
| 4024 | 4027 | vset(&ret.type, VT_LOCAL | VT_LVAL, addr + offset); |
| 4025 | 4028 | vswap(); |
| 4026 | 4029 | vstore(); |
| 4027 | 4030 | vtop--; |
| 4031 | + if (--ret_nregs == 0) |
| 4032 | + break; |
| 4033 | + /* XXX: compatible with arm only: ret_align == register_size */ |
| 4034 | + offset += ret_align; |
| 4028 | 4035 | } |
| 4029 | 4036 | vset(&s->type, VT_LOCAL | VT_LVAL, addr); |
| 4030 | 4037 | } |
| @@ -4596,8 +4603,9 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, · 565 unmodified lines |
| 4596 | 4603 | gen_assign_cast(&func_vt); |
| 4597 | 4604 | if ((func_vt.t & VT_BTYPE) == VT_STRUCT) { |
| 4598 | 4605 | CType type, ret_type; |
| 4599 | | − int ret_align; |
| 4600 | | − if (!gfunc_sret(&func_vt, &ret_type, &ret_align)) { |
| 4606 | + int ret_align, ret_nregs; |
| 4607 | + ret_nregs = gfunc_sret(&func_vt, &ret_type, &ret_align); |
| 4608 | + if (0 == ret_nregs) { |
| 4601 | 4609 | /* if returning structure, must copy it to implicit |
| 4602 | 4610 | first pointer arg location */ |
| 4603 | 4611 | type = func_vt; |
| @@ -4609,7 +4617,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, · 5 unmodified lines |
| 4609 | 4617 | vstore(); |
| 4610 | 4618 | } else { |
| 4611 | 4619 | /* returning structure packed into registers */ |
| 4612 | | − int r, size, addr, offset, align; |
| 4620 | + int r, size, addr, align; |
| 4613 | 4621 | size = type_size(&func_vt,&align); |
| 4614 | 4622 | if ((vtop->r != (VT_LOCAL | VT_LVAL) || (vtop->c.i & (ret_align-1))) |
| 4615 | 4623 | && (align & (ret_align-1))) { |
| @@ -4626,11 +4634,16 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym, · 10 unmodified lines |
| 4626 | 4634 | r = rc_fret(ret_type.t); |
| 4627 | 4635 | else |
| 4628 | 4636 | r = RC_IRET; |
| 4629 | | − /* We assume that when a structure is returned in multiple |
| 4630 | | − registers, their classes are consecutive values of the |
| 4631 | | − suite s(n) = 2^n */ |
| 4632 | | − for (offset = 0; offset < size; offset += ret_align, r<<=1) { |
| 4637 | + |
| 4638 | + for (;;) { |
| 4633 | 4639 | gv(r); |
| 4640 | + if (--ret_nregs == 0) |
| 4641 | + break; |
| 4642 | + /* We assume that when a structure is returned in multiple |
| 4643 | + registers, their classes are consecutive values of the |
| 4644 | + suite s(n) = 2^n */ |
| 4645 | + r <<= 1; |
| 4646 | + /* XXX: compatible with arm only: ret_align == register_size */ |
| 4634 | 4647 | vtop->c.i += ret_align; |
| 4635 | 4648 | vtop->r = VT_LOCAL | VT_LVAL; |
| 4636 | 4649 | } |