scc

simple C compiler
git clone git://git.2f30.org/scc
Log | Files | Refs | README | LICENSE

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:
Mcc1/cc1.h | 2++
Mcc1/code.c | 2++
Mcc1/expr.c | 5+++--
Mcc1/types.c | 4++++
Mcc2/arch/qbe/arch.h | 1+
Mcc2/arch/qbe/cgen.c | 3++-
Mcc2/arch/qbe/code.c | 7+++++--
Mcc2/cc2.h | 1+
Mcc2/parser.c | 1+
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},