aboutsummaryrefslogtreecommitdiff
path: root/qbe.c
diff options
context:
space:
mode:
authorMichael Forney <mforney@mforney.org>2021-09-05 12:01:26 -0700
committerMichael Forney <mforney@mforney.org>2021-10-25 10:18:18 -0700
commit9540626e5793583b6feb36d025dc640c7cb97cc8 (patch)
tree348f347f43b764bc08a84f8ed0daef9476864200 /qbe.c
parentb764d2eaff0d2031bbc823bfe1eb76531b3335af (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.c24
1 files changed, 15 insertions, 9 deletions
diff --git a/qbe.c b/qbe.c
index f9a6f08..78a2feb 100644
--- a/qbe.c
+++ b/qbe.c
@@ -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: