diff options
author | Quentin Carbonneaux <quentin.carbonneaux@yale.edu> | 2016-08-15 22:59:52 -0700 |
---|---|---|
committer | Quentin Carbonneaux <quentin.carbonneaux@yale.edu> | 2016-08-16 12:54:24 -0700 |
commit | fbbb8e4d78e8b2e9410699fd27af282cc6ddfc4b (patch) | |
tree | ff19ad7b7d03c8ed953e253106fd603dfdf65a76 | |
parent | 3f8af2ba7b8f79bd577ca4f2fef5fb922494042d (diff) | |
download | roux-fbbb8e4d78e8b2e9410699fd27af282cc6ddfc4b.tar.gz |
parse union types
-rw-r--r-- | all.h | 8 | ||||
-rw-r--r-- | parse.c | 163 | ||||
-rw-r--r-- | sysv.c | 11 |
3 files changed, 110 insertions, 72 deletions
diff --git a/all.h b/all.h index 08056c4..b6392e5 100644 --- a/all.h +++ b/all.h @@ -25,6 +25,7 @@ typedef struct Con Con; typedef struct Addr Mem; typedef struct Fn Fn; typedef struct Typ Typ; +typedef struct Seg Seg; typedef struct Dat Dat; enum Reg { @@ -422,8 +423,9 @@ struct Fn { struct Typ { char name[NString]; int dark; - ulong size; int align; + size_t size; + int nunion; struct Seg { enum { @@ -433,8 +435,8 @@ struct Typ { Styp, }; uint type:2; - uint len:30; - } seg[NSeg+1]; + uint len:30; /* index in typ[] for Styp */ + } (*seg)[NSeg+1]; }; struct Dat { diff --git a/parse.c b/parse.c index 38c212e..7afa977 100644 --- a/parse.c +++ b/parse.c @@ -412,20 +412,23 @@ parseref() } static int -parsecls(int *tyn) +findtyp(int i) { - int i; + while (--i >= 0) + if (strcmp(tokval.str, typ[i].name) == 0) + return i; + err("undefined type :%s", tokval.str); +} +static int +parsecls(int *tyn) +{ switch (next()) { default: err("invalid class specifier"); case Ttyp: - for (i=0; i<ntyp; i++) - if (strcmp(tokval.str, typ[i].name) == 0) { - *tyn = i; - return 4; - } - err("undefined type :%s", tokval.str); + *tyn = findtyp(ntyp); + return 4; case Tw: return Kw; case Tl: @@ -788,18 +791,85 @@ parsefn(int export) } static void +parseseg(Seg *seg, Typ *ty, int t) +{ + Typ *ty1; + int n, c, a, al, type; + size_t sz, s; + + n = 0; + sz = 0; + al = ty->align; + while (t != Trbrace) { + type = Sint; + switch (t) { + default: err("invalid type member specifier"); + case Td: type = Sflt; + case Tl: s = 8; a = 3; break; + case Ts: type = Sflt; + case Tw: s = 4; a = 2; break; + case Th: s = 2; a = 1; break; + case Tb: s = 1; a = 0; break; + case Ttyp: + type = Styp; + ty1 = &typ[findtyp(ntyp-1)]; + s = ty1->size; + a = ty1->align; + break; + } + if (a > al) + al = a; + if ((a = sz & (s-1))) { + a = s - a; + if (n < NSeg) { + /* padding segment */ + seg[n].type = Spad; + seg[n].len = a; + n++; + } + } + t = nextnl(); + if (t == Tint) { + c = tokval.num; + t = nextnl(); + } else + c = 1; + sz += a + c*s; + if (type == Styp) + s = ty1 - typ; + for (; c>0 && n<NSeg; c--, n++) { + seg[n].type = type; + seg[n].len = s; + } + if (t != Tcomma) + break; + t = nextnl(); + } + if (t != Trbrace) + err(", or } expected"); + seg[n].type = Sint; + seg[n].len = 0; + a = 1 << al; + sz = (sz + a - 1) & -a; + if (sz >= ty->size) + ty->size = sz; + ty->align = al; +} + +static void parsetyp() { Typ *ty; - int t, n, c, a, al, type; - ulong sz, s; + int t, n, al; if (ntyp >= NTyp) err("too many type definitions"); ty = &typ[ntyp++]; + ty->dark = 0; ty->align = -1; + ty->size = 0; if (nextnl() != Ttyp || nextnl() != Teq) - err("type name, then = expected"); + err("type name and then = expected"); strcpy(ty->name, tokval.str); t = nextnl(); if (t == Talign) { @@ -818,62 +888,23 @@ parsetyp() ty->size = tokval.num; if (ty->align == -1) err("dark types need alignment"); - t = nextnl(); - } else { - ty->dark = 0; - n = 0; - sz = 0; - al = 0; - while (t != Trbrace) { - type = Sint; - switch (t) { - default: err("invalid size specifier %c", tokval.chr); - case Td: type = Sflt; - case Tl: s = 8; a = 3; break; - case Ts: type = Sflt; - case Tw: s = 4; a = 2; break; - case Th: s = 2; a = 1; break; - case Tb: s = 1; a = 0; break; - } - if (a > al) - al = a; - if ((a = sz & (s-1))) { - a = s - a; - if (n < NSeg) { - /* padding segment */ - ty->seg[n].type = Spad; - ty->seg[n].len = a; - n++; - } - } - t = nextnl(); - if (t == Tint) { - c = tokval.num; - t = nextnl(); - } else - c = 1; - sz += a + c*s; - for (; c>0 && n<NSeg; c--, n++) { - ty->seg[n].type = type; - ty->seg[n].len = s; - } - if (t != Tcomma) - break; - t = nextnl(); - } - if (n >= NSeg) - ty->dark = 1; - else - ty->seg[n].len = 0; - if (ty->align == -1) - ty->align = al; - else - al = ty->align; - a = 1 << al; - ty->size = (sz + a - 1) & -a; + if (nextnl() != Trbrace) + err("} expected"); + return; } - if (t != Trbrace) - err(", or } expected"); + n = 0; + ty->seg = vnew(1, sizeof ty->seg[0], emalloc); + if (t == Tlbrace) + do { + if (t != Tlbrace) + err("invalid union member"); + vgrow(&ty->seg, n+1); + parseseg(ty->seg[n++], ty, nextnl()); + t = nextnl(); + } while (t != Trbrace); + else + parseseg(ty->seg[n++], ty, t); + ty->nunion = n; } static void diff --git a/sysv.c b/sysv.c index c8bc730..7e5b819 100644 --- a/sysv.c +++ b/sysv.c @@ -21,6 +21,7 @@ aclass(AClass *a, Typ *t) { int e, s, n, cls; uint sz, al; + Seg *seg; sz = t->size; al = 1u << t->align; @@ -45,11 +46,12 @@ aclass(AClass *a, Typ *t) return; } + seg = t->seg[0]; a->inmem = 0; for (e=0, s=0; e<2; e++) { cls = -1; - for (n=0; n<8 && t->seg[s].len; s++) { - switch (t->seg[s].type) { + for (n=0; n<8 && seg[s].len; s++) { + switch (seg[s].type) { case Spad: /* don't change anything */ break; @@ -60,8 +62,11 @@ aclass(AClass *a, Typ *t) case Sint: cls = Kl; break; + case Styp: + assert(!"todo"); + break; } - n += t->seg[s].len; + n += seg[s].len; } assert(n <= 8); a->cls[e] = cls; |