History

riscv: implement stdarg functions

this also fixes passing of params > 16 bytes. In riscv they aren't passed by value on stack, but via reference (and because callees are allowed to modify by-ref params the caller must allocate an own copy per call). This fixes the stdarg parts of 73_arm.c.

Michael Matz committed 7 years ago

Commit 982de781 parent f44df9d4 files · +61 −15Browse files

Unified · Split

4 files
  1. include/stdarg.h +10 −0
  2. riscv64-gen.c +34 −14
  3. tccgen.c +15 −1
  4. tcctok.h +2 −0
include/stdarg.h+10−0
@@ -63,6 +63,16 @@ typedef struct { · 62 unmodified lines
63#define va_end(ap) ((void)0)63#define va_end(ap) ((void)0)
64#define va_copy(dest, src) ((dest) = (src))64#define va_copy(dest, src) ((dest) = (src))
65 65
66#elif defined __riscv
67#define __va_reg_size (__riscv_xlen >> 3)
68#define _tcc_align(addr,type) (((unsigned long)addr + __alignof__(type) - 1) \
69 & -(__alignof__(type)))
70typedef char *va_list;
71#define va_start __builtin_va_start
72#define va_arg(ap,type) (*(sizeof(type) > (2*__va_reg_size) ? *(type **)((ap += __va_reg_size) - __va_reg_size) : (ap = (va_list)(_tcc_align(ap,type) + (sizeof(type)+__va_reg_size - 1)& -__va_reg_size), (type *)(ap - ((sizeof(type)+ __va_reg_size - 1)& -__va_reg_size)))))
73#define va_copy(dest, src) (dest) = (src)
74#define va_end(ap) ((void)0)
75
66#else /* __i386__ */76#else /* __i386__ */
67typedef char *va_list;77typedef char *va_list;
68/* only correct for i386 */78/* only correct for i386 */
riscv64-gen.c+34−14
@@ -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.c418 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 else431 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, adj544 EI(0x13, 0, 2, 2, stack_adj + tempspace); // addi sp, sp, adj
538}545}
539 546
540static int func_sub_sp_offset;547static int func_sub_sp_offset, num_va_regs;
541 548
542ST_FUNC void gfunc_prolog(CType *func_type)549ST_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 s0559 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 correct564 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, t0689 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, v693 EI(0x13, 0, 2, 2, d); // addi sp, sp, v
674 EI(0x67, 0, 0, 1, 0); // jalr x0, 0(x1), aka ret694 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, d697 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, t0700 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, -d706 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, d710 EI(0x13, 0, 8, 2, d - num_va_regs * 8); // addi s0, sp, d
691 else711 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)
tccgen.c+15−1
@@ -5159,6 +5159,20 @@ ST_FUNC void unary(void) · 5158 unmodified lines
5159 }5159 }
5160 }5160 }
5161 break;5161 break;
5162#ifdef TCC_TARGET_RISCV64
5163 case TOK_builtin_va_start:
5164 parse_builtin_params(0, "ee");
5165 r = vtop->r & VT_VALMASK;
5166 if (r == VT_LLOCAL)
5167 r = VT_LOCAL;
5168 if (r != VT_LOCAL)
5169 tcc_error("__builtin_va_start expects a local variable");
5170 vtop->r = r;
5171 vtop->type = char_pointer_type;
5172 vtop->c.i = 0;
5173 vstore();
5174 break;
5175#endif
5162#ifdef TCC_TARGET_X86_645176#ifdef TCC_TARGET_X86_64
5163#ifdef TCC_TARGET_PE5177#ifdef TCC_TARGET_PE
5164 case TOK_builtin_va_start:5178 case TOK_builtin_va_start:
@@ -5972,7 +5986,7 @@ static void expr_cond(void) · 807 unmodified lines
5972 5986
5973 if (c < 0) {5987 if (c < 0) {
5974 r1 = gv(rc);5988 r1 = gv(rc);
5975 move_reg(r2, r1, type.t);5989 move_reg(r2, r1, islv ? VT_PTR : type.t);
5976 vtop->r = r2;5990 vtop->r = r2;
5977 gsym(tt);5991 gsym(tt);
5978 }5992 }
tcctok.h+2−0
@@ -158,6 +158,8 @@ · 157 unmodified lines
158#elif defined TCC_TARGET_ARM64158#elif defined TCC_TARGET_ARM64
159 DEF(TOK___va_start, "__va_start")159 DEF(TOK___va_start, "__va_start")
160 DEF(TOK___va_arg, "__va_arg")160 DEF(TOK___va_arg, "__va_arg")
161#elif defined TCC_TARGET_RISCV64
162 DEF(TOK_builtin_va_start, "__builtin_va_start")
161#endif163#endif
162 164
163/* pragma */165/* pragma */

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