summaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
authorWormHeamer2025-08-30 23:20:51 -0400
committerWormHeamer2025-08-30 23:20:51 -0400
commitcbca8b454309122632615f0bcb787bc898503df9 (patch)
tree5b888ba81858df7f45baffe4a760d816cd59cd08 /main.c
parent6e419a23faf6550c3d3e986796ccf33bdec79c74 (diff)
separate IR graph parts of Proc into a Graph struct
Diffstat (limited to 'main.c')
-rw-r--r--main.c177
1 files changed, 95 insertions, 82 deletions
diff --git a/main.c b/main.c
index 1787245..debb0ae 100644
--- a/main.c
+++ b/main.c
@@ -12,6 +12,7 @@
#include "strio.h"
#include "ir.h"
#include "peephole.h"
+#include "proc.h"
int no_opt = 0;
@@ -41,7 +42,7 @@ Node *parse_expr(Lexer *l, Proc *p, Type *twant);
* graph has been generated.
*/
-Node *ctrl(Proc *p, Node *n) {
+Node *ctrl(Graph *p, Node *n) {
if (!n) {
p->ctrl = node_new_lit(p, (Value) {
.type = { .lvl = T_XCTRL, .t = T_NONE }
@@ -55,18 +56,19 @@ Node *ctrl(Proc *p, Node *n) {
void parse_return(Lexer *l, Proc *p) {
lex_next(l);
Node *n;
+ Graph *g = &p->graph;
if (p->ret_type.t == T_NONE) {
- n = node_new(p, N_RETURN, p->ctrl);
+ n = node_new(g, N_RETURN, g->ctrl);
} else {
Node *e = parse_expr(l, p, &p->ret_type);
- n = node_new(p, N_RETURN, p->ctrl, e);
+ n = node_new(g, N_RETURN, g->ctrl, e);
}
- n = node_peephole(n, p, l);
+ n = node_peephole(n, g, l);
if (n->type.lvl != T_XCTRL) {
- node_add(p, n, p->stop);
+ node_add(g, n, g->stop);
}
- ctrl(p, n);
- ctrl(p, NULL);
+ ctrl(g, n);
+ ctrl(g, NULL);
}
Type parse_type(Lexer *l, Proc *proc) {
@@ -94,6 +96,7 @@ Type parse_type(Lexer *l, Proc *proc) {
}
void parse_let(Lexer *l, Proc *p) {
+ Graph *g = &p->graph;
recurse:
lex_expect(l, TM_IDENT);
Str name = l->ident;
@@ -104,7 +107,7 @@ recurse:
if (l->tok != TOK_EQL) {
t = parse_type(l, p);
if (l->tok != TOK_EQL) {
- rhs = node_new(p, N_UNINIT, p->start);
+ rhs = node_new(g, N_UNINIT, g->start);
rhs->type = t;
}
}
@@ -112,11 +115,12 @@ recurse:
lex_next(l);
rhs = parse_expr(l, p, t.t == T_NONE ? NULL : &t);
}
- NameBinding *b = scope_bind(&p->scope, name, rhs, pos, p);
+ NameBinding *b = scope_bind(&p->scope, name, rhs, pos, g);
if (b) {
lex_error_at(l, pos, LE_WARN, S("shadowing previous declaration"));
lex_error_at(l, b->src_pos, LE_WARN, S("declared here"));
}
+ /* TODO: isn't this just a do while loop */
if (l->tok == TOK_COMMA) goto recurse;
}
@@ -124,17 +128,18 @@ void parse_stmt(Lexer *l, Proc *p);
/* TODO: return node from this! */
void parse_block(Lexer *l, Proc *p, ScopeNameList *nl) {
+ Graph *g = &p->graph;
lex_next(l);
arena_reset(&p->scratch);
- scope_push(&p->scope, p);
+ scope_push(&p->scope);
while (l->tok != TOK_RBRACE) {
lex_expected_not(l, TM_EOF);
parse_stmt(l, p);
}
if (nl) {
- scope_collect(&p->scope, p, nl, &p->scratch);
+ scope_collect(&p->scope, g, nl, &p->scratch);
}
- scope_pop(&p->scope, p);
+ scope_pop(&p->scope, g);
lex_expected(l, TM_RBRACE);
lex_next(l);
}
@@ -158,7 +163,7 @@ void parse_assign(Lexer *l, Proc *p) {
str_fmt(&p->scratch, "possibly uninitialized %S",
type_desc(&e->type, &p->scratch)));
}
- scope_update(b, e, p);
+ scope_update(b, e, &p->graph);
}
/* TODO: Implement a better system for this.
@@ -195,6 +200,7 @@ void parse_assign(Lexer *l, Proc *p) {
*/
void merge_scope(Lexer *l, Proc *p, Node *region, ScopeNameList *before, ScopeNameList *ntrue, ScopeNameList *nfalse) {
+ Graph *g = &p->graph;
for (int i = 0; i < before->len; i++) {
int j, k;
ScopeName *b4 = &before->data[i];
@@ -206,18 +212,18 @@ void merge_scope(Lexer *l, Proc *p, Node *region, ScopeNameList *before, ScopeNa
Node *phi;
if (!no) {
if (yes->node == b4->node) continue;
- phi = node_new(p, N_PHI, region, yes->node, b4->node);
+ phi = node_new(g, N_PHI, region, yes->node, b4->node);
} else if (!yes) {
if (no->node == b4->node) continue;
- phi = node_new(p, N_PHI, region, b4->node, no->node);
+ phi = node_new(g, N_PHI, region, b4->node, no->node);
} else {
if (yes->node == b4->node && no->node == b4->node) continue;
- phi = node_new(p, N_PHI, region, yes->node, no->node);
+ phi = node_new(g, N_PHI, region, yes->node, no->node);
}
- phi = node_peephole(phi, p, l);
+ phi = node_peephole(phi, g, l);
NameBinding *b = scope_find(&p->scope, b4->name);
assert(b);
- scope_update(b, phi, p);
+ scope_update(b, phi, g);
}
}
@@ -242,85 +248,86 @@ void merge_scope(Lexer *l, Proc *p, Node *region, ScopeNameList *before, ScopeNa
*/
void parse_if(Lexer *l, Proc *p) {
+ Graph *g = &p->graph;
lex_next(l);
Node *cond = parse_expr(l, p, &(Type) { .t = T_BOOL });
Node *ctrl_if = NULL, *ctrl_else = NULL;
- Node *if_node = node_new(p, N_IF_ELSE, p->ctrl, cond);
+ Node *if_node = node_new(g, N_IF_ELSE, g->ctrl, cond);
if_node->val = (Value) {
.type = { .lvl = T_TOP, .t = T_TUPLE },
.tuple = { 0 }
};
- ZDA_PUSH(&p->perm, &if_node->val.tuple, (Value) { .type = { .lvl = T_CTRL, .t = T_NONE } });
- ZDA_PUSH(&p->perm, &if_node->val.tuple, (Value) { .type = { .lvl = T_CTRL, .t = T_NONE } });
- if_node = node_peephole(if_node, p, l);
- node_add(p, if_node, p->keepalive);
- Node *if_true = node_new(p, N_PROJ, if_node);
- Node *if_false = node_new(p, N_PROJ, if_node);
+ ZDA_PUSH(g->pool->arena, &if_node->val.tuple, (Value) { .type = { .lvl = T_CTRL, .t = T_NONE } });
+ ZDA_PUSH(g->pool->arena, &if_node->val.tuple, (Value) { .type = { .lvl = T_CTRL, .t = T_NONE } });
+ if_node = node_peephole(if_node, g, l);
+ node_add(g, if_node, g->keepalive);
+ Node *if_true = node_new(g, N_PROJ, if_node);
+ Node *if_false = node_new(g, N_PROJ, if_node);
if_true->val.i = 0;
if_false->val.i = 1;
- if_true = node_peephole(if_true, p, l);
- if_false = node_peephole(if_false, p, l);
- node_remove(p, if_node, p->keepalive);
+ if_true = node_peephole(if_true, g, l);
+ if_false = node_peephole(if_false, g, l);
+ node_remove(g, if_node, g->keepalive);
assert(if_true->in.len > 0);
assert(if_false->in.len > 0);
- node_add(p, if_true, p->keepalive);
- node_add(p, if_false, p->keepalive);
+ node_add(g, if_true, g->keepalive);
+ node_add(g, if_false, g->keepalive);
ScopeNameList scope_before = { 0 }, scope_true = { 0 }, scope_false = { 0 };
- scope_collect(&p->scope, p, &scope_before, &p->scratch);
+ scope_collect(&p->scope, g, &scope_before, &p->scratch);
if (cond->type.lvl == T_CONST) {
if (cond->val.i) if_false->type.lvl = T_XCTRL;
else if_true->type.lvl = T_XCTRL;
}
- ctrl(p, if_true);
+ ctrl(g, if_true);
lex_expected(l, TM_LBRACE);
int pos = l->pos.ofs;
parse_block(l, p, &scope_true);
if_true->src_pos = (LexSpan) { .ofs = pos, .n = l->pos.ofs - pos };
- ctrl_if = p->ctrl;
- node_add(p, ctrl_if, p->keepalive);
+ ctrl_if = g->ctrl;
+ node_add(g, ctrl_if, g->keepalive);
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);
+ scope_update(scope_find(&p->scope, scope_before.data[i].name), scope_before.data[i].node, g);
}
- ctrl(p, if_false);
+ ctrl(g, if_false);
lex_expect(l, TM_LBRACE);
pos = l->pos.ofs;
parse_block(l, p, &scope_false);
if_false->src_pos = (LexSpan) { .ofs = pos, .n = l->pos.ofs - pos };
- ctrl_else = p->ctrl;
- node_add(p, ctrl_else, p->keepalive);
+ ctrl_else = g->ctrl;
+ node_add(g, ctrl_else, g->keepalive);
}
Node *region;
if (ctrl_else) {
assert(ctrl_if);
assert(ctrl_else);
- region = node_new(p, N_REGION, ctrl_if, ctrl_else);
- node_add_out(p, region, p->keepalive);
- node_remove(p, ctrl_if, p->keepalive);
- node_remove(p, ctrl_else, p->keepalive);
+ region = node_new(g, N_REGION, ctrl_if, ctrl_else);
+ node_add_out(g, region, g->keepalive);
+ node_remove(g, ctrl_if, g->keepalive);
+ node_remove(g, ctrl_else, g->keepalive);
} else {
assert(ctrl_if);
assert(if_false);
- region = node_new(p, N_REGION, ctrl_if, if_false);
- node_add_out(p, region, p->keepalive);
- node_remove(p, ctrl_if, p->keepalive);
+ region = node_new(g, N_REGION, ctrl_if, if_false);
+ node_add_out(g, region, g->keepalive);
+ node_remove(g, ctrl_if, g->keepalive);
assert(if_true->refs > 0);
assert(if_false->refs > 0);
}
- ctrl(p, region);
- node_remove(p, if_true, p->keepalive);
- node_remove(p, if_false, p->keepalive);
- assert(p->ctrl->in.len > 0);
+ ctrl(g, region);
+ node_remove(g, if_true, g->keepalive);
+ node_remove(g, if_false, g->keepalive);
+ assert(g->ctrl->in.len > 0);
assert(region->in.data[0]);
assert(region->in.data[1]);
merge_scope(l, p, region, &scope_before, &scope_true, &scope_false);
- scope_uncollect(&p->scope, p, &scope_true);
- scope_uncollect(&p->scope, p, &scope_false);
- scope_uncollect(&p->scope, p, &scope_before);
- node_del_out(region, p->keepalive);
+ scope_uncollect(&p->scope, g, &scope_true);
+ scope_uncollect(&p->scope, g, &scope_false);
+ scope_uncollect(&p->scope, g, &scope_before);
+ node_del_out(region, g->keepalive);
/* make sure we're not orphaning any phi nodes*/
- if (p->ctrl->out.len < 1) {
- ctrl(p, node_peephole(p->ctrl, p, l));
+ if (g->ctrl->out.len < 1) {
+ ctrl(g, node_peephole(g->ctrl, g, l));
}
}
@@ -350,7 +357,8 @@ void parse_stmt(Lexer *l, Proc *p) {
}
void parse_args_list(Lexer *l, Proc *proc) {
- Node *start = proc->start;
+ Node *start = proc->graph.start;
+ Graph *g = &proc->graph;
int i = 0;
struct {
Str name;
@@ -371,11 +379,11 @@ void parse_args_list(Lexer *l, Proc *proc) {
Value v = (Value) { .type = parse_type(l, proc) };
lex_expected(l, TM_RPAREN | TM_COMMA);
for (int j = 0; j < id; j++) {
- Node *proj = node_new(proc, N_PROJ, proc->start);
+ Node *proj = node_new(g, N_PROJ, start);
proj->type = v.type;
proj->val.i = i++;
ZDA_PUSH(&proc->perm, &start->val.tuple, v);
- scope_bind(&proc->scope, idbuf[j].name, proj, idbuf[j].pos, proc);
+ scope_bind(&proc->scope, idbuf[j].name, proj, idbuf[j].pos, g);
}
id = 0;
}
@@ -393,6 +401,7 @@ Node *find_return(Node *n) {
}
void proc_opt_fwd(Proc *p, Lexer *l, Node *n) {
+ Graph *g = &p->graph;
if (n->walked == 2) return;
n->walked = 2;
switch (n->op) {
@@ -427,7 +436,7 @@ void proc_opt_fwd(Proc *p, Lexer *l, Node *n) {
assert(n->out.data[0]->in.data[0] == n);
Node *new_ctrl = CTRL(CTRL(CTRL(n)));
Node *out = n->out.data[0];
- node_set_in(p, out, 0, new_ctrl);
+ node_set_in(g, out, 0, new_ctrl);
proc_opt_fwd(p, l, new_ctrl);
return;
}
@@ -443,19 +452,20 @@ void proc_opt_fwd(Proc *p, Lexer *l, Node *n) {
}
void proc_opt(Proc *p, Lexer *l) {
- if (p->stop->in.len == 0) {
+ Graph *g = &p->graph;
+ if (g->stop->in.len == 0) {
if (p->ret_type.t != T_NONE) {
lex_error(l, LE_ERROR, str_fmt(&p->scratch, "no return statement in function expecting %S", type_desc(&p->ret_type, &p->scratch)));
}
}
- for (int i = 0; i < p->start->out.len; i++) {
- Node *n = p->start->out.data[i];
+ for (int i = 0; i < g->start->out.len; i++) {
+ Node *n = g->start->out.data[i];
if (n->op == N_LIT && n->out.len < 1) {
- node_kill(n, p);
+ node_kill(n, g);
i--;
}
}
- proc_opt_fwd(p, l, p->start);
+ proc_opt_fwd(p, l, g->start);
}
Proc *parse_proc(Lexer *l, Unit *u) {
@@ -464,7 +474,7 @@ Proc *parse_proc(Lexer *l, Unit *u) {
Proc *proc = &u->procs.data[u->procs.len++];
lex_expect(l, TM_IDENT);
proc_init(proc, l->ident);
- scope_push(&proc->scope, proc);
+ scope_push(&proc->scope);
lex_next(l);
if (l->tok == TOK_LPAREN) {
parse_args_list(l, proc);
@@ -480,22 +490,22 @@ Proc *parse_proc(Lexer *l, Unit *u) {
lex_expected_not(l, TM_EOF);
parse_stmt(l, proc);
}
- scope_pop(&proc->scope, proc);
+ scope_pop(&proc->scope, &proc->graph);
lex_expected(l, TM_RBRACE);
lex_next(l);
proc_opt(proc, l);
return proc;
}
-void uninit_check(Lexer *l, Proc *p, Node *n, LexSpan pos) {
+void uninit_check(Lexer *l, Node *n, LexSpan pos) {
if (node_uninit(n)) {
lex_error_at(l, pos, LE_ERROR,
- str_fmt(&p->scratch, "uninitialized %S",
- type_desc(&n->type, &p->scratch)));
+ str_fmt(&l->arena, "uninitialized %S",
+ type_desc(&n->type, &l->arena)));
} else if (node_maybe_uninit(n)) {
lex_error_at(l, pos, LE_WARN,
- str_fmt(&p->scratch, "possibly uninitialized %S",
- type_desc(&n->type, &p->scratch)));
+ str_fmt(&l->arena, "possibly uninitialized %S",
+ type_desc(&n->type, &l->arena)));
}
}
@@ -503,6 +513,7 @@ Node *parse_term(Lexer *l, Proc *p, Type *twant) {
(void)twant; /* to be used for .ENUM_TYPE and stuff */
Node *node = NULL;
NodeType op_after = N_START;
+ Graph *g = &p->graph;
if (TMASK(l->tok) & (TM_MINUS | TM_PLUS | TM_NOT)) {
Token t = l->tok;
lex_next(l);
@@ -514,7 +525,7 @@ Node *parse_term(Lexer *l, Proc *p, Type *twant) {
default: return node;
}
if (post_op == N_START) return node;
- return node_peephole(node_new(p, post_op, NULL, node), p, l);
+ return node_peephole(node_new(g, post_op, NULL, node), g, l);
}
if (l->tok == TOK_LPAREN) {
lex_next(l);
@@ -530,10 +541,10 @@ Node *parse_term(Lexer *l, Proc *p, Type *twant) {
} else {
lex_error(l, LE_ERROR, S("undeclared identifier"));
}
- uninit_check(l, p, node, l->pos);
+ uninit_check(l, node, l->pos);
lex_next(l);
} else if (TMASK(l->tok) & (TM_TRUE | TM_FALSE)) {
- node = node_new_lit_bool(p, l->tok == TOK_TRUE);
+ node = node_new_lit_bool(g, l->tok == TOK_TRUE);
lex_next(l);
} else {
lex_expected(l, TM_LIT_NUM);
@@ -545,14 +556,14 @@ Node *parse_term(Lexer *l, Proc *p, Type *twant) {
}
val = (val * 10) + (l->ident.s[i] - '0');
}
- node = node_new_lit_i64(p, val);
+ node = node_new_lit_i64(g, val);
node->src_pos = l->pos;
lex_next(l);
}
if (op_after != N_START) {
- node = node_new(p, op_after, NULL, node_peephole(node, p, l));
+ node = node_new(g, op_after, NULL, node_peephole(node, g, l));
}
- return node_peephole(node, p, l);
+ return node_peephole(node, g, l);
}
NodeType tok_to_bin_op(Token t) {
@@ -580,6 +591,7 @@ NodeType tok_to_bin_op(Token t) {
/* TODO: operator precedence would be kinda nice actually, sad to say */
Node *parse_expr(Lexer *l, Proc *p, Type *twant) {
LexSpan pos = l->pos;
+ Graph *g = &p->graph;
Node *lhs = parse_term(l, p, twant);
NodeType nt = tok_to_bin_op(l->tok);;
if (lhs->refs <= 0) lex_error(l, LE_ERROR, S("dead lhs"));
@@ -589,10 +601,10 @@ Node *parse_expr(Lexer *l, Proc *p, Type *twant) {
/* necessary because if lhs is a deduplicated literal, it may be an input to rhs
* and therefore culled by peephole optimizations */
Node *rhs;
- NODE_KEEP(p, lhs, {
+ NODE_KEEP(g, lhs, {
rhs = parse_expr(l, p, &lhs->type);
});
- lhs = node_peephole(node_new(p, nt, NULL, lhs, rhs), p, l);
+ lhs = node_peephole(node_new(g, nt, NULL, lhs, rhs), g, l);
}
lhs->src_pos = (LexSpan) { pos.ofs, l->pos.ofs - pos.ofs };
if (twant) type_expected(twant, lhs, l);
@@ -689,10 +701,11 @@ void node_print(Node *n, Proc *p) {
}
void proc_print(Proc *p) {
- if (p->start) {
+ Graph *g = &p->graph;
+ if (g->start) {
Str d = type_desc(&p->ret_type, &p->scratch);
- printf("\t\"%.*s %.*s\" -> %d\n", (int)p->name.n, p->name.s, (int)d.n, d.s, p->start->id);
- node_print(p->start, p);
+ printf("\t\"%.*s %.*s\" -> %d\n", (int)p->name.n, p->name.s, (int)d.n, d.s, g->start->id);
+ node_print(g->start, p);
if (no_opt) {
for (NameBinding *b = p->scope.free_bind; b; b = b->prev) {
uint64_t id = (uintptr_t)b->node;