diff options
author | Michael Forney <mforney@mforney.org> | 2021-09-05 12:01:26 -0700 |
---|---|---|
committer | Michael Forney <mforney@mforney.org> | 2021-10-25 10:18:18 -0700 |
commit | 9540626e5793583b6feb36d025dc640c7cb97cc8 (patch) | |
tree | 348f347f43b764bc08a84f8ed0daef9476864200 /qbe.c | |
parent | b764d2eaff0d2031bbc823bfe1eb76531b3335af (diff) |
qbe: Use ... to separate named and variadic arguments
This requires a not-yet-upstream QBE patch, and is needed for riscv64
support, since the calling convention may be different depending
on whether the argument is named or variadic.
Diffstat (limited to 'qbe.c')
-rw-r--r-- | qbe.c | 24 |
1 files changed, 15 insertions, 9 deletions
@@ -40,6 +40,7 @@ enum instkind { #undef OP IARG, + IVARARG, }; struct qbetype { @@ -722,7 +723,7 @@ funcexpr(struct func *f, struct expr *e) struct lvalue lval; struct expr *arg; struct block *b[3]; - struct type *t; + struct type *t, *functype; size_t i; switch (e->kind) { @@ -761,7 +762,6 @@ funcexpr(struct func *f, struct expr *e) v = funcstore(f, e->type, e->qual, lval, v); return e->incdec.post ? l : v; case EXPRCALL: - op = e->base->type->base->func.isvararg ? IVACALL : ICALL; argvals = xreallocarray(NULL, e->call.nargs, sizeof(argvals[0])); for (arg = e->call.args, i = 0; arg; arg = arg->next, ++i) { emittype(arg->type); @@ -769,12 +769,15 @@ funcexpr(struct func *f, struct expr *e) } t = e->type; emittype(t); - v = funcinst(f, op, qbetype(t).base, funcexpr(f, e->base), t->value); + v = funcinst(f, ICALL, qbetype(t).base, funcexpr(f, e->base), t->value); + functype = e->base->type->base; for (arg = e->call.args, i = 0; arg; arg = arg->next, ++i) { + if (functype->func.isvararg && i == functype->func.nparam) + funcinst(f, IVARARG, 0, NULL, NULL); t = arg->type; funcinst(f, IARG, qbetype(t).base, argvals[i], t->value); } - //if (e->base->type->base->func.isnoreturn) + //if (functype->func.isnoreturn) // funcret(f, NULL); return v; case EXPRUNARY: @@ -1181,20 +1184,23 @@ emitinst(struct inst **instp, struct inst **instend) op = inst->kind; switch (op) { case ICALL: - case IVACALL: putchar('('); - for (first = 1; instp != instend && (*instp)->kind == IARG; ++instp) { + for (first = 1; instp != instend; ++instp) { + inst = *instp; + if (inst->kind == IVARARG) { + fputs(", ...", stdout); + continue; + } + if (inst->kind != IARG) + break; if (first) first = 0; else fputs(", ", stdout); - inst = *instp; emitclass(inst->class, inst->arg[1]); putchar(' '); emitvalue(inst->arg[0]); } - if (op == IVACALL) - fputs(", ...", stdout); putchar(')'); break; default: |