diff options
| author | 2022-08-25 09:06:45 +0200 | |
|---|---|---|
| committer | 2022-08-25 09:06:45 +0200 | |
| commit | d42b0c4c6e69fce63cb16289213eab053a602588 (patch) | |
| tree | 5dabb5594106061ba3fe626996c5392b1052f59a | |
| parent | a39378db8ce05f8ab45b5ae0f3252c0a5322fd70 (diff) | |
eu switch
| -rw-r--r-- | bootstrap/test2.cff | 47 | ||||
| -rw-r--r-- | src/cffc.hff | 2 | ||||
| -rw-r--r-- | src/llvm.cff | 71 | ||||
| -rw-r--r-- | src/parse.cff | 6 | ||||
| -rw-r--r-- | vgcore.7962 | bin | 6991872 -> 0 bytes |
5 files changed, 112 insertions, 14 deletions
diff --git a/bootstrap/test2.cff b/bootstrap/test2.cff index 0c546bb..f5dec29 100644 --- a/bootstrap/test2.cff +++ b/bootstrap/test2.cff @@ -45,5 +45,50 @@ extern fn main() void { x = X + 1 + Y; let const v= Value:None; - v = :Int(1 + x); + switch v { + case None; + case Int i; + i; + case Flo *f; + let x f32 = *f; + } + let t = v.#tag; + let i = v.Int; + // v.#tag++; + + #'outer for let i = 0; i++ < 10; { + printf("%d\n", i); + while #t { + if i < 2 { + continue #'outer; + } + break #'outer; + } + } + + let x = Option<f32>:None; + let x = Option<int>:Some(42); + switch (do x;) { + case None; + printf("x empty\n"); + case Some i; + printf("x by value %d\n", i); + } + switch x { + case None; + printf("x empty\n"); + case Some *i; + printf("x by ptr %d\n", *i); + } + + printf("n %d\n", n.value); + printf("n link %d\n", n.link.value); + + let x Node<f32> = {}; + n->ok(); + x->ok(); + + Bit<i32>:foo(3); + Bit<i64>:foo(3); } + diff --git a/src/cffc.hff b/src/cffc.hff index ca6ebea..d1d423f 100644 --- a/src/cffc.hff +++ b/src/cffc.hff @@ -241,7 +241,7 @@ struct Stmt { Expr Expr, Decl *Decl, ISwitch struct { ex Expr, cs [#]ISwitchCase, f Block }, - EUSwitch struct { ex Expr, cs [#]EUSwitchCase, f Block }, + EUSwitch struct { lvalue bool, ex Expr, cs [#]EUSwitchCase, f Block }, CSwitch struct { cs [#]CSwitchCase, f Block } } } diff --git a/src/llvm.cff b/src/llvm.cff index 9ad67a2..b0111fe 100644 --- a/src/llvm.cff +++ b/src/llvm.cff @@ -243,16 +243,17 @@ fn genaddr(f *Fn, ex *Expr) Value { case :Struct; gen("\t%v = getelementptr %t, %t %v, i32 0, i32 %d\n", addr, lhs.ty.u.Ptr, lhs.ty, lhs, idx); case :Union; - gen("\t%v = bitcast %t %v to %v", addr, lhs.ty, lhs, addr.ty); + gen("\t%v = bitcast %t %v to %t", addr, lhs.ty, lhs, addr.ty); case else - assert(#f, "nyi eunion access"); + let off int = dot.fld.off; + gen("\t%v = getelementptr i8, %t %v, i32 %d\n", addr, lhs.ty, lhs, off); } return addr; case EUTag eex; let lhs = eex.ty->is(:Ptr) ? genexpr(f, eex) : genaddr(f, eex); let addr = mktmp(mkptrtype(ex.ty)); - gen("\t%v = bitcast %t %v to %v", addr, lhs.ty, lhs, addr); + gen("\t%v = bitcast %t %v to %t", addr, lhs.ty, lhs, addr.ty); return addr; case AggIni ini; @@ -906,24 +907,74 @@ fn genstmt(f *Fn, block *Block, st *Stmt) void { gen("ISe%d: ", id); nop(); + case EUSwitch *sw; + static swid int = {}; + let id = swid++; + let exaddr Value #?; + if sw.lvalue { + exaddr = genaddr(f, &sw.ex); + } else { + exaddr = mktmp(mkptrtype(sw.ex.ty)); + gen("\t%v = alloca %t\n", exaddr, exaddr.ty); + let test = genexpr(f, &sw.ex); + gen("\tstore %t %v, %t %v\n", test.ty, test, exaddr.ty, exaddr); + } + let tag = (do + let addr = mktmp(mkptrtype(sw.ex.ty.u.Agg.enumty)); + gen("\t%v = bitcast %t %v to %t\n", addr, exaddr.ty, exaddr, addr.ty); + let tmp = mktmp(sw.ex.ty.u.Agg.enumty); + gen("\t%v = load %t, %t %v\n", tmp, tmp.ty, addr.ty, addr); + tmp; + ); + gen("\tswitch %t %v, label %%ESx%d [ ", tag.ty, tag, id); + foreach (c, i, sw.cs) { + let t = Value{tag.ty, :IImm(c.variant)}; + gen(" %t %v, label %%ES%d.%d ", t.ty, t, id, i); + } + gen(" ]\n"); + foreach (c, i, sw.cs) { + gen("ES%d.%d: ", id, i); + if c.capt { + gen("\t%%%s.%d = alloca %t\n", c.capt, c.captid, c.captty); + let valaddr = mktmp(mkptrtype(c.fld.ty)); + gen("\t%v = getelementptr i8, %t %v, i32 %d\n", valaddr, exaddr.ty, exaddr, as(int)c.fld.off); + if c.captptr { + gen("\tstore %t %v, %t %%%s.%d\n", valaddr.ty, valaddr, mkptrtype(c.captty), c.capt, c.captid); + } else { + let val = mktmp(c.captty); + gen("\t%v = load %t, %t %v\n", val, val.ty, valaddr.ty, valaddr); + gen("\tstore %t %v, %t %%%s.%d\n", val.ty, val, mkptrtype(c.captty), c.capt, c.captid); + } + } + genblock(f, c.t); + gen("\tbr label %%ESe%d\n", id); + } + gen("ESx%d: ", id); + genblock(f, sw.f); + gen("\tbr label %%ESe%d\n", id); + gen("ESe%d: ", id); + nop(); + case else assert(#f, "stmt? %d", st.u.#tag); } } fn genblock(f *Fn, block Block) Option<Value> { - foreach_ptr (st, _, block.sts) { - genstmt(f, &block, st); + let res Option<Value> = :None; + foreach_ptr (st, i, block.sts) { + if i == block.sts.#len - 1 and st.u.#tag == :Expr { + res = :Some(genexpr(f, &st.u.Expr)); + } else { + genstmt(f, &block, st); + } } for let defers = block.defers; defers; defers = defers.next { if defers.blockid == block.id { - let ex = genexpr(f, &defers.ex); - if defers.next == #null { - return :Some(ex); - } + genexpr(f, &defers.ex); } } - return :None; + return res; } struct GloblKey { diff --git a/src/parse.cff b/src/parse.cff index 2611906..2ac15ba 100644 --- a/src/parse.cff +++ b/src/parse.cff @@ -2272,8 +2272,9 @@ fn psteuswitch(P *Parser, loc Loc, test Expr) Stmt { ty = mkptrtype(test.ty.konst ? constify(ty) : ty); } pushenv(P, env); + c.captid = P.varid++; putdecl(P, tok.loc, { - c.capt, tok.loc, .u: :Let { c.captty = ty, :None, #f, P.curfn.id, P.varid++ } + c.capt, tok.loc, .u: :Let { c.captty = ty, :None, #f, P.curfn.id, c.captid } }); } lexexpect(P, ';'); @@ -2281,10 +2282,11 @@ fn psteuswitch(P *Parser, loc Loc, test Expr) Stmt { if c.capt { popenv(P); } + cs->push(c); } - return { loc, :EUSwitch { test, cs->move(P.alloc), f }}; + return { loc, :EUSwitch { islvalue(test), test, cs->move(P.alloc), f }}; } fn pstcswitch(P *Parser, loc Loc) Stmt { diff --git a/vgcore.7962 b/vgcore.7962 Binary files differdeleted file mode 100644 index 3f25c9e..0000000 --- a/vgcore.7962 +++ /dev/null |