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