aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bootstrap/test2.cff47
-rw-r--r--src/cffc.hff2
-rw-r--r--src/llvm.cff71
-rw-r--r--src/parse.cff6
-rw-r--r--vgcore.7962bin6991872 -> 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
deleted file mode 100644
index 3f25c9e..0000000
--- a/vgcore.7962
+++ /dev/null
Binary files differ