summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main.c61
-rw-r--r--test.lang7
2 files changed, 54 insertions, 14 deletions
diff --git a/main.c b/main.c
index edeb6a5..276ea69 100644
--- a/main.c
+++ b/main.c
@@ -33,6 +33,27 @@ void unit_free(Unit *u) {
Node *parse_expr(Lexer *l, Proc *p);
+/* TODO: eliminate unused if-else statements at the end of compilation
+ * they don't get pruned out by peephole optimizations if there are phi
+ * nodes that are connected to keepalive (due to still being in scope).
+ * so probably this will have to be done in a separate step after the
+ * graph has been generated.
+ */
+
+Node *ctrl(Proc *p, Node *n) {
+ if (!n) {
+ p->ctrl = node_new_lit(p, (Value) {
+ .type = { .lvl = T_XCTRL, .t = T_NONE }
+ });
+ return NULL;
+ }
+ if (p->ctrl->val.type.lvl == T_XCTRL) {
+ return NULL;
+ }
+ p->ctrl = n;
+ return n;
+}
+
void parse_return(Lexer *l, Proc *p) {
lex_next(l);
Node *n;
@@ -52,9 +73,8 @@ void parse_return(Lexer *l, Proc *p) {
if (n->val.type.lvl != T_XCTRL) {
node_add(p, n, p->stop);
}
- p->ctrl = node_new_lit(p, (Value) {
- .type = { .lvl = T_XCTRL, .t = T_NONE }
- });
+ ctrl(p, n);
+ ctrl(p, NULL);
}
void parse_let(Lexer *l, Proc *p) {
@@ -131,7 +151,7 @@ void merge_scope(Lexer *l, Proc *p, ScopeNameList *before, ScopeNameList *ntrue,
if (yes->node == b4->node && no->node == b4->node) continue;
phi = node_new(p, N_PHI, p->ctrl, yes->node, no->node);
}
- fprintf(stderr, "phi('%.*s', %d, %d)\n", (int)b4->name.n, b4->name.s, phi->in.data[1]->id, phi->in.data[2]->id);
+ //fprintf(stderr, "phi('%.*s', %d, %d)\n", (int)b4->name.n, b4->name.s, phi->in.data[1]->id, phi->in.data[2]->id);
phi = node_peephole(phi, p, l);
NameBinding *b = scope_find(&p->scope, b4->name);
assert(b);
@@ -140,6 +160,26 @@ void merge_scope(Lexer *l, Proc *p, ScopeNameList *before, ScopeNameList *ntrue,
node_remove(p, p->ctrl, p->keepalive);
}
+/* TODO: find out a way to encode known relations between nodes, based on the
+ * conditional, within the body of an if statement --- e.g., for a statement
+ *
+ * if a < 5 {
+ * if a < 10 {
+ * foo()
+ * }
+ * } else {
+ * if a > 3 {
+ * bar()
+ * }
+ * }
+ *
+ * we should be able to infer that the second condition is always true, because
+ * it's only reachable if a < 5, and 5 < 10. conversely, in the else branch,
+ * we know that a >= 5, and can use that to make assumptions on comparisons
+ * made there too!
+ *
+ */
+
void parse_if(Lexer *l, Proc *p) {
lex_next(l);
Node *cond = parse_expr(l, p);
@@ -170,20 +210,18 @@ void parse_if(Lexer *l, Proc *p) {
if (cond->val.i) if_false->val.type.lvl = T_XCTRL;
else if_true->val.type.lvl = T_XCTRL;
}
- p->ctrl = if_true;
- fprintf(stderr, ":+ %d\n", p->ctrl->id);
+ ctrl(p, if_true);
//assert(if_true->in.len > 0);
lex_expected(l, TM_LBRACE);
parse_block(l, p, &scope_true);
ctrl_if = p->ctrl;
node_add(p, ctrl_if, p->keepalive);
- fprintf(stderr, ":- %d\n", p->ctrl->id);
//assert(ctrl_if->in.len > 0);
if (l->tok == TOK_ELSE) {
for (int i = 0; i < scope_before.len; i++) {
scope_update(scope_find(&p->scope, scope_before.data[i].name), scope_before.data[i].node, p);
}
- p->ctrl = if_false;
+ ctrl(p, if_false);
lex_expect(l, TM_LBRACE);
parse_block(l, p, &scope_false);
ctrl_else = p->ctrl;
@@ -208,7 +246,7 @@ void parse_if(Lexer *l, Proc *p) {
assert(if_true->refs > 0);
assert(if_false->refs > 0);
}
- p->ctrl = region;
+ ctrl(p, region);
node_remove(p, if_true, p->keepalive);
node_remove(p, if_false, p->keepalive);
//p->ctrl = node_peephole(node_new(p, N_REGION, if_true, if_false), p, l);
@@ -217,12 +255,11 @@ void parse_if(Lexer *l, Proc *p) {
scope_uncollect(&p->scope, p, &scope_true);
scope_uncollect(&p->scope, p, &scope_false);
scope_uncollect(&p->scope, p, &scope_before);
- fprintf(stderr, "%ld\n", p->ctrl->out.len);
- node_del_out(p->ctrl, p->keepalive);
+ node_del_out(region, p->keepalive);
assert(p->ctrl == region);
/* make sure we're not orphaning any phi nodes*/
if (p->ctrl->out.len < 1) {
- p->ctrl = node_peephole(p->ctrl, p, l);
+ ctrl(p, node_peephole(p->ctrl, p, l));
}
}
diff --git a/test.lang b/test.lang
index f717086..d7f3c89 100644
--- a/test.lang
+++ b/test.lang
@@ -1,6 +1,9 @@
func main(a, b i64) i64 {
if a < b {
- return a + b
+ let t = a
+ a := b
+ b := t
}
- return b
+ /* TODO: error on failing to return from a function */
+ return a + b
}