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