shithub: scc

Download patch

ref: 408195a30834d7d539d45ffdc62834aec429478a
parent: 9493bae2f3591649473115922fcc1a6f9b552b1d
author: Roberto E. Vargas Caballero <k0ga@shike2.com>
date: Fri Feb 10 15:00:57 EST 2017

[cc1] Add support for va_arg builtins

--- a/cc1/Makefile
+++ b/cc1/Makefile
@@ -6,7 +6,8 @@
 include ../config.mk
 
 OBJS = types.o decl.o lex.o error.o symbol.o main.o expr.o \
-	code.o stmt.o cpp.o fold.o init.o arch/$(ARCH)/arch.o
+       code.o stmt.o cpp.o fold.o init.o builtin.o \
+       arch/$(ARCH)/arch.o
 
 all: cc1-$(ARCH)
 
--- a/cc1/arch/amd64-sysv/arch.c
+++ b/cc1/arch/amd64-sysv/arch.c
@@ -183,13 +183,13 @@
 		.align = 8,
 		.n.rank = RANK_LONG,
 	},
-	{       /* 20 = va_list_type */
-		.op = PTR,
-		.letter = L_POINTER,
+	{      /* 20 = va_type */
+		.op = STRUCT,
+		.letter = L_VA_ARG,
 		.prop = TDEFINED,
-		.size = 8,
+		.size = 24,
 		.align = 8,
-	}
+	},
 };
 
 Type *voidtype = &types[0], *pvoidtype = &types[1],
@@ -202,9 +202,21 @@
      *floattype = &types[14], *doubletype = &types[15],
      *ldoubletype = &types[16],
      *sizettype = &types[17], *pdifftype = &types[19],
-     *ellipsistype = &types[18],
-     *va_list_type = &types[20];
+     *ellipsistype = &types[18], *va_type = &types[20],
+     *va_list_type;
 
 static Symbol dummy0 = {.u.i = 0, .type = &types[9]},
               dummy1 = {.u.i = 1, .type = &types[9]};
 Symbol *zero = &dummy0, *one = &dummy1;
+
+void
+iarch(void)
+{
+	va_list_type = mktype(va_type, ARY, 1, NULL);
+}
+
+int
+valid_va_list(Type *tp)
+{
+	return tp->op == PTR && tp->type == va_type;
+}
--- a/cc1/arch/i386-sysv/arch.c
+++ b/cc1/arch/i386-sysv/arch.c
@@ -183,13 +183,13 @@
 		.align = 4,
 		.n.rank = RANK_INT,
 	},
-	{       /* 20 = va_list_type */
+	{      /* 20 = va_list_type */
 		.op = PTR,
 		.letter = L_POINTER,
 		.prop = TDEFINED,
-		.size = 8,
-		.align = 8,
-	}
+		.size = 4,
+		.align = 4,
+	},
 };
 
 
@@ -203,8 +203,7 @@
      *floattype = &types[14], *doubletype = &types[15],
      *ldoubletype = &types[16],
      *sizettype = &types[17], *pdifftype = &types[19],
-     *ellipsistype = &types[18],
-     *va_list_type = &types[20];
+     *ellipsistype = &types[18], *va_list_type = &types[20];
 
 
 
@@ -211,3 +210,14 @@
 static Symbol dummy0 = {.u.i = 0, .type = &types[9]},
               dummy1 = {.u.i = 1, .type = &types[9]};
 Symbol *zero = &dummy0, *one = &dummy1;
+
+void
+iarch(void)
+{
+}
+
+int
+valid_va_list(Type *tp)
+{
+	return tp == va_list_type;
+}
--- a/cc1/arch/qbe/arch.c
+++ b/cc1/arch/qbe/arch.c
@@ -183,13 +183,13 @@
 		.align = 8,
 		.n.rank = RANK_LONG,
 	},
