aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2022-08-19 08:00:19 +0200
committerlemon <lsof@mailbox.org>2022-08-19 08:00:19 +0200
commit3481ab142293bd82fdd59e3ec86dd66352e457c3 (patch)
treea22bfef6fc5ce7b310ca5752b0765775d5bc921a
parentc82ffed2326500d1df4058cf629f341190b84b89 (diff)
enum union size,align and enumty
-rw-r--r--bootstrap/test.cff6
-rw-r--r--src/cffc.hff1
-rw-r--r--src/parse.cff63
3 files changed, 59 insertions, 11 deletions
diff --git a/bootstrap/test.cff b/bootstrap/test.cff
index ef0bbfb..31dfd6b 100644
--- a/bootstrap/test.cff
+++ b/bootstrap/test.cff
@@ -76,6 +76,12 @@ defmacro transmute(Type, x) [
)
]
+enum union Number {
+ none,
+ int i64,
+ flo f32,
+}
+
extern fn main (argc int, argv **u8) int {
let colors [3]Color = { :Red, :Green, :Blue } ;
diff --git a/src/cffc.hff b/src/cffc.hff
index af5bd6a..eff95e4 100644
--- a/src/cffc.hff
+++ b/src/cffc.hff
@@ -100,6 +100,7 @@ struct Type {
name *const u8,
id int,
fwd bool,
+ enumty *const Type,
flds [#]AggField,
decls *Env,
},
diff --git a/src/parse.cff b/src/parse.cff
index 1449eab..84df71a 100644
--- a/src/parse.cff
+++ b/src/parse.cff
@@ -692,14 +692,25 @@ fn parseagg(P *Parser, kind AggKind, name *const u8, retdecl **Decl) *const Type
let size = 0, align = 1;
let flds Vec<AggField> = {};
let havedecls = #f;
- while !lexmatch(P, #null, '}') {
+ let f0align = -1i64;
+ while !lexmatch(P, &tok, '}') {
if isdecltokt(lexpeek(P).t) {
havedecls = #t;
break;
}
let off = size;
- let name = lexexpects(P, :ident, "field name").u.ident;
- let type = parsetype(P);
+ let name = (tok = lexexpects(P, :ident, "field name")).u.ident;
+ let type *const Type = #null;
+
+ if !(kind == :EUnion and lexpeek(P).t == ',') {
+ type = parsetype(P);
+ if f0align < 0 {
+ f0align = type.align;
+ }
+ }
+ if type != #null and !completetype(type) {
+ err(P, tok.loc, "field `%s' is of incomplete type (%t)", name, type);
+ }
if type {
off = ALIGNUP(off, type.align);
align = MAX(align, type.align);
@@ -713,9 +724,39 @@ fn parseagg(P *Parser, kind AggKind, name *const u8, retdecl **Decl) *const Type
break;
}
}
+ size = ALIGNUP(size, align);
ty.size = size;
ty.align = align;
agg.flds = flds.dat[0::flds.len];
+ if kind == :EUnion {
+ // add enum tag field on top and offset every other field down
+ static id int = 0;
+ let enumty Type = { .u: :Enum { #null, name, .id: --id }};
+ let n = flds.len;
+ enumty.u.Enum.vals = (as(*EnumVal)malloc(n * sizeof EnumVal))[0::n];
+ if n < 256 {
+ enumty.u.Enum.intty = ty_u8;
+ } else if n < 65536 {
+ enumty.u.Enum.intty = ty_u16;
+ } else { assert(#f, "wow"); }
+ enumty.size = enumty.u.Enum.intty.size;
+ enumty.align = enumty.u.Enum.intty.align;
+ vec_each(fld, i, flds) {
+ let ev = &enumty.u.Enum.vals[i];
+ ev.name = fld.name;
+ ev.i = i;
+ }
+ agg.enumty = interntype(enumty);
+
+ let off = f0align < 0 ? 0z : ALIGNUP(enumty.size, f0align);
+ ty.size += off;
+ align = MAX(align, enumty.align);
+ ty.size = ALIGNUP(ty.size, align);
+
+ foreach_ptr(fld, _, agg.flds) {
+ fld.off += off;
+ }
+ }
if havedecls {
agg.decls = mkenv(P.curenv, P.alloc);
pushenv(P, agg.decls);
@@ -1758,9 +1799,9 @@ fn pstwhile(P *Parser) Stmt {
}
lexexpect(P, '{');
let t [#]Stmt #?;
- with_tmpchange(P.curloop, ++P.loopid,
+ with_tmpchange(P.curloop, ++P.loopid) {
t = parseblock(P);
- )
+ }
return { loc, :While { test, t, P.loopid }};
}
@@ -1799,9 +1840,9 @@ fn pstfor(P *Parser) Stmt {
lexexpect(P, '{');
}
let body [#]Stmt #?;
- with_tmpchange(P.curloop, ++P.loopid,
+ with_tmpchange(P.curloop, ++P.loopid) {
body = parseblock(P);
- )
+ }
return { loc, :For { ini, test, next, body, P.loopid }};
}
@@ -2040,8 +2081,8 @@ fn parsefn(P *Parser, externp bool, name *const u8) *Decl {
return decl;
}
- with_tmpchange(P.alloc, &Allocator { &Arena {}, &Arena:allocf },
- with_tmpchange(P.curfn, Fn,
+ with_tmpchange(P.alloc, &Allocator { &Arena {}, &Arena:allocf }) {
+ with_tmpchange(P.curfn, Fn) {
let env = mkenv(P.curenv, P.alloc);
pushenv(P, env);
foreach(name, i, Fn.paramnames) {
@@ -2055,8 +2096,8 @@ fn parsefn(P *Parser, externp bool, name *const u8) *Decl {
popenv(P);
envfree(env);
(as(*Arena)P.alloc.a)->destroy();
- );
- );
+ }
+ }
return decl;
}