aboutsummaryrefslogtreecommitdiff
path: root/src/llvm.cff
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2022-08-25 09:06:45 +0200
committerlemon <lsof@mailbox.org>2022-08-25 09:06:45 +0200
commitd42b0c4c6e69fce63cb16289213eab053a602588 (patch)
tree5dabb5594106061ba3fe626996c5392b1052f59a /src/llvm.cff
parenta39378db8ce05f8ab45b5ae0f3252c0a5322fd70 (diff)
eu switch
Diffstat (limited to 'src/llvm.cff')
-rw-r--r--src/llvm.cff71
1 files changed, 61 insertions, 10 deletions
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 {