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