aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2022-08-22 13:07:20 +0200
committerlemon <lsof@mailbox.org>2022-08-22 13:07:20 +0200
commitc9bcf39a2ad78c7bc9cbfaab43e03771899cfa44 (patch)
treebd3c305a3d6b558fde1f04e9683d0f97bb4f8620
parent135e66c64adf0ef5d2723c243d2f2f6a059ae753 (diff)
ir
-rw-r--r--bootstrap/parse.c2
-rw-r--r--src/ir.hff4
-rw-r--r--src/irdump.cff7
-rw-r--r--src/irgen.cff73
-rw-r--r--src/parse.cff4
5 files changed, 86 insertions, 4 deletions
diff --git a/bootstrap/parse.c b/bootstrap/parse.c
index 91c7567..99d317a 100644
--- a/bootstrap/parse.c
+++ b/bootstrap/parse.c
@@ -1809,7 +1809,7 @@ pexlog(struct parser *P) {
struct expr rhs = pexcmp(P);
if (tokt == '?\?') {
const struct type *ty = typeof2(ex.ty, rhs.ty);
- if (ex.ty->t != TYptr || rhs.ty->t != TYptr || !ty)
+ if (!(ex.ty->t == TYptr || rhs.ty->t == TYptr) || !ty)
fatal(P, tok.span,
"invalid operands %t and %t to binary operator %k",
ex.ty, rhs.ty, tok.t);
diff --git a/src/ir.hff b/src/ir.hff
index 3b8ae99..2f7b98f 100644
--- a/src/ir.hff
+++ b/src/ir.hff
@@ -54,6 +54,10 @@ enum IRInstT {
neq,
lt,
lteq,
+ ftrunc,
+ itof,
+ getelem,
+ pgetelem,
copy,
setvar,
load,
diff --git a/src/irdump.cff b/src/irdump.cff
index ee68f91..9d31935 100644
--- a/src/irdump.cff
+++ b/src/irdump.cff
@@ -138,8 +138,13 @@ extern fn irdump(inst *IRInst) void {
dump("\n");
continue #'dump;
}
+ exprinst(:ftrunc, "ftrunc", 2);
+ exprinst(:itof, "itof", 2);
+ exprinst(:getelem, "getelem", 4);
+ exprinst(:pgetelem, "pgetelem", 4);
+
stmtinst(:nop, "nop", 0);
- exprinst(:copy, "copy", 2)
+ exprinst(:copy, "copy", 2);
if inst.t == :setvar {
dump("set %a, %a\n", inst.args[0], inst.args[1]);
continue #'dump;
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);
diff --git a/src/parse.cff b/src/parse.cff
index 11c17cc..a1f0dd0 100644
--- a/src/parse.cff
+++ b/src/parse.cff
@@ -1609,8 +1609,8 @@ fn pexpostfix(P *Parser) Expr {
ty = ty.u.Ptr;
}
switch ty.u {
- case Slice;
- ex = { tok.loc, ty_usize, :SPtr(exprdup(P.alloc, ex)) };
+ case Slice sl;
+ ex = { tok.loc, mkptrtype(sl), :SPtr(exprdup(P.alloc, ex)) };
case else;
fatal(P, ex.loc, "invalid operand to `#len' (%t)", ex.ty);
}