aboutsummaryrefslogtreecommitdiff
path: root/src/llvm.cff
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2022-08-26 22:08:52 +0200
committerlemon <lsof@mailbox.org>2022-08-26 22:11:30 +0200
commit4a7d610bb9a441f6fb7f88caaa803c1c85e4fcfd (patch)
tree3ac01c9be375f30efd09f0a670da74f886ad44ca /src/llvm.cff
parent475125eaba2852f88a4ee8d9be64c8b4964df3a9 (diff)
bitfields
Diffstat (limited to 'src/llvm.cff')
-rw-r--r--src/llvm.cff92
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));