commit 45e74e1d82c733ea83a2af7b06c2c897ff1df3e9
parent 0289c983456b286aea8fcf95c4a2e9950964317f
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date: Sun, 16 Nov 2014 05:45:24 -0500
Rewrite struct data structures
Type had a special type for fields of structures, and we were looking
in a list of fields each time that a . ir -> were used. This list needed
special routines for everyting. This patch removes this list and use
the symbol hash to storing the fields of structs. It uses a unique hash
for all the fields of all the structs, so it is needed a field in the
symbols to store the namespace.
Diffstat:
7 files changed, 136 insertions(+), 158 deletions(-)
diff --git a/cc1/cc1.h b/cc1/cc1.h
@@ -26,31 +26,26 @@ enum {
NS_IDEN = 0,
NS_TAG,
NS_LABEL,
+ NS_STRUCTS,
NR_NAMESPACES
};
typedef struct ctype Type;
typedef struct symbol Symbol;
-typedef struct field {
- char *name;
- Type *type;
- int id;
- struct field *next;
-} Field;
-
struct ctype {
uint8_t op; /* type builder operator */
+ uint8_t ns;
char letter; /* letter of the type */
bool defined : 1; /* type defined (is not a forward reference) */
bool sign : 1; /* sign type */
struct ctype *type; /* base type */
struct ctype *next; /* next element in the hash */
+ Type **pars; /* type parameters */
union {
unsigned char rank; /* convertion rank */
short elem; /* number of type parameters */
} n;
- void *pars; /* type parameters */
};
@@ -61,6 +56,7 @@ struct symbol {
Type *type;
short id;
uint8_t ctx;
+ uint8_t ns;
uint8_t token;
struct {
bool isglobal : 1;
@@ -68,11 +64,11 @@ struct symbol {
bool isauto : 1;
bool isregister : 1;
bool isdefined : 1;
+ bool isfield : 1;
} s;
union {
int i;
char *s;
- struct symbol *sym;
uint8_t token;
} u;
struct symbol *next;
@@ -90,7 +86,6 @@ extern Symbol
typedef struct caselist Caselist;
extern void compound(Symbol *lbreak, Symbol *lcont, Caselist *lswitch);
-extern Type *aggregate(Type *(*fun)(void));
extern void context(Symbol *lbreak, Symbol *lcont, Caselist *lswitch);
extern Type *typename(void);
@@ -161,7 +156,6 @@ typedef struct node {
Symbol *sym;
Type *type;
char op;
- Field *field;
} u;
struct node *childs[];
} Node;
@@ -191,7 +185,8 @@ extern void
emitswitch(short, Node *), emitcase(Symbol *, Node *),
emitret(Type *tp),
emitfun(Symbol *sym),
- emitdefault(Symbol *);
+ emitdefault(Symbol *),
+ emitstruct(Symbol *sym), emitestruct(void);
extern Node
*node(void (*code)(Node *),
@@ -202,7 +197,7 @@ extern Node
*sizeofcode(Type *tp),
*ternarycode(Node *cond, Node *ifyes, Node *ifno),
*symcode(Symbol *sym),
- *fieldcode(Node *child, struct field *fp);
+ *fieldcode(Node *child, Symbol *field);
extern void freetree(Node *np);
diff --git a/cc1/code.c b/cc1/code.c
@@ -92,6 +92,8 @@ emitsym2(Symbol *sym)
c = 'G';
else if (sym->s.isregister)
c = 'R';
+ else if (sym->s.isfield)
+ c = 'M';
else
c = 'A';
printf("%c%d", c, sym->id);
@@ -113,6 +115,18 @@ emitconst(Node *np)
}
void
+emitstruct(Symbol *sym)
+{
+ printf("S%d\t(\n", sym->id);
+}
+
+void
+emitestruct(void)
+{
+ puts(")");
+}
+
+void
emitsym(Node *np)
{
putchar('\t');
@@ -280,14 +294,14 @@ emitfield(Node *np)
child = np->childs[0];
(*child->code)(child);
-
- printf("\tM%d", np->u.field->id);
+ putchar('\t');
+ emitsym2(np->u.sym);
}
Node *
-fieldcode(Node *child, struct field *fp)
+fieldcode(Node *child, Symbol *field)
{
- Node *np = node(emitfield, fp->type, FIELD(fp), 1);
+ Node *np = node(emitfield, field->type, SYM(field), 1);
np->childs[0] = child;
return np;
}
diff --git a/cc1/decl.c b/cc1/decl.c
@@ -70,33 +70,33 @@ fundcl(struct dcldata *dp)
}
static Symbol *
-newiden(void)
+newiden(uint8_t ns)
{
Symbol *sym;
extern uint8_t curctx;
- if (yylval.sym && yylval.sym->ctx == curctx)
+ if (yylval.sym && yylval.sym->ctx == curctx && yylval.sym->ns == ns)
error("redeclaration of '%s'", yytext);
- sym = install(yytext, NS_IDEN);
+ sym = install(yytext, ns);
next();
return sym;
}
-static struct dcldata *declarator0(struct dcldata *dp);
+static struct dcldata *declarator0(struct dcldata *dp, uint8_t ns);
static struct dcldata *
-directdcl(struct dcldata *dp)
+directdcl(struct dcldata *dp, uint8_t ns)
{
register Symbol *sym;
if (accept('(')) {
- dp = declarator0(dp);
+ dp = declarator0(dp, ns);
expect(')');
} else {
if (yytoken == IDEN || yytoken == TYPEIDEN)
- sym = newiden();
+ sym = newiden(ns);
else
- sym = install("", NS_IDEN);
+ sym = install("", ns);
dp = queue(dp, IDEN, 0, sym);
}
@@ -110,7 +110,7 @@ directdcl(struct dcldata *dp)
}
static struct dcldata*
-declarator0(struct dcldata *dp)
+declarator0(struct dcldata *dp, uint8_t ns)
{
register uint8_t n;
@@ -119,7 +119,7 @@ declarator0(struct dcldata *dp)
/* nothing */;
}
- dp = directdcl(dp);
+ dp = directdcl(dp, ns);
while (n--)
dp = queue(dp, PTR, 0, NULL);
@@ -128,7 +128,7 @@ declarator0(struct dcldata *dp)
}
static Symbol *
-declarator(Type *tp, int8_t flags)
+declarator(Type *tp, int8_t flags, uint8_t ns)
{
struct dcldata data[NR_DECLARATORS+2];
register struct dcldata *bp;
@@ -136,7 +136,7 @@ declarator(Type *tp, int8_t flags)
memset(data, 0, sizeof(data));
data[NR_DECLARATORS].op = 255;
- for (bp = declarator0(data)-1; bp >= data; --bp) {
+ for (bp = declarator0(data, ns)-1; bp >= data; --bp) {
if (bp->op != IDEN) {
tp = mktype(tp, bp->op, bp->nelem, bp->data);
} else {
@@ -212,7 +212,7 @@ specifier(int8_t *sclass)
if (dcl) {
if (size || sign)
goto invalid_type;
- tp = aggregate(dcl);
+ tp = (*dcl)();
} else {
next();
}
@@ -248,70 +248,11 @@ initializer(Symbol *sym)
return NULL;
}
-/* TODO: bitfields */
-
-static void
-newfield(Type *tp, Symbol *sym)
-{
- register Field *p, *q;
- register char *s, *t;
-
- s = sym->name;
- for (q = p = tp->pars; p; q = p, p = p->next) {
- t = p->name;
- if (*s == *t && !strcmp(s, t))
- error("duplicated fields '%s' and '%s'", s, t);
- if (sym->u.i == p->id)
- error("duplicated enumeration fields '%s' and '%s'",
- s, t);
- }
-
- p = xmalloc(sizeof(*p));
- p->name = xstrdup(s);
- p->next = NULL;
- p->id = sym->id;
- p->type = sym->type;
- if (!q)
- tp->pars= p;
- else
- q->next = p;
-
- return;
-}
-
-static void
-fielddcl(Type *base)
-{
- Type *tp;
- Symbol *sym;
-
- switch (yytoken) {
- case SCLASS:
- error("storage class '%s' in struct/union field", yytext);
- case IDEN: case TYPE: case TYPEIDEN: case TQUALIFIER:
- tp = specifier(NULL);
- case ';':
- break;
- default:
- unexpected();
- }
-
- if (yytoken != ';') {
- do {
- sym = declarator(tp, ID_EXPECTED);
- newfield(base, sym);
- } while (accept(','));
- }
-
- expect(';');
- return;
-}
-
-static Type *
+static Symbol *
newtag(uint8_t tag)
{
register Symbol *sym;
- register Type *tp;
+ static uint8_t ns = NS_STRUCTS;
switch (yytoken) {
case IDEN: case TYPEIDEN:
@@ -323,32 +264,80 @@ newtag(uint8_t tag)
sym = install("", NS_TAG);
break;
}
- if (!sym->type)
+ if (!sym->type) {
+ if (ns == NS_STRUCTS + NR_MAXSTRUCTS)
+ error("too much tags declared");
sym->type = mktype(NULL, tag, 0, NULL);
- tp = sym->type;
- if (tp->op != tag)
+ sym->type->ns = ns++;
+ }
+
+ if (sym->type->op != tag)
error("'%s' defined as wrong kind of tag", yytext);
- return tp;
+ return sym;
}
+/* TODO: bitfields */
+
static Type *
structdcl(void)
{
- Type *tp;
- uint8_t tag;
+ Type *tagtype, *buff[NR_MAXSTRUCTS], **bp = &buff[0];
+ Symbol *tagsym, *sym;
+ uint8_t tag, n;
+ size_t siz;
tag = yylval.token;
next();
- tp = newtag(tag);
- if (accept('{')) {
- if (tp->defined)
- error("redefinition of struct/union '%s'", yytext);
- tp->defined = 1;
- while (!accept('}'))
- fielddcl(tp);
+ tagsym = newtag(tag);
+ tagtype = tagsym->type;
+ if (!accept('{'))
+ return tagtype;
+
+ if (tagtype->defined)
+ error("redefinition of struct/union '%s'", yytext);
+ tagtype->defined = 1;
+ emitstruct(tagsym);
+
+ while (!accept('}')) {
+ Type *base, *tp;
+
+ switch (yytoken) {
+ case SCLASS:
+ error("storage class '%s' in struct/union field",
+ yytext);
+ case IDEN: case TYPE: case TYPEIDEN: case TQUALIFIER:
+ base = specifier(NULL);
+ break;
+ case ';':
+ next();
+ continue;
+ default:
+ unexpected();
+ }
+
+ if (accept(';'))
+ error("identifier expected");
+
+ do {
+ sym = declarator(base, ID_EXPECTED, tagtype->ns);
+ sym->s.isfield = 1;
+ tp = sym->type;
+ if (tp->op == FTN)
+ error("invalid type in struct/union");
+ if (bp == &buff[NR_MAXSTRUCTS])
+ error("too much fields in struct/union");
+ *bp++ = sym->type;
+ emitdcl(sym);
+ } while (accept(','));
+ expect(';');
}
- return tp;
+ emitestruct();
+ n = bp - buff - 1;
+ siz = sizeof(Type *) * n;
+ tagtype->n.elem = n;
+ tagtype->pars = memcpy(xmalloc(siz), buff, siz);
+ return tagtype;
}
static Type *
@@ -359,7 +348,8 @@ enumdcl(void)
int val = 0;
next();
- tp = newtag(ENUM);
+ tp = newtag(ENUM)->type;
+
if (yytoken == ';')
return tp;
@@ -370,12 +360,11 @@ enumdcl(void)
while (yytoken != '}') {
if (yytoken != IDEN)
unexpected();
- sym = newiden();
+ sym = newiden(NS_IDEN);
sym->type = inttype;
if (accept('='))
initializer(sym);
sym->u.i = val++;
- newfield(tp, sym);
if (!accept(','))
break;
}
@@ -393,7 +382,7 @@ parameter(void)
if ((tp = specifier(&sclass)) == voidtype)
return tp;
- sym = declarator(tp, ID_ACCEPTED);
+ sym = declarator(tp, ID_ACCEPTED, NS_IDEN);
sym->s.isdefined = 1;
/* TODO: check type of the parameter */
switch (sclass) {
@@ -421,7 +410,7 @@ decl(void)
return;
do {
- sym = declarator(tp, ID_EXPECTED);
+ sym = declarator(tp, ID_EXPECTED, NS_IDEN);
sym->s.isdefined = 1;
isfun = sym->type->op == FTN;
@@ -470,7 +459,7 @@ typename(void)
tp = specifier(&sclass);
if (sclass)
error("class storage in type name");
- sym = declarator(tp, ID_FORBIDDEN);
+ sym = declarator(tp, ID_FORBIDDEN, NS_IDEN);
return sym->type;
}
@@ -488,7 +477,7 @@ extdecl(void)
if (accept(';'))
return;
do {
- sym = declarator(base, ID_EXPECTED);
+ sym = declarator(base, ID_EXPECTED, NS_IDEN);
tp = sym->type;
sym->s.isstatic = 1;
sym->s.isglobal= 1;
diff --git a/cc1/expr.c b/cc1/expr.c
@@ -292,19 +292,20 @@ logic(char op, Node *np1, Node *np2)
static Node *
field(Node *np)
{
- Field *fp;
+ extern uint8_t lex_ns;
+ Symbol *sym;
- if (yytoken != IDEN)
- unexpected();
switch (np->typeop) {
case STRUCT: case UNION:
- for (fp = np->type->pars; fp; fp = fp->next) {
- if (!strcmp(fp->name, yytext)) {
- next();
- return fieldcode(np, fp);
- }
- }
- error("field '%s' not found", yytext);
+ lex_ns = np->type->ns;
+ next();
+ if (yytoken != IDEN)
+ unexpected();
+ if ((sym = yylval.sym) == NULL)
+ error("incorrect field in struct/union");
+ lex_ns = NS_IDEN;
+ next();
+ return fieldcode(np, sym);
default:
error("struct or union expected");
}
@@ -482,7 +483,6 @@ postfix(void)
case INDIR:
np1 = content(OPTR, np1);
case '.':
- next();
np1 = field(np1);
break;
case '(':
diff --git a/cc1/lex.c b/cc1/lex.c
@@ -10,6 +10,7 @@
#include "cc1.h"
static FILE *yyin;
+uint8_t lex_ns = NS_IDEN;
const char *filename;
unsigned linenum;
@@ -202,7 +203,7 @@ iden(void)
*bp = '\0';
ungetc(c, yyin);
- sym = yylval.sym = lookup(yytext, NS_IDEN);
+ sym = yylval.sym = lookup(yytext, lex_ns);
if (!sym || sym->token == IDEN)
return IDEN;
yylval.token = sym->u.token;
diff --git a/cc1/symbol.c b/cc1/symbol.c
@@ -47,18 +47,6 @@ freesyms(uint8_t ns)
}
}
-Type *
-aggregate(Type * (*fun)(void))
-{
- Type *tp;
-
- ++curctx;
- tp = (*fun)();
- --curctx;
- freesyms(NS_IDEN);
- return tp;
-}
-
void
context(Symbol *lbreak, Symbol *lcont, Caselist *lswitch)
{
@@ -67,6 +55,7 @@ context(Symbol *lbreak, Symbol *lcont, Caselist *lswitch)
--curctx;
freesyms(NS_IDEN);
freesyms(NS_TAG);
+ freesyms(NS_STRUCTS);
if (curctx == 0) {
localcnt = 0;
freesyms(NS_LABEL);
@@ -79,9 +68,9 @@ lookup(register char *s, uint8_t ns)
struct symtab *tbl;
register Symbol *sym;
- tbl = &symtab[ns];
+ tbl = &symtab[(ns > NS_STRUCTS) ? NS_STRUCTS : ns];
for (sym = tbl->htab[hash(s)]; sym; sym = sym->hash) {
- if (!strcmp(sym->name, s))
+ if (!strcmp(sym->name, s) && sym->ns == ns)
return sym;
}
@@ -99,8 +88,9 @@ install(char *s, uint8_t ns)
sym->ctx = curctx;
sym->token = IDEN;
sym->id = (curctx) ? ++localcnt : ++globalcnt;
- sym->s.isdefined = 1;
- tbl = &symtab[ns];
+ sym->s.isdefined = 0;
+ sym->ns = ns;
+ tbl = &symtab[(ns > NS_STRUCTS) ? NS_STRUCTS : ns];
sym->next = tbl->head;
tbl->head = sym;
diff --git a/cc1/types.c b/cc1/types.c
@@ -206,6 +206,7 @@ mktype(Type *tp, uint8_t op, short nelem, void *data)
type.letter = letters[op];
type.pars = data;
type.n.elem = nelem;
+ type.ns = 0;
if (op == ARY && nelem == 0 || op == STRUCT || op == UNION)
type.defined = 0;
@@ -236,9 +237,11 @@ eqtype(Type *tp1, Type *tp2)
if (tp1->op != tp2->op || tp1->n.elem != tp2->n.elem)
return 0;
switch (tp1->op) {
+ case ARY:
case PTR:
return eqtype(tp1->type, tp2->type);
- /* TODO: use the same struct for function parameters and fields */
+ case UNION:
+ case STRUCT:
case FTN:
p1 = tp1->pars, p2 = tp2->pars;
for (n = tp1->n.elem; n != 0; --n) {
@@ -246,23 +249,9 @@ eqtype(Type *tp1, Type *tp2)
return 0;
}
return 1;
- case UNION:
- case STRUCT: {
- Field *fp1 = tp1->pars, *fp2 = tp2->pars;
-
- while (fp1 && fp2) {
- if (!eqtype(fp1->type, fp2->type))
- break;
- fp1 = fp1->next;
- fp2 = fp2->next;
- }
- return fp1 == fp2;
- }
- case ARY:
- if (!eqtype(tp1->type, tp2->type))
- return 0;
- return 1;
- case ENUM: case INT: case FLOAT:
+ case ENUM:
+ /* TODO: Check when two enum are the same type */
+ case INT: case FLOAT:
return tp1->letter == tp2->letter;
default:
fputs("internal type error, aborting\n", stderr);