diff options
| author | WormHeamer | 2025-08-02 04:29:52 -0400 |
|---|---|---|
| committer | WormHeamer | 2025-08-02 04:29:52 -0400 |
| commit | 828396144285492b14a6d8f5c50a4a0d9d0714ef (patch) | |
| tree | cf19ff90ea0c296a0f9f6889109d5dbe63c9e990 /main.c | |
| parent | dbfb6ab16c6ff83291b9401a0432d814f9c6fda0 (diff) | |
some junk
Diffstat (limited to 'main.c')
| -rw-r--r-- | main.c | 136 |
1 files changed, 77 insertions, 59 deletions
@@ -24,12 +24,26 @@ typedef enum { const char *node_type_name[] = { "start", "return", - "integer literal", + "literal", "add", "sub", "mul", "div", "and", "or", "xor", "neg", "not", }; +typedef enum { + T_BOT, + T_TOP, + T_CONST, + T_INT +} Type; + +typedef struct { + Type type; + union { + int64_t i; + }; +} Value; + typedef struct Node { union { struct Node *prev_free; @@ -39,11 +53,7 @@ typedef struct Node { NodeType type; LexSpan src_pos; DYNARR(struct Node *) in, out; - union { - struct { - int64_t i; - } lit; - }; + Value val; }; }; } Node; @@ -176,7 +186,7 @@ Node *node_new(Proc *p, NodeType t, ...) { void node_print(Node *n) { if (n->type == N_LIT) { - printf("\t%d [label=\"%ld\"]\n", n->id, n->lit.i); + printf("\t%d [label=\"%ld\"]\n", n->id, n->val.i); } else { printf("\t%d [label=\"%s\", shape=record]\n", n->id, node_type_name[n->type]); } @@ -213,7 +223,7 @@ void unit_print(Unit *u) { Node *node_new_lit_i64(Proc *p, int64_t i) { Node *n = node_new(p, N_LIT, p->start); - n->lit.i = i; + n->val = (Value) { T_INT, { .i = i } }; return n; } @@ -225,71 +235,79 @@ static inline int node_op_communative(NodeType t) { return 0; } -/* needs lexer for error reporting */ -Node *node_peephole(Node *n, Proc *p, Lexer *l) { - /* - * Is there a method to convey these transformations a little more nicely? - * - * add(lit, lit) -> lit - * add(lit, add(N, lit)) -> add(N, add(lit, lit)) - * - */ - +Value node_compute(Node *n, Lexer *l) { + Type lit_type = T_BOT; Node **in = n->in.data; - Node *r = n; - - int all_lit = 1; for (int i = 0; i < n->in.len; i++) { - if (n->in.data[i]->type != N_LIT) all_lit = 0; + Node *p = in[i]; + if (p->type != N_LIT) break; + if (p->val.type != lit_type) { + if (lit_type == T_BOT) { + lit_type = p->val.type; + } else { + lit_type = T_BOT; + break; + } + } } - - if (all_lit) { + if (lit_type == T_INT) { + Value v = { .type = lit_type }; switch (n->type) { - case N_OP_NEG: r = node_new_lit_i64(p, -in[0]->lit.i); break; - case N_OP_NOT: r = node_new_lit_i64(p, ~in[0]->lit.i); break; - case N_OP_ADD: r = node_new_lit_i64(p, in[0]->lit.i + in[1]->lit.i); break; - case N_OP_SUB: r = node_new_lit_i64(p, in[0]->lit.i - in[1]->lit.i); break; - case N_OP_MUL: r = node_new_lit_i64(p, in[0]->lit.i * in[1]->lit.i); break; + case N_OP_NEG: v.i = -in[0]->val.i; break; + case N_OP_NOT: v.i = ~in[0]->val.i; break; + case N_OP_ADD: v.i = in[0]->val.i + in[1]->val.i; break; + case N_OP_SUB: v.i = in[0]->val.i - in[1]->val.i; break; + case N_OP_MUL: v.i = in[0]->val.i * in[1]->val.i; break; case N_OP_DIV: - if (in[1]->lit.i == 0) { - lex_error_at(l, in[1]->src_pos, LE_ERROR, S("divisor always evaluates to zero")); - } - r = node_new_lit_i64(p, in[0]->lit.i / in[1]->lit.i); - break; - case N_OP_AND: r = node_new_lit_i64(p, in[0]->lit.i & in[1]->lit.i); break; - case N_OP_OR: r = node_new_lit_i64(p, in[0]->lit.i | in[1]->lit.i); break; - case N_OP_XOR: r = node_new_lit_i64(p, in[0]->lit.i ^ in[1]->lit.i); break; - default: break; + if (in[1]->val.i == 0) { + lex_error_at(l, in[1]->src_pos, LE_ERROR, S("divisor always evaluates to zero")); + } + v.i = in[0]->val.i / in[1]->val.i; + break; + case N_OP_AND: v.i = in[0]->val.i & in[1]->val.i; break; + case N_OP_OR: v.i = in[0]->val.i | in[1]->val.i; break; + case N_OP_XOR: v.i = in[0]->val.i ^ in[1]->val.i; break; + default: return n->val; } - } else { - /* TODO: figure out to do peepholes recursively, without fucking up the graph or having to clone everything */ - if (node_op_communative(n->type)) { - /* transformations to help encourage constant folding */ - if (in[0]->type == N_LIT + return v; + } + return n->val; +} + +/* needs lexer for error reporting */ +Node *node_peephole(Node *n, Proc *p, Lexer *l) { + Value v = node_compute(n, l); + if (n->type != N_LIT && v.type > T_CONST) { + Node *r = node_new(p, N_LIT, p->start); + r->val = v; + r->src_pos = n->src_pos; + node_kill(n, p); + return r; + } + + Node **in = n->in.data; + /* TODO: figure out to do peepholes recursively, without fucking up the graph or having to clone everything */ + if (node_op_communative(n->type)) { + /* transformations to help encourage constant folding */ + if (in[0]->type == N_LIT && in[1]->type == n->type && in[1]->in.data[0]->type != N_LIT && in[1]->in.data[1]->type == N_LIT) { - /* op(lit, op(X, lit)) -> op(X, op(lit, lit)) */ - Node *tmp = in[1]->in.data[0]; - in[1]->in.data[0] = in[0]; - in[0] = tmp; - } else if (in[0]->type == n->type + /* op(lit, op(X, lit)) -> op(X, op(lit, lit)) */ + Node *tmp = in[1]->in.data[0]; + in[1]->in.data[0] = in[0]; + in[0] = tmp; + } else if (in[0]->type == n->type && in[0]->in.data[0]->type != N_LIT && in[0]->in.data[1]->type == N_LIT && in[1]->type != N_LIT) { - /* op(op(X, lit), Y) -> op(op(X, Y), lit) */ - Node *tmp = in[0]->in.data[1]; - in[0]->in.data[1] = in[1]; - in[1] = tmp; - } + /* op(op(X, lit), Y) -> op(op(X, Y), lit) */ + Node *tmp = in[0]->in.data[1]; + in[0]->in.data[1] = in[1]; + in[1] = tmp; } } - - if (r != n) { - r->src_pos = n->src_pos; - if (n->out.len == 0) node_kill(n, p); - } - return r; + return n; } /* parsing */ |
