History

riscv: TLC of param passing

factor and cleanup the param passing code somewhat.

Michael Matz committed 7 years ago

Commit 83cf5bf1 parent c5050742 files · +73 −117Browse files

Unified · Split

2 files
  1. riscv64-gen.c +73 −116
  2. tcc.h +0 −1
riscv64-gen.c+73−116
@@ -433,20 +433,20 @@ static void gcall_or_jmp(int docall) · 432 unmodified lines
433 }433 }
434}434}
435 435
436static void reg_pass(CType *type, int *rc, int *fieldofs, int ofs)436static void reg_pass_rec(CType *type, int *rc, int *fieldofs, int ofs)
437{437{
438 if ((type->t & VT_BTYPE) == VT_STRUCT) {438 if ((type->t & VT_BTYPE) == VT_STRUCT) {
439 Sym *f;439 Sym *f;
440 if (type->ref->type.t == VT_UNION)440 if (type->ref->type.t == VT_UNION)
441 rc[0] = -1;441 rc[0] = -1;
442 else for (f = type->ref->next; f; f = f->next)442 else for (f = type->ref->next; f; f = f->next)
443 reg_pass(&f->type, rc, fieldofs, ofs + f->c);443 reg_pass_rec(&f->type, rc, fieldofs, ofs + f->c);
444 } else if (type->t & VT_ARRAY) {444 } else if (type->t & VT_ARRAY) {
445 if (type->ref->c < 0 || type->ref->c > 2)445 if (type->ref->c < 0 || type->ref->c > 2)
446 rc[0] = -1;446 rc[0] = -1;
447 else {447 else {
448 int a, sz = type_size(&type->ref->type, &a);448 int a, sz = type_size(&type->ref->type, &a);
449 reg_pass(&type->ref->type, rc, fieldofs, ofs);449 reg_pass_rec(&type->ref->type, rc, fieldofs, ofs);
450 if (rc[0] > 2 || (rc[0] == 2 && type->ref->c > 1))450 if (rc[0] > 2 || (rc[0] == 2 && type->ref->c > 1))
451 rc[0] = -1;451 rc[0] = -1;
452 else if (type->ref->c == 2 && rc[0] && rc[1] == RC_FLOAT) {452 else if (type->ref->c == 2 && rc[0] && rc[1] == RC_FLOAT) {
@@ -465,20 +465,32 @@ static void reg_pass(CType *type, int *rc, int *fieldofs, int ofs) · 12 unmodified lines
465 rc[0] = -1;465 rc[0] = -1;
466}466}
467 467
468static void reg_pass(CType *type, int *prc, int *fieldofs, int named)
469{
470 prc[0] = 0;
471 reg_pass_rec(type, prc, fieldofs, 0);
472 if (prc[0] <= 0 || !named) {
473 int align, size = type_size(type, &align);
474 prc[0] = (size + 7) >> 3;
475 prc[1] = prc[2] = RC_INT;
476 fieldofs[1] = (0 << 4) | (size <= 1 ? VT_BYTE : size <= 2 ? VT_SHORT : size <= 4 ? VT_INT : VT_LLONG);
477 fieldofs[2] = (8 << 4) | (size <= 9 ? VT_BYTE : size <= 10 ? VT_SHORT : size <= 12 ? VT_INT : VT_LLONG);
478 }
479}
480
468ST_FUNC void gfunc_call(int nb_args)481ST_FUNC void gfunc_call(int nb_args)
469{482{
470 int i, align, size, aireg, afreg;483 int i, align, size, areg[2];
471 int info[nb_args ? nb_args : 1];484 int info[nb_args ? nb_args : 1];
472 int stack_adj = 0, tempspace = 0, ofs, splitofs = 0;485 int stack_adj = 0, tempspace = 0, ofs, splitofs = 0;
473 int force_stack = 0;
474 SValue *sv;486 SValue *sv;
475 Sym *sa;487 Sym *sa;
476 aireg = afreg = 0;488 areg[0] = 0; /* int arg regs */
489 areg[1] = 8; /* float arg regs */
477 sa = vtop[-nb_args].type.ref->next;490 sa = vtop[-nb_args].type.ref->next;
478 for (i = 0; i < nb_args; i++) {491 for (i = 0; i < nb_args; i++) {
479 int *pareg, nregs, byref = 0, tempofs;492 int nregs, byref = 0, tempofs;
480 int prc[3], fieldofs[3];493 int prc[3], fieldofs[3];
481 prc[0] = 0;
482 sv = &vtop[1 + i - nb_args];494 sv = &vtop[1 + i - nb_args];
483 sv->type.t &= ~VT_ARRAY; // XXX this should be done in tccgen.c495 sv->type.t &= ~VT_ARRAY; // XXX this should be done in tccgen.c
484 size = type_size(&sv->type, &align);496 size = type_size(&sv->type, &align);
@@ -489,53 +501,43 @@ ST_FUNC void gfunc_call(int nb_args) · 4 unmodified lines
489 tempofs = tempspace;501 tempofs = tempspace;
490 tempspace += size;502 tempspace += size;
491 size = align = 8;503 size = align = 8;
492 byref = 1;504 byref = 64 | (tempofs << 7);
493 }
494 if (size > 8)
495 nregs = 2;
496 else
497 nregs = 1;
498 if (!sa) {
499 prc[0] = nregs, prc[1] = prc[2] = RC_INT;
500 } else {
501 reg_pass(&sv->type, prc, fieldofs, 0);
502 if (prc[0] < 0)
503 prc[0] = nregs, prc[1] = prc[2] = RC_INT;
504 }505 }
506 reg_pass(&sv->type, prc, fieldofs, sa != 0);
505 if (!sa && align == 2*XLEN && size <= 2*XLEN)507 if (!sa && align == 2*XLEN && size <= 2*XLEN)
506 aireg = (aireg + 1) & ~1;508 areg[0] = (areg[0] + 1) & ~1;
507 nregs = prc[0];509 nregs = prc[0];
508 assert(nregs);510 if ((prc[1] == RC_INT && areg[0] >= 8)
509 if (!nregs511 || (prc[1] == RC_FLOAT && areg[1] >= 16)
510 || (prc[1] == RC_INT && aireg >= 8)512 || (nregs == 2 && prc[1] == RC_FLOAT && prc[2] == RC_FLOAT
511 || (prc[1] == RC_FLOAT && afreg >= 8)513 && areg[1] >= 15)
512 || (nregs == 2 && prc[2] == RC_FLOAT && afreg >= 7)514 || (nregs == 2 && prc[1] != prc[2]
513 || (nregs == 2 && prc[1] != prc[2] && (afreg >= 8 || aireg >= 8))515 && (areg[1] >= 16 || areg[0] >= 8))) {
514 || force_stack) {
515 info[i] = 32;516 info[i] = 32;
516 if (align < XLEN)517 if (align < XLEN)
517 align = XLEN;518 align = XLEN;
518 stack_adj += (size + align - 1) & -align;519 stack_adj += (size + align - 1) & -align;
519 if (!sa)520 if (!sa) /* one vararg on stack forces the rest on stack */
520 force_stack = 1;521 areg[0] = 8, areg[1] = 16;
521 } else {522 } else {
522 if (prc[1] == RC_FLOAT)523 info[i] = areg[prc[1] - 1]++;
523 info[i] = 8 + afreg++;524 if (!byref)
524 else525 info[i] |= (fieldofs[1] & VT_BTYPE) << 12;
525 info[i] = aireg++;526 assert(!(fieldofs[1] >> 4));
526 if (nregs == 2) {527 if (nregs == 2) {
527 if (prc[2] == RC_FLOAT)528 if (prc[2] == RC_FLOAT || areg[0] < 8)
528 info[i] |= (1 + 8 + afreg++) << 7;529 info[i] |= (1 + areg[prc[2] - 1]++) << 7;
529 else if (aireg < 8)
530 info[i] |= (1 + aireg++) << 7;
531 else {530 else {
532 info[i] |= 16;531 info[i] |= 16;
533 stack_adj += 8;532 stack_adj += 8;
534 }533 }
534 if (!byref) {
535 assert((fieldofs[2] >> 4) < 2048);
536 info[i] |= fieldofs[2] << (12 + 4); // includes offset
537 }
535 }538 }
536 }539 }
537 if (byref)540 info[i] |= byref;
538 info[i] |= 64 | (tempofs << 7);
539 if (sa)541 if (sa)
540 sa = sa->next;542 sa = sa->next;
541 }543 }
@@ -544,7 +546,7 @@ ST_FUNC void gfunc_call(int nb_args) · 2 unmodified lines
544 if (stack_adj + tempspace) {546 if (stack_adj + tempspace) {
545 EI(0x13, 0, 2, 2, -(stack_adj + tempspace)); // addi sp, sp, -adj547 EI(0x13, 0, 2, 2, -(stack_adj + tempspace)); // addi sp, sp, -adj
546 for (i = ofs = 0; i < nb_args; i++) {548 for (i = ofs = 0; i < nb_args; i++) {
547 if (info[i] >= 32) {549 if (info[i] & (64 | 32)) {
548 vrotb(nb_args - i);550 vrotb(nb_args - i);
549 size = type_size(&vtop->type, &align);551 size = type_size(&vtop->type, &align);
550 if (info[i] & 64) {552 if (info[i] & 64) {
@@ -587,26 +589,19 @@ ST_FUNC void gfunc_call(int nb_args) · 36 unmodified lines
587 }589 }
588 }590 }
589 for (i = 0; i < nb_args; i++) {591 for (i = 0; i < nb_args; i++) {
590 int r = info[nb_args - 1 - i], r2 = r;592 int ii = info[nb_args - 1 - i], r = ii, r2 = r;
591 if (!(r & 32)) {593 if (!(r & 32)) {
592 CType origtype;594 CType origtype;
593 int prc[3], fieldofs[3], loadt;595 int loadt;
594 prc[0] = 0;
595 r &= 15;596 r &= 15;
596 r2 = r2 & 64 ? 0 : r2 >> 7;597 r2 = r2 & 64 ? 0 : (r2 >> 7) & 31;
598 assert(r2 <= 16);
597 vrotb(i+1);599 vrotb(i+1);
598 origtype = vtop->type;600 origtype = vtop->type;
599 size = type_size(&vtop->type, &align);601 size = type_size(&vtop->type, &align);
600 reg_pass(&vtop->type, prc, fieldofs, 0);
601 if (prc[0] <= 0 || (!r2 && prc[0] > 1)) {
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;602 loadt = vtop->type.t & VT_BTYPE;
608 if (loadt == VT_STRUCT) {603 if (loadt == VT_STRUCT) {
609 loadt = fieldofs[1] & VT_BTYPE;604 loadt = (ii >> 12) & VT_BTYPE;
610 }605 }
611 if (info[nb_args - 1 - i] & 16) {606 if (info[nb_args - 1 - i] & 16) {
612 assert(!r2);607 assert(!r2);
@@ -629,13 +624,13 @@ ST_FUNC void gfunc_call(int nb_args) · 16 unmodified lines
629 vswap();624 vswap();
630 gaddrof();625 gaddrof();
631 vtop->type = char_pointer_type;626 vtop->type = char_pointer_type;
632 vpushi(fieldofs[2] >> 4);627 vpushi(ii >> 20);
633 gen_op('+');628 gen_op('+');
634 indir();629 indir();
635 vtop->type = origtype;630 vtop->type = origtype;
636 loadt = vtop->type.t & VT_BTYPE;631 loadt = vtop->type.t & VT_BTYPE;
637 if (loadt == VT_STRUCT) {632 if (loadt == VT_STRUCT) {
638 loadt = fieldofs[2] & VT_BTYPE;633 loadt = (ii >> 16) & VT_BTYPE;
639 }634 }
640 save_reg_upstack(r2, 1);635 save_reg_upstack(r2, 1);
641 vtop->type.t = loadt;636 vtop->type.t = loadt;
@@ -671,7 +666,7 @@ ST_FUNC void gfunc_prolog(CType *func_type) · 29 unmodified lines
671{666{
672 int i, addr, align, size;667 int i, addr, align, size;
673 int param_addr = 0;668 int param_addr = 0;
674 int aireg, afreg;669 int areg[2];
675 Sym *sym;670 Sym *sym;
676 CType *type;671 CType *type;
677 672
@@ -681,69 +676,51 @@ ST_FUNC void gfunc_prolog(CType *func_type) · 3 unmodified lines
681 func_sub_sp_offset = ind;676 func_sub_sp_offset = ind;
682 ind += 5 * 4;677 ind += 5 * 4;
683 678
684 aireg = afreg = 0;679 areg[0] = 0, areg[1] = 0;
685 addr = 0; // XXX not correct680 addr = 0;
686 /* if the function returns by reference, then add an681 /* if the function returns by reference, then add an
687 implicit pointer parameter */682 implicit pointer parameter */
688 size = type_size(&func_vt, &align);683 size = type_size(&func_vt, &align);
689 if (size > 2 * XLEN) {684 if (size > 2 * XLEN) {
690 loc -= 8;685 loc -= 8;
691 func_vc = loc;686 func_vc = loc;
692 ES(0x23, 3, 8, 10 + aireg, loc); // sd a0, loc(s0)687 ES(0x23, 3, 8, 10 + areg[0]++, loc); // sd a0, loc(s0)
693 aireg++;
694 }688 }
695 /* define parameters */689 /* define parameters */
696 while ((sym = sym->next) != NULL) {690 while ((sym = sym->next) != NULL) {
697 int byref = 0;691 int byref = 0;
692 int regcount;
693 int prc[3], fieldofs[3];
698 type = &sym->type;694 type = &sym->type;
699 size = type_size(type, &align);695 size = type_size(type, &align);
700 if (size > 2 * XLEN) {696 if (size > 2 * XLEN) {
701 type = &char_pointer_type;697 type = &char_pointer_type;
702 size = align = byref = 8;698 size = align = byref = 8;
703 }699 }
704 if (size > 2 * XLEN) {700 reg_pass(type, prc, fieldofs, 1);
705 from_stack:701 regcount = prc[0];
702 if (areg[prc[1] - 1] >= 8
703 || (regcount == 2
704 && ((prc[1] == RC_FLOAT && prc[2] == RC_FLOAT && areg[1] >= 7)
705 || (prc[1] != prc[2] && (areg[1] >= 8 || areg[0] >= 8))))) {
706 if (align < XLEN)706 if (align < XLEN)
707 align = XLEN;707 align = XLEN;
708 addr = (addr + align - 1) & -align;708 addr = (addr + align - 1) & -align;
709 param_addr = addr;709 param_addr = addr;
710 addr += size;710 addr += size;
711 } else {711 } else {
712 int regcount, *pareg;
713 int prc[3], fieldofs[3];
714 prc[0] = 0;
715 reg_pass(type, prc, fieldofs, 0);
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);
721 }
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)))
728 goto from_stack;
729 if (size > XLEN)
730 assert(regcount == 2);
731 loc -= regcount * 8; // XXX could reserve only 'size' bytes712 loc -= regcount * 8; // XXX could reserve only 'size' bytes
732 param_addr = loc;713 param_addr = loc;
733 for (i = 0; i < regcount; i++) {714 for (i = 0; i < regcount; i++) {
734 pareg = prc[1+i] == RC_INT ? &aireg : &afreg;715 if (areg[prc[1+i] - 1] >= 8) {
735 if (*pareg >= 8) {
736 assert(i == 1 && regcount == 2 && !(addr & 7));716 assert(i == 1 && regcount == 2 && !(addr & 7));
737 EI(0x03, 3, 5, 8, addr); // ld t0, addr(s0)717 EI(0x03, 3, 5, 8, addr); // ld t0, addr(s0)
738 addr += 8;718 addr += 8;
739 ES(0x23, 3, 8, 5, loc + i*8); // sd t0, loc(s0)719 ES(0x23, 3, 8, 5, loc + i*8); // sd t0, loc(s0)
740 continue;720 } else if (prc[1+i] == RC_FLOAT) {
741 }721 ES(0x27, (size / regcount) == 4 ? 2 : 3, 8, 10 + areg[1]++, loc + (fieldofs[i+1] >> 4)); // fs[wd] FAi, loc(s0)
742 if (pareg == &afreg) {
743 //assert(type->t == VT_FLOAT || type->t == VT_DOUBLE);
744 ES(0x27, (size / regcount) == 4 ? 2 : 3, 8, 10 + afreg++, loc + (fieldofs[i+1] >> 4)); // fs[wd] FAi, loc(s0)
745 } else {722 } else {
746 ES(0x23, 3, 8, 10 + aireg++, loc + i*8); // sd aX, loc(s0) // XXX723 ES(0x23, 3, 8, 10 + areg[0]++, loc + i*8); // sd aX, loc(s0) // XXX
747 }724 }
748 }725 }
749 }726 }
@@ -754,9 +731,9 @@ ST_FUNC void gfunc_prolog(CType *func_type) · 4 unmodified lines
754 func_va_list_ofs = addr;731 func_va_list_ofs = addr;
755 num_va_regs = 0;732 num_va_regs = 0;
756 if (func_type->ref->f.func_type == FUNC_ELLIPSIS) {733 if (func_type->ref->f.func_type == FUNC_ELLIPSIS) {
757 for (; aireg < 8; aireg++) {734 for (; areg[0] < 8; areg[0]++) {
758 num_va_regs++;735 num_va_regs++;
759 ES(0x23, 3, 8, 10 + aireg, -8 + num_va_regs * 8); // sd aX, loc(s0)736 ES(0x23, 3, 8, 10 + areg[0], -8 + num_va_regs * 8); // sd aX, loc(s0)
760 }737 }
761 }738 }
762}739}
@@ -764,22 +741,14 @@ ST_FUNC void gfunc_prolog(CType *func_type) · 1 unmodified line
764ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret,741ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret,
765 int *ret_align, int *regsize)742 int *ret_align, int *regsize)
766{743{
767 int align, size = type_size(vt, &align), infreg, nregs;744 int align, size = type_size(vt, &align), nregs;
768 int prc[3], fieldofs[3];745 int prc[3], fieldofs[3];
769 *ret_align = 1;746 *ret_align = 1;
770 *regsize = 8;747 *regsize = 8;
771 if (size > 16)748 if (size > 16)
772 return 0;749 return 0;
773 prc[0] = 0;750 reg_pass(vt, prc, fieldofs, 1);
774 reg_pass(vt, prc, fieldofs, 0);
775 if (prc[0] <= 0) {
776 prc[0] = (size + 7) >> 3;
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);
780 }
781 nregs = prc[0];751 nregs = prc[0];
782 assert(nregs > 0);
783 if (nregs == 2 && prc[1] != prc[2])752 if (nregs == 2 && prc[1] != prc[2])
784 return -1; /* generic code can't deal with this case */753 return -1; /* generic code can't deal with this case */
785 if (prc[1] == RC_FLOAT) {754 if (prc[1] == RC_FLOAT) {
@@ -792,22 +761,15 @@ ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, · 6 unmodified lines
792ST_FUNC void arch_transfer_ret_regs(int aftercall)761ST_FUNC void arch_transfer_ret_regs(int aftercall)
793{762{
794 int prc[3], fieldofs[3];763 int prc[3], fieldofs[3];
795 prc[0] = 0;764 reg_pass(&vtop->type, prc, fieldofs, 1);
796 reg_pass(&vtop->type, prc, fieldofs, 0);
797 assert(prc[0] == 2 && prc[1] != prc[2] && !(fieldofs[1] >> 4));765 assert(prc[0] == 2 && prc[1] != prc[2] && !(fieldofs[1] >> 4));
798 assert(vtop->r == (VT_LOCAL | VT_LVAL));766 assert(vtop->r == (VT_LOCAL | VT_LVAL));
799 vpushv(vtop);767 vpushv(vtop);
800 vtop->type.t = fieldofs[1] & VT_BTYPE;768 vtop->type.t = fieldofs[1] & VT_BTYPE;
801 if (aftercall)769 (aftercall ? store : load)(prc[1] == RC_INT ? REG_IRET : REG_FRET, vtop);
802 store(prc[1] == RC_INT ? REG_IRET : REG_FRET, vtop);
803 else
804 load(prc[1] == RC_INT ? REG_IRET : REG_FRET, vtop);
805 vtop->c.i += fieldofs[2] >> 4;770 vtop->c.i += fieldofs[2] >> 4;
806 vtop->type.t = fieldofs[2] & VT_BTYPE;771 vtop->type.t = fieldofs[2] & VT_BTYPE;
807 if (aftercall)772 (aftercall ? store : load)(prc[2] == RC_INT ? REG_IRET : REG_FRET, vtop);
808 store(prc[2] == RC_INT ? REG_IRET : REG_FRET, vtop);
809 else
810 load(prc[2] == RC_INT ? REG_IRET : REG_FRET, vtop);
811 vtop--;773 vtop--;
812}774}
813 775
@@ -857,11 +819,6 @@ ST_FUNC void gen_va_start(void) · 43 unmodified lines
857 vset(&char_pointer_type, VT_LOCAL, func_va_list_ofs);819 vset(&char_pointer_type, VT_LOCAL, func_va_list_ofs);
858}820}
859 821
860ST_FUNC void gen_va_arg(CType *t)
861{
862 tcc_error("implement me: %s", __FUNCTION__);
863}
864
865ST_FUNC void gen_fill_nops(int bytes)822ST_FUNC void gen_fill_nops(int bytes)
866{823{
867 if ((bytes & 3))824 if ((bytes & 3))
tcc.h+0−1
@@ -1606,7 +1606,6 @@ ST_FUNC void gen_cvt_sxtw(void); · 1605 unmodified lines
1606ST_FUNC void gen_opl(int op);1606ST_FUNC void gen_opl(int op);
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);
1610ST_FUNC void arch_transfer_ret_regs(int);1609ST_FUNC void arch_transfer_ret_regs(int);
1611#endif1610#endif
1612/* ------------ c67-gen.c ------------ */1611/* ------------ c67-gen.c ------------ */

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