diff options
| author | WormHeamer | 2025-10-28 18:42:28 -0400 |
|---|---|---|
| committer | WormHeamer | 2025-10-28 18:42:28 -0400 |
| commit | 8b407058485dbad82d670c6cbcacbe1d993fb4aa (patch) | |
| tree | 7505a078a572ee8c96f0712a9aa3e1efd3494715 /main.c | |
| parent | ae9a859b306e88e0324c30d3bc9f67aa6c24bd3f (diff) | |
Diffstat (limited to 'main.c')
| -rw-r--r-- | main.c | 64 |
1 files changed, 50 insertions, 14 deletions
@@ -1,5 +1,6 @@ #include <stdio.h> #include <stdint.h> +#include <stdbit.h> #include <stddef.h> #include <stdlib.h> #include <string.h> @@ -16,6 +17,39 @@ int no_opt = 0; +/* bit set */ + +typedef struct { + u64 cap; + u64 *data; +} BitSet; + +void bitset_fit(BitSet *s, u32 sz, Arena *a) { + if (s->cap >= sz) return; + u32 c = stdc_bit_ceil(sz); + s->data = resize(a, s->data, s->cap, c); + for (u32 i = s->cap; i < c; i++) s->data[i] = 0; + s->cap = c; +} + +static inline int bitset_has(BitSet *s, u32 n) { + if (n / 64 >= s->cap) return 0; + return !!((1L << (n & 63)) & s->data[n / 64]); +} + +static inline void bitset_add(BitSet *s, u32 n, Arena *a) { + bitset_fit(s, (n / 64) + 1, a); + s->data[n / 64] |= (1L << (n & 63)); +} + +static inline void bitset_del(BitSet *s, u32 n) { + if (bitset_has(s, n)) { + s->data[n / 64] &= ~(1L << (n & 63)); + } +} + +/* units */ + typedef struct { Arena *arena; XAR(Proc) procs; @@ -345,14 +379,14 @@ Node *find_return(Node *n) { return NULL; } -void proc_opt_fwd(Proc *p, Lexer *l, Node *n) { +void proc_opt_fwd(Proc *p, Lexer *l, Node *n, BitSet *walked) { Graph *g = &p->graph; - if (n->walked == 2) return; - n->walked = 2; + if (bitset_has(walked, n->id)) return; + bitset_add(walked, n->id, &p->scratch); switch (n->op) { case N_START: for (u32 i = 0; i < n->out.len; i++) { - proc_opt_fwd(p, l, OUT(n, i)); + proc_opt_fwd(p, l, OUT(n, i), walked); } break; case N_IF_ELSE: @@ -364,11 +398,11 @@ void proc_opt_fwd(Proc *p, Lexer *l, Node *n) { if (!r) { lex_error_at(l, OUT(n, i)->src_pos, LE_ERROR, S("not all codepaths return")); } - proc_opt_fwd(p, l, OUT(n, i)); + proc_opt_fwd(p, l, OUT(n, i), walked); } break; case N_PROJ: - proc_opt_fwd(p, l, OUT(n, 0)); + proc_opt_fwd(p, l, OUT(n, 0), walked); break; case N_REGION: /* cull empty if else */ @@ -382,12 +416,12 @@ void proc_opt_fwd(Proc *p, Lexer *l, Node *n) { Node *new_ctrl = CTRL(CTRL(CTRL(n))); Node *out = OUT(n, 0); node_set_in(g, out, 0, new_ctrl); - proc_opt_fwd(p, l, new_ctrl); + proc_opt_fwd(p, l, new_ctrl, walked); return; } for (u32 i = 0; i < n->out.len; i++) { if (OUT(n, i)->op != N_PHI) { - proc_opt_fwd(p, l, OUT(n, i)); + proc_opt_fwd(p, l, OUT(n, i), walked); } } break; @@ -410,7 +444,8 @@ void proc_opt(Proc *p, Lexer *l) { i--; } } - proc_opt_fwd(p, l, g->start); + BitSet walked = { 0 }; + proc_opt_fwd(p, l, g->start, &walked); } Proc *parse_proc(Lexer *l, Unit *u) { @@ -579,9 +614,9 @@ void parse_unit(Lexer *l, Unit *u) { * each, so problems can be debugged visually as they occur. */ -void node_print(Node *n, Proc *p) { - if (n->walked == 1) return; - n->walked = 1; +void node_print(Node *n, Proc *p, BitSet *walked) { + if (bitset_has(walked, n->id)) return; + bitset_add(walked, n->id, &p->scratch); if (n->op == N_START) { Str s = S(""); int c = n->val.tuple.len; @@ -634,16 +669,17 @@ void node_print(Node *n, Proc *p) { } } for (u32 i = 0; i < n->out.len; i++) { - node_print(OUT(n, i), p); + node_print(OUT(n, i), p, walked); } } void proc_print(Proc *p) { + BitSet walked = { 0 }; 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, g->start->id); - node_print(g->start, p); + node_print(g->start, p, &walked); if (no_opt) { for (NameBinding *b = p->scope.free_bind; b; b = b->prev) { uint64_t id = (uintptr_t)b->node; |
