diff options
Diffstat (limited to 'src/llvm.cff')
| -rw-r--r-- | src/llvm.cff | 54 |
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; |