History

riscv: Start fixing float struct passing/returnig

this fixes ret_2float_test, ret_2double_test and ret_8plus2double_test of abitest.c. The common gfunc_return actually works for these cases, so let's use that for now. The ret_mixed_test (as well as mixed2 and mixed3) are left broken, and tccgen.c:gfunc_return can't be used for that as is, so I'll leave the gfunc_return implementation in riscv64-gen.c for now, I'll have to think about this some more.

Michael Matz committed 7 years ago

Commit 98f1b831 parent 98dc4c13 files · +88 −18Browse files

Unified · Split

3 files
  1. riscv64-gen.c +87 −15
  2. tcc.h +1 −1
  3. tccgen.c +0 −2
riscv64-gen.c+87−15
@@ -147,8 +147,8 @@ ST_FUNC void load(int r, SValue *sv) · 146 unmodified lines
147 if (fr & VT_LVAL) {147 if (fr & VT_LVAL) {
148 int func3, opcode = 0x03, doload = 0;148 int func3, opcode = 0x03, doload = 0;
149 if (is_freg(r)) {149 if (is_freg(r)) {
150 assert(bt == VT_DOUBLE || bt == VT_FLOAT);
151 opcode = 0x07;150 opcode = 0x07;
151 assert(bt == VT_DOUBLE || bt == VT_FLOAT);
152 func3 = bt == VT_DOUBLE ? 3 : 2;152 func3 = bt == VT_DOUBLE ? 3 : 2;
153 } else {153 } else {
154 assert(is_ireg(r));154 assert(is_ireg(r));
@@ -433,6 +433,33 @@ static void gcall_or_jmp(int docall) · 278 unmodified lines
433 }433 }
434}434}
435 435
436static int pass_in_freg(CType *type, int regs)
437{
438 int tr;
439 int toplevel = !regs;
440 if ((type->t & VT_BTYPE) == VT_STRUCT) {
441 Sym *f;
442 if (type->ref->type.t == VT_UNION)
443 return toplevel ? 0 : -1;
444 for (f = type->ref->next; f; f = f->next) {
445 tr = pass_in_freg(&f->type, regs);
446 if (tr < 0 || (regs + tr) > 2)
447 return toplevel ? 0 : -1;
448 regs += tr;
449 }
450 return regs;
451 } else if (type->t & VT_ARRAY) {
452 if (type->ref->c < 0 || type->ref->c > 2)
453 return toplevel ? 0 : -1;
454 tr = pass_in_freg(&type->ref->type, regs);
455 tr *= type->ref->c;
456 if (tr < 0 || (regs + tr) > 2)
457 return toplevel ? 0 : -1;
458 return regs + tr;
459 }
460 return is_float(type->t) && (type->t & VT_BTYPE) != VT_LDOUBLE;
461}
462
436ST_FUNC void gfunc_call(int nb_args)463ST_FUNC void gfunc_call(int nb_args)
437{464{
438 int i, align, size, aireg, afreg;465 int i, align, size, aireg, afreg;
@@ -461,14 +488,15 @@ ST_FUNC void gfunc_call(int nb_args) · 22 unmodified lines
461 nregs = 2;488 nregs = 2;
462 else489 else
463 nregs = 1;490 nregs = 1;
464 if ((sv->type.t & VT_BTYPE) == VT_LDOUBLE) {491 if (!sa) {
465 infreg = 0;492 infreg = 0;
466 } else493 } else {
467 infreg = sa && is_float(sv->type.t);494 infreg = pass_in_freg(&sv->type, 0);
495 }
468 if (!infreg && !sa && align == 2*XLEN && size <= 2*XLEN)496 if (!infreg && !sa && align == 2*XLEN && size <= 2*XLEN)
469 aireg = (aireg + 1) & ~1;497 aireg = (aireg + 1) & ~1;
470 pareg = infreg ? &afreg : &aireg;498 pareg = infreg ? &afreg : &aireg;
471 if ((*pareg < 8) && !force_stack) {499 if ((*pareg < 8 && (!infreg || (*pareg + nregs) <= 8)) && !force_stack) {
472 info[i] = *pareg + (infreg ? 8 : 0);500 info[i] = *pareg + (infreg ? 8 : 0);
473 (*pareg)++;501 (*pareg)++;
474 if (nregs == 1)502 if (nregs == 1)
@@ -547,7 +575,38 @@ ST_FUNC void gfunc_call(int nb_args) · 72 unmodified lines
547 vrotb(i+1);575 vrotb(i+1);
548 origtype = vtop->type;576 origtype = vtop->type;
549 size = type_size(&vtop->type, &align);577 size = type_size(&vtop->type, &align);
550 if (size > 8 && (vtop->type.t & VT_BTYPE) == VT_STRUCT)578 if (r >= 8 && (vtop->r & VT_LVAL)) {
579 int infreg = pass_in_freg(&vtop->type, 0);
580 int loadt = vtop->type.t & VT_BTYPE;
581 if (loadt == VT_STRUCT) {
582 if (infreg == 1)
583 loadt = size == 4 ? VT_FLOAT : VT_DOUBLE;
584 else
585 loadt = size == 8 ? VT_FLOAT : VT_DOUBLE;
586 }
587 vtop->type.t = loadt;
588 assert (infreg && infreg <= 2);
589 save_reg_upstack(r, 1);
590 if (infreg > 1) {
591 save_reg_upstack(r + 1, 1);
592 test_lvalue();
593 }
594 load(r, vtop);
595 vset(&origtype, r, 0);
596 vswap();
597 if (infreg > 1) {
598 assert(r + 1 < 16);
599 gaddrof();
600 mk_pointer(&vtop->type);
601 vpushi(1);
602 gen_op('+');
603 indir();
604 load(r + 1, vtop);
605 vtop[-1].r2 = r + 1;
606 }
607 vtop--;
608 } else {
609 if (r < 8 && size > 8 && (vtop->type.t & VT_BTYPE) == VT_STRUCT)
551 vtop->type.t = VT_LDOUBLE; // force loading a pair of regs610 vtop->type.t = VT_LDOUBLE; // force loading a pair of regs
552 gv(r < 8 ? RC_R(r) : RC_F(r - 8));611 gv(r < 8 ? RC_R(r) : RC_F(r - 8));
553 vtop->type = origtype;612 vtop->type = origtype;
@@ -565,6 +624,7 @@ ST_FUNC void gfunc_call(int nb_args) · 11 unmodified lines
565 vtop->r2 = 1 + vtop->r;624 vtop->r2 = 1 + vtop->r;
566 }625 }
567 }626 }
627 }
568 vrott(i+1);628 vrott(i+1);
569 }629 }
570 }630 }
@@ -621,11 +681,14 @@ ST_FUNC void gfunc_prolog(CType *func_type) · 50 unmodified lines
621 addr += size;681 addr += size;
622 } else {682 } else {
623 int regcount = 1, *pareg = &aireg;683 int regcount = 1, *pareg = &aireg;
624 if (is_float(type->t) && (type->t & VT_BTYPE) != VT_LDOUBLE)684 if ((regcount = pass_in_freg(type, 0)))
625 pareg = &afreg;685 pareg = &afreg;
686 else {
687 regcount = 1;
688 }
626 if (regcount + *pareg > 8)689 if (regcount + *pareg > 8)
627 goto from_stack;690 goto from_stack;
628 if (size > XLEN)691 if (size > XLEN && pareg == &aireg)
629 regcount++;692 regcount++;
630 loc -= regcount * 8; // XXX could reserve only 'size' bytes693 loc -= regcount * 8; // XXX could reserve only 'size' bytes
631 param_addr = loc;694 param_addr = loc;
@@ -638,8 +701,8 @@ ST_FUNC void gfunc_prolog(CType *func_type) · 6 unmodified lines
638 continue;701 continue;
639 }702 }
640 if (pareg == &afreg) {703 if (pareg == &afreg) {
641 assert(type->t == VT_FLOAT || type->t == VT_DOUBLE);704 //assert(type->t == VT_FLOAT || type->t == VT_DOUBLE);
642 ES(0x27, size == 4 ? 2 : 3, 8, 10 + *pareg, loc + i*8); // fs[wd] FAi, loc(s0)705 ES(0x27, (size / regcount) == 4 ? 2 : 3, 8, 10 + *pareg, loc + i*(size / regcount)); // fs[wd] FAi, loc(s0)
643 } else {706 } else {
644 ES(0x23, 3, 8, 10 + *pareg, loc + i*8); // sd aX, loc(s0) // XXX707 ES(0x23, 3, 8, 10 + *pareg, loc + i*8); // sd aX, loc(s0) // XXX
645 }708 }
@@ -666,11 +729,17 @@ ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, · 20 unmodified lines
666 /* generic code can only deal with structs of pow(2) sizes729 /* generic code can only deal with structs of pow(2) sizes
667 (it always deals with whole registers), so go through our own730 (it always deals with whole registers), so go through our own
668 code. */731 code. */
669 int align, size = type_size(vt, &align);732 int align, size = type_size(vt, &align), infreg;
670 *ret_align = 1;733 *ret_align = 1;
671 *regsize = 8;734 *regsize = 8;
672 if (size > 16)735 if (size > 16)
673 return 0;736 return 0;
737 infreg = pass_in_freg(vt, 0);
738 if (infreg) {
739 *regsize = size / infreg;
740 ret->t = (size / infreg) == 4 ? VT_FLOAT : VT_DOUBLE;
741 return infreg;
742 }
674 if (size > 8)743 if (size > 8)
675 ret->t = VT_LLONG;744 ret->t = VT_LLONG;
676 else if (size > 4)745 else if (size > 4)
@@ -684,7 +753,7 @@ ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, · 7 unmodified lines
684 return (size + 7) / 8;753 return (size + 7) / 8;
685}754}
686 755
687ST_FUNC void gfunc_return(CType *func_type)756ST_FUNC void gfunc_return2(CType *func_type)
688{757{
689 int align, size = type_size(func_type, &align), nregs;758 int align, size = type_size(func_type, &align), nregs;
690 CType type = *func_type;759 CType type = *func_type;
@@ -697,9 +766,12 @@ ST_FUNC void gfunc_return(CType *func_type) · 6 unmodified lines
697 vpop();766 vpop();
698 return;767 return;
699 }768 }
700 nregs = (size + 7) / 8;769 nregs = pass_in_freg(func_type, 0);
701 if (nregs == 2)770 if (!nregs) {
702 vtop->type.t = VT_LDOUBLE;771 nregs = (size + 7) / 8;
772 if (nregs == 2)
773 vtop->type.t = VT_LDOUBLE;
774 }
703 775
704 if (is_float(func_type->t) && (vtop->type.t & VT_BTYPE) != VT_LDOUBLE)776 if (is_float(func_type->t) && (vtop->type.t & VT_BTYPE) != VT_LDOUBLE)
705 gv(RC_FRET);777 gv(RC_FRET);
tcc.h+1−1
@@ -1604,7 +1604,7 @@ ST_FUNC void gen_clear_cache(void); · 1603 unmodified lines
1604#ifdef TCC_TARGET_RISCV641604#ifdef TCC_TARGET_RISCV64
1605ST_FUNC void gen_cvt_sxtw(void);1605ST_FUNC void gen_cvt_sxtw(void);
1606ST_FUNC void gen_opl(int op);1606ST_FUNC void gen_opl(int op);
1607ST_FUNC void gfunc_return(CType *func_type);1607//ST_FUNC void gfunc_return(CType *func_type);
1608ST_FUNC void gen_va_start(void);1608ST_FUNC void gen_va_start(void);
1609ST_FUNC void gen_va_arg(CType *t);1609ST_FUNC void gen_va_arg(CType *t);
1610#endif1610#endif
tccgen.c+0−2
@@ -6083,7 +6083,6 @@ ST_FUNC int expr_const(void) · 6082 unmodified lines
6083/* return from function */6083/* return from function */
6084 6084
6085#ifndef TCC_TARGET_ARM646085#ifndef TCC_TARGET_ARM64
6086#ifndef TCC_TARGET_RISCV64
6087static void gfunc_return(CType *func_type)6086static void gfunc_return(CType *func_type)
6088{6087{
6089 if ((func_type->t & VT_BTYPE) == VT_STRUCT) {6088 if ((func_type->t & VT_BTYPE) == VT_STRUCT) {
@@ -6148,7 +6147,6 @@ static void gfunc_return(CType *func_type) · 58 unmodified lines
6148 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */6147 vtop--; /* NOT vpop() because on x86 it would flush the fp stack */
6149}6148}
6150#endif6149#endif
6151#endif
6152 6150
6153static void check_func_return(void)6151static void check_func_return(void)
6154{6152{

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t