-	{       /* 20 = va_list_type */
-		.op = PTR,
-		.letter = L_POINTER,
+	{      /* 20 = va_type */
+		.op = STRUCT,
+		.letter = L_VA_ARG,
 		.prop = TDEFINED,
-		.size = 8,
+		.size = 24,
 		.align = 8,
-	}
+	},
 };
 
 Type *voidtype = &types[0], *pvoidtype = &types[1],
@@ -202,9 +202,21 @@
      *floattype = &types[14], *doubletype = &types[15],
      *ldoubletype = &types[16],
      *sizettype = &types[17], *pdifftype = &types[19],
-     *ellipsistype = &types[18],
-     *va_list_type = &types[20];
+     *ellipsistype = &types[18], *va_type = &types[20],
+     *va_list_type;
 
 static Symbol dummy0 = {.u.i = 0, .type = &types[9]},
               dummy1 = {.u.i = 1, .type = &types[9]};
 Symbol *zero = &dummy0, *one = &dummy1;
+
+void
+iarch(void)
+{
+	va_list_type = mktype(va_type, ARY, 1, NULL);
+}
+
+int
+valid_va_list(Type *tp)
+{
+	return tp->op == PTR && tp->type == va_type;
+}
--- a/cc1/arch/z80/arch.c
+++ b/cc1/arch/z80/arch.c
@@ -187,8 +187,8 @@
 		.op = PTR,
 		.letter = L_POINTER,
 		.prop = TDEFINED,
-		.size = 8,
-		.align = 8,
+		.size = 2,
+		.align = 1,
 	}
 };
 
@@ -202,10 +202,20 @@
      *floattype = &types[14], *doubletype = &types[15],
      *ldoubletype = &types[16],
      *sizettype = &types[17], *pdifftype = &types[19],
-     *ellipsistype = &types[18],
-     *va_list_type = &types[20];
+     *ellipsistype = &types[18], *va_list_type = &types[20];
 
 
 static Symbol dummy0 = {.u.i = 0, .type = &types[9]},
               dummy1 = {.u.i = 1, .type = &types[9]};
 Symbol *zero = &dummy0, *one = &dummy1;
+
+void
+iarch(void)
+{
+}
+
+int
+valid_va_list(Type *tp)
+{
+	return tp == va_list_type;
+}
--- /dev/null
+++ b/cc1/builtin.c
@@ -1,0 +1,100 @@
+/* See LICENSE file for copyright and license details. */
+static char sccsid[] = "@(#) ./cc1/builtin.c";
+
+#include <stdio.h>
+
+#include "../inc/cc.h"
+#include "cc1.h"
+
+static Node *
+builtin_va_arg(Symbol *sym)
+{
+	Node *np, *ap;
+	Type *tp;
+
+	ap = assign();
+	expect(',');
+	tp = typename();
+
+	if (!valid_va_list(ap->type)) {
+		errorp("incorrect parameters for va_arg");
+		return constnode(zero);
+	}
+
+	np = node(OBUILTIN, tp, ap, NULL);
+	np->sym = sym;
+	return np;
+}
+
+static Node *
+builtin_va_copy(Symbol *sym)
+{
+	Node *np, *src, *dst;
+
+	dst = assign();
+	expect(',');
+	src = assign();
+
+	if (!valid_va_list(dst->type) || !valid_va_list(src->type)) {
+		errorp("incorrect parameters for va_copy");
+		return constnode(zero);
+	}
+
+	np = node(OBUILTIN, voidtype, dst, src);
+	np->sym = sym;
+	return np;
+}
+
+static Node *
+builtin_va_start(Symbol *sym)
+{
+	Node *np, *ap, *last;
+
+	ap = assign();
+	expect(',');
+	if (yytoken != IDEN)
+		goto error;
+	last = varnode(yylval.sym);
+	next();
+
+	if (!valid_va_list(ap->type))
+		goto error;
+
+	np = node(OBUILTIN, voidtype, ap, last);
+	np->sym = sym;
+	return np;
+
+error:
+	errorp("incorrect parameters for va_start");
+	return constnode(zero);
+}
+
+static Node *
+builtin_va_end(Symbol *sym)
+{
+	Node *ap, *np;
+
+	ap = assign();
+
+	if (!valid_va_list(ap->type)) {
+		errorp("incorrect parameters for va_end");
+		return constnode(zero);
+	}
+
+	np = node(OBUILTIN, voidtype, ap, NULL);
+	np->sym = sym;
+	return np;
+}
+
+void
+ibuilts(void)
+{
+	struct builtin built[] = {
+		{"__builtin_va_arg", builtin_va_arg},
+		{"__builtin_va_copy", builtin_va_copy},
+		{"__builtin_va_start", builtin_va_start},
+		{"__builtin_va_end", builtin_va_end},
+		{NULL}
+	};
+	builtins(built);
+}
--- a/cc1/cc1.h
+++ b/cc1/cc1.h
@@ -54,6 +54,7 @@
 	L_ARRAY     = 'V',
 	L_UNION     = 'U',
 	L_STRUCT    = 'S',
