ref: 1fdd688f2589ef64f711bc369e1a54f45c318967
parent: 3b4a60233fe5779548a6f085b4a2496a4537c62c
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Tue Feb 14 10:20:09 EST 2017
[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.
--- a/cc1/cc1.h
+++ b/cc1/cc1.h
@@ -21,6 +21,7 @@
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 @@
OFUN,
OPAR,
OCALL,
+ OCALLE,
ORET,
ODECL,
OBSWITCH,
--- a/cc1/code.c
+++ b/cc1/code.c
@@ -72,6 +72,7 @@
[ORET] = "\th",
[OPAR] = "p",
[OCALL] = "c",
+ [OCALLE] = "z",
[OFIELD] = "."
};
@@ -134,6 +135,7 @@
[OESWITCH] = emitsymid,
[OPAR] = emitbin,
[OCALL] = emitbin,
+ [OCALLE] = emitbin,
[OINIT] = emitinit,
[OBUILTIN] = emitbuilt,
[OTYP] = emittype,
--- a/cc1/expr.c
+++ b/cc1/expr.c
@@ -660,7 +660,7 @@
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 @@
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);
--- a/cc1/types.c
+++ b/cc1/types.c
@@ -298,7 +298,11 @@
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:
--- a/cc2/arch/qbe/arch.h
+++ b/cc2/arch/qbe/arch.h
@@ -135,6 +135,7 @@
ASRET,
ASCALL,
ASCALLE,
+ ASCALLEX,
ASPAR,
ASPARE,
ASALLOC,
--- a/cc2/arch/qbe/cgen.c
+++ b/cc2/arch/qbe/cgen.c
@@ -249,7 +249,7 @@
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 @@
code(op, ret, &aux1, &aux2);
return ret;
case OCALL:
+ case OCALLE:
if (l->op == OPTR)
l = rhs(l, &aux1);
return call(np, l, ret);
--- a/cc2/arch/qbe/code.c
+++ b/cc2/arch/qbe/code.c
@@ -138,7 +138,8 @@
[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 @@
static void
ecall(void)
{
- puts(")");
+ struct opdata *p = &optbl[pc->op];
+
+ puts(p->txt);
}
static void
--- a/cc2/cc2.h
+++ b/cc2/cc2.h
@@ -84,6 +84,7 @@
OASSIG = ':',
OSNEG = '_',
OCALL = 'c',
+ OCALLE = 'z',
OPAR = 'p',
OFIELD = '.',
OCOMMA = ',',
--- a/cc2/parser.c
+++ b/cc2/parser.c
@@ -127,6 +127,7 @@
[':'] = { 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},