summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ir.c74
-rw-r--r--test.lang4
2 files changed, 49 insertions, 29 deletions
diff --git a/ir.c b/ir.c
index 8201724..c64001e 100644
--- a/ir.c
+++ b/ir.c
@@ -6,6 +6,24 @@
extern int no_opt;
+/* convenience macros (lisp-inspired lol) */
+
+#define CAR(n) n->in.data[0]
+#define CDR(n) n->in.data[1]
+#define CAAR(n) CAR(CAR(n))
+#define CADR(n) CDR(CAR(n))
+#define CDAR(n) CAR(CDR(n))
+#define CDDR(n) CDR(CDR(n))
+#define CAAAR(n) CAR(CAAR(n))
+#define CAADR(n) CDR(CAAR(n))
+#define CADAR(n) CAR(CADR(n))
+#define CADDR(n) CDR(CADR(n))
+#define CDAAR(n) CAR(CDAR(n))
+#define CDADR(n) CDR(CDAR(n))
+#define CDDAR(n) CAR(CDDR(n))
+#define CDDDR(n) CDR(CDDR(n))
+#define T(a,b) ((a)->type == b)
+
/* types */
int type_eql(Type *a, Type *b) {
@@ -64,12 +82,13 @@ int type_check(Node *n) {
case N_CMP_LES: case N_CMP_GTR:
case N_CMP_LTE: case N_CMP_GTE:
n->val.type = (Type) { .lvl = T_TOP, .t = T_BOOL };
- return n->in.data[0]->val.type.t == T_INT && n->in.data[1]->val.type.t == T_INT;
+ return CAR(n)->val.type.t == T_INT && CDR(n)->val.type.t == T_INT;
case N_CMP_EQL:
case N_CMP_NEQ:
n->val.type = (Type) { .lvl = T_TOP, .t = T_BOOL };
- return (n->in.data[0]->val.type.t == T_INT && n->in.data[1]->val.type.t == T_INT)
- || (n->in.data[0]->val.type.t == T_BOOL && n->in.data[1]->val.type.t == T_BOOL);
+ return type_base_eql(&n->in.data[0]->val.type, &n->in.data[1]->val.type);
+ /* (n->in.data[0]->val.type.t == T_INT && n->in.data[1]->val.type.t == T_INT)
+ || (n->in.data[0]->val.type.t == T_BOOL && n->in.data[1]->val.type.t == T_BOOL); */
default:
return 1;
}
@@ -354,22 +373,6 @@ void node_peephole_in(Node *n, int idx, Proc *p, Lexer *l) {
#define NODE(...) node_peephole(node_new(p, __VA_ARGS__), p, l)
#define OP(...) NODE(n->type, __VA_ARGS__)
-#define CAR(n) n->in.data[0]
-#define CDR(n) n->in.data[1]
-#define CAAR(n) CAR(CAR(n))
-#define CADR(n) CDR(CAR(n))
-#define CDAR(n) CAR(CDR(n))
-#define CDDR(n) CDR(CDR(n))
-#define CAAAR(n) CAR(CAAR(n))
-#define CAADR(n) CDR(CAAR(n))
-#define CADAR(n) CAR(CADR(n))
-#define CADDR(n) CDR(CADR(n))
-#define CDAAR(n) CAR(CDAR(n))
-#define CDADR(n) CDR(CDAR(n))
-#define CDDAR(n) CAR(CDDR(n))
-#define CDDDR(n) CDR(CDDR(n))
-
-#define T(a,b) ((a)->type == b)
static inline int node_eql_i64(Node *n, int64_t i) {
return n->type == N_LIT && n->val.type.t == T_INT && n->val.i == i;
@@ -411,6 +414,10 @@ static inline int node_equiv_input(Node *a, Node *b) {
/* needs lexer for error reporting */
Node *node_idealize(Node *n, Proc *p, Lexer *l) {
+ if (!type_check(n)) {
+ type_err(n, l);
+ }
+
if (no_opt) return NULL;
/* try to compute a literal value */
@@ -491,9 +498,19 @@ Node *node_idealize(Node *n, Proc *p, Lexer *l) {
if (node_cmp_incompat(CAR(n)->type, CDR(n)->type) && node_equiv_input(CAR(n), CDR(n))) {
return node_new_lit_bool(p, 0);
}
+ if (CAR(n)->val.type.t == T_INT) {
+ if (T(CAR(n), N_OP_NOT) && node_equiv(CAAR(n), CDR(n))) return node_new_lit_i64(p, 0);
+ if (T(CDR(n), N_OP_NOT) && node_equiv(CDAR(n), CAR(n))) return node_new_lit_i64(p, 0);
+ }
break;
case N_OP_XOR:
- if (same) return node_new_lit_i64(p, 0);
+ if (same) {
+ switch (CAR(n)->val.type.t) {
+ case T_INT: return node_new_lit_i64(p, 0); break;
+ case T_BOOL: return node_new_lit_bool(p, 0); break;
+ default: break;
+ }
+ }
if (node_cmp_opposite(CAR(n)->type, CDR(n)->type) && node_equiv_input(CAR(n), CDR(n))) {
return node_new_lit_bool(p, 1);
}
@@ -525,27 +542,33 @@ zero_no_effect: if (node_eql_i64(CAR(n), 0)) return CDR(n);
/* transformations to help encourage constant folding */
/* the overall trend is to move them rightwards */
+ /* need to check for type compatibility */
+ #define C(a, b) type_eql(&(a)->val.type, &(b)->val.type)
if (node_op_communative(n->type)) {
/* op(lit, X) -> op(X, lit) */
if (T(CAR(n), N_LIT) && !T(CDR(n), N_LIT)) return OP(CDR(n), CAR(n));
/* op(X, op(Y,Z)) -> op(op(Y,Z), X) */
- if (!T(CAR(n), n->type) && T(CDR(n), n->type)) return OP(CDR(n), CAR(n));
+ if (!T(CAR(n), n->type) && T(CDR(n), n->type)
+ && C(CAR(n), CDAR(n))) return OP(CDR(n), CAR(n));
/* op(op(X,Y), op(Z, lit)) -> op(op(X, op(Y, Z)), lit) */
- if (T(CAR(n), n->type) && T(CDR(n), n->type) && T(CDDR(n), N_LIT)) {
+ if (T(CAR(n), n->type) && T(CDR(n), n->type) && T(CDDR(n), N_LIT)
+ && C(CAAR(n), CDAR(n)) && C(CAR(n), CDR(n))) {
return OP(OP(CAAR(n), OP(CADR(n), CDAR(n))), CDDR(n));
}
/* op(op(X, lit), lit) -> op(X, op(lit, lit)) */
if (T(CDR(n), N_LIT) && T(CAR(n), n->type)
- && !T(CAAR(n), N_LIT) && T(CADR(n), N_LIT)) {
+ && !T(CAAR(n), N_LIT) && T(CADR(n), N_LIT)
+ && C(CADR(n), CDR(n))) {
return OP(CAAR(n), OP(CADR(n), CDR(n)));
}
/* op(op(X, lit), Y) -> op(op(X, Y), lit) */
if (T(CAR(n), n->type) && !T(CAAR(n), N_LIT)
- && T(CADR(n), N_LIT) && !T(CDR(n), N_LIT)) {
+ && T(CADR(n), N_LIT) && !T(CDR(n), N_LIT)
+ && C(CADR(n), CDR(n))) {
return OP(OP(CAAR(n), CDR(n)), CADR(n));
}
}
@@ -564,9 +587,6 @@ Node *node_peephole(Node *n, Proc *p, Lexer *l) {
n = r;
}
/* FIXME: figure out why this shows the wrong position when in an assignment */
- if (!type_check(n)) {
- type_err(n, l);
- }
return n;
}
diff --git a/test.lang b/test.lang
index af8927d..bda2c90 100644
--- a/test.lang
+++ b/test.lang
@@ -9,6 +9,6 @@
// also single-line now
proc main(a i64, b i64) {
- let c = a + b
- return (a - b) = (((a + b) - b) - b)
+ return (a = a) & (b = a)
+ // (true = 0) = (a xor b)
}