summaryrefslogtreecommitdiff
path: root/main.c
diff options
context:
space:
mode:
authorWormHeamer2025-08-04 22:13:25 -0400
committerWormHeamer2025-08-04 22:13:25 -0400
commit88b01f43312eeceba87a1378be5cd63bb11f167f (patch)
treec7046558223ac692958ca1c7b9da71f05493f148 /main.c
parent22aa7559a37c49def05e8a43b12561b17a4af258 (diff)
fix bug of lhs getting culled if same node optimized out of rhs
Diffstat (limited to 'main.c')
-rw-r--r--main.c61
1 files changed, 33 insertions, 28 deletions
diff --git a/main.c b/main.c
index ce8981b..8533e49 100644
--- a/main.c
+++ b/main.c
@@ -213,41 +213,46 @@ Node *parse_term(Lexer *l, Proc *p) {
return node_peephole(node, p, l);
}
+NodeType tok_to_bin_op(Token t) {
+ switch (t) {
+ case TOK_PLUS: return N_OP_ADD; break;
+ case TOK_MINUS: return N_OP_SUB; break;
+ case TOK_ASTERISK: return N_OP_MUL; break;
+ case TOK_SLASH: return N_OP_DIV; break;
+ case TOK_NOT: return N_OP_NOT; break;
+ case TOK_AND: return N_OP_AND; break;
+ case TOK_OR: return N_OP_OR; break;
+ case TOK_XOR: return N_OP_XOR; break;
+ case TOK_SHL: return N_OP_SHL; break;
+ case TOK_SHR: return N_OP_SHR; break;
+ case TOK_EQL: return N_CMP_EQL; break;
+ case TOK_NEQ: return N_CMP_NEQ; break;
+ case TOK_LES: return N_CMP_LES; break;
+ case TOK_GTR: return N_CMP_GTR; break;
+ case TOK_LTE: return N_CMP_LTE; break;
+ case TOK_GTE: return N_CMP_GTE; break;
+ default: return N_START; break;
+ }
+}
+
/* TODO: operator precedence would be kinda nice actually, sad to say */
Node *parse_expr(Lexer *l, Proc *p) {
LexSpan pos = l->pos;
Node *lhs = parse_term(l, p);
- if (TMASK(l->tok) & (TM_PLUS | TM_MINUS | TM_ASTERISK | TM_SLASH
- | TM_NOT | TM_AND | TM_XOR | TM_OR | TM_SHL | TM_SHR
- | TM_EQL | TM_NEQ | TM_LES | TM_GTR | TM_LTE | TM_GTE)) {
- Token t = l->tok;
+ NodeType nt = tok_to_bin_op(l->tok);;
+ assert(lhs->refs > 0);
+ if (nt != N_START) {
lex_next(l);
+ /* necessary because if lhs is a deduplicated literal, it may be an input to rhs
+ * and therefore culled by peephole optimizations */
+ node_add(p, lhs, p->keepalive);
Node *rhs = parse_expr(l, p);
- NodeType nt = N_OP_ADD;
- switch (t) {
- case TOK_PLUS: nt = N_OP_ADD; break;
- case TOK_MINUS: nt = N_OP_SUB; break;
- case TOK_ASTERISK: nt = N_OP_MUL; break;
- case TOK_SLASH: nt = N_OP_DIV; break;
- case TOK_NOT: nt = N_OP_NOT; break;
- case TOK_AND: nt = N_OP_AND; break;
- case TOK_OR: nt = N_OP_OR; break;
- case TOK_XOR: nt = N_OP_XOR; break;
- case TOK_SHL: nt = N_OP_SHL; break;
- case TOK_SHR: nt = N_OP_SHR; break;
- case TOK_EQL: nt = N_CMP_EQL; break;
- case TOK_NEQ: nt = N_CMP_NEQ; break;
- case TOK_LES: nt = N_CMP_LES; break;
- case TOK_GTR: nt = N_CMP_GTR; break;
- case TOK_LTE: nt = N_CMP_LTE; break;
- case TOK_GTE: nt = N_CMP_GTE; break;
- default: break;
- }
- lhs = node_new(p, nt, lhs, rhs);
+ Node *n = node_peephole(node_new(p, nt, lhs, rhs), p, l);
+ node_remove(p, lhs, p->keepalive);
+ lhs = n;
}
- Node *n = node_peephole(lhs, p, l);
- n->src_pos = (LexSpan) { pos.ofs, l->pos.ofs - pos.ofs };
- return n;
+ lhs->src_pos = (LexSpan) { pos.ofs, l->pos.ofs - pos.ofs };
+ return lhs;
}
void parse_toplevel(Lexer *l, Unit *u) {