From cbca8b454309122632615f0bcb787bc898503df9 Mon Sep 17 00:00:00 2001 From: WormHeamer Date: Sat, 30 Aug 2025 23:20:51 -0400 Subject: separate IR graph parts of Proc into a Graph struct --- main.c | 177 +++++++++++++++++++++++++++++++++++------------------------------ 1 file changed, 95 insertions(+), 82 deletions(-) (limited to 'main.c') 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; -- cgit v1.2.3