aboutsummaryrefslogtreecommitdiff
path: root/src/irgen.cff
diff options
context:
space:
mode:
Diffstat (limited to 'src/irgen.cff')
-rw-r--r--src/irgen.cff73
1 files changed, 73 insertions, 0 deletions
diff --git a/src/irgen.cff b/src/irgen.cff
index 9d32bfd..e157406 100644
--- a/src/irgen.cff
+++ b/src/irgen.cff
@@ -54,6 +54,15 @@ struct InstStream {
return inst;
}
+ fn mkinst4(S *InstStream, inst0 IRInst, a IRArg, b IRArg, c IRArg, d IRArg) *IRInst {
+ let inst = S->mkinst(inst0, 4);
+ inst.args[0] = a;
+ inst.args[1] = b;
+ inst.args[2] = c;
+ inst.args[3] = d;
+ return inst;
+ }
+
fn pushnop(S *InstStream) *IRInst {
S->push(S->mkinst({:nop}, 0));
return S.tail;
@@ -190,6 +199,70 @@ fn genexpr(S *InstStream, ex *Expr) IRValue {
}
}
+ case Cast src;
+ let src = genexpr(S, src);
+ let ret = IRValue{ex.ty, .u: :Tmp(tmpid++)};
+ switch {
+ case ex.ty->is(:Int) and src.ty->is(:Flo);
+ S->push(S->mkinst2({:ftrunc}, :Val(ret), :Val(src)));
+
+ case ex.ty->is(:Flo) and src.ty->is(:Int);
+ S->push(S->mkinst2({:itof}, :Val(ret), :Val(src)));
+
+ case ex.ty->is(:Int) and src.ty->is(:Int);
+ S->push(S->mkinst2({:copy}, :Val(ret), :Val(src)));
+
+ case ex.ty->is(:Int) and src.ty->is(:Bool);
+ S->push(S->mkinst2({:copy}, :Val(ret), :Val(src)));
+
+ case ex.ty->is(:Bool) and src.ty->is(:Int);
+ S->push(S->mkinst2({:copy}, :Val(ret), :Val(src)));
+
+ case ex.ty->is(:Ptr) and src.ty->is(:Int);
+ S->push(S->mkinst2({:copy}, :Val(ret), :Val(src)));
+
+ case ex.ty->is(:Int) and src.ty->is(:Ptr);
+ S->push(S->mkinst2({:copy}, :Val(ret), :Val(src)));
+
+ case else
+ assert(#f, "bad cast");
+ }
+ return ret;
+
+ case Dot dot;
+ let lhs = genexpr(S, dot.lhs);
+ let res = IRValue{ex.ty, .u: :Tmp(tmpid++)};
+ let inst = S->mkinst4({lhs.ty->is(:Ptr) ? :pgetelem : :getelem},
+ :Val(res), :Val(lhs), :Val{ty_usize,:IImm(dot.fld.off)}, :Ty(ex.ty));
+ S->push(inst);
+ return res;
+
+ case SLen lhs;
+ let lhs = genexpr(S, lhs);
+ let res = IRValue{ex.ty, .u: :Tmp(tmpid++)};
+ let inst = S->mkinst4({lhs.ty->is(:Ptr) ? :pgetelem : :getelem},
+ :Val(res), :Val(lhs), :Val{ty_usize,:IImm(g_targ.ptrsize)},
+ :Ty(ex.ty));
+ S->push(inst);
+ return res;
+
+ case SPtr lhs;
+ let lhs = genexpr(S, lhs);
+ let res = IRValue{ex.ty, .u: :Tmp(tmpid++)};
+ let inst = S->mkinst4({lhs.ty->is(:Ptr) ? :pgetelem : :getelem},
+ :Val(res), :Val(lhs), :Val{ty_usize,:IImm(0)}, :Ty(ex.ty));
+ S->push(inst);
+ return res;
+
+ case EUTag lhs;
+ let lhs = genexpr(S, lhs);
+ let res = IRValue{ex.ty, .u: :Tmp(tmpid++)};
+ let inst = S->mkinst4({lhs.ty->is(:Ptr) ? :pgetelem : :getelem},
+ :Val(res), :Val(lhs), :Val{ty_usize,:IImm(0)}, :Ty(ex.ty));
+ S->push(inst);
+ return res;
+
+
case Index idx;
let i = genexpr(S, idx.lhs);
let off = genexpr(S, idx.rhs);