diff options
| author | 2022-08-25 09:06:45 +0200 | |
|---|---|---|
| committer | 2022-08-25 09:06:45 +0200 | |
| commit | d42b0c4c6e69fce63cb16289213eab053a602588 (patch) | |
| tree | 5dabb5594106061ba3fe626996c5392b1052f59a /src/llvm.cff | |
| parent | a39378db8ce05f8ab45b5ae0f3252c0a5322fd70 (diff) | |
eu switch
Diffstat (limited to 'src/llvm.cff')
| -rw-r--r-- | src/llvm.cff | 71 |
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 { |