scc

simple C compiler
git clone git://git.2f30.org/scc
Log | Files | Refs | README | LICENSE

commit fd33aabb1f822618a90a1f05ad820f313fff0953
parent 729bca35c55764bb98afccbd790570e5c94b47ed
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Sun,  1 Jul 2012 19:57:06 +0200

Removed type struct

The ctype struct supplant the place of the old struct type, because ctype
has the information about the type qualifiers needed by pointers. This imply
that different variables will share the same ctype struct (pointers will
share the same base type), so it is necessary a reference count system. The
reference count system is implement using the new functions newctype and
delctype.

Diffstat:
Mdecl.c | 32+++++++++++++++++---------------
Msymbol.h | 32++++++++------------------------
Mtypes.c | 138+++++++++++++++++++++++++++++++++++++++++++++----------------------------------
3 files changed, 104 insertions(+), 98 deletions(-)

diff --git a/decl.c b/decl.c @@ -77,16 +77,16 @@ static unsigned char spec(register struct ctype *cp) goto signed_and_unsigned; sign = yytoken; break; - case VOID: case CHAR: case SHORT: case INT: case FLOAT: - case DOUBLE: case LONG: case BOOL: - cp->base = btype(cp->base, yytoken); + case VOID: case CHAR: case SHORT: case INT: + case FLOAT: case DOUBLE: case LONG: case BOOL: + cp->type = btype(cp->type, yytoken); break; case STRUCT: /* TODO */ case UNION: /* TODO */ case ENUM: /* TODO */ default: - if (!cp->base && sign) - cp->base = T_INT; + if (!cp->type && sign) + cp->type = INT; return n; } } @@ -125,18 +125,18 @@ static void declarator(void) pushtype(*bp); } -static unsigned char listdcl(register struct ctype *cp) +static unsigned char listdcl(register struct ctype *tp) { - register struct type *tp; - do { + register struct ctype *new; + declarator(); - tp = decl_type(cp->base); - if (!tp) { + new = decl_type(tp); + if (!new->type) { warning_error(user_opt.implicit_int, "type defaults to 'int' in declaration of '%s'", yytext); - } else if (tp->op == FTN && yytoken == '{') { + } else if (new->type == FTN && yytoken == '{') { compound(); return 0; } @@ -147,12 +147,13 @@ static unsigned char listdcl(register struct ctype *cp) unsigned char decl(void) { - auto struct ctype ctype; + register struct ctype *tp; if (accept(';')) return 1; - memset(&ctype, 0, sizeof(ctype)); - if (!spec(&ctype)) { + tp = newctype(); + + if (!spec(tp)) { if (nested_level != 0) return 0; warning("data definition has no type or storage class"); @@ -160,10 +161,11 @@ unsigned char decl(void) if (yytoken == ';') { warning_error(user_opt.useless_typename, "useless type name in empty declaration"); - } else if (listdcl(&ctype)) { /* in case of not being a function */ + } else if (listdcl(tp)) { /* in case of not being a function */ expect(';'); } + delctype(tp); return 1; } diff --git a/symbol.h b/symbol.h @@ -7,17 +7,6 @@ # include <stdbool.h> #endif -#define T_CHAR (&tschar) -#define T_SHORT (&tshort) -#define T_INT (&tint) -#define T_FLOAT (&tfloat) -#define T_DOUBLE (&tdouble) -#define T_LDOUBLE (&tdouble) -#define T_LONG (&tlong) -#define T_LLONG (&tllong) -#define T_VOID (&tvoid) -#define T_BOOL (&tbool) - enum namespace { NS_IDEN, NS_KEYWORD, @@ -27,6 +16,7 @@ enum namespace { }; struct ctype { + unsigned type : 5; bool c_type : 1; bool c_extern : 1; bool c_static : 1; @@ -36,16 +26,8 @@ struct ctype { bool c_volatile : 1; bool c_restrict : 1; bool c_unsigned : 1; - struct type *base; -}; - -struct type { - unsigned char op; - struct type *base; - - union { - size_t nelem; /* size of array */ - }; + struct ctype *base; + unsigned char refcnt; }; struct symbol { @@ -74,18 +56,20 @@ extern struct type tchar, tshort, tint, tulong, tllong, tvoid, tkeyword; extern struct type tfloat, tdouble, tldouble, tlong; -extern struct type *decl_type(struct type *t); +extern struct ctype *decl_type(struct ctype *t); extern void pushtype(unsigned char mod); -extern struct type *btype(struct type *tp, unsigned char tok); +extern unsigned char btype(unsigned char, unsigned char tok); extern void new_ctx(struct symctx *ctx); extern void del_ctx(void); extern struct symbol *install(const char *s, unsigned char key); extern struct symbol *lookup(char *s, unsigned char key); extern unsigned char hashfun(register const char *s); extern void ctype(struct ctype *cp, unsigned char mod); +extern struct ctype *newctype(void); +extern void delctype(register struct ctype *tp); #ifndef NDEBUG -extern void ptype(register struct type *t); +extern void ptype(register struct ctype *t); #else # define ptype(t) #endif diff --git a/types.c b/types.c @@ -7,32 +7,56 @@ #include "tokens.h" #include "symbol.h" -struct type tschar = {.op = CHAR}; -struct type tshort = {.op = SHORT}; -struct type tint = {.op = INT}; -struct type tfloat = {.op = FLOAT}; -struct type tdouble = {.op = DOUBLE}; -struct type tldouble = {.op = LDOUBLE}; -struct type tlong = {.op = LONG}; -struct type tllong = {.op = LLONG}; -struct type tvoid = {.op = VOID}; -struct type tbool = {.op = BOOL}; static unsigned char stack[NR_DECLARATORS]; static unsigned char *stackp = stack; -static struct type * -mktype(register struct type *base, unsigned char op) +struct ctype *newctype(void) { - register struct type *nt; - assert(op == PTR || op == ARY || op == FTN || - op == VOLATILE || op == RESTRICT || op == CONST); - - nt = xcalloc(sizeof(*base), 1); - nt->op = op; - nt->base = base; - return nt; + register struct ctype *tp = xcalloc(sizeof(tp), 1); + + ++tp->refcnt; + return tp; +} + +void delctype(register struct ctype *tp) +{ + if (--tp->refcnt == 0) { + if (tp->base) + delctype(tp->base); + free(tp); + } +} + +static struct ctype * +mktype(register struct ctype *tp, unsigned char op) +{ + switch (op) { + case PTR: case ARY: case FTN: { + register struct ctype *aux = tp; + + ++tp->refcnt; + tp = newctype(); + tp->type = op; + tp->base = aux; + break; + } + case VOLATILE: + tp->c_volatile = 1; + break; + case RESTRICT: + tp->c_restrict = 1; + break; + case CONST: + tp->c_const = 1; + break; +#ifndef NDEBUG + default: + abort(); +#endif + } + return tp; } void pushtype(unsigned char mod) @@ -42,62 +66,57 @@ void pushtype(unsigned char mod) *stackp++ = mod; } -struct type *decl_type(struct type *t) +struct ctype *decl_type(struct ctype *tp) { while (stackp != stack) - t = mktype(t, *--stackp); - ptype(t); - return t; + tp = mktype(tp, *--stackp); + ptype(tp); + return tp; } -struct type *btype(struct type *tp, unsigned char tok) +unsigned char btype(unsigned char type, unsigned char tok) { switch (tok) { case VOID: - if (tp == NULL) - return T_VOID; + if (!type) + return VOID; break; case BOOL: - if (tp == NULL) - return T_BOOL; + if (!type) + return BOOL; break; case CHAR: - if (tp == NULL) - return T_CHAR; + if (!type) + return CHAR; break; case SHORT: - if (tp == NULL || tp == T_INT) - return T_SHORT; + if (!type || type == INT) + return SHORT; break; case INT: - if (tp == NULL) - return T_INT; - if (tp == T_SHORT) - return T_SHORT; - if (tp == T_LONG) - return T_LONG; + switch (type) { + case 0: return INT; + case SHORT: return INT; + case LONG: return LONG; + } break; case LONG: - if (tp == NULL || tp == T_INT) - return T_LONG; - if (tp == T_LONG) - return T_LLONG; - if (tp == T_DOUBLE) - return T_LDOUBLE; - if (tp == T_LLONG) - error("'long long long' is too long"); - if (tp == T_LDOUBLE) - error("'long long double' is too long"); + switch (type) { + case 0: case INT: return LONG; + case LONG: return LLONG; + case DOUBLE: return LDOUBLE; + case LLONG: case LDOUBLE: error("too much long"); + } break; case FLOAT: - if (tp == NULL) - return T_FLOAT; + if (!type) + return FLOAT; break; case DOUBLE: - if (tp == NULL) - return T_DOUBLE; - if (tp == T_LONG) - return T_LDOUBLE; + if (!type) + return DOUBLE; + if (type == LONG) + return LDOUBLE; break; default: abort(); @@ -171,9 +190,10 @@ duplicated: #ifndef NDEBUG #include <stdio.h> -void ptype(register struct type *t) +void ptype(register struct ctype *tp) { static const char *strings[] = { + [0] = "[no type]", [ARY] = "array of ", [PTR] = "pointer to ", [FTN] = "function that returns ", @@ -190,10 +210,10 @@ void ptype(register struct type *t) [DOUBLE] = "double ", [LDOUBLE] = "long double " }; - assert(t); + assert(tp); - for (; t; t = t->base) - fputs(strings[t->op], stdout); + for (; tp; tp = tp->base) + fputs(strings[tp->type], stdout); putchar('\n'); }