diff options
Diffstat (limited to 'src/irgen.cff')
| -rw-r--r-- | src/irgen.cff | 100 |
1 files changed, 75 insertions, 25 deletions
diff --git a/src/irgen.cff b/src/irgen.cff index 1cd5172..9d32bfd 100644 --- a/src/irgen.cff +++ b/src/irgen.cff @@ -3,6 +3,7 @@ import "common.hff"; import "map.hff"; extern fn ir_genstatic(IR *IRCtx, decl *Decl) void { + g_targ.B.genstaticf(g_targ.B, decl); } struct IntTraits { @@ -64,7 +65,7 @@ fn genblock(S *InstStream, block [#]Stmt) void; fn genexpr(S *InstStream, ex *Expr) IRValue { static tmpid int = 0; - // fold(ex); + fold(ex); defmacro genunop(u,t) [ { let child = genexpr(S, (u).ex); @@ -94,7 +95,12 @@ fn genexpr(S *InstStream, ex *Expr) IRValue { case :neg; genunop(u, ex.ty->is(:Int) ? :neg : :fneg); case :not; genunop(u, :not); case :compl; genunop(u, :compl); - case :deref; genunop(u, :load); + case :deref; + let child = genexpr(S, (u).ex); + let res = IRValue{ex.ty, .u: :Tmp(tmpid++)}; + let inst = S->mkinst3({:load}, :Val(res), :Val(child), :Val{ty_int,:IImm(0)}); + S->push(inst); + return res; case :preinc, :predec; let one = u.op == :preinc ? 1 : -1; switch u.ex.u { @@ -106,14 +112,8 @@ fn genexpr(S *InstStream, ex *Expr) IRValue { S->push(rhs); let inst = S->mkinst2({:setvar}, :Val(ex), :Val(inced)); S->push(inst); - let ex = genexpr(S, u.ex); - if decl.u.#tag == :Let { - return {ex.ty, :Local(decl)}; - } else { - return {ex.ty, :Global(decl)}; - } + return inced; } - } case BinOp b; switch b.op { @@ -146,27 +146,58 @@ fn genexpr(S *InstStream, ex *Expr) IRValue { S->push(inst); return res; case '='; - switch b.lhs.u { + switch b.lhs.u { // var = ex case Symbol decl; - let inst = S->mkinst2({:setvar}, :Val(genexpr(S, b.lhs)), :Val(genexpr(S, b.rhs))); + let r = genexpr(S, b.rhs); + let inst = S->mkinst2({:setvar}, :Val(genexpr(S, b.lhs)), :Val(r)); S->push(inst); - if decl.u.#tag == :Let { - return {ex.ty, :Local(decl)}; - } else { - return {ex.ty, :Global(decl)}; - } - case UnOp u; + return r; + case UnOp u; // *a = ex assert(u.op == :deref, "deref?? unop="); let child = genexpr(S, u.ex); - let inst = S->mkinst2({:store}, :Val(child), :Val(genexpr(S, b.rhs))); + let r = genexpr(S, b.rhs); + let inst = S->mkinst3({:store}, :Val(child), :Val{ty_int,:IImm(0)}, :Val(r)); S->push(inst); - let it = genexpr(S, b.lhs); - return it; - + return r; + case Index index; // a[b] = ex + let indexee = genexpr(S, index.lhs); + let index = genexpr(S, index.rhs); + let newval = genexpr(S, b.rhs); + S->push(S->mkinst3({:store}, :Val(indexee), :Val(index), :Val(newval))); + return newval; case else assert(#f, "nyi ="); } + case '+=', '-=', '*=', '/=', '%=', '&=', '|=', '^=', '<<=', '>>='; + let o IRInstT = b.op == '+=' ? (ex.ty->is(:Flo) ? :fadd : :add) + : b.op == '-=' ? (ex.ty->is(:Flo) ? :fsub : :sub) + : b.op == '*=' ? (ex.ty->is(:Flo) ? :fmul : :mul) + : b.op == '/=' ? (ex.ty->is(:Flo) ? :fdiv : :div) + : b.op == '%=' ? :mod + : b.op == '&=' ? :band + : b.op == '|=' ? :bor + : b.op == '<<=' ? :lsl + : b.op == '>>=' ? (ex.ty.u.Int.sgn ? :asr : :lsr) : :nop; + switch b.lhs.u { + case Symbol decl; // var += ex + let lhs = genexpr(S, b.lhs); + let rhs = genexpr(S, b.rhs); + let new = IRValue{ex.ty, .u: :Tmp(tmpid++)}; + S->push(S->mkinst3({o}, :Val(new), :Val(lhs), :Val(rhs))); + let inst = S->mkinst2({:setvar}, :Val(lhs), :Val(new)); + S->push(inst); + return new; + } + } + case Index idx; + let i = genexpr(S, idx.lhs); + let off = genexpr(S, idx.rhs); + let res = IRValue{ex.ty, .u: :Tmp(tmpid++)}; + let inst = S->mkinst3({:load}, :Val(res), :Val(i), :Val(off)); + S->push(inst); + return res; + case Cond c; let test = genexpr(S, c.test); let beqz = S->mkinst1({:beqz}, :Val(test)); @@ -226,6 +257,15 @@ fn genstmt(S *InstStream, stmt *Stmt) void { } case If If; + #{ + %t = <test> + beqz %t, .L0 + <t> + b .L1 + .L0: + <f> + .L1: + } let t = genexpr(S, &If.test); let beqz = S->mkinst1({:beqz}, :Val(t)); S->push(beqz); @@ -241,6 +281,14 @@ fn genstmt(S *InstStream, stmt *Stmt) void { } case While loop; + #{ + .cont: + %t = <test> + beqz %t, .brk + <body> + b .cont + .brk: + } let begin = S->pushnop(); let t = genexpr(S, &loop.test); let beqz = S->mkinst1({:beqz}, :Val(t)); @@ -277,12 +325,14 @@ fn genstmt(S *InstStream, stmt *Stmt) void { beqz.branch = end; case Break id; - let jumpto = *S.loopbrks->get(id); - S->push(S->mkinst({:b, .branch: jumpto},0)); + let jumpto = S.loopbrks->get(id); + assert(jumpto != #null, "no brk label %d", id); + S->push(S->mkinst({:b, .branch: *jumpto},0)); case Continue id; - let jumpto = *S.loopconts->get(id); - S->push(S->mkinst({:b, .branch: jumpto},0)); + let jumpto = S.loopconts->get(id); + assert(jumpto != #null, "no cont label %d", id); + S->push(S->mkinst({:b, .branch: *jumpto},0)); case Return retex; if retex->empty() { |