commit 6ab66ac2cfce3feebebaaa9ad3963abb29a10d1c
parent 94acab63933f1d05f6e7d35dcd3e1dd7bf655d5a
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Tue, 14 Feb 2017 15:20:09 +0100
[cc1-cc2] Differentiate varadic calls
Qbe has a special support for variadic functions, because having this
information saves to Qbe to use eax in all the calls.
Diffstat:
9 files changed, 21 insertions(+), 5 deletions(-)
diff --git a/cc1/cc1.h b/cc1/cc1.h
@@ -21,6 +21,7 @@ enum typeprops {
TARITH = 1 << 3, /* the type is INT, ENUM or FLOAT */
TAGGREG = 1 << 4, /* the type is struct or union */
TK_R = 1 << 5, /* this is a K&R-function */
+ TELLIPSIS= 1 << 6, /* this function has an ellipsis par */
};
enum inputtype {
@@ -257,6 +258,7 @@ enum op {
OFUN,
OPAR,
OCALL,
+ OCALLE,
ORET,
ODECL,
OBSWITCH,
diff --git a/cc1/code.c b/cc1/code.c
@@ -72,6 +72,7 @@ char *optxt[] = {
[ORET] = "\th",
[OPAR] = "p",
[OCALL] = "c",
+ [OCALLE] = "z",
[OFIELD] = "."
};
@@ -134,6 +135,7 @@ void (*opcode[])(unsigned, void *) = {
[OESWITCH] = emitsymid,
[OPAR] = emitbin,
[OCALL] = emitbin,
+ [OCALLE] = emitbin,
[OINIT] = emitinit,
[OBUILTIN] = emitbuilt,
[OTYP] = emittype,
diff --git a/cc1/expr.c b/cc1/expr.c
@@ -660,7 +660,7 @@ primary(void)
static Node *
arguments(Node *np)
{
- int toomany, n;
+ int toomany, n, op;
Node *par = NULL, *arg;
Type *argtype, **targs, *tp = np->type, *rettype;
@@ -721,7 +721,8 @@ no_pars:
if (n > 0 && *targs != ellipsistype)
errorp("too few arguments in function call");
- return node(OCALL, rettype, np, par);
+ op = (tp->prop&TELLIPSIS) ? OCALLE : OCALL;
+ return node(op, rettype, np, par);
}
static Node *unary(int);
diff --git a/cc1/types.c b/cc1/types.c
@@ -298,7 +298,11 @@ mktype(Type *tp, int op, TINT nelem, Type *pars[])
case KRFTN:
type.prop |= TK_R;
type.op = FTN;
+ type.letter = L_FUNCTION;
+ break;
case FTN:
+ if (pars[nelem-1] == ellipsistype)
+ type.prop |= TELLIPSIS;
type.letter = L_FUNCTION;
break;
case PTR:
diff --git a/cc2/arch/qbe/arch.h b/cc2/arch/qbe/arch.h
@@ -135,6 +135,7 @@ enum asmop {
ASRET,
ASCALL,
ASCALLE,
+ ASCALLEX,
ASPAR,
ASPARE,
ASALLOC,
diff --git a/cc2/arch/qbe/cgen.c b/cc2/arch/qbe/cgen.c
@@ -249,7 +249,7 @@ call(Node *np, Node *fun, Node *ret)
tmpnode(&aux, &(*q)->type);
code(op, NULL, *q, &aux);
}
- code(ASCALLE, NULL, NULL, NULL);
+ code((np->op == OCALL) ? ASCALLE : ASCALLEX, NULL, NULL, NULL);
return ret;
}
@@ -535,6 +535,7 @@ rhs(Node *np, Node *ret)
code(op, ret, &aux1, &aux2);
return ret;
case OCALL:
+ case OCALLE:
if (l->op == OPTR)
l = rhs(l, &aux1);
return call(np, l, ret);
diff --git a/cc2/arch/qbe/code.c b/cc2/arch/qbe/code.c
@@ -138,7 +138,8 @@ static struct opdata {
[ASJMP] = {.fun = jmp},
[ASRET] = {.fun = ret},
[ASCALL] = {.fun = call},
- [ASCALLE] = {.fun = ecall},
+ [ASCALLE] = {.fun = ecall, .txt = ")"},
+ [ASCALLEX] = {.fun = ecall, .txt = ", ...)"},
[ASPAR] = {.fun = param, .txt = "%s %s, "},
[ASPARE] = {.fun = param, .txt = "%s %s"},
[ASALLOC] = {.fun = alloc},
@@ -461,7 +462,9 @@ param(void)
static void
ecall(void)
{
- puts(")");
+ struct opdata *p = &optbl[pc->op];
+
+ puts(p->txt);
}
static void
diff --git a/cc2/cc2.h b/cc2/cc2.h
@@ -84,6 +84,7 @@ enum op {
OASSIG = ':',
OSNEG = '_',
OCALL = 'c',
+ OCALLE = 'z',
OPAR = 'p',
OFIELD = '.',
OCOMMA = ',',
diff --git a/cc2/parser.c b/cc2/parser.c
@@ -127,6 +127,7 @@ static struct decoc {
[':'] = { NULL, assign, .u.op = OASSIG},
['?'] = { NULL, ternary, .u.op = OASK},
['c'] = { NULL, call, .u.op = OCALL},
+ ['z'] = { NULL, call, .u.op = OCALLE},
['#'] = { NULL,constant, .u.op = OCONST},