+	L_VA_ARG    = '1',
 };
 
 /* recovery points */
@@ -196,6 +197,7 @@
 	IFNDEF,
 	UNDEF,
 	ENDIF,
+	BUILTIN,
 	EOFTOK
 };
 
@@ -260,6 +262,7 @@
 	OBSWITCH,
 	OESWITCH,
 	OINIT,
+	OBUILTIN,
 	OTYP,
 };
 
@@ -283,6 +286,11 @@
 	} min;
 };
 
+struct builtin {
+	char *str;
+	Node *(*fun)(Symbol *);
+};
+
 struct keyword {
 	char *str;
 	unsigned char token, value;
@@ -327,6 +335,7 @@
 		unsigned char token;
 		Node **init;
 		Symbol **pars;
+		Node *(*fun)(Symbol *);
 	} u;
 	struct symbol *next;
 	struct symbol *hash;
@@ -387,6 +396,7 @@
 extern void killsym(Symbol *sym);
 extern Symbol *newlabel(void);
 extern void keywords(struct keyword *key, int ns);
+extern void builtins(struct builtin *builts);
 extern Symbol *newstring(char *s, size_t len);
 extern unsigned newid(void);
 
@@ -417,6 +427,7 @@
 extern Node *constnode(Symbol *sym);
 extern Node *sizeofnode(Type *tp);
 extern void freetree(Node *np);
+extern void icode(void);
 #define BTYPE(np) ((np)->type->op)
 
 /* fold.c */
@@ -444,6 +455,13 @@
 extern void defdefine(char *macro, char *val, char *source);
 extern void undefmacro(char *s);
 
+/* builtin.c */
+extern void ibuilts(void);
+
+/* arch.c */
+extern void iarch(void);
+extern int valid_va_list(Type *tp);
+
 /*
  * Definition of global variables
  */
@@ -470,4 +488,4 @@
             *longtype,    *ulongtype,
             *ullongtype,  *llongtype,
             *floattype,   *doubletype,  *ldoubletype,
-            *ellipsistype, *va_list_type;
+            *ellipsistype, *va_list_type, *va_type;
--- a/cc1/code.c
+++ b/cc1/code.c
@@ -17,7 +17,8 @@
             emitfun(unsigned, void *),
             emitdcl(unsigned, void *),
             emitinit(unsigned, void *),
-            emittype(unsigned, void *);
+            emittype(unsigned, void *),
+            emitbuilt(unsigned, void *);
 
 char *optxt[] = {
 	[OADD] = "+",
@@ -134,6 +135,7 @@
 	[OPAR] = emitbin,
 	[OCALL] = emitbin,
 	[OINIT] = emitinit,
+	[OBUILTIN] = emitbuilt,
 	[OTYP] = emittype,
 };
 
