History

riscv: rewrite parameter passing

this fixes the ret_mixed_test of abitest.c, now everything of the testsuite works. The generic code for returns is good enough for our use, except in the specific case of a mixed int/float structures returned in registers, so instead of duplicating the whole generic gfunc_return function, add another modus for gfunc_sret: returning -1 makes the actual register transfer by a new backend function.

Michael Matz committed 7 years ago

Commit c5050741 parent 9b0efa93 files · +209 −164Browse files

Unified · Split

3 files
  1. riscv64-gen.c +165 −135
  2. tcc.h +1 −0
  3. tccgen.c +43 −29
riscv64-gen.c+165−135
@@ -433,32 +433,36 @@ static void gcall_or_jmp(int docall) · 432 unmodified lines
433 }433 }
434}434}
435 435
436static int pass_in_freg(CType *type, int regs)436static void reg_pass(CType *type, int *rc, int *fieldofs, int ofs)
437{437{
438 int tr;
439 int toplevel = !regs;
440 if ((type->t & VT_BTYPE) == VT_STRUCT) {438 if ((type->t & VT_BTYPE) == VT_STRUCT) {
441 Sym *f;439 Sym *f;
442 if (type->ref->type.t == VT_UNION)440 if (type->ref->type.t == VT_UNION)
443 return toplevel ? 0 : -1;441 rc[0] = -1;
444 for (f = type->ref->next; f; f = f->next) {442 else for (f = type->ref->next; f; f = f->next)
445 tr = pass_in_freg(&f->type, regs);443 reg_pass(&f->type, rc, fieldofs, ofs + f->c);
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) {444 } else if (type->t & VT_ARRAY) {
452 if (type->ref->c < 0 || type->ref->c > 2)445 if (type->ref->c < 0 || type->ref->c > 2)
453 return toplevel ? 0 : -1;446 rc[0] = -1;
454 tr = pass_in_freg(&type->ref->type, regs);447 else {
455 tr *= type->ref->c;448 int a, sz = type_size(&type->ref->type, &a);
456 if (tr < 0 || (regs + tr) > 2)449 reg_pass(&type->ref->type, rc, fieldofs, ofs);
457 return toplevel ? 0 : -1;450 if (rc[0] > 2 || (rc[0] == 2 && type->ref->c > 1))
458 return regs + tr;451 rc[0] = -1;
459 }452 else if (type->ref->c == 2 && rc[0] && rc[1] == RC_FLOAT) {
460 return is_float(type->t) && (type->t & VT_BTYPE) != VT_LDOUBLE453 rc[++rc[0]] = RC_FLOAT;
461 ? 1 : toplevel ? 0 : -1;454 fieldofs[rc[0]] = ((ofs + sz) << 4)
455 | (type->ref->type.t & VT_BTYPE);
456 } else if (type->ref->c == 2)
457 rc[0] = -1;
458 }
459 } else if (rc[0] == 2 || rc[0] < 0 || (type->t & VT_BTYPE) == VT_LDOUBLE)
460 rc[0] = -1;
461 else if (!rc[0] || rc[1] == RC_FLOAT || is_float(type->t)) {
462 rc[++rc[0]] = is_float(type->t) ? RC_FLOAT : RC_INT;
463 fieldofs[rc[0]] = (ofs << 4) | (type->t & VT_BTYPE);
464 } else
465 rc[0] = -1;
462}466}
463 467
464ST_FUNC void gfunc_call(int nb_args)468ST_FUNC void gfunc_call(int nb_args)
@@ -472,7 +476,9 @@ ST_FUNC void gfunc_call(int nb_args) · 7 unmodified lines
472 aireg = afreg = 0;476 aireg = afreg = 0;
473 sa = vtop[-nb_args].type.ref->next;477 sa = vtop[-nb_args].type.ref->next;
474 for (i = 0; i < nb_args; i++) {478 for (i = 0; i < nb_args; i++) {
475 int *pareg, nregs, infreg = 0, byref = 0, tempofs;479 int *pareg, nregs, byref = 0, tempofs;
480 int prc[3], fieldofs[3];
481 prc[0] = 0;
476 sv = &vtop[1 + i - nb_args];482 sv = &vtop[1 + i - nb_args];
477 sv->type.t &= ~VT_ARRAY; // XXX this should be done in tccgen.c483 sv->type.t &= ~VT_ARRAY; // XXX this should be done in tccgen.c
478 size = type_size(&sv->type, &align);484 size = type_size(&sv->type, &align);
@@ -490,31 +496,43 @@ ST_FUNC void gfunc_call(int nb_args) · 11 unmodified lines
490 else496 else
491 nregs = 1;497 nregs = 1;
492 if (!sa) {498 if (!sa) {
493 infreg = 0;499 prc[0] = nregs, prc[1] = prc[2] = RC_INT;
494 } else {500 } else {
495 infreg = pass_in_freg(&sv->type, 0);501 reg_pass(&sv->type, prc, fieldofs, 0);
502 if (prc[0] < 0)
503 prc[0] = nregs, prc[1] = prc[2] = RC_INT;
496 }504 }
497 if (!infreg && !sa && align == 2*XLEN && size <= 2*XLEN)505 if (!sa && align == 2*XLEN && size <= 2*XLEN)
498 aireg = (aireg + 1) & ~1;506 aireg = (aireg + 1) & ~1;
499 pareg = infreg ? &afreg : &aireg;507 nregs = prc[0];
500 if ((*pareg < 8 && (!infreg || (*pareg + nregs) <= 8)) && !force_stack) {508 assert(nregs);
501 info[i] = *pareg + (infreg ? 8 : 0);509 if (!nregs
502 (*pareg)++;510 || (prc[1] == RC_INT && aireg >= 8)
503 if (nregs == 1)511 || (prc[1] == RC_FLOAT && afreg >= 8)
504 ;512 || (nregs == 2 && prc[2] == RC_FLOAT && afreg >= 7)
505 else if (*pareg < 8)513 || (nregs == 2 && prc[1] != prc[2] && (afreg >= 8 || aireg >= 8))
506 (*pareg)++;514 || force_stack) {
507 else {
508 info[i] |= 16;
509 stack_adj += 8;
510 }
511 } else {
512 info[i] = 32;515 info[i] = 32;
513 if (align < XLEN)516 if (align < XLEN)
514 align = XLEN;517 align = XLEN;
515 stack_adj += (size + align - 1) & -align;518 stack_adj += (size + align - 1) & -align;
516 if (!sa)519 if (!sa)
517 force_stack = 1;520 force_stack = 1;
521 } else {
522 if (prc[1] == RC_FLOAT)
523 info[i] = 8 + afreg++;
524 else
525 info[i] = aireg++;
526 if (nregs == 2) {
527 if (prc[2] == RC_FLOAT)
528 info[i] |= (1 + 8 + afreg++) << 7;
529 else if (aireg < 8)
530 info[i] |= (1 + aireg++) << 7;
531 else {
532 info[i] |= 16;
533 stack_adj += 8;
534 }
535 }
518 }536 }
519 if (byref)537 if (byref)
520 info[i] |= 64 | (tempofs << 7);538 info[i] |= 64 | (tempofs << 7);
@@ -569,62 +587,72 @@ ST_FUNC void gfunc_call(int nb_args) · 48 unmodified lines
569 }587 }
570 }588 }
571 for (i = 0; i < nb_args; i++) {589 for (i = 0; i < nb_args; i++) {
572 int r = info[nb_args - 1 - i];590 int r = info[nb_args - 1 - i], r2 = r;
573 if (!(r & 32)) {591 if (!(r & 32)) {
574 CType origtype;592 CType origtype;
593 int prc[3], fieldofs[3], loadt;
594 prc[0] = 0;
575 r &= 15;595 r &= 15;
596 r2 = r2 & 64 ? 0 : r2 >> 7;
576 vrotb(i+1);597 vrotb(i+1);
577 origtype = vtop->type;598 origtype = vtop->type;
578 size = type_size(&vtop->type, &align);599 size = type_size(&vtop->type, &align);
579 if (r >= 8 && (vtop->r & VT_LVAL)) {600 reg_pass(&vtop->type, prc, fieldofs, 0);
580 int infreg = pass_in_freg(&vtop->type, 0);601 if (prc[0] <= 0 || (!r2 && prc[0] > 1)) {
581 int loadt = vtop->type.t & VT_BTYPE;602 prc[0] = (size + 7) >> 3;
603 prc[1] = prc[2] = RC_INT;
604 fieldofs[1] = (0 << 4) | (size <= 1 ? VT_BYTE : size <= 2 ? VT_SHORT : size <= 4 ? VT_INT : VT_LLONG);
605 fieldofs[2] = (8 << 4) | (size <= 9 ? VT_BYTE : size <= 10 ? VT_SHORT : size <= 12 ? VT_INT : VT_LLONG);
606 }
607 loadt = vtop->type.t & VT_BTYPE;
608 if (loadt == VT_STRUCT) {
609 loadt = fieldofs[1] & VT_BTYPE;
610 }
611 if (info[nb_args - 1 - i] & 16) {
612 assert(!r2);
613 r2 = 1 + TREG_RA;
614 }
615 if (loadt == VT_LDOUBLE) {
616 assert(r2);
617 r2--;
618 } else if (r2) {
619 test_lvalue();
620 vpushv(vtop);
621 }
622 vtop->type.t = loadt;
623 gv(r < 8 ? RC_R(r) : RC_F(r - 8));
624 vtop->type = origtype;
625
626 if (r2 && loadt != VT_LDOUBLE) {
627 r2--;
628 assert(r2 < 16 || r2 == TREG_RA);
629 vswap();
630 gaddrof();
631 vtop->type = char_pointer_type;
632 vpushi(fieldofs[2] >> 4);
633 gen_op('+');
634 indir();
635 vtop->type = origtype;
636 loadt = vtop->type.t & VT_BTYPE;
582 if (loadt == VT_STRUCT) {637 if (loadt == VT_STRUCT) {
583 if (infreg == 1)638 loadt = fieldofs[2] & VT_BTYPE;
584 loadt = size == 4 ? VT_FLOAT : VT_DOUBLE;
585 else
586 loadt = size == 8 ? VT_FLOAT : VT_DOUBLE;
587 }639 }
640 save_reg_upstack(r2, 1);
588 vtop->type.t = loadt;641 vtop->type.t = loadt;
589 assert (infreg && infreg <= 2);642 load(r2, vtop);
590 save_reg_upstack(r, 1);643 assert(r2 < VT_CONST);
591 if (infreg > 1) {
592 save_reg_upstack(r + 1, 1);
593 test_lvalue();
594 }
595 load(r, vtop);
596 vset(&origtype, r, 0);
597 vswap();
598 if (infreg > 1) {
599 assert(r + 1 < 16);
600 gaddrof();
601 mk_pointer(&vtop->type);
602 vpushi(1);
603 gen_op('+');
604 indir();
605 load(r + 1, vtop);
606 vtop[-1].r2 = r + 1;
607 }
608 vtop--;644 vtop--;
609 } else {645 vtop->r2 = r2;
610 if (r < 8 && size > 8 && (vtop->type.t & VT_BTYPE) == VT_STRUCT)
611 vtop->type.t = VT_LDOUBLE; // force loading a pair of regs
612 gv(r < 8 ? RC_R(r) : RC_F(r - 8));
613 vtop->type = origtype;
614 if (size > 8) {
615 assert((vtop->type.t & VT_BTYPE) == VT_LDOUBLE
616 || (vtop->type.t & VT_BTYPE) == VT_STRUCT);
617 assert(vtop->r2 < VT_CONST);
618 if (info[nb_args - 1 - i] & 16) {
619 ES(0x23, 3, 2, ireg(vtop->r2), splitofs); // sd t0, ofs(sp)
620 } else if (vtop->r2 != 1 + vtop->r) {
621 assert(vtop->r < 7);
622 /* XXX we'd like to have 'gv' move directly into
623 the right class instead of us fixing it up. */
624 EI(0x13, 0, ireg(vtop->r) + 1, ireg(vtop->r2), 0); // mv Ra+1, RR2
625 vtop->r2 = 1 + vtop->r;
626 }
627 }646 }
647 if (info[nb_args - 1 - i] & 16) {
648 ES(0x23, 3, 2, ireg(vtop->r2), splitofs); // sd t0, ofs(sp)
649 vtop->r2 = VT_CONST;
650 } else if (loadt == VT_LDOUBLE && vtop->r2 != r2) {
651 assert(vtop->r2 <= 7 && r2 <= 7);
652 /* XXX we'd like to have 'gv' move directly into
653 the right class instead of us fixing it up. */
654 EI(0x13, 0, ireg(r2), ireg(vtop->r2), 0); // mv Ra+1, RR2
655 vtop->r2 = r2;
628 }656 }
629 vrott(i+1);657 vrott(i+1);
630 }658 }
@@ -681,19 +709,29 @@ ST_FUNC void gfunc_prolog(CType *func_type) · 50 unmodified lines
681 param_addr = addr;709 param_addr = addr;
682 addr += size;710 addr += size;
683 } else {711 } else {
684 int regcount = 1, *pareg = &aireg;712 int regcount, *pareg;
685 if ((regcount = pass_in_freg(type, 0)))713 int prc[3], fieldofs[3];
686 pareg = &afreg;714 prc[0] = 0;
687 else {715 reg_pass(type, prc, fieldofs, 0);
688 regcount = 1;716 if (prc[0] <= 0) {
717 prc[0] = (size + 7) >> 3;
718 prc[1] = prc[2] = RC_INT;
719 fieldofs[1] = (0 << 4) | (size <= 1 ? VT_BYTE : size <= 2 ? VT_SHORT : size <= 4 ? VT_INT : VT_LLONG);
720 fieldofs[2] = (8 << 4) | (size <= 9 ? VT_BYTE : size <= 10 ? VT_SHORT : size <= 12 ? VT_INT : VT_LLONG);
689 }721 }
690 if (regcount + *pareg > 8)722 regcount = prc[0];
723 if (!regcount
724 || (prc[1] == RC_INT && aireg >= 8)
725 || (prc[1] == RC_FLOAT && afreg >= 8)
726 || (regcount == 2 && prc[2] == RC_FLOAT && afreg >= 7)
727 || (regcount == 2 && prc[1] != prc[2] && (afreg >= 8 || aireg >= 8)))
691 goto from_stack;728 goto from_stack;
692 if (size > XLEN && pareg == &aireg)729 if (size > XLEN)
693 regcount++;730 assert(regcount == 2);
694 loc -= regcount * 8; // XXX could reserve only 'size' bytes731 loc -= regcount * 8; // XXX could reserve only 'size' bytes
695 param_addr = loc;732 param_addr = loc;
696 for (i = 0; i < regcount; i++) {733 for (i = 0; i < regcount; i++) {
734 pareg = prc[1+i] == RC_INT ? &aireg : &afreg;
697 if (*pareg >= 8) {735 if (*pareg >= 8) {
698 assert(i == 1 && regcount == 2 && !(addr & 7));736 assert(i == 1 && regcount == 2 && !(addr & 7));
699 EI(0x03, 3, 5, 8, addr); // ld t0, addr(s0)737 EI(0x03, 3, 5, 8, addr); // ld t0, addr(s0)
@@ -703,11 +741,10 @@ ST_FUNC void gfunc_prolog(CType *func_type) · 3 unmodified lines
703 }741 }
704 if (pareg == &afreg) {742 if (pareg == &afreg) {
705 //assert(type->t == VT_FLOAT || type->t == VT_DOUBLE);743 //assert(type->t == VT_FLOAT || type->t == VT_DOUBLE);
706 ES(0x27, (size / regcount) == 4 ? 2 : 3, 8, 10 + *pareg, loc + i*(size / regcount)); // fs[wd] FAi, loc(s0)744 ES(0x27, (size / regcount) == 4 ? 2 : 3, 8, 10 + afreg++, loc + (fieldofs[i+1] >> 4)); // fs[wd] FAi, loc(s0)
707 } else {745 } else {
708 ES(0x23, 3, 8, 10 + *pareg, loc + i*8); // sd aX, loc(s0) // XXX746 ES(0x23, 3, 8, 10 + aireg++, loc + i*8); // sd aX, loc(s0) // XXX
709 }747 }
710 (*pareg)++;
711 }748 }
712 }749 }
713 sym_push(sym->v & ~SYM_FIELD, &sym->type,750 sym_push(sym->v & ~SYM_FIELD, &sym->type,
@@ -727,57 +764,50 @@ ST_FUNC void gfunc_prolog(CType *func_type) · 13 unmodified lines
727ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret,764ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret,
728 int *ret_align, int *regsize)765 int *ret_align, int *regsize)
729{766{
730 /* generic code can only deal with structs of pow(2) sizes767 int align, size = type_size(vt, &align), infreg, nregs;
731 (it always deals with whole registers), so go through our own768 int prc[3], fieldofs[3];
732 code. */
733 int align, size = type_size(vt, &align), infreg;
734 *ret_align = 1;769 *ret_align = 1;
735 *regsize = 8;770 *regsize = 8;
736 if (size > 16)771 if (size > 16)
737 return 0;772 return 0;
738 infreg = pass_in_freg(vt, 0);773 prc[0] = 0;
739 if (infreg) {774 reg_pass(vt, prc, fieldofs, 0);
740 *regsize = size / infreg;775 if (prc[0] <= 0) {
741 ret->t = (size / infreg) == 4 ? VT_FLOAT : VT_DOUBLE;776 prc[0] = (size + 7) >> 3;
742 return infreg;777 prc[1] = prc[2] = RC_INT;
778 fieldofs[1] = (0 << 4) | (size <= 1 ? VT_BYTE : size <= 2 ? VT_SHORT : size <= 4 ? VT_INT : VT_LLONG);
779 fieldofs[2] = (8 << 4) | (size <= 9 ? VT_BYTE : size <= 10 ? VT_SHORT : size <= 12 ? VT_INT : VT_LLONG);
743 }780 }
744 if (size > 8)781 nregs = prc[0];
745 ret->t = VT_LLONG;782 assert(nregs > 0);
746 else if (size > 4)783 if (nregs == 2 && prc[1] != prc[2])
747 ret->t = VT_LLONG;784 return -1; /* generic code can't deal with this case */
748 else if (size > 2)785 if (prc[1] == RC_FLOAT) {
749 ret->t = VT_INT;786 *regsize = size / nregs;
750 else if (size > 1)787 }
751 ret->t = VT_SHORT;788 ret->t = fieldofs[1] & VT_BTYPE;
752 else789 return nregs;
753 ret->t = VT_BYTE;
754 return (size + 7) / 8;
755}790}
756 791
757ST_FUNC void gfunc_return2(CType *func_type)792ST_FUNC void arch_transfer_ret_regs(int aftercall)
758{793{
759 int align, size = type_size(func_type, &align), nregs;794 int prc[3], fieldofs[3];
760 CType type = *func_type;795 prc[0] = 0;
761 if (size > 2 * XLEN) {796 reg_pass(&vtop->type, prc, fieldofs, 0);
762 mk_pointer(&type);797 assert(prc[0] == 2 && prc[1] != prc[2] && !(fieldofs[1] >> 4));
763 vset(&type, VT_LOCAL | VT_LVAL, func_vc);798 assert(vtop->r == (VT_LOCAL | VT_LVAL));
764 indir();799 vpushv(vtop);
765 vswap();800 vtop->type.t = fieldofs[1] & VT_BTYPE;
766 vstore();801 if (aftercall)
767 vpop();802 store(prc[1] == RC_INT ? REG_IRET : REG_FRET, vtop);
768 return;803 else
769 }804 load(prc[1] == RC_INT ? REG_IRET : REG_FRET, vtop);
770 nregs = pass_in_freg(func_type, 0);805 vtop->c.i += fieldofs[2] >> 4;
771 if (!nregs) {806 vtop->type.t = fieldofs[2] & VT_BTYPE;
772 nregs = (size + 7) / 8;807 if (aftercall)
773 if (nregs == 2)808 store(prc[2] == RC_INT ? REG_IRET : REG_FRET, vtop);
774 vtop->type.t = VT_LDOUBLE;
775 }
776
777 if (is_float(func_type->t) && (vtop->type.t & VT_BTYPE) != VT_LDOUBLE)
778 gv(RC_FRET);
779 else809 else
780 gv(RC_IRET);810 load(prc[2] == RC_INT ? REG_IRET : REG_FRET, vtop);
781 vtop--;811 vtop--;
782}812}
783 813
tcc.h+1−0
@@ -1607,6 +1607,7 @@ ST_FUNC void gen_opl(int op); · 1606 unmodified lines
1607//ST_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);
1610ST_FUNC void arch_transfer_ret_regs(int);
1610#endif1611#endif
1611/* ------------ c67-gen.c ------------ */1612/* ------------ c67-gen.c ------------ */
1612#ifdef TCC_TARGET_C671613#ifdef TCC_TARGET_C67
tccgen.c+43−29
@@ -5490,7 +5490,7 @@ special_math_val: · 5489 unmodified lines
5490 variadic = (s->f.func_type == FUNC_ELLIPSIS);5490 variadic = (s->f.func_type == FUNC_ELLIPSIS);
5491 ret_nregs = gfunc_sret(&s->type, variadic, &ret.type,5491 ret_nregs = gfunc_sret(&s->type, variadic, &ret.type,
5492 &ret_align, &regsize);5492 &ret_align, &regsize);
5493 if (!ret_nregs) {5493 if (ret_nregs <= 0) {
5494 /* get some space for the returned structure */5494 /* get some space for the returned structure */
5495 size = type_size(&s->type, &align);5495 size = type_size(&s->type, &align);
5496#ifdef TCC_TARGET_ARM645496#ifdef TCC_TARGET_ARM64
@@ -5509,14 +5509,17 @@ special_math_val: · 12 unmodified lines
5509 problems */5509 problems */
5510 vseti(VT_LOCAL, loc);5510 vseti(VT_LOCAL, loc);
5511 ret.c = vtop->c;5511 ret.c = vtop->c;
5512 nb_args++;5512 if (ret_nregs < 0)
5513 vtop--;
5514 else
5515 nb_args++;
5513 }5516 }
5514 } else {5517 } else {
5515 ret_nregs = 1;5518 ret_nregs = 1;
5516 ret.type = s->type;5519 ret.type = s->type;
5517 }5520 }
5518 5521
5519 if (ret_nregs) {5522 if (ret_nregs > 0) {
5520 /* return in register */5523 /* return in register */
5521 if (is_float(ret.type.t)) {5524 if (is_float(ret.type.t)) {
5522 ret.r = reg_fret(ret.type.t);5525 ret.r = reg_fret(ret.type.t);
@@ -5559,34 +5562,41 @@ special_math_val: · 36 unmodified lines
5559 skip(')');5562 skip(')');
5560 gfunc_call(nb_args);5563 gfunc_call(nb_args);
5561 5564
5562 /* return value */5565 if (ret_nregs < 0) {
5563 for (r = ret.r + ret_nregs + !ret_nregs; r-- > ret.r;) {5566 vsetc(&ret.type, ret.r, &ret.c);
5564 vsetc(&ret.type, r, &ret.c);5567#ifdef TCC_TARGET_RISCV64
5565 vtop->r2 = ret.r2; /* Loop only happens when r2 is VT_CONST */5568 arch_transfer_ret_regs(1);
5566 }5569#endif
5570 } else {
5571 /* return value */
5572 for (r = ret.r + ret_nregs + !ret_nregs; r-- > ret.r;) {
5573 vsetc(&ret.type, r, &ret.c);
5574 vtop->r2 = ret.r2; /* Loop only happens when r2 is VT_CONST */
5575 }
5567 5576
5568 /* handle packed struct return */5577 /* handle packed struct return */
5569 if (((s->type.t & VT_BTYPE) == VT_STRUCT) && ret_nregs) {5578 if (((s->type.t & VT_BTYPE) == VT_STRUCT) && ret_nregs) {
5570 int addr, offset;5579 int addr, offset;
5571 5580
5572 size = type_size(&s->type, &align);5581 size = type_size(&s->type, &align);
5573 /* We're writing whole regs often, make sure there's enough5582 /* We're writing whole regs often, make sure there's enough
5574 space. Assume register size is power of 2. */5583 space. Assume register size is power of 2. */
5575 if (regsize > align)5584 if (regsize > align)
5576 align = regsize;5585 align = regsize;
5577 loc = (loc - size) & -align;5586 loc = (loc - size) & -align;
5578 addr = loc;5587 addr = loc;
5579 offset = 0;5588 offset = 0;
5580 for (;;) {5589 for (;;) {
5581 vset(&ret.type, VT_LOCAL | VT_LVAL, addr + offset);5590 vset(&ret.type, VT_LOCAL | VT_LVAL, addr + offset);
5582 vswap();5591 vswap();
5583 vstore();5592 vstore();
5584 vtop--;5593 vtop--;
5585 if (--ret_nregs == 0)5594 if (--ret_nregs == 0)
5586 break;5595 break;
5587 offset += regsize;5596 offset += regsize;
5597 }
5598 vset(&s->type, VT_LOCAL | VT_LVAL, addr);
5588 }5599 }
5589 vset(&s->type, VT_LOCAL | VT_LVAL, addr);
5590 }5600 }
5591 if (s->f.func_noreturn)5601 if (s->f.func_noreturn)
5592 CODE_OFF();5602 CODE_OFF();
@@ -6090,7 +6100,11 @@ static void gfunc_return(CType *func_type) · 497 unmodified lines
6090 int ret_align, ret_nregs, regsize;6100 int ret_align, ret_nregs, regsize;
6091 ret_nregs = gfunc_sret(func_type, func_var, &ret_type,6101 ret_nregs = gfunc_sret(func_type, func_var, &ret_type,
6092 &ret_align, &regsize);6102 &ret_align, &regsize);
6093 if (0 == ret_nregs) {6103 if (ret_nregs < 0) {
6104#ifdef TCC_TARGET_RISCV64
6105 arch_transfer_ret_regs(0);
6106#endif
6107 } else if (0 == ret_nregs) {
6094 /* if returning structure, must copy it to implicit6108 /* if returning structure, must copy it to implicit
6095 first pointer arg location */6109 first pointer arg location */
6096 type = *func_type;6110 type = *func_type;

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