| @@ -418,12 +418,15 @@ ST_FUNC void gfunc_call(int nb_args) · 417 unmodified lines |
| 418 | 418 | sv->type.t &= ~VT_ARRAY; // XXX this should be done in tccgen.c |
| 419 | 419 | size = type_size(&sv->type, &align); |
| 420 | 420 | if (size > 16) { |
| 421 | + if (align < XLEN) |
| 422 | + align = XLEN; |
| 421 | 423 | tempspace = (tempspace + align - 1) & -align; |
| 422 | 424 | tempofs = tempspace; |
| 423 | 425 | tempspace += size; |
| 424 | 426 | size = align = 8; |
| 425 | 427 | byref = 1; |
| 426 | | − } else if (size > 8) |
| 428 | + } |
| 429 | + if (size > 8) |
| 427 | 430 | nregs = 2; |
| 428 | 431 | else |
| 429 | 432 | nregs = 1; |
| @@ -447,6 +450,8 @@ ST_FUNC void gfunc_call(int nb_args) · 17 unmodified lines |
| 447 | 450 | } |
| 448 | 451 | } else { |
| 449 | 452 | info[i] = 32; |
| 453 | + if (align < XLEN) |
| 454 | + align = XLEN; |
| 450 | 455 | stack_adj += (size + align - 1) & -align; |
| 451 | 456 | if (!sa) |
| 452 | 457 | force_stack = 1; |
| @@ -478,6 +483,8 @@ ST_FUNC void gfunc_call(int nb_args) · 25 unmodified lines |
| 478 | 483 | size = align = 8; |
| 479 | 484 | } |
| 480 | 485 | if (info[i] & 32) { |
| 486 | + if (align < XLEN) |
| 487 | + align = XLEN; |
| 481 | 488 | /* Once we support offseted regs we can do this: |
| 482 | 489 | vset(&vtop->type, TREG_SP | VT_LVAL, ofs); |
| 483 | 490 | to construct the lvalue for the outgoing stack slot, |
| @@ -537,7 +544,7 @@ ST_FUNC void gfunc_call(int nb_args) · 53 unmodified lines |
| 537 | 544 | EI(0x13, 0, 2, 2, stack_adj + tempspace); // addi sp, sp, adj |
| 538 | 545 | } |
| 539 | 546 | |
| 540 | | −static int func_sub_sp_offset; |
| 547 | +static int func_sub_sp_offset, num_va_regs; |
| 541 | 548 | |
| 542 | 549 | ST_FUNC void gfunc_prolog(CType *func_type) |
| 543 | 550 | { |
| @@ -552,9 +559,6 @@ ST_FUNC void gfunc_prolog(CType *func_type) · 8 unmodified lines |
| 552 | 559 | loc = -16; // for ra and s0 |
| 553 | 560 | func_sub_sp_offset = ind; |
| 554 | 561 | ind += 5 * 4; |
| 555 | | − if (sym->f.func_type == FUNC_ELLIPSIS) { |
| 556 | | − tcc_error("unimp: vararg prologue"); |
| 557 | | − } |
| 558 | 562 | |
| 559 | 563 | aireg = afreg = 0; |
| 560 | 564 | addr = 0; // XXX not correct |
| @@ -569,10 +573,17 @@ ST_FUNC void gfunc_prolog(CType *func_type) · 8 unmodified lines |
| 569 | 573 | } |
| 570 | 574 | /* define parameters */ |
| 571 | 575 | while ((sym = sym->next) != NULL) { |
| 576 | + int byref = 0; |
| 572 | 577 | type = &sym->type; |
| 573 | 578 | size = type_size(type, &align); |
| 579 | + if (size > 2 * XLEN) { |
| 580 | + type = &char_pointer_type; |
| 581 | + size = align = byref = 8; |
| 582 | + } |
| 574 | 583 | if (size > 2 * XLEN) { |
| 575 | 584 | from_stack: |
| 585 | + if (align < XLEN) |
| 586 | + align = XLEN; |
| 576 | 587 | addr = (addr + align - 1) & -align; |
| 577 | 588 | param_addr = addr; |
| 578 | 589 | addr += size; |
| @@ -603,8 +614,16 @@ ST_FUNC void gfunc_prolog(CType *func_type) · 24 unmodified lines |
| 603 | 614 | (*pareg)++; |
| 604 | 615 | } |
| 605 | 616 | } |
| 606 | | − sym_push(sym->v & ~SYM_FIELD, type, |
| 607 | | − VT_LOCAL | lvalue_type(type->t), param_addr); |
| 617 | + sym_push(sym->v & ~SYM_FIELD, &sym->type, |
| 618 | + (byref ? VT_LLOCAL : VT_LOCAL) | lvalue_type(sym->type.t), |
| 619 | + param_addr); |
| 620 | + } |
| 621 | + num_va_regs = 0; |
| 622 | + if (func_type->ref->f.func_type == FUNC_ELLIPSIS) { |
| 623 | + for (; aireg < 8; aireg++) { |
| 624 | + num_va_regs++; |
| 625 | + ES(0x23, 3, 8, 10 + aireg, -8 + num_va_regs * 8); // sd aX, loc(s0) |
| 626 | + } |
| 608 | 627 | } |
| 609 | 628 | } |
| 610 | 629 | |
| @@ -620,7 +639,7 @@ ST_FUNC int gfunc_sret(CType *vt, int variadic, CType *ret, · 9 unmodified lines |
| 620 | 639 | if (size > 16) |
| 621 | 640 | return 0; |
| 622 | 641 | if (size > 8) |
| 623 | | − ret->t = VT_LDOUBLE; |
| 642 | + ret->t = VT_LLONG; |
| 624 | 643 | else if (size > 4) |
| 625 | 644 | ret->t = VT_LLONG; |
| 626 | 645 | else if (size > 2) |
| @@ -660,6 +679,7 @@ ST_FUNC void gfunc_epilog(void) · 33 unmodified lines |
| 660 | 679 | { |
| 661 | 680 | int v, saved_ind, d, large_ofs_ind; |
| 662 | 681 | |
| 682 | + loc = (loc - num_va_regs * 8); |
| 663 | 683 | d = v = (-loc + 15) & -16; |
| 664 | 684 | |
| 665 | 685 | if (v >= (1 << 11)) { |
| @@ -668,13 +688,13 @@ ST_FUNC void gfunc_epilog(void) · 2 unmodified lines |
| 668 | 688 | EI(0x13, 0, 5, 5, (v-16) << 20 >> 20); // addi t0, t0, lo(v) |
| 669 | 689 | o(0x33 | (2 << 7) | (2 << 15) | (5 << 20)); //add sp, sp, t0 |
| 670 | 690 | } |
| 671 | | − EI(0x03, 3, 1, 2, d - 8); // ld ra, v-8(sp) |
| 672 | | − EI(0x03, 3, 8, 2, d - 16); // ld s0, v-16(sp) |
| 691 | + EI(0x03, 3, 1, 2, d - 8 - num_va_regs * 8); // ld ra, v-8(sp) |
| 692 | + EI(0x03, 3, 8, 2, d - 16 - num_va_regs * 8); // ld s0, v-16(sp) |
| 673 | 693 | EI(0x13, 0, 2, 2, d); // addi sp, sp, v |
| 674 | 694 | EI(0x67, 0, 0, 1, 0); // jalr x0, 0(x1), aka ret |
| 675 | 695 | if (v >= (1 << 11)) { |
| 676 | 696 | large_ofs_ind = ind; |
| 677 | | − EI(0x13, 0, 8, 2, d); // addi s0, sp, d |
| 697 | + EI(0x13, 0, 8, 2, d - num_va_regs * 8); // addi s0, sp, d |
| 678 | 698 | o(0x37 | (5 << 7) | ((0x800 + (v-16)) & 0xfffff000)); //lui t0, upper(v) |
| 679 | 699 | EI(0x13, 0, 5, 5, (v-16) << 20 >> 20); // addi t0, t0, lo(v) |
| 680 | 700 | o(0x33 | (2 << 7) | (2 << 15) | (5 << 20) | (0x20 << 25)); //sub sp, sp, t0 |
| @@ -684,10 +704,10 @@ ST_FUNC void gfunc_epilog(void) · 3 unmodified lines |
| 684 | 704 | |
| 685 | 705 | ind = func_sub_sp_offset; |
| 686 | 706 | EI(0x13, 0, 2, 2, -d); // addi sp, sp, -d |
| 687 | | − ES(0x23, 3, 2, 1, d - 8); // sd ra, d-8(sp) |
| 688 | | − ES(0x23, 3, 2, 8, d - 16); // sd s0, d-16(sp) |
| 707 | + ES(0x23, 3, 2, 1, d - 8 - num_va_regs * 8); // sd ra, d-8(sp) |
| 708 | + ES(0x23, 3, 2, 8, d - 16 - num_va_regs * 8); // sd s0, d-16(sp) |
| 689 | 709 | if (v < (1 << 11)) |
| 690 | | − EI(0x13, 0, 8, 2, d); // addi s0, sp, d |
| 710 | + EI(0x13, 0, 8, 2, d - num_va_regs * 8); // addi s0, sp, d |
| 691 | 711 | else |
| 692 | 712 | gjmp_addr(large_ofs_ind); |
| 693 | 713 | if ((ind - func_sub_sp_offset) != 5*4) |