aboutsummaryrefslogtreecommitdiff
path: root/src/irgen.cff
diff options
context:
space:
mode:
Diffstat (limited to 'src/irgen.cff')
-rw-r--r--src/irgen.cff100
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() {