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
433433 }
434434 }
435435
436−static void reg_pass(CType *type, int *rc, int *fieldofs, int ofs)
436+static void reg_pass_rec(CType *type, int *rc, int *fieldofs, int ofs)
437437 {
438438 if ((type->t & VT_BTYPE) == VT_STRUCT) {
439439 Sym *f;
440440 if (type->ref->type.t == VT_UNION)
441441 rc[0] = -1;
442442 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);
444444 } else if (type->t & VT_ARRAY) {
445445 if (type->ref->c < 0 || type->ref->c > 2)
446446 rc[0] = -1;
447447 else {
448448 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);
450450 if (rc[0] > 2 || (rc[0] == 2 && type->ref->c > 1))
451451 rc[0] = -1;
452452 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
465465 rc[0] = -1;
466466 }
467467
468+static 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+
468481 ST_FUNC void gfunc_call(int nb_args)
469482 {
470− int i, align, size, aireg, afreg;
483+ int i, align, size, areg[2];
471484 int info[nb_args ? nb_args : 1];
472485 int stack_adj = 0, tempspace = 0, ofs, splitofs = 0;
473− int force_stack = 0;
474486 SValue *sv;
475487 Sym *sa;
476− aireg = afreg = 0;
488+ areg[0] = 0; /* int arg regs */
489+ areg[1] = 8; /* float arg regs */
477490 sa = vtop[-nb_args].type.ref->next;
478491 for (i = 0; i < nb_args; i++) {
479− int *pareg, nregs, byref = 0, tempofs;
492+ int nregs, byref = 0, tempofs;
480493 int prc[3], fieldofs[3];
481− prc[0] = 0;
482494 sv = &vtop[1 + i - nb_args];
483495 sv->type.t &= ~VT_ARRAY; // XXX this should be done in tccgen.c
484496 size = type_size(&sv->type, &align);
@@ -489,53 +501,43 @@ ST_FUNC void gfunc_call(int nb_args) · 4 unmodified lines
489501 tempofs = tempspace;
490502 tempspace += size;
491503 size = align = 8;
492− byref = 1;
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+ byref = 64 | (tempofs << 7);
504505 }
506+ reg_pass(&sv->type, prc, fieldofs, sa != 0);
505507 if (!sa && align == 2*XLEN && size <= 2*XLEN)
506− aireg = (aireg + 1) & ~1;
508+ areg[0] = (areg[0] + 1) & ~1;
507509 nregs = prc[0];
508− assert(nregs);
509− if (!nregs
510− || (prc[1] == RC_INT && aireg >= 8)
511− || (prc[1] == RC_FLOAT && afreg >= 8)
512− || (nregs == 2 && prc[2] == RC_FLOAT && afreg >= 7)
513− || (nregs == 2 && prc[1] != prc[2] && (afreg >= 8 || aireg >= 8))
514− || force_stack) {
510+ if ((prc[1] == RC_INT && areg[0] >= 8)
511+ || (prc[1] == RC_FLOAT && areg[1] >= 16)
512+ || (nregs == 2 && prc[1] == RC_FLOAT && prc[2] == RC_FLOAT
513+ && areg[1] >= 15)
514+ || (nregs == 2 && prc[1] != prc[2]
515+ && (areg[1] >= 16 || areg[0] >= 8))) {
515516 info[i] = 32;
516517 if (align < XLEN)
517518 align = XLEN;
518519 stack_adj += (size + align - 1) & -align;
519− if (!sa)
520− force_stack = 1;
520+ if (!sa) /* one vararg on stack forces the rest on stack */
521+ areg[0] = 8, areg[1] = 16;
521522 } else {
522− if (prc[1] == RC_FLOAT)
523− info[i] = 8 + afreg++;
524− else
525− info[i] = aireg++;
523+ info[i] = areg[prc[1] - 1]++;
524+ if (!byref)
525+ info[i] |= (fieldofs[1] & VT_BTYPE) << 12;
526+ assert(!(fieldofs[1] >> 4));
526527 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;
528+ if (prc[2] == RC_FLOAT || areg[0] < 8)
529+ info[i] |= (1 + areg[prc[2] - 1]++) << 7;
531530 else {
532531 info[i] |= 16;
533532 stack_adj += 8;
534533 }
534+ if (!byref) {
535+ assert((fieldofs[2] >> 4) < 2048);
536+ info[i] |= fieldofs[2] << (12 + 4); // includes offset
537+ }
535538 }
536539 }
537− if (byref)
538− info[i] |= 64 | (tempofs << 7);
540+ info[i] |= byref;
539541 if (sa)
540542 sa = sa->next;
541543 }
@@ -544,7 +546,7 @@ ST_FUNC void gfunc_call(int nb_args) · 2 unmodified lines
544546 if (stack_adj + tempspace) {
545547 EI(0x13, 0, 2, 2, -(stack_adj + tempspace)); // addi sp, sp, -adj
546548 for (i = ofs = 0; i < nb_args; i++) {
547− if (info[i] >= 32) {
549+ if (info[i] & (64 | 32)) {
548550 vrotb(nb_args - i);
549551 size = type_size(&vtop->type, &align);
550552 if (info[i] & 64) {
@@ -587,26 +589,19 @@ ST_FUNC void gfunc_call(int nb_args) · 36 unmodified lines
587589 }
588590 }
589591 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;
591593 if (!(r & 32)) {
592594 CType origtype;
593− int prc[3], fieldofs[3], loadt;
594− prc[0] = 0;
595+ int loadt;
595596 r &= 15;
596− r2 = r2 & 64 ? 0 : r2 >> 7;
597+ r2 = r2 & 64 ? 0 : (r2 >> 7) & 31;
598+ assert(r2 <= 16);
597599 vrotb(i+1);
598600 origtype = vtop->type;
599601 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− }
607602 loadt = vtop->type.t & VT_BTYPE;
608603 if (loadt == VT_STRUCT) {
609− loadt = fieldofs[1] & VT_BTYPE;
604+ loadt = (ii >> 12) & VT_BTYPE;
610605 }
611606 if (info[nb_args - 1 - i] & 16) {
612607 assert(!r2);
@@ -629,13 +624,13 @@ ST_FUNC void gfunc_call(int nb_args) · 16 unmodified lines
629624 vswap();
630625 gaddrof();
631626 vtop->type = char_pointer_type;
632− vpushi(fieldofs[2] >> 4);
627+ vpushi(ii >> 20);
633628 gen_op('+');
634629 indir();
635630 vtop->type = origtype;
636631 loadt = vtop->type.t & VT_BTYPE;
637632 if (loadt == VT_STRUCT) {
638− loadt = fieldofs[2] & VT_BTYPE;
633+ loadt = (ii >> 16) & VT_BTYPE;
639634 }
640635 save_reg_upstack(r2, 1);
641636 vtop->type.t = loadt;
@@ -671,7 +666,7 @@ ST_FUNC void gfunc_prolog(CType *func_type) · 29 unmodified lines
671666 {
672667 int i, addr, align, size;
673668 int param_addr = 0;
674− int aireg, afreg;
669+ int areg[2];
675670 Sym *sym;
676671 CType *type;
677672
@@ -681,69 +676,51 @@ ST_FUNC void gfunc_prolog(CType *func_type) · 3 unmodified lines
681676 func_sub_sp_offset = ind;
682677 ind += 5 * 4;
683678
684− aireg = afreg = 0;
685− addr = 0; // XXX not correct
679+ areg[0] = 0, areg[1] = 0;
680+ addr = 0;
686681 /* if the function returns by reference, then add an
687682 implicit pointer parameter */
688683 size = type_size(&func_vt, &align);
689684 if (size > 2 * XLEN) {
690685 loc -= 8;
691686 func_vc = loc;
692− ES(0x23, 3, 8, 10 + aireg, loc); // sd a0, loc(s0)
693− aireg++;
687+ ES(0x23, 3, 8, 10 + areg[0]++, loc); // sd a0, loc(s0)
694688 }
695689 /* define parameters */
696690 while ((sym = sym->next) != NULL) {
697691 int byref = 0;
692+ int regcount;
693+ int prc[3], fieldofs[3];
698694 type = &sym->type;
699695 size = type_size(type, &align);
700696 if (size > 2 * XLEN) {
701697 type = &char_pointer_type;
702698 size = align = byref = 8;
703699 }
704− if (size > 2 * XLEN) {
705− from_stack:
700+ reg_pass(type, prc, fieldofs, 1);
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))))) {
706706 if (align < XLEN)
707707 align = XLEN;
708708 addr = (addr + align - 1) & -align;
709709 param_addr = addr;
710710 addr += size;
711711 } 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);
731712 loc -= regcount * 8; // XXX could reserve only 'size' bytes
732713 param_addr = loc;
733714 for (i = 0; i < regcount; i++) {
734− pareg = prc[1+i] == RC_INT ? &aireg : &afreg;
735− if (*pareg >= 8) {
715+ if (areg[prc[1+i] - 1] >= 8) {
736716 assert(i == 1 && regcount == 2 && !(addr & 7));
737717 EI(0x03, 3, 5, 8, addr); // ld t0, addr(s0)
738718 addr += 8;
739719 ES(0x23, 3, 8, 5, loc + i*8); // sd t0, loc(s0)
740− continue;
741− }
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)
720+ } else if (prc[1+i] == RC_FLOAT) {
721+ ES(0x27, (size / regcount) == 4 ? 2 : 3, 8, 10 + areg[1]++, loc + (fieldofs[i+1] >> 4)); // fs[wd] FAi, loc(s0)
745722 } else {
746− ES(0x23, 3, 8, 10 + aireg++, loc + i*8); // sd aX, loc(s0) // XXX
723+ ES(0x23, 3, 8, 10 + areg[0]++, loc + i*8); // sd aX, loc(s0) // XXX
747724 }
748725 }
749726 }
@@ -754,9 +731,9 @@ ST_FUNC void gfunc_prolog(CType *func_type) · 4 unmodified lines
754731 func_va_list_ofs = addr;
755732 num_va_regs = 0;
756733 if (func_type->ref->f.func_type == FUNC_ELLIPSIS) {
757− for (; aireg < 8; aireg++) {
734+ for (; areg[0] < 8; areg[0]++) {
758735 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)
760737 }
761738 }
762739 }
@@ -764,22 +741,14 @@ ST_FUNC void gfunc_prolog(CType *func_type) · 1 unmodified line
764741 ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret,
765742 int *ret_align, int *regsize)
766743 {
767− int align, size = type_size(vt, &align), infreg, nregs;
744+ int align, size = type_size(vt, &align), nregs;
768745 int prc[3], fieldofs[3];
769746 *ret_align = 1;
770747 *regsize = 8;
771748 if (size > 16)
772749 return 0;
773− prc[0] = 0;
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− }
750+ reg_pass(vt, prc, fieldofs, 1);
781751 nregs = prc[0];
782− assert(nregs > 0);
783752 if (nregs == 2 && prc[1] != prc[2])
784753 return -1; /* generic code can't deal with this case */
785754 if (prc[1] == RC_FLOAT) {
@@ -792,22 +761,15 @@ ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, · 6 unmodified lines
792761 ST_FUNC void arch_transfer_ret_regs(int aftercall)
793762 {
794763 int prc[3], fieldofs[3];
795− prc[0] = 0;
796− reg_pass(&vtop->type, prc, fieldofs, 0);
764+ reg_pass(&vtop->type, prc, fieldofs, 1);
797765 assert(prc[0] == 2 && prc[1] != prc[2] && !(fieldofs[1] >> 4));
798766 assert(vtop->r == (VT_LOCAL | VT_LVAL));
799767 vpushv(vtop);
800768 vtop->type.t = fieldofs[1] & VT_BTYPE;
801− if (aftercall)
802− store(prc[1] == RC_INT ? REG_IRET : REG_FRET, vtop);
803− else
804− load(prc[1] == RC_INT ? REG_IRET : REG_FRET, vtop);
769+ (aftercall ? store : load)(prc[1] == RC_INT ? REG_IRET : REG_FRET, vtop);
805770 vtop->c.i += fieldofs[2] >> 4;
806771 vtop->type.t = fieldofs[2] & VT_BTYPE;
807− if (aftercall)
808− store(prc[2] == RC_INT ? REG_IRET : REG_FRET, vtop);
809− else
810− load(prc[2] == RC_INT ? REG_IRET : REG_FRET, vtop);
772+ (aftercall ? store : load)(prc[2] == RC_INT ? REG_IRET : REG_FRET, vtop);
811773 vtop--;
812774 }
813775
@@ -857,11 +819,6 @@ ST_FUNC void gen_va_start(void) · 43 unmodified lines
857819 vset(&char_pointer_type, VT_LOCAL, func_va_list_ofs);
858820 }
859821
860−ST_FUNC void gen_va_arg(CType *t)
861−{
862− tcc_error("implement me: %s", __FUNCTION__);
863−}
864−
865822 ST_FUNC void gen_fill_nops(int bytes)
866823 {
867824 if ((bytes & 3))
tcc.h+0−1
@@ -1606,7 +1606,6 @@ ST_FUNC void gen_cvt_sxtw(void); · 1605 unmodified lines
16061606 ST_FUNC void gen_opl(int op);
16071607 //ST_FUNC void gfunc_return(CType *func_type);
16081608 ST_FUNC void gen_va_start(void);
1609−ST_FUNC void gen_va_arg(CType *t);
16101609 ST_FUNC void arch_transfer_ret_regs(int);
16111610 #endif
16121611 /* ------------ 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