diff options
| author | 2022-08-26 22:08:52 +0200 | |
|---|---|---|
| committer | 2022-08-26 22:11:30 +0200 | |
| commit | 4a7d610bb9a441f6fb7f88caaa803c1c85e4fcfd (patch) | |
| tree | 3ac01c9be375f30efd09f0a670da74f886ad44ca /src/llvm.cff | |
| parent | 475125eaba2852f88a4ee8d9be64c8b4964df3a9 (diff) | |
bitfields
Diffstat (limited to 'src/llvm.cff')
| -rw-r--r-- | src/llvm.cff | 92 |
1 files changed, 71 insertions, 21 deletions
diff --git a/src/llvm.cff b/src/llvm.cff index 8ff32ba..32b1066 100644 --- a/src/llvm.cff +++ b/src/llvm.cff @@ -96,6 +96,7 @@ fn gen(fmt *const u8, ...) void { case Agg; genagg(ty); case Enum enu; pritype(enu.intty); + case BitF bitf; pritype(bitf.intty); case Fn f; gen("%t(", f.ret); foreach(ty, i, f.params) { @@ -202,6 +203,16 @@ fn mktmp(ty *const Type) Value { return Value{ty, :Tmp(tmpid++)}; } +defmacro gentmp(type, ...rest) [ + (do + let $tmp = mktmp(type); + gen("\t%v = ", $tmp); + gen(rest); + gen("\n"); + $tmp; + ) +] + fn convert(f *Fn, to *const Type, ex *Expr) Value; fn genexpr(f *Fn, ex *Expr) Value; static arena Arena = {}; @@ -235,20 +246,18 @@ fn genaddr(f *Fn, ex *Expr) Value { switch idx.lhs.ty.u { case Arr arrty; let arr = genaddr(f, idx.lhs); - lhs = mktmp(mkptrtype(ex.ty)); - gen("\t%v = getelementptr %t, %t %v, i32 0, i32 0\n", lhs, 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 = mktmp(mkptrtype(child)); - gen("\t%v = extractvalue %t %v, 0\n", lhs, 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), - addr = mktmp(mkptrtype(ex.ty)); - gen("\t%v = getelementptr %t, %t %v, %t %v\n", addr, ex.ty, lhs.ty, lhs, rhs.ty, rhs); + 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); return addr; case Dot dot; @@ -262,27 +271,30 @@ fn genaddr(f *Fn, ex *Expr) Value { } else { idx = dot.fld - dot.lhs.ty.u.Agg.flds.#ptr; } - let addr = mktmp(mkptrtype(ex.ty)); + let addr Value #?; + let ptrty = mkptrtype(ex.ty); switch lhs.ty.u.Ptr.u.Agg.kind { case :Struct; - gen("\t%v = getelementptr %t, %t %v, i32 0, i32 %d\n", addr, lhs.ty.u.Ptr, lhs.ty, lhs, idx); + addr = gentmp(ptrty, "getelementptr %t, %t %v, i32 0, i32 %d", + lhs.ty.u.Ptr, lhs.ty, lhs, idx); case :Union; - gen("\t%v = bitcast %t %v to %t", addr, lhs.ty, lhs, addr.ty); + addr = gentmp(ptrty, "bitcast %t %v to %t", lhs.ty, lhs, ptrty); case else let off int = dot.fld.off; - gen("\t%v = getelementptr i8, %t %v, i32 %d\n", addr, lhs.ty, lhs, off); + addr = gentmp(ptrty, "getelementptr i8, %t %v, i32 %d", 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 %t", addr, lhs.ty, lhs, addr.ty); + let addr = gentmp(mkptrtype(ex.ty), "bitcast %t %v to %t", lhs.ty, lhs, mkptrtype(ex.ty)); return addr; + case BitRaw ex; + return genaddr(f, ex); + case AggIni ini; - let tmp = mktmp(mkptrtype(ex.ty)); - gen("\t%v = alloca %t\n", tmp, ex.ty); + let tmp = gentmp(mkptrtype(ex.ty), "alloca %t", ex.ty); gen("\tstore %t zeroinitializer, %t %v\n", ex.ty, tmp.ty, tmp); foreach(fld, i, ini.flds) { let fex = &ini.exs[i]; @@ -300,8 +312,7 @@ fn genaddr(f *Fn, ex *Expr) Value { case ArrIni ini; let ty = mkarrtype(ini.maxn, #f, ex.ty.u.Arr.child); - let tmp = mktmp(mkptrtype(ty)); - gen("\t%v = alloca %t\n", tmp, ty); + let tmp = gentmp(mkptrtype(ty), "alloca %t", ty); gen("\tstore %t zeroinitializer, %t %v\n", ty, tmp.ty, tmp); foreach(idx, i, ini.idxs) { let fex = &ini.exs[i]; @@ -524,10 +535,28 @@ fn genexpr(f *Fn, ex *Expr) Value { case '>'; gencmp(ty2->is(:Flo) ? "ogt" : ty2.u.Int.sgn ? "sgt" : "ugt"); case '>='; gencmp(ty2->is(:Flo) ? "oge" : ty2.u.Int.sgn ? "sge" : "uge"); case '='; - let addr = genaddr(f, b.lhs); - let rhs = convert(f, b.lhs.ty, b.rhs); - gen("\tstore %t %v, %t %v\n", ex.ty, rhs, addr.ty, addr); - return rhs; + if b.lhs.u.#tag != :BitDot { + let addr = genaddr(f, b.lhs); + let rhs = convert(f, b.lhs.ty, b.rhs); + gen("\tstore %t %v, %t %v\n", ex.ty, rhs, addr.ty, addr); + return rhs; + } else { + let dot = &b.lhs.u.BitDot; + let intty = dot.lhs.ty.u.BitF.intty; + let fld = dot.fld; + let srcmask = fld.size == 64 ? ~0u64 : ((1u64 << fld.size) - 1); + let addr = genaddr(f, dot.lhs); + let src0 = convert(f, intty, b.rhs); + let src = gentmp(intty, "and %t %v, %I", src0.ty, 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(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 res = gentmp(intty, "load %t, %t %v", fld.ty, addr.ty, addr); + return res; + } case '+='; let addr = genaddr(f, b.lhs); let rhs = convert(f, b.lhs.ty, b.rhs); @@ -696,6 +725,27 @@ fn genexpr(f *Fn, ex *Expr) Value { gen("\t%v = load %t, %t %v\n", tmp, ex.ty, addr.ty, addr); return tmp; + case BitRaw ex; + return genexpr(f, ex); + + case BitDot dot; + let fld = dot.fld; + let lhs = genexpr(f, 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 res = mktmp(fld.ty); + switch { + case dot.fld.ty->is(:Bool); + let tmp = gentmp(ty_bool, "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", truncd, fld.size, lhs.ty); + + case else assert(#f, ""); + } + return res; + case SPtr sl; let sl = genexpr(f, sl); let ptr = mktmp(mkptrtype(sl.ty.u.Slice)); |