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 | |
| parent | b764d2eaff0d2031bbc823bfe1eb76531b3335af (diff) | |
| download | cproc-9540626e5793583b6feb36d025dc640c7cb97cc8.tar.xz | |
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.
| -rw-r--r-- | cc.h | 1 | ||||
| -rw-r--r-- | decl.c | 2 | ||||
| -rw-r--r-- | ops.h | 1 | ||||
| -rw-r--r-- | qbe.c | 24 | ||||
| -rw-r--r-- | test/float-promote.qbe | 2 | 
5 files changed, 19 insertions, 11 deletions
| @@ -219,6 +219,7 @@ struct type {  		struct {  			_Bool isprototype, isvararg, isnoreturn, paraminfo;  			struct param *params; +			size_t nparam;  		} func;  		struct {  			char *tag; @@ -516,6 +516,7 @@ declaratortypes(struct scope *s, struct list *result, char **name, bool allowabs  			t->func.isvararg = false;  			t->func.isnoreturn = false;  			t->func.params = NULL; +			t->func.nparam = 0;  			p = &t->func.params;  			switch (tok.kind) {  			case TIDENT: @@ -534,6 +535,7 @@ declaratortypes(struct scope *s, struct list *result, char **name, bool allowabs  				for (;;) {  					*p = parameter(s);  					p = &(*p)->next; +					++t->func.nparam;  					if (!consume(TCOMMA))  						break;  					if (consume(TELLIPSIS)) { @@ -93,7 +93,6 @@ OP(ICOPY,    "copy")  /* call */  OP(ICALL,    "call") -OP(IVACALL,  "call")  /* variadic */  OP(IVASTART, "vastart") @@ -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: diff --git a/test/float-promote.qbe b/test/float-promote.qbe index 5dad07c..97638e7 100644 --- a/test/float-promote.qbe +++ b/test/float-promote.qbe @@ -5,7 +5,7 @@ function $f() {  	%.1 =d exts s_1  	call $g1(d %.1)  	%.2 =d exts s_1 -	call $g2(w 0, d %.2, ...) +	call $g2(w 0, ..., d %.2)  	call $g3(s s_1)  	ret  } | 
