scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

commit 1557ce048255aed8b072675b250ecdfd6a0df0ab
parent a84618bba7d82a3c2cd9f96bcf12344199174761
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Fri, 10 Feb 2017 20:00:57 +0100

[cc1] Add support for va_arg builtins

Diffstat:
Mcc1/Makefile | 3++-
Mcc1/arch/amd64-sysv/arch.c | 26+++++++++++++++++++-------
Mcc1/arch/i386-sysv/arch.c | 22++++++++++++++++------
Mcc1/arch/qbe/arch.c | 26+++++++++++++++++++-------
Mcc1/arch/z80/arch.c | 18++++++++++++++----
Acc1/builtin.c | 100+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mcc1/cc1.h | 20+++++++++++++++++++-
Mcc1/code.c | 18++++++++++++++++--
Mcc1/expr.c | 28++++++++++++++++++++++------
Mcc1/main.c | 7+++++++
Mcc1/symbol.c | 20++++++++++++++++++++
11 files changed, 254 insertions(+), 34 deletions(-)

diff --git a/cc1/Makefile b/cc1/Makefile @@ -6,7 +6,8 @@ CSTDINC = -I../inc/$(STD) 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) diff --git a/cc1/arch/amd64-sysv/arch.c b/cc1/arch/amd64-sysv/arch.c @@ -183,13 +183,13 @@ static Type types[] = { .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 @@ Type *voidtype = &types[0], *pvoidtype = &types[1], *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; +} diff --git a/cc1/arch/i386-sysv/arch.c b/cc1/arch/i386-sysv/arch.c @@ -183,13 +183,13 @@ static Type types[] = { .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,11 +203,21 @@ Type *voidtype = &types[0], *pvoidtype = &types[1], *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; +} diff --git a/cc1/arch/qbe/arch.c b/cc1/arch/qbe/arch.c @@ -183,13 +183,13 @@ static Type types[] = { .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 @@ Type *voidtype = &types[0], *pvoidtype = &types[1], *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; +} diff --git a/cc1/arch/z80/arch.c b/cc1/arch/z80/arch.c @@ -187,8 +187,8 @@ static Type types[] = { .op = PTR, .letter = L_POINTER, .prop = TDEFINED, - .size = 8, - .align = 8, + .size = 2, + .align = 1, } }; @@ -202,10 +202,20 @@ Type *voidtype = &types[0], *pvoidtype = &types[1], *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; +} diff --git a/cc1/builtin.c b/cc1/builtin.c @@ -0,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); +} diff --git a/cc1/cc1.h b/cc1/cc1.h @@ -54,6 +54,7 @@ enum ns { L_ARRAY = 'V', L_UNION = 'U', L_STRUCT = 'S', + L_VA_ARG = '1', }; /* recovery points */ @@ -196,6 +197,7 @@ enum tokens { IFNDEF, UNDEF, ENDIF, + BUILTIN, EOFTOK }; @@ -260,6 +262,7 @@ enum op { OBSWITCH, OESWITCH, OINIT, + OBUILTIN, OTYP, }; @@ -283,6 +286,11 @@ struct limits { } min; }; +struct builtin { + char *str; + Node *(*fun)(Symbol *); +}; + struct keyword { char *str; unsigned char token, value; @@ -327,6 +335,7 @@ struct symbol { unsigned char token; Node **init; Symbol **pars; + Node *(*fun)(Symbol *); } u; struct symbol *next; struct symbol *hash; @@ -387,6 +396,7 @@ extern void pushctx(void), popctx(void); 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 *varnode(Symbol *sym); 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 outcpp(void); 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 @@ extern Type *voidtype, *pvoidtype, *booltype, *longtype, *ulongtype, *ullongtype, *llongtype, *floattype, *doubletype, *ldoubletype, - *ellipsistype, *va_list_type; + *ellipsistype, *va_list_type, *va_type; diff --git a/cc1/code.c b/cc1/code.c @@ -17,7 +17,8 @@ static void emitbin(unsigned, void *), 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 @@ void (*opcode[])(unsigned, void *) = { [OPAR] = emitbin, [OCALL] = emitbin, [OINIT] = emitinit, + [OBUILTIN] = emitbuilt, [OTYP] = emittype, }; @@ -430,12 +432,24 @@ emitbin(unsigned op, void *arg) 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) { Node *np = arg; diff --git a/cc1/expr.c b/cc1/expr.c @@ -11,7 +11,7 @@ static char sccsid[] = "@(#) ./cc1/expr.c"; #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 @@ primary(void) { Node *np; Symbol *sym; + Node *(*fun)(Symbol *); sym = yylval.sym; switch (yytoken) { @@ -624,6 +625,15 @@ primary(void) 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 @@ arguments(Node *np) toomany = 0; do { - arg = assign(); + arg = xassign(); argtype = *targs; if (argtype == ellipsistype) { n = 0; @@ -1064,8 +1074,8 @@ ternary(void) return cond; } -Node * -assign(void) +static Node * +xassign(void) { Node *np, *(*fun)(int , Node *, Node *); int op; @@ -1098,15 +1108,21 @@ xexpr(void) { 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 * constexpr(void) { Node *np; diff --git a/cc1/main.c b/cc1/main.c @@ -58,6 +58,7 @@ main(int argc, char *argv[]) ilex(); icpp(); icode(); + ibuilts(); ARGBEGIN { case 'D': @@ -102,6 +103,12 @@ main(int argc, char *argv[]) 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 { diff --git a/cc1/symbol.c b/cc1/symbol.c @@ -296,3 +296,23 @@ keywords(struct keyword *key, int ns) 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; +}