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;
+}