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:
M | decl.c | | | 65 | ++++++++++++++++++++++++++++++++++++++++++++++++++--------------- |
A | machine.h | | | 16 | ++++++++++++++++ |
M | symbol.h | | | 15 | ++++++++++++--- |
M | 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);