diff options
| author | WormHeamer | 2025-08-10 04:46:09 -0400 |
|---|---|---|
| committer | WormHeamer | 2025-08-10 04:46:09 -0400 |
| commit | c9980711ce42de9cf58db35f41ce1ac42bfea0c7 (patch) | |
| tree | caa99c741b012f5fc683f131c6c2281fec4e2f61 /ir.c | |
| parent | d4c768a481b923d407201c25d3d750040b6ccd44 (diff) | |
fix peephole bug (communative(phi(a,b), phi(a,b)) =/= communative(a,b))
Diffstat (limited to 'ir.c')
| -rw-r--r-- | ir.c | 53 |
1 files changed, 46 insertions, 7 deletions
@@ -4,8 +4,6 @@ #include "ir.h" #include "strio.h" -extern int no_opt; - /* nodes */ const char *node_type_name(NodeType t) { @@ -361,13 +359,54 @@ static int type_ok(Node *n) { } } -void type_check(Node *n, Lexer *l) { +/* TODO: make it so + * func foo(a, b i64) i64 { + * let x i64 + * if a < b { + * return 0 + * } else { + * x := 3 + * } + * return x + * } + * doesn't throw warnings (e.g. don't generate phi nodes if one scope is + * guaranteed to return early) + */ + +int node_uninit(Node *n) { + return n->op == N_UNINIT; +} + +int node_maybe_uninit(Node *n) { + if (node_uninit(n)) return 1; for (int i = 0; i < n->in.len; i++) { - if (IN(n,i) && IN(n,i)->op == N_UNINIT) { - lex_error_at(l, n->src_pos, LE_ERROR, - str_fmt(&l->arena, "attempt to use uninitialized %S value", - type_desc(&IN(n,i)->type, &l->arena))); + if (IN(n,i) && node_maybe_uninit(IN(n,i))) { + return 1; } } + return 0; +} + +void uninit_check(Node *n, Lexer *l) { + if (NMASK(n->op) & ~NM_PHI) { + for (int i = 0; i < n->in.len; i++) { + Node *o = IN(n, i); + if (!o) continue; + if (node_uninit(o)) { + fprintf(stderr, "%s\n", node_type_name(n->op)); + lex_error_at(l, o->src_pos, LE_WARN, + str_fmt(&l->arena, "uninitialized %S", + type_desc(&IN(n,i)->type, &l->arena))); + } else if (node_maybe_uninit(o)) { + lex_error_at(l, o->src_pos, LE_WARN, + str_fmt(&l->arena, "possibly uninitialized %S", + type_desc(&o->type, &l->arena))); + } + } + } +} + +void type_check(Node *n, Lexer *l) { + uninit_check(n, l); if (!type_ok(n)) type_err(n, l); } |