@@ -430,10 +432,22 @@
 	emitnode(np->left);
 	emitnode(np->right);
 	if ((s = optxt[op]) != NULL)  {      /* do not print in OCOLON case */
-		fprintf(outfp, "\t%s", optxt[op]);
+		fprintf(outfp, "\t%s", s);
 		emitletter(np->type);
 	}
 }
+
+static void
+emitbuilt(unsigned op, void *arg)
+{
+	Node *np = arg;
+
+	emitnode(np->left);
+	emitnode(np->right);
+	fprintf(outfp, "\t\"%s\tk", np->sym->name);
+	emitletter(np->type);
+}
+
 
 static void
 emitexp(unsigned op, void *arg)
--- a/cc1/expr.c
+++ b/cc1/expr.c
@@ -11,7 +11,7 @@
 
 #define XCHG(lp, rp, np) (np = lp, lp = rp, rp = np)
 
-static Node *xexpr(void);
+static Node *xexpr(void), *xassign(void);
 
 int
 cmpnode(Node *np, TUINT val)
@@ -614,6 +614,7 @@
 {
 	Node *np;
 	Symbol *sym;
+	Node *(*fun)(Symbol *);
 
 	sym = yylval.sym;
 	switch (yytoken) {
@@ -624,6 +625,15 @@
 		emit(OINIT, np);
 		np = varnode(sym);
 		break;
+	case BUILTIN:
+		fun = sym->u.fun;
+		next();
+		expect('(');
+		np = (*fun)(sym);
+		expect(')');
+
+		/* do not call to next */
+		return np;
 	case CONSTANT:
 		np = constnode(sym);
 		break;
@@ -675,7 +685,7 @@
 	toomany = 0;
 
 	do {
-		arg = assign();
+		arg = xassign();
 		argtype = *targs;
 		if (argtype == ellipsistype) {
 			n = 0;
@@ -1064,8 +1074,8 @@
 	return cond;
 }
 
-Node *
-assign(void)
+static Node *
+xassign(void)
 {
 	Node *np, *(*fun)(int , Node *, Node *);
 	int op;
@@ -1098,12 +1108,18 @@
 {
 	Node *lp, *rp;
 
-	lp = assign();
+	lp = xassign();
 	while (accept(',')) {
-		rp = assign();
+		rp = xassign();
 		lp = node(OCOMMA, rp->type, lp, rp);
 	}
 	return lp;
+}
+
+Node *
+assign(void)
+{
+	return simplify(xassign());
 }
 
 Node *
--- a/cc1/main.c
+++ b/cc1/main.c
@@ -58,6 +58,7 @@
 	ilex();
 	icpp();
 	icode();
+	ibuilts();
 
 	ARGBEGIN {
 	case 'D':
@@ -102,6 +103,12 @@
 		die("error: failed to open input file '%s': %s",
 		    *argv, strerror(errno));
 	}
+
+	/*
+	 * we cannot initialize types until we have an
+	 * output stream, because we maybe want to emit new types
+	 */
+	iarch();
 	if (onlycpp || onlyheader) {
 		outcpp();
 	} else {
--- a/cc1/symbol.c
+++ b/cc1/symbol.c
@@ -296,3 +296,23 @@
 	counterid = 0;
 	head = NULL;
 }
+
+void
+builtins(struct builtin *built)
+{
+	Symbol *sym;
+	struct builtin *bp;
+
+	for (bp = built; bp->str; ++bp) {
+		sym = linkhash(newsym(NS_KEYWORD, bp->str));
+		sym->token = BUILTIN;
+		sym->u.fun = bp->fun;
+	}
+	/*
+	 * Remove all the predefined symbols from * the symbol list. It
+	 * will make faster some operations. There is no problem of memory
+	 * leakeage because this memory is not ever freed
+	 */
+	counterid = 0;
+	head = NULL;
+}