scc

Simple C99 Compiler
Log | Files | Refs | README | LICENSE

commit 40566c3a7324fdb0e23dcee2e207c630f4460098
parent b2ce2879bce1b20bd28c99ca44d0dd46d50078aa
Author: Roberto E. Vargas Caballero <k0ga@shike2.com>
Date:   Mon, 17 Mar 2014 19:56:44 +0100

Add struct/union fields and calculate offset of every field

Diffstat:
decl.c | 65++++++++++++++++++++++++++++++++++++++++++++++++++---------------
machine.h | 16++++++++++++++++
symbol.h | 15++++++++++++---
types.c | 15+++------------
4 files changed, 81 insertions(+), 30 deletions(-)

diff --git a/decl.c b/decl.c @@ -8,6 +8,7 @@ #include "tokens.h" #include "syntax.h" #include "symbol.h" +#include "machine.h" int8_t forbid_eof; @@ -251,12 +252,48 @@ initializer(register struct ctype *tp) /* TODO: add define for the 3 parameter of declarator */ /* TODO: bitfields */ -static short -fielddcl(uint8_t ns, uint8_t type) + +static void +newfield(struct ctype *tp, struct symbol *sym) +{ + struct field *p, *q; + short size, offset; + char *s, *t; + + s = sym->name; + for (q = p = tp->u.fields; p; q = p, p = p->next) { + t = p->sym->name; + if (*s == *t && !strcmp(s, t)) + error("duplicated field '%s'", s); + } + + p = xmalloc(sizeof(*p)); + p->next = NULL; + p->sym = sym; + size = sym->type->size; + if (!q) { + tp->u.fields = p; + tp->size = size; + sym->u.offset = 0; + } else { + q->next = p; + if (tp->op == STRUCT) { + offset = ALIGN(size, tp->size); + sym->u.offset = offset; + tp->size = offset + size; + } else { + sym->u.offset = 0; + if (tp->size < size) + tp->size = size; + } + } +} + +static void +fielddcl(struct ctype *base, uint8_t ns) { struct ctype *tp; struct symbol *sym; - short offset = 0, size; switch (yytoken) { case IDEN: @@ -278,23 +315,18 @@ fielddcl(uint8_t ns, uint8_t type) if (yytoken != ';') { do { sym = declarator(tp, ns, 1); - sym->u.offset = offset; - size = sym->type->size; - if (type == STRUCT) - offset += size; - else if (offset < size) - offset = size; + newfield(tp, sym); } while (accept(',')); } expect(';'); - return offset; } static struct ctype * newtag(uint8_t tag) { register struct symbol *sym; + struct ctype *tp; extern uint8_t namespace; if (yytoken == IDEN) { @@ -309,8 +341,10 @@ newtag(uint8_t tag) } else { sym = install(NULL, NS_TAG); } - ++namespace; - return sym->type = mktype(NULL, tag, NULL, 0); + tp = sym->type = mktype(NULL, tag, NULL, 0); + sym->u.ns = ++namespace; + tp->sym = sym; + return tp; bad_tag: error("'%s' defined as wrong kind of tag", yytext); @@ -320,17 +354,18 @@ static struct ctype * structdcl(uint8_t tag) { struct ctype *tp; - short size = 0; + uint8_t ns; tp = newtag(tag); + tp->u.fields = NULL; + ns = tp->sym->u.ns; if (yytoken != ';') { expect('{'); if (tp->defined) goto redefined; tp->defined = 1; while (!accept('}')) - size = fielddcl(namespace, tag);/* TODO: check duplicated */ - tp->size = size; + fielddcl(tp, ns); } return tp; diff --git a/machine.h b/machine.h @@ -0,0 +1,16 @@ + +#ifndef MACHINE_H_ +#define MACHINE_H_ + +#define ALIGN(size, offset) ((size) + (offset)) +#define PTRSIZE 2 +#define CHARSIZE 1 +#define SHORTSIZE 2 +#define INTSIZE 2 +#define LONGSIZE 4 +#define LLONGSIZE 8 +#define FLOATSIZE 4 +#define LFLOATSIZE 8 +#define LLFLOATSIZE 16 + +#endif diff --git a/symbol.h b/symbol.h @@ -30,12 +30,20 @@ struct ctype { struct symbol *sym; /* symbol of the tag identifier */ struct ctype *type; /* base type */ struct ctype *next; /* next element in the hash */ - struct funpars *pars; /* function parameters */ + union { + struct funpar *pars; /* function parameters */ + struct field *fields; /* aggregate fields */ + } u; +}; + +struct field { + struct symbol *sym; + struct field *next; }; -struct funpars { +struct funpar { struct ctype *type; - struct funpars *next; + struct funpar *next; }; struct symbol { @@ -47,6 +55,7 @@ struct symbol { union { char c; int i; + uint8_t ns; short offset; } u; struct symbol *next; diff --git a/types.c b/types.c @@ -7,17 +7,9 @@ #include "cc.h" #include "tokens.h" #include "symbol.h" +#include "machine.h" #define NR_TYPE_HASH 16 -#define PTRSIZE 2 -#define CHARSIZE 1 -#define SHORTSIZE 2 -#define INTSIZE 2 -#define LONGSIZE 4 -#define LLONGSIZE 8 -#define FLOATSIZE 4 -#define LFLOATSIZE 8 -#define LLFLOATSIZE 16 struct ctype *voidtype = &(struct ctype) { @@ -185,7 +177,6 @@ mktype(struct ctype *tp, uint8_t op, bp->op = op; bp->nelem = nelem; bp->sym = sym; - bp->pars = NULL; bp->size = size; return *tbl = bp; } @@ -210,7 +201,7 @@ static void ptype(struct ctype *tp) { uint8_t op; - struct funpars *fp; + struct funpar *fp; if (!tp) return; @@ -241,7 +232,7 @@ ptype(struct ctype *tp) break; case FTN: fputs("function(", stdout); - for (fp = tp->pars; fp; fp = fp->next) { + for (fp = tp->u.pars; fp; fp = fp->next) { ptype(tp); if (fp->next) fputs(", ", stdout);