scc

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

commit bc8deaccc553b9709ee43dffbaa9580adf28e9fa
parent 35755ad1c9f5cbba9db0ef500d20f73ce654c3c7
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Tue, 13 Dec 2016 09:20:08 +0100

[cc1] Rewrite mktype()

This function had several caveats and it was a bit difficult to read.
With this new version is clearer that struct, enum and unions are not
hashed and the flow is more linear.

Diffstat:
Mcc1/types.c | 96+++++++++++++++++++++++++++++++++++++++++--------------------------------------
1 file changed, 50 insertions(+), 46 deletions(-)

diff --git a/cc1/types.c b/cc1/types.c @@ -252,95 +252,99 @@ typesize(Type *tp) } } +static Type * +newtype(Type *base) +{ + Type *tp; + + tp = xmalloc(sizeof(*tp)); + *tp = *base; + tp->id = newid(); + if (curctx > GLOBALCTX+1) { + /* it is a type defined in the body of a function */ + tp->next = localtypes; + localtypes = tp; + } + if (tp->prop & TDEFINED) + typesize(tp); + tp->h_next = tp->h_prev = tp; + return tp; +} + Type * mktype(Type *tp, int op, TINT nelem, Type *pars[]) { Type *tbl, *h_next, type; unsigned t; Type *bp; - int c, k_r = 0; if (op == PTR && tp == voidtype) return pvoidtype; - if (op == KRFTN) { - k_r = 1; - op = FTN; - } - switch (op) { - case PTR: c = L_POINTER; break; - case ARY: c = L_ARRAY; break; - case FTN: c = L_FUNCTION; break; - case ENUM: c = inttype->letter; break; - case STRUCT: c = L_STRUCT; break; - case UNION: c = L_UNION; break; - } - memset(&type, 0, sizeof(type)); type.type = tp; type.op = op; - type.prop = k_r ? TK_R : 0; - type.letter = c; + type.prop = 0; type.p.pars = pars; type.n.elem = nelem; type.ns = 0; switch (op) { case ARY: - if (nelem == 0) - break; - /* PASSTROUGH */ + type.letter = L_ARRAY; + if (nelem != 0) + type.prop |= TDEFINED; + break; + case KRFTN: + type.prop |= TK_R; + type.op = FTN; case FTN: + type.letter = L_FUNCTION; + type.prop |= TDEFINED; + break; case PTR: + type.letter = L_POINTER; type.prop |= TDEFINED; break; case ENUM: + type.letter = inttype->letter; type.prop |= TPRINTED | TINTEGER | TARITH; type.n.rank = inttype->n.rank; - break; + goto create_type; case STRUCT: + type.letter = L_STRUCT; + type.prop |= TAGGREG; + goto create_type; case UNION: + type.letter = L_UNION; type.prop |= TAGGREG; - break; + create_type: + return newtype(&type); default: abort(); } - t = (op ^ (uintptr_t) tp>>3) & NR_TYPE_HASH-1; + t = (type.op ^ (uintptr_t) tp>>3) & NR_TYPE_HASH-1; tbl = &typetab[t]; - if (op != STRUCT && op != UNION && op != ENUM) { - for (bp = tbl; bp->h_next != tbl; bp = bp->h_next) { - if (eqtype(bp, &type, 0)) { - /* - * pars was allocated by the caller - * but the type already exists, so - * we have to deallocte it - */ - free(pars); - return bp; - } + for (bp = tbl; bp->h_next != tbl; bp = bp->h_next) { + if (eqtype(bp, &type, 0)) { + /* + * pars was allocated by the caller + * but the type already exists, so + * we have to deallocte it + */ + free(pars); + return bp; } } - if (type.prop & TDEFINED) - typesize(&type); - bp = xmalloc(sizeof(*bp)); - *bp = type; - bp->id = newid(); - - /* insert the new type in the circular double list */ + bp = newtype(&type); h_next = tbl->h_next; bp->h_next = h_next; bp->h_prev = h_next->h_prev; h_next->h_prev = bp; tbl->h_next = bp; - if (curctx > GLOBALCTX+1) { - /* it is a type defined in the body of a function */ - bp->next = localtypes; - localtypes = bp; - } - return bp; }