shithub: scc

Download patch

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},