diff options
Diffstat (limited to 'src/llvm.cff')
| -rw-r--r-- | src/llvm.cff | 350 |
1 files changed, 177 insertions, 173 deletions
diff --git a/src/llvm.cff b/src/llvm.cff index 1a7f24a..1e9eb03 100644 --- a/src/llvm.cff +++ b/src/llvm.cff @@ -23,8 +23,6 @@ struct Value { } } -static ty_i1 Type = {}; // dummy - fn gen(fmt *const u8, ...) void; extern fn genagg(ty *const Type) void { let agg = &ty.u.Agg; @@ -80,15 +78,14 @@ extern fn llvm_addtype(ty *const Type) void { } } - fn gendata(ty *const Type, ex *Expr) void; fn gen(fmt *const u8, ...) void { let ap va_list #?; ap->start(fmt); fn pritype(ty *const Type) void { - if ty == &ty_i1 { - gen("i1"); + if ty == #null { + gen("(nil)"); return; } switch ty.u { @@ -139,7 +136,7 @@ fn gen(fmt *const u8, ...) void { case 's'; fprintf(outfp, "%s", ap->arg(*const u8)); case 'S'; - let str = ap->arg([#]const u8); + let str = *ap->arg(*[#]const u8); fputc('"', outfp); foreach(c, _, str) { extern fn isprint(int) int; @@ -162,7 +159,7 @@ fn gen(fmt *const u8, ...) void { case 'z'; fprintf(outfp, "%zu", ap->arg(usize)); case 'v'; - let val = ap->arg(Value); + let val = ap->arg(*const Value); switch val.u { case IImm i; gen("%I", i); case FImm f; gen(val.ty.size == 4 ? "%f" : "%F", f); @@ -194,7 +191,7 @@ fn gen(fmt *const u8, ...) void { } case StrConstRef id; gen("@.str.%d", id); - case StrLit s; + case StrLit *s; gen("c%S", s); case else assert(#f, "value? %d", val.u.#tag); @@ -222,7 +219,7 @@ fn mktmp(ty *const Type) Value { defmacro gentmp(type, ...rest) [ (do let $tmp = mktmp(type); - gen("\t%v = ", $tmp); + gen("\t%v = ", &$tmp); gen(rest); gen("\n"); $tmp; @@ -267,18 +264,18 @@ fn genref(f *Fn, ex *Expr) Ref { switch idx.lhs.ty.u { case Arr arrty; let arr = genref(f, idx.lhs).Addr; - lhs = gentmp(mkptrtype(ex.ty), "getelementptr %t, %t %v, i32 0, i32 0", idx.lhs.ty, arr.ty, arr); + lhs = gentmp(mkptrtype(ex.ty), "getelementptr %t, %t %v, i32 0, i32 0", idx.lhs.ty, arr.ty, &arr); case Ptr; lhs = genexpr(f, idx.lhs); case Slice child; let tmp = genexpr(f, idx.lhs); - lhs = gentmp(mkptrtype(child), "extractvalue %t %v, 0", tmp.ty, tmp); + lhs = gentmp(mkptrtype(child), "extractvalue %t %v, 0", tmp.ty, &tmp); case else; assert(#f, "index"); } let rhs = genexpr(f, idx.rhs); let addr = gentmp(mkptrtype(ex.ty), "getelementptr %t, %t %v, %t %v", - ex.ty, lhs.ty, lhs, rhs.ty, rhs); + ex.ty, lhs.ty, &lhs, rhs.ty, &rhs); return :Addr(addr); case Dot dot; @@ -297,12 +294,12 @@ fn genref(f *Fn, ex *Expr) Ref { switch lhs.ty.u.Ptr.u.Agg.kind { case :Struct; addr = gentmp(ptrty, "getelementptr %t, %t %v, i32 0, i32 %d", - lhs.ty.u.Ptr, lhs.ty, lhs, idx); + lhs.ty.u.Ptr, lhs.ty, &lhs, idx); case :Union; - addr = gentmp(ptrty, "bitcast %t %v to %t", lhs.ty, lhs, ptrty); + addr = gentmp(ptrty, "bitcast %t %v to %t", lhs.ty, &lhs, ptrty); case else let off int = dot.fld.off; - addr = gentmp(ptrty, "getelementptr i8, %t %v, i32 %d", lhs.ty, lhs, off); + addr = gentmp(ptrty, "getelementptr i8, %t %v, i32 %d", lhs.ty, &lhs, off); } return :Addr(addr); @@ -311,7 +308,7 @@ fn genref(f *Fn, ex *Expr) Ref { case EUTag eex; let lhs = eex.ty->is(:Ptr) ? genexpr(f, eex) : genref(f, eex).Addr; - let addr = gentmp(mkptrtype(ex.ty), "bitcast %t %v to %t", lhs.ty, lhs, mkptrtype(ex.ty)); + let addr = gentmp(mkptrtype(ex.ty), "bitcast %t %v to %t", lhs.ty, &lhs, mkptrtype(ex.ty)); return :Addr(addr); case BitRaw ex; @@ -319,37 +316,39 @@ fn genref(f *Fn, ex *Expr) Ref { case AggIni ini; let tmp = gentmp(mkptrtype(ex.ty), "alloca %t", ex.ty); - gen("\tstore %t zeroinitializer, %t %v\n", ex.ty, tmp.ty, tmp); + gen("\tstore %t zeroinitializer, %t %v\n", ex.ty, tmp.ty, &tmp); foreach(fld, i, ini.flds) { let fex = &ini.exs[i]; let ptr = mktmp(mkptrtype(fex.ty)); let idx int = fld - ex.ty.u.Agg.flds.#ptr; switch ex.ty.u.Agg.kind { case :Struct; - gen("\t%v = getelementptr %t, %t %v, i32 0, i32 %d\n", ptr, ex.ty, tmp.ty, tmp, idx); + gen("\t%v = getelementptr %t, %t %v, i32 0, i32 %d\n", &ptr, ex.ty, tmp.ty, &tmp, idx); case :Union; - gen("\t%v = bitcast %t %v to %t\n", ptr, tmp.ty, tmp, ptr.ty); + gen("\t%v = bitcast %t %v to %t\n", &ptr, tmp.ty, &tmp, ptr.ty); } - gen("\tstore %t %v, %t %v\n", fld.ty, convert(f, fld.ty, fex), ptr.ty, ptr); + let it = convert(f, fld.ty, fex); + gen("\tstore %t %v, %t %v\n", fld.ty, &it, ptr.ty, &ptr); } return :Addr(tmp); case ArrIni ini; let ty = mkarrtype(ini.maxn, #f, ex.ty.u.Arr.child); let tmp = gentmp(mkptrtype(ty), "alloca %t", ty); - gen("\tstore %t zeroinitializer, %t %v\n", ty, tmp.ty, tmp); + gen("\tstore %t zeroinitializer, %t %v\n", ty, tmp.ty, &tmp); foreach(idx, i, ini.idxs) { let fex = &ini.exs[i]; let ptr = mktmp(mkptrtype(fex.ty)); - gen("\t%v = getelementptr %t, %t %v, i32 0, i32 %d\n", ptr, ty, tmp.ty, tmp, idx); - gen("\tstore %t %v, %t %v\n", fex.ty, convert(f, ty.u.Arr.child, fex), ptr.ty, ptr); + gen("\t%v = getelementptr %t, %t %v, i32 0, i32 %d\n", &ptr, ty, tmp.ty, &tmp, idx); + let it = convert(f, ty.u.Arr.child, fex); + gen("\tstore %t %v, %t %v\n", fex.ty, &it, ptr.ty, &ptr); } return :Addr(tmp); case else let it = genexpr(f, ex); let tmp = gentmp(mkptrtype(ex.ty), "alloca %t", ex.ty); - gen("store %t %v, %t %v", it.ty, it, tmp.ty, tmp); + gen("store %t %v, %t %v", it.ty, &it, tmp.ty, &tmp); return :Addr(tmp); } assert(#f, "genref %d", ex.u.#tag); @@ -358,22 +357,22 @@ fn genref(f *Fn, ex *Expr) Ref { fn genload(f *Fn, ref Ref) Value { switch ref { case Addr addr; - return gentmp(addr.ty.u.Ptr, "load %t, %t %v", addr.ty.u.Ptr, addr.ty, addr); + return gentmp(addr.ty.u.Ptr, "load %t, %t %v", addr.ty.u.Ptr, addr.ty, &addr); case BitDot dot; let intty = dot.lhs.ty.u.BitF.intty; let fld = dot.fld; let lhs = genload(f, :Addr(dot.lhs)); - let shifted = fld.off == 0 ? lhs : gentmp(lhs.ty, "lshr %t %v, %d", lhs.ty, lhs, fld.off); - let truncd = gentmp(#null, "trunc %t %v to i%d", shifted.ty, shifted, fld.size); + let shifted = fld.off == 0 ? lhs : gentmp(lhs.ty, "lshr %t %v, %d", lhs.ty, &lhs, fld.off); + let truncd = gentmp(#null, "trunc %t %v to i%d", shifted.ty, &shifted, fld.size); let res = mktmp(fld.ty); switch { case dot.fld.ty->is(:Bool); - let tmp = gentmp(&ty_i1, "icmp ne i%d %v, 0", fld.size, truncd); - gen("\t%v = zext i1 %v to %t\n", res, tmp, res.ty); + let tmp = gentmp(#null, "icmp ne i%d %v, 0", fld.size, &truncd); + gen("\t%v = zext i1 %v to %t\n", &res, &tmp, res.ty); case dot.fld.ty->is(:Int); - gen("\t%v = %s i%d %v to %t\n", res, - dot.fld.ty.u.Int.sgn ? "sext" : "zext", fld.size, truncd, lhs.ty); + gen("\t%v = %s i%d %v to %t\n", &res, + dot.fld.ty.u.Int.sgn ? "sext" : "zext", fld.size, &truncd, lhs.ty); case else assert(#f, ""); } return res; @@ -382,8 +381,8 @@ fn genload(f *Fn, ref Ref) Value { fn genstore(f *Fn, ref Ref, v Value) void { switch ref { - case Addr addr; - gen("\tstore %t %v, %t %v\n", v.ty, v, addr.ty, addr); + case Addr *addr; + gen("\tstore %t %v, %t %v\n", v.ty, &v, addr.ty, addr); case BitDot dot; let intty = dot.lhs.ty.u.BitF.intty; @@ -391,14 +390,14 @@ fn genstore(f *Fn, ref Ref, v Value) void { let srcmask = fld.size == 64 ? ~0u64 : ((1u64 << fld.size) - 1); let addr = dot.lhs; let src0 = v; - let src = gentmp(intty, "and %t %v, %I", intty, src0, srcmask); - let src = gentmp(intty, "shl %t %v, %d", src.ty, src, fld.off); + let src = gentmp(intty, "and %t %v, %I", intty, &src0, srcmask); + let src = gentmp(intty, "shl %t %v, %d", src.ty, &src, fld.off); let dstmask = ~(srcmask << fld.off); - let lhs = gentmp(intty, "load %t, %t %v", intty, addr.ty, addr); + let lhs = gentmp(intty, "load %t, %t %v", intty, addr.ty, &addr); let lhs = genload(f, :Addr(addr)); - let lhs = gentmp(lhs.ty, "and %t %v, %I", lhs.ty, lhs, dstmask); - let raw = gentmp(lhs.ty, "or %t %v, %v", lhs.ty, lhs, src); - gen("\tstore %t %v, %t %v\n", raw.ty, raw, addr.ty, addr); + let lhs = gentmp(lhs.ty, "and %t %v, %I", lhs.ty, &lhs, dstmask); + let raw = gentmp(lhs.ty, "or %t %v, %v", lhs.ty, &lhs, &src); + gen("\tstore %t %v, %t %v\n", raw.ty, &raw, addr.ty, &addr); } } @@ -411,7 +410,7 @@ fn convert(f *Fn, to *const Type, ex *Expr) Value { defmacro cvt(inst) [ (do let $t = mktmp(to), val = genexpr(f, ex); - gen("\t%v = %s %t %v to %t\n", $t, inst, from, val, to); + gen("\t%v = %s %t %v to %t\n", &$t, inst, from, &val, to); $t; ) ] @@ -449,26 +448,28 @@ fn convert(f *Fn, to *const Type, ex *Expr) Value { case to->is(:Int) and from->is(:Flo) and to.size < ty_int.size; let t0 = mktmp(ty_int); let val = genexpr(f, ex); - gen("\t%v = fptosi %t %v to %t\n", t0, from, val, ty_int); + gen("\t%v = fptosi %t %v to %t\n", &t0, from, &val, ty_int); let t1 = mktmp(to); - gen("\t%v = trunc %t %v to %t\n", t1, t0.ty, t0, to); + gen("\t%v = trunc %t %v to %t\n", &t1, t0.ty, &t0, to); return t1; case to->is(:Int) and from->is(:Flo); return cvt(to.u.Int.sgn ? "fptosi" : "fptoui"); case to->is(:Int) and from->is(:Bool); - let t0 = mktmp(&ty_i1); - gen("\t%v = icmp ne %t %v, 0\n", t0, ex.ty, genexpr(f, ex)); + let t0 = mktmp(#null); + let b = genexpr(f, ex); + gen("\t%v = icmp ne %t %v, 0\n", &t0, ex.ty, &b); let t1 = mktmp(to); - gen("\t%v = zext %t %v to %t\n", t1, t0.ty, t0, t1.ty); + gen("\t%v = zext %t %v to %t\n", &t1, t0.ty, &t0, t1.ty); return t1; case to->is(:Bool) and from->is(:Int); - let t0 = mktmp(&ty_i1); - gen("\t%v = icmp ne %t %v, 0\n", t0, ex.ty, genexpr(f, ex)); + let t0 = mktmp(#null); + let b = genexpr(f, ex); + gen("\t%v = icmp ne %t %v, 0\n", &t0, ex.ty, &b); let t1 = mktmp(to); - gen("\t%v = zext %t %v to %t\n", t1, t0.ty, t0, t1.ty); + gen("\t%v = zext %t %v to %t\n", &t1, t0.ty, &t0, t1.ty); return t1; case to->is(:Ptr) and from->is(:Ptr); @@ -480,7 +481,7 @@ fn convert(f *Fn, to *const Type, ex *Expr) Value { case to->is(:Ptr) and from->is(:Arr); let addr = genref(f, ex).Addr; let t = mktmp(ex.ty); - gen("\t%v = getelementptr %t, %t %v, %t 0, %t 0\n", t, addr.ty.u.Ptr, addr.ty, addr, + gen("\t%v = getelementptr %t, %t %v, %t 0, %t 0\n", &t, addr.ty.u.Ptr, addr.ty, &addr, ty_usize, ty_usize); return t; @@ -493,6 +494,9 @@ fn convert(f *Fn, to *const Type, ex *Expr) Value { fn genblock(f *Fn, block Block) Option<Value>; fn llvmbool(f *Fn, ex *Expr) Value; +fn nop() Value { + return gentmp(ty_i8, "bitcast i8 0 to i8 ; NOP"); +} fn genexpr(f *Fn, ex *Expr) Value { fold(ex); @@ -510,7 +514,7 @@ fn genexpr(f *Fn, ex *Expr) Value { let lhs = convert(f, ex.ty, a), rhs = convert(f, ex.ty, b), t = mktmp(ex.ty); - gen("\t%v = %s %t %v, %v\n", t, inst, ex.ty, lhs, rhs); + gen("\t%v = %s %t %v, %v\n", &t, inst, ex.ty, &lhs, &rhs); t; ) ] @@ -520,27 +524,26 @@ fn genexpr(f *Fn, ex *Expr) Value { rhs = convert(f, ty2, b.rhs), t0 = mktmp(ex.ty), t1 = mktmp(ex.ty); - gen("\t%v = %s %s %t %v, %v\n", t0, ty2->is(:Flo) ? "fcmp" : "icmp", op, - ty2, lhs, rhs); - gen("\t%v = zext i1 %v to %t\n", t1, t0, ex.ty); + gen("\t%v = %s %s %t %v, %v\n", &t0, ty2->is(:Flo) ? "fcmp" : "icmp", op, + ty2, &lhs, &rhs); + gen("\t%v = zext i1 %v to %t\n", &t1, &t0, ex.ty); return t1; } ] defmacro genadd(type, lhs, rhs) [ (do let res Value #?; if isnumtype(type) { - let $t = mktmp(type); - gen("\t%v = %s %t %v, %v\n", $t, ex.ty->is(:Flo) ? "fadd" : "add", ex.ty, lhs, rhs); + let $t = gentmp(type, "%s %t %v, %v", ex.ty->is(:Flo) ? "fadd" : "add", ex.ty, &lhs, &rhs); res = $t; } else if lhs.ty->is(:Ptr) { let $t = mktmp(type); gen("\t%v = getelementptr %t, %t %v, %t %v\n", - $t, lhs.ty.u.Ptr, lhs.ty, lhs, rhs.ty, rhs); + &$t, lhs.ty.u.Ptr, lhs.ty, &lhs, rhs.ty, &rhs); res = $t; } else if rhs.ty->is(:Ptr) { let $t = mktmp(type); gen("\t%v = getelementptr %t, %t %v, %t %v\n", - $t, rhs.ty.u.Ptr, rhs.ty, rhs, rhs.ty, lhs); + &$t, rhs.ty.u.Ptr, rhs.ty, &rhs, rhs.ty, &lhs); res = $t; } else { assert(#f, "bad ad"); @@ -553,20 +556,20 @@ fn genexpr(f *Fn, ex *Expr) Value { let res Value #?; if isnumtype(type) and !lhs.ty->is(:Ptr) { let $t = mktmp(type); - gen("\t%v = %s %t %v, %v\n", $t, ex.ty->is(:Flo) ? "fsub" : "sub", ex.ty, lhs, rhs); + gen("\t%v = %s %t %v, %v\n", &$t, ex.ty->is(:Flo) ? "fsub" : "sub", ex.ty, &lhs, &rhs); res = $t; } else if lhs.ty->is(:Ptr) and rhs.ty->is(:Int) { let $off = mktmp(rhs.ty); - gen("\t%v = sub %t 0, %v\n", $off, rhs.ty, rhs); + gen("\t%v = sub %t 0, %v\n", &$off, rhs.ty, &rhs); let $t = mktmp(type); gen("\t%v = getelementptr %t, %t %v, %t %v\n", - $t, lhs.ty.u.Ptr == ty_void ? ty_i8 : lhs.ty.u.Ptr, lhs.ty, lhs, $off.ty, $off); + &$t, lhs.ty.u.Ptr == ty_void ? ty_i8 : lhs.ty.u.Ptr, lhs.ty, &lhs, $off.ty, &$off); res = $t; } else if lhs.ty->is(:Ptr) and rhs.ty->is(:Ptr) { - let $l = gentmp(ty_isize, "ptrtoint ptr %v to %t", lhs, ty_isize); - let $r = gentmp(ty_isize, "ptrtoint ptr %v to %t", rhs, ty_isize); - let $diff = gentmp(ty_isize, "sub %t %v, %v", ty_isize, $l, $r); - let $res = gentmp(ty_isize, "sdiv %t %v, %v", ty_isize, $l, $r); + let $l = gentmp(ty_isize, "ptrtoint ptr %v to %t", &lhs, ty_isize); + let $r = gentmp(ty_isize, "ptrtoint ptr %v to %t", &rhs, ty_isize); + let $diff = gentmp(ty_isize, "sub %t %v, %v", ty_isize, &$l, &$r); + let $res = gentmp(ty_isize, "sdiv %t %v, %v", ty_isize, &$l, &$r); return $res; } else { assert(#f, "bad sub"); @@ -579,7 +582,7 @@ fn genexpr(f *Fn, ex *Expr) Value { let ref = genref(f, a); let rhs = convert(f, a.ty, b); let lhs0 = genload(f, ref); - let tmp = gentmp(ex.ty, "%s %t %v, %v", inst, ex.ty, lhs0, rhs); + let tmp = gentmp(ex.ty, "%s %t %v, %v", inst, ex.ty, &lhs0, &rhs); genstore(f, ref, tmp); genload(f, ref); // load again because value could have overflowed when storing it ) @@ -648,57 +651,57 @@ fn genexpr(f *Fn, ex *Expr) Value { static orid int = {}; let id = orid++; let lhs = genexpr(f, b.lhs); - let cnd = mktmp(&ty_i1); + let cnd = mktmp(#null); let tmpvar = mktmp(mkptrtype(ex.ty)); let res = mktmp(ex.ty); - gen("\t%v = alloca %t\n", tmpvar, ex.ty); - gen("\tstore %t %v, %t %v\n", ex.ty, lhs, tmpvar.ty, tmpvar); - gen("\t%v = icmp ne %t %v, 0\n", cnd, lhs.ty, lhs); - gen("\tbr i1 %v, label %%OrT%d, label %%OrF%d\n", cnd, id, id); + gen("\t%v = alloca %t\n", &tmpvar, ex.ty); + gen("\tstore %t %v, %t %v\n", ex.ty, &lhs, tmpvar.ty, &tmpvar); + gen("\t%v = icmp ne %t %v, 0\n", &cnd, lhs.ty, &lhs); + gen("\tbr i1 %v, label %%OrT%d, label %%OrF%d\n", &cnd, id, id); gen("OrF%d: ", id); let rhs = genexpr(f, b.rhs); - gen("\tstore %t %v, %t %v\n", ex.ty, rhs, tmpvar.ty, tmpvar); - gen("\tbr label %%OrT%d\n", cnd, id, id); + gen("\tstore %t %v, %t %v\n", ex.ty, &rhs, tmpvar.ty, &tmpvar); + gen("\tbr label %%OrT%d\n", id); gen("OrT%d: ", id); - gen("\t%v = load %t, %t %v\n", res, ex.ty, tmpvar.ty, tmpvar); + gen("\t%v = load %t, %t %v\n", &res, ex.ty, tmpvar.ty, &tmpvar); return res; case 'and'; static andid int = {}; let id = andid++; let lhs = genexpr(f, b.lhs); - let cnd = mktmp(&ty_i1); + let cnd = mktmp(#null); let tmpvar = mktmp(mkptrtype(ex.ty)); let res = mktmp(ex.ty); - gen("\t%v = alloca %t\n", tmpvar, ex.ty); - gen("\tstore %t %v, %t %v\n", ex.ty, lhs, tmpvar.ty, tmpvar); - gen("\t%v = icmp ne %t %v, 0\n", cnd, lhs.ty, lhs); - gen("\tbr i1 %v, label %%AndT%d, label %%AndF%d\n", cnd, id, id); + gen("\t%v = alloca %t\n", &tmpvar, ex.ty); + gen("\tstore %t %v, %t %v\n", ex.ty, &lhs, tmpvar.ty, &tmpvar); + gen("\t%v = icmp ne %t %v, 0\n", &cnd, lhs.ty, &lhs); + gen("\tbr i1 %v, label %%AndT%d, label %%AndF%d\n", &cnd, id, id); gen("AndT%d: ", id); let rhs = genexpr(f, b.rhs); - gen("\tstore %t %v, %t %v\n", ex.ty, rhs, tmpvar.ty, tmpvar); - gen("\tbr label %%AndF%d\n", cnd, id, id); + gen("\tstore %t %v, %t %v\n", ex.ty, &rhs, tmpvar.ty, &tmpvar); + gen("\tbr label %%AndF%d\n", id); gen("AndF%d: ", id); - gen("\t%v = load %t, %t %v\n", res, ex.ty, tmpvar.ty, tmpvar); + gen("\t%v = load %t, %t %v\n", &res, ex.ty, tmpvar.ty, &tmpvar); return res; case '??'; static orid int = {}; let id = orid++; let lhs = genexpr(f, b.lhs); - let cnd = mktmp(&ty_i1); + let cnd = mktmp(#null); let tmpvar = mktmp(mkptrtype(ex.ty)); let res = mktmp(ex.ty); - gen("\t%v = alloca %t\n", tmpvar, ex.ty); - gen("\tstore %t %v, %t %v\n", ex.ty, lhs, tmpvar.ty, tmpvar); - gen("\t%v = icmp ne %t %v, null\n", cnd, lhs.ty, lhs); - gen("\tbr i1 %v, label %%OrT%d, label %%OrF%d\n", cnd, id, id); + gen("\t%v = alloca %t\n", &tmpvar, ex.ty); + gen("\tstore %t %v, %t %v\n", ex.ty, &lhs, tmpvar.ty, &tmpvar); + gen("\t%v = icmp ne %t %v, null\n", &cnd, lhs.ty, &lhs); + gen("\tbr i1 %v, label %%OrT%d, label %%OrF%d\n", &cnd, id, id); gen("OrF%d: ", id); let rhs = genexpr(f, b.rhs); - gen("\tstore %t %v, %t %v\n", ex.ty, rhs, tmpvar.ty, tmpvar); - gen("\tbr label %%OrT%d\n", cnd, id, id); + gen("\tstore %t %v, %t %v\n", ex.ty, &rhs, tmpvar.ty, &tmpvar); + gen("\tbr label %%OrT%d\n", &cnd, id, id); gen("OrT%d: ", id); - gen("\t%v = load %t, %t %v\n", res, ex.ty, tmpvar.ty, tmpvar); + gen("\t%v = load %t, %t %v\n", &res, ex.ty, tmpvar.ty, &tmpvar); return res; case else @@ -708,45 +711,48 @@ fn genexpr(f *Fn, ex *Expr) Value { static condid int = {}; let id = condid++; let lhs = genexpr(f, cond.test); - let cnd = mktmp(&ty_i1); + let cnd = mktmp(#null); let tmpvar = mktmp(mkptrtype(ex.ty)); let res = mktmp(ex.ty); - gen("\t%v = alloca %t\n", tmpvar, ex.ty); - gen("\t%v = icmp ne %t %v, %s\n", cnd, lhs.ty, lhs, lhs.ty->is(:Ptr) ? "null" : "0"); - gen("\tbr i1 %v, label %%CondT%d, label %%CondF%d\n", cnd, id, id); + gen("\t%v = alloca %t\n", &tmpvar, ex.ty); + gen("\t%v = icmp ne %t %v, %s\n", &cnd, lhs.ty, &lhs, lhs.ty->is(:Ptr) ? "null" : "0"); + gen("\tbr i1 %v, label %%CondT%d, label %%CondF%d\n", &cnd, id, id); gen("CondT%d: ", id); let t = convert(f, ex.ty, cond.t); - gen("\tstore %t %v, %t %v\n", ex.ty, t, tmpvar.ty, tmpvar); - gen("\tbr label %%CondFin%d\n", cnd, id, id); + gen("\tstore %t %v, %t %v\n", ex.ty, &t, tmpvar.ty, &tmpvar); + gen("\tbr label %%CondFin%d\n", id); gen("CondF%d: ", id); let f = convert(f, ex.ty, cond.f); - gen("\tstore %t %v, %t %v\n", ex.ty, f, tmpvar.ty, tmpvar); - gen("\tbr label %%CondFin%d\n", cnd, id, id); + gen("\tstore %t %v, %t %v\n", ex.ty, &f, tmpvar.ty, &tmpvar); + gen("\tbr label %%CondFin%d\n", id); gen("CondFin%d: ", id); - gen("\t%v = load %t, %t %v\n", res, ex.ty, tmpvar.ty, tmpvar); + gen("\t%v = load %t, %t %v\n", &res, ex.ty, tmpvar.ty, &tmpvar); return res; case UnOp un; switch un.op { case :neg; let tmp = mktmp(ex.ty); + let rhs = convert(f, ex.ty, un.ex); if ex.ty->is(:Int) { - gen("\t%v = sub %t 0, %v\n", tmp, ex.ty, convert(f, ex.ty, un.ex)); + gen("\t%v = sub %t 0, %v\n", &tmp, ex.ty, &rhs); } else { - gen("\t%v = fsub %t 0.0, %v\n", tmp, ex.ty, convert(f, ex.ty, un.ex)); + gen("\t%v = fsub %t 0.0, %v\n", &tmp, ex.ty, &rhs); } return tmp; case :compl; let tmp = mktmp(ex.ty); - gen("\t%v = xor %t -1, %v\n", tmp, ex.ty, convert(f, ex.ty, un.ex)); + let rhs = convert(f, ex.ty, un.ex); + gen("\t%v = xor %t -1, %v\n", &tmp, ex.ty, &rhs); return tmp; case :not; - let tmp = mktmp(&ty_i1); - gen("\t%v = xor i1 1, %v\n", tmp, ex.ty, llvmbool(f, un.ex)); + let tmp = mktmp(#null); + let rhs = llvmbool(f, un.ex); + gen("\t%v = xor i1 1, %v\n", &tmp, &rhs); let res = mktmp(ex.ty); - gen("\t%v = zext i1 %v to %t\n", res, tmp, res.ty); + gen("\t%v = zext i1 %v to %t\n", &res, &tmp, res.ty); return res; case :preinc, :predec; @@ -755,9 +761,9 @@ fn genexpr(f *Fn, ex *Expr) Value { let val = mktmp(ex.ty); let var = genload(f, ref); if ex.ty->is(:Ptr) { - gen("\t%v = getelementptr %t, %t %v, i32 %v\n", val, ex.ty.u.Ptr, ex.ty, var, one); + gen("\t%v = getelementptr %t, %t %v, i32 %v\n", &val, ex.ty.u.Ptr, ex.ty, &var, &one); } else { - gen("\t%v = add %t %v, %v\n", val, ex.ty, var, one); + gen("\t%v = add %t %v, %v\n", &val, ex.ty, &var, &one); } genstore(f, ref, val); return genload(f, ref); // load again because value could have overflowed when storing it @@ -768,9 +774,9 @@ fn genexpr(f *Fn, ex *Expr) Value { let val = mktmp(ex.ty); let var = genload(f, ref); if ex.ty->is(:Ptr) { - gen("\t%v = getelementptr %t, %t %v, i32 %v\n", val, ex.ty.u.Ptr, ex.ty, var, one); + gen("\t%v = getelementptr %t, %t %v, i32 %v\n", &val, ex.ty.u.Ptr, ex.ty, &var, &one); } else { - gen("\t%v = add %t %v, %v\n", val, ex.ty, var, one); + gen("\t%v = add %t %v, %v\n", &val, ex.ty, &var, &one); } genstore(f, ref, val); return var; @@ -778,7 +784,7 @@ fn genexpr(f *Fn, ex *Expr) Value { case :deref; let rhs = genexpr(f, un.ex); let val = mktmp(ex.ty); - gen("\t%v = load %t, %t %v\n", val, ex.ty, rhs.ty, rhs); + gen("\t%v = load %t, %t %v\n", &val, ex.ty, rhs.ty, &rhs); return val; case :addrof; @@ -806,13 +812,13 @@ fn genexpr(f *Fn, ex *Expr) Value { case SPtr sl; let sl = genexpr(f, sl); let ptr = mktmp(mkptrtype(sl.ty.u.Slice)); - gen("\t%v = extractvalue %t %v, 0\n", ptr, sl.ty, sl); + gen("\t%v = extractvalue %t %v, 0\n", &ptr, sl.ty, &sl); return ptr; case SLen sl; let sl = genexpr(f, sl); let len = mktmp(ty_usize); - gen("\t%v = extractvalue %t %v, 1\n", len, sl.ty, sl); + gen("\t%v = extractvalue %t %v, 1\n", &len, sl.ty, &sl); return len; case EUTag; @@ -837,41 +843,41 @@ fn genexpr(f *Fn, ex *Expr) Value { let begin = convert(f, ty_usize, sl.begin); let end = convert(f, ty_usize, sl.end); let len = mktmp(ty_usize); - gen("\t%v = sub %t %v, %v\n", len, ty_usize, end, begin); + gen("\t%v = sub %t %v, %v\n", &len, ty_usize, &end, &begin); let addr2 = mktmp(addr.ty); - gen("\t%v = getelementptr %t, %t %v, %t %v\n", addr2, ex.ty.u.Slice, addr.ty, addr, ty_usize, begin); + gen("\t%v = getelementptr %t, %t %v, %t %v\n", &addr2, ex.ty.u.Slice, addr.ty, &addr, ty_usize, &begin); let tmp = mktmp(ex.ty); - gen("\t%v = insertvalue %t undef, %t %v, 0\n", tmp, ex.ty, addr2.ty, addr2); + gen("\t%v = insertvalue %t undef, %t %v, 0\n", &tmp, ex.ty, addr2.ty, &addr2); let res = mktmp(ex.ty); - gen("\t%v = insertvalue %t %v, %t %v, 1\n", res, ex.ty, tmp, len.ty, len); + gen("\t%v = insertvalue %t %v, %t %v, 1\n", &res, ex.ty, &tmp, len.ty, &len); return res; } else if sl.lhs.ty.u.#tag == :Ptr { let addr = genexpr(f, sl.lhs); let begin = convert(f, ty_usize, sl.begin); let end = convert(f, ty_usize, sl.end); let len = mktmp(ty_usize); - gen("\t%v = sub %t %v, %v\n", len, ty_usize, end, begin); + gen("\t%v = sub %t %v, %v\n", &len, ty_usize, &end, &begin); let addr2 = mktmp(addr.ty); - gen("\t%v = getelementptr %t, %t %v, %t %v\n", addr2, ex.ty.u.Slice, addr.ty, addr, ty_usize, begin); + gen("\t%v = getelementptr %t, %t %v, %t %v\n", &addr2, ex.ty.u.Slice, addr.ty, &addr, ty_usize, &begin); let tmp = mktmp(ex.ty); - gen("\t%v = insertvalue %t undef, %t %v, 0\n", tmp, ex.ty, addr2.ty, addr2); + gen("\t%v = insertvalue %t undef, %t %v, 0\n", &tmp, ex.ty, addr2.ty, &addr2); let res = mktmp(ex.ty); - gen("\t%v = insertvalue %t %v, %t %v, 1\n", res, ex.ty, tmp, len.ty, len); + gen("\t%v = insertvalue %t %v, %t %v, 1\n", &res, ex.ty, &tmp, len.ty, &len); return res; } else if sl.lhs.ty.u.#tag == :Slice { let slice = genexpr(f, sl.lhs); let begin = convert(f, ty_usize, sl.begin); let end = convert(f, ty_usize, sl.end); let addr = mktmp(mkptrtype(slice.ty.u.Slice)); - gen("\t%v = extractvalue %t %v, 0", addr, ex.ty, slice); + gen("\t%v = extractvalue %t %v, 0", &addr, ex.ty, &slice); let len = mktmp(ty_usize); - gen("\t%v = sub %t %v, %v\n", len, ty_usize, end, begin); + gen("\t%v = sub %t %v, %v\n", &len, ty_usize, &end, &begin); let addr2 = mktmp(addr.ty); - gen("\t%v = getelementptr %t, %t %v, %t %v\n", addr2, ex.ty.u.Slice, addr.ty, addr, ty_usize, begin); + gen("\t%v = getelementptr %t, %t %v, %t %v\n", &addr2, ex.ty.u.Slice, addr.ty, &addr, ty_usize, &begin); let tmp = mktmp(ex.ty); - gen("\t%v = insertvalue %t undef, %t %v, 0\n", tmp, ex.ty, addr2.ty, addr2); + gen("\t%v = insertvalue %t undef, %t %v, 0\n", &tmp, ex.ty, addr2.ty, &addr2); let res = mktmp(ex.ty); - gen("\t%v = insertvalue %t %v, %t %v, 1\n", res, ex.ty, tmp, len.ty, len); + gen("\t%v = insertvalue %t %v, %t %v, 1\n", &res, ex.ty, &tmp, len.ty, &len); return res; } @@ -895,14 +901,14 @@ fn genexpr(f *Fn, ex *Expr) Value { } let t Value = mktmp(ex.ty); if fnty.ret->is(:Void) { - gen("\tcall void %v(", lhs); + gen("\tcall void %v(", &lhs); } else { t = mktmp(ex.ty); - gen("\t%v = call %t %v(", t, call.lhs.ty->is(:Ptr) ? call.lhs.ty.u.Ptr : call.lhs.ty, lhs); + gen("\t%v = call %t %v(", &t, call.lhs.ty->is(:Ptr) ? call.lhs.ty.u.Ptr : call.lhs.ty, &lhs); } foreach_ptr(arg, i, call.args) { let ty = i < fnty.params.#len ? fnty.params[i] : varargpromote(arg.ty); - gen("%t %v", ty, args[i]); + gen("%t %v", ty, &args[i]); if i < call.args.#len - 1 { gen(", "); } @@ -918,37 +924,38 @@ fn genexpr(f *Fn, ex *Expr) Value { let ty = mkarrtype(ini.maxn, #f, ex.ty.u.Arr.child); let tmp = genref(f, ex).Addr; let val = mktmp(ty); - gen("\t%v = load %t, %t %v\n", val, ty, tmp.ty, tmp); + gen("\t%v = load %t, %t %v\n", &val, ty, tmp.ty, &tmp); return val; case EUnionIni ini; let t0 = mktmp(mkptrtype(ex.ty)); let vidx = ini.var - ex.ty.u.Agg.flds.#ptr; - gen("\t%v = alloca %t\n", t0, ex.ty); - gen("\tstore %t zeroinitializer, %t %v\n", ex.ty, t0.ty, t0); - gen("\tstore %t %d, %t %v\n", ex.ty.u.Agg.enumty.u.Enum.intty, vidx, t0.ty, t0); + gen("\t%v = alloca %t\n", &t0, ex.ty); + gen("\tstore %t zeroinitializer, %t %v\n", ex.ty, t0.ty, &t0); + gen("\tstore %t %d, %t %v\n", ex.ty.u.Agg.enumty.u.Enum.intty, vidx, t0.ty, &t0); if ini.var.ty != #null { let tini = convert(f, ini.var.ty, ini.ex); let t1 = mktmp(mkptrtype(ini.var.ty)); - gen("\t%v = bitcast %t %v to %t\n", t1, t0.ty, t0, t1.ty); + gen("\t%v = bitcast %t %v to %t\n", &t1, t0.ty, &t0, t1.ty); let t2 = mktmp(t1.ty); - gen("\t%v = getelementptr %t, %t %v, i32 1\n", t2, ini.var.ty, t1.ty, t1); - gen("\tstore %t %v, %t %v\n", tini.ty, tini, t2.ty, t2); + gen("\t%v = getelementptr %t, %t %v, i32 1\n", &t2, ini.var.ty, t1.ty, &t1); + gen("\tstore %t %v, %t %v\n", tini.ty, &tini, t2.ty, &t2); } let res = mktmp(ex.ty); - gen("\t%v = load %t, %t %v\n", res, res.ty, t0.ty, t0); + gen("\t%v = load %t, %t %v\n", &res, res.ty, t0.ty, &t0); return res; case VaStart ap; - gen("\tcall void @llvm.va_start(ptr %v)\n", genref(f, ap).Addr); - return mktmp(ty_void); + // gen("\tcall void @llvm.va_start(ptr %v)\n", genref(f, ap).Addr); + return nop(); case VaArg ap; - return gentmp(ex.ty, "va_arg ptr %v, %t", genref(f, ap).Addr, ex.ty); + let ap = genref(f, ap).Addr; + return gentmp(ex.ty, "va_arg ptr %v, %t", &ap, ex.ty); case VaEnd ap; - gen("\tcall void @llvm.va_end(ptr %v)\n", genref(f, ap).Addr); - return mktmp(ty_void); + // gen("\tcall void @llvm.va_end(ptr %v)\n", genref(f, ap).Addr); + return nop(); case Stmt block; switch genblock(f, block) { @@ -963,19 +970,15 @@ fn genexpr(f *Fn, ex *Expr) Value { fn llvmbool(f *Fn, ex *Expr) Value { let v = genexpr(f, ex); - let t = mktmp(&ty_i1); + let t = mktmp(#null); if v.ty->is(:Bool) or v.ty->is(:Int) { - gen("\t%v = icmp ne %t %v, 0\n", t, v.ty, v); + gen("\t%v = icmp ne %t %v, 0\n", &t, v.ty, &v); } else { - gen("\t%v = icmp ne %t %v, null\n", t, v.ty, v); + gen("\t%v = icmp ne %t %v, null\n", &t, v.ty, &v); } return t; } -fn nop() void { - gen("\t%%t%d = bitcast i8 0 to i8 ; NOP\n", tmpid++); -} - fn genstmt(f *Fn, block *Block, st *Stmt) void { gen(";; line %d\n", st.loc.line); switch st.u { @@ -993,15 +996,16 @@ fn genstmt(f *Fn, block *Block, st *Stmt) void { gen("\t%%%s.%d = alloca %t\n", nam, var.id, ty); switch var.ini { case Some *ex; + let it = convert(f, ty, ex); gen("\tstore %t %v, %t %%%s.%d\n", - ty, convert(f, ty, ex), mkptrtype(ty), nam, var.id); + ty, &it, mkptrtype(ty), nam, var.id); } } case If *cnd; static ifid int = {}; let id = ifid++; - gen("\tbr i1 %v, label %%IfT%d, label %%IfF%d\n", - llvmbool(f, &cnd.test), id, id); + let test = llvmbool(f, &cnd.test); + gen("\tbr i1 %v, label %%IfT%d, label %%IfF%d\n", &test, id, id); gen("IfT%d:", id); nop(); genblock(f, cnd.t); @@ -1021,8 +1025,8 @@ fn genstmt(f *Fn, block *Block, st *Stmt) void { gen("\tbr label %%Cont%d\n", loop.id); gen("Cont%d:", loop.id); nop(); - gen("\tbr i1 %v, label %%Next%d, label %%Brk%d\n", - llvmbool(f, &loop.test), loop.id, loop.id); + let test = llvmbool(f, &loop.test); + gen("\tbr i1 %v, label %%Next%d, label %%Brk%d\n", &test, loop.id, loop.id); gen("Next%d:", loop.id); nop(); genblock(f, loop.body); @@ -1038,8 +1042,8 @@ fn genstmt(f *Fn, block *Block, st *Stmt) void { gen("\tbr label %%Cont%d\n", loop.id); gen("Cont%d:", loop.id); nop(); - gen("\tbr i1 %v, label %%Next%d, label %%Brk%d\n", - llvmbool(f, &loop.test), loop.id, loop.id); + let test = llvmbool(f, &loop.test); + gen("\tbr i1 %v, label %%Next%d, label %%Brk%d\n", &test, loop.id, loop.id); gen("Brk%d:",loop.id); nop(); @@ -1048,8 +1052,8 @@ fn genstmt(f *Fn, block *Block, st *Stmt) void { gen("\tbr label %%Cont%d\n", loop.id); gen("Cont%d:", loop.id); nop(); - gen("\tbr i1 %v, label %%Next%d, label %%Brk%d\n", - llvmbool(f, &loop.test), loop.id, loop.id); + let test = llvmbool(f, &loop.test); + gen("\tbr i1 %v, label %%Next%d, label %%Brk%d\n", &test, loop.id, loop.id); gen("Next%d:", loop.id); nop(); genblock(f, loop.body); @@ -1077,13 +1081,14 @@ fn genstmt(f *Fn, block *Block, st *Stmt) void { gen("\tret void\n"); case Some *e; let retty = f.ty.u.Fn.ret; - gen("\tret %t %v\n", retty, convert(f, retty, e)); + let it = convert(f, retty, e); + gen("\tret %t %v\n", retty, &it); } case ISwitch *sw; static swid int = {}; let id = swid++; let test = genexpr(f, &sw.ex); - gen("\tswitch %t %v, label %%ISx%d [", test.ty, test, id); + gen("\tswitch %t %v, label %%ISx%d [", test.ty, &test, id); foreach (c, i, sw.cs) { foreach_ptr (ex, _, c.es) { assert(ex.u.#tag == :IntLit or ex.u.#tag == :EnumIni, "case"); @@ -1110,21 +1115,21 @@ fn genstmt(f *Fn, block *Block, st *Stmt) void { exaddr = genref(f, &sw.ex).Addr; } else { exaddr = mktmp(mkptrtype(sw.ex.ty)); - gen("\t%v = alloca %t\n", exaddr, exaddr.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); + 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); + 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); + 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); + 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(" %t %v, label %%ES%d.%d ", t.ty, &t, id, i); } gen(" ]\n"); foreach (c, i, sw.cs) { @@ -1132,14 +1137,14 @@ fn genstmt(f *Fn, block *Block, st *Stmt) void { 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, + 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); + 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); + 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); @@ -1161,7 +1166,7 @@ fn genstmt(f *Fn, block *Block, st *Stmt) void { } foreach (c, i, sw.cs) { let t = llvmbool(f, &c.test); - gen("\tbr i1 %v, label %%CST%d.%d, label %%CSF%d.%d\n", t, id, i, id, i); + gen("\tbr i1 %v, label %%CST%d.%d, label %%CSF%d.%d\n", &t, id, i, id, i); gen("CST%d.%d: ", id, i); genblock(f, c.t); gen("\tbr label %%CSe%d\n", id); @@ -1281,7 +1286,6 @@ struct IntTraits<T> { } fn gendata(ty *const Type, ex *Expr) void { - fn dataaddr(ex *Expr) void { switch ex.u { case Symbol decl; @@ -1306,11 +1310,11 @@ fn gendata(ty *const Type, ex *Expr) void { case BoolLit b; return gen("%d", b); case NullLit; return gen("null"); case ZeroIni; return gen("zeroinitializer"); - case StrLit s; + case StrLit *s; if ty->is(:Arr) { return gen("c%S", s); } else { - strs->push(s); + strs->push(*s); return gen("@.str.%z", strs.len - 1); } case UnOp un; @@ -1390,7 +1394,7 @@ extern fn llvm_fini() void { gen("declare void @llvm.va_copy(ptr, ptr)\n"); gen("declare void @llvm.va_end(ptr)\n"); vec_each(s, i, strs) { - gen("@.str.%z = private unnamed_addr constant [%z x i8] c%S;\n", i, s.#len + 1, s); + gen("@.str.%z = private unnamed_addr constant [%z x i8] c%S;\n", i, s.#len + 1, &s); } map_each(g, k, globls) { if g.t != :Decl { |