aboutsummaryrefslogtreecommitdiff
path: root/src/llvm.cff
diff options
context:
space:
mode:
Diffstat (limited to 'src/llvm.cff')
-rw-r--r--src/llvm.cff54
1 files changed, 49 insertions, 5 deletions
diff --git a/src/llvm.cff b/src/llvm.cff
index 56a28ed..d266cbb 100644
--- a/src/llvm.cff
+++ b/src/llvm.cff
@@ -225,9 +225,14 @@ fn genaddr(f *Fn, ex *Expr) Value {
case Dot dot;
let lhs = dot.lhs.ty->is(:Ptr) ? genexpr(f, dot.lhs) : genaddr(f, dot.lhs);
assert(dot.fld.off % dot.fld.ty.align == 0, "field align");
- let idx int = dot.fld.off / dot.fld.ty.align;
+ let idx int = dot.fld - ex.ty.u.Agg.flds.#ptr;
let addr = mktmp(mkptrtype(ex.ty));
- gen("\t%v = getelementptr %t, %t %v, i32 0, i32 %d\n", addr, lhs.ty.u.Ptr, lhs.ty, lhs, idx);
+ 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);
+ case :Union;
+ gen("\t%v = bitcast %t %v to %v", addr, lhs.ty, lhs, addr.ty);
+ }
return addr;
case AggIni ini;
@@ -237,8 +242,13 @@ fn genaddr(f *Fn, ex *Expr) Value {
foreach(fld, i, ini.flds) {
let fex = &ini.exs[i];
let ptr = mktmp(mkptrtype(fex.ty));
- let idx int = fld.off / fld.ty.align;
- gen("\t%v = getelementptr %t, %t %v, i32 0, i32 %d\n", ptr, ex.ty, tmp.ty, tmp, idx);
+ 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);
+ case :Union;
+ gen("\t%v = bitcast %t %v to %t\n", ptr, tmp.ty, tmp, ptr.ty);
+ }
gen("\tstore %t %v, %t %v\n", fex.ty, convert(f, fld.ty, fex), ptr.ty, ptr);
}
return tmp;
@@ -247,7 +257,8 @@ fn genaddr(f *Fn, ex *Expr) Value {
}
fn convert(f *Fn, to *const Type, ex *Expr) Value {
- let from = ex.ty;
+ to = unconstify(to);
+ let from = unconstify(ex.ty);
defmacro cvt(inst) [
(do let t = mktmp(to),
@@ -286,6 +297,21 @@ fn convert(f *Fn, to *const Type, ex *Expr) Value {
case to->is(:Flo) and from->is(:Flo) and to.size < from.size;
return cvt("fptrunc");
+
+ case to->is(:Flo) and from->is(:Int);
+ return cvt(from.u.Int.sgn ? "sitofp" : "uitofp");
+
+ 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);
+ let t1 = mktmp(to);
+ gen("\t%v =%s %t %v to %t\n", t1, to.u.Int.sgn ? "sext" : "zext", 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(:Ptr) and from->is(:Ptr);
let t = mktmp(to),
@@ -574,6 +600,24 @@ fn genexpr(f *Fn, ex *Expr) Value {
gen("\t%v = load %t, %t %v\n", val, ex.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);
+ 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);
+ 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);
+ }
+ let res = mktmp(ex.ty);
+ gen("\t%v = load %t, %t %v\n", res, res.ty, t0.ty, t0);
+ return res;
+
case Stmt block;
switch genblock(f, block) {
case Some val; return val;