summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ir.c43
-rw-r--r--ir.h29
-rw-r--r--test.lang2
3 files changed, 53 insertions, 21 deletions
diff --git a/ir.c b/ir.c
index c75113e..0ef19b9 100644
--- a/ir.c
+++ b/ir.c
@@ -3,9 +3,20 @@
extern int no_opt;
+/* types */
+
+int type_eql(Type *a, Type *b) {
+ if (a->t != b->t) return 0;
+ if (a->next != b->next) return 0;
+ return a->next ? type_eql(a->next, b->next) : 1;
+}
+
+/* nodes */
+
const char *node_type_name(NodeType t) {
const char *names[] = {
"start",
+ "projection",
"return",
"keepalive",
"literal",
@@ -50,18 +61,19 @@ void node_del_in(Node *n, Node *p) {
}
void node_kill(Node *n, Proc *p) {
- for (int i = 0; i < n->in.len; i++) {
+ if (n->refs < 1) return;
+ while (n->in.len > 0) {
+ int i = --n->in.len;
node_del_out(n->in.data[i], n);
n->in.data[i]->refs--;
if (n->in.data[i]->out.len < 1) node_kill(n->in.data[i], p);
}
- for (int i = 0; i < n->out.len; i++) {
+ while (n->out.len > 0) {
+ int i = --n->out.len;
node_del_in(n->out.data[i], n);
n->out.data[i]->refs--;
if (n->out.data[i]->refs < 1) node_die(n->out.data[i], p);
}
- n->in.len = 0;
- n->out.len = 0;
node_die(n, p);
}
@@ -116,7 +128,7 @@ Node *node_dedup_lit(Proc *p, Value v) {
* how many literals even usually occur in a procedure? */
for (int i = 0; i < p->start->out.len; i++) {
Node *t = p->start->out.data[i];
- if (t->type == N_LIT && t->val.type == v.type && t->val.i == v.i) {
+ if (t->type == N_LIT && type_eql(&t->val.type, &v.type) && t->val.i == v.i) {
return t;
}
}
@@ -124,7 +136,7 @@ Node *node_dedup_lit(Proc *p, Value v) {
}
Node *node_new_lit_i64(Proc *p, int64_t i) {
- Value v = (Value) { T_INT, { .i = i } };
+ Value v = (Value) { { .lvl = T_CONST, .t = T_INT }, { .i = i } };
Node *t = node_dedup_lit(p, v);
if (t) return t;
Node *n = node_new(p, N_LIT, p->start);
@@ -141,21 +153,24 @@ static inline int node_op_communative(NodeType t) {
}
Value node_compute(Node *n, Lexer *l) {
- Type lit_type = T_BOT;
+ Type lit_type = { .lvl = T_BOT };
Node **in = n->in.data;
for (int i = 0; i < n->in.len; i++) {
Node *p = in[i];
- if (p->type != N_LIT) break;
- if (p->val.type != lit_type) {
- if (lit_type == T_BOT) {
+ if (p->val.type.lvl != T_CONST) {
+ lit_type.lvl = T_BOT;
+ break;
+ }
+ if (!type_eql(&p->val.type, &lit_type)) {
+ if (lit_type.lvl == T_BOT) {
lit_type = p->val.type;
} else {
- lit_type = T_BOT;
+ lit_type.lvl = T_BOT;
break;
}
}
}
- if (lit_type == T_INT) {
+ if (lit_type.lvl == T_CONST && lit_type.t == T_INT) {
Value v = { .type = lit_type };
switch (n->type) {
case N_OP_NEG: v.i = -in[0]->val.i; break;
@@ -187,7 +202,7 @@ Node *node_peephole(Node *n, Proc *p, Lexer *l) {
if (n->type != N_LIT) {
Value v = node_compute(n, l);
- if (v.type > T_CONST) {
+ if (v.type.lvl == T_CONST) {
node_kill(n, p);
Node *t = node_dedup_lit(p, v);
if (t) return t;
@@ -310,8 +325,8 @@ NameBinding *scope_bind(Scope *scope, Str name, Node *value, LexSpan pos, Proc *
NameBinding *scope_update(Scope *scope, Str name, Node *to, Proc *proc) {
NameBinding *b = scope_find(scope, name);
if (!b) return NULL;
- node_remove(proc, b->node, proc->keepalive);
node_add(proc, to, proc->keepalive);
+ node_remove(proc, b->node, proc->keepalive);
b->node = to;
return b;
}
diff --git a/ir.h b/ir.h
index 9351864..72586f2 100644
--- a/ir.h
+++ b/ir.h
@@ -6,10 +6,32 @@
#include "lex.h" /* for error reporting only */
#include "str.h"
+/* types */
+
+typedef enum {
+ T_TOP, /* may or may not be a constant */
+ T_CONST, /* known compile-time constant */
+ T_BOT, /* known not a constant */
+} TypeLevel;
+
+typedef enum {
+ T_TUPLE,
+ T_INT
+} BaseType;
+
+typedef struct Type {
+ BaseType t;
+ TypeLevel lvl;
+ struct Type *next;
+} Type;
+
+int type_eql(Type *a, Type *b);
+
/* nodes */
typedef enum {
N_START,
+ N_PROJ,
N_RETURN,
N_KEEPALIVE,
N_LIT,
@@ -22,13 +44,6 @@ typedef enum {
const char *node_type_name(NodeType t);
-typedef enum {
- T_BOT,
- T_TOP,
- T_CONST,
- T_INT
-} Type;
-
typedef struct {
Type type;
union {
diff --git a/test.lang b/test.lang
index 0f2d4b8..a0a325f 100644
--- a/test.lang
+++ b/test.lang
@@ -13,5 +13,7 @@ proc main {
let b = 1 << a
let c = b xor 2381
b := b + c
+ a := a + 12
+ b := b + 27
return (a + b) * c
}