From 5e38aebb97048d9c634e88f1be02f825a93720fe Mon Sep 17 00:00:00 2001 From: WormHeamer Date: Wed, 27 Aug 2025 19:00:27 -0400 Subject: add scratch arena to Proc --- doc/xar.txt | 36 ++++++++++++++++++++++++++++++++++++ ir.c | 13 +++++++------ ir.h | 18 +++++++++++++++++- main.c | 41 +++++++++++++++++++++-------------------- test.lang | 12 ++---------- 5 files changed, 83 insertions(+), 37 deletions(-) create mode 100644 doc/xar.txt diff --git a/doc/xar.txt b/doc/xar.txt new file mode 100644 index 0000000..548827a --- /dev/null +++ b/doc/xar.txt @@ -0,0 +1,36 @@ +/* andrew reese's Exponential Array datatype */ + +use bits, mem.Arena, mem.arena_alloc + +const XAR_INIT_SZ = 8 +const XAR_MAX_DOUBLE = 20 + +struct Xar(T) { + n u32, + chunk [XAR_MAX_DOUBLE]^T +} + +#[inline] +func xar_chnk_slot(xar ^Xar(T), idx u32) (u32, u32) { + let chnk = 31 - bits.clz((idx / XAR_INIT_SZ) + 1) + let slot = idx - ((XAR_INIT_SZ << chnk) - XAR_INIT_SZ) + return (chnk, slot) +} + +func xar_get(xar ^Xar(T), idx u32) ^T { + let chnk, slot = xar_chnk_slot(xar, idx) + return xar->chunk[chnk] + (slot * sizeof(T)) +} + +func xar_put(xar ^Xar(T), idx u32, a ^Arena) { + let chnk, slot = xar_chnk_slot(xar, idx) + if (!xar->chunk[chnk]) { + xar->chunk[chnk] := arena_alloc(a, sizeof(T) * (XAR_INIT_SZ << chnk)), alignof(T)) + } + return xar->chunk[chnk] + (slot * sizeof(T)) +} + +proc xar_push(xar ^Xar(T), v T, a ^Arena) { + xar_put(xar, xar.n, a)^ = v + xar.n := xar.n + 1 +} diff --git a/ir.c b/ir.c index 0e8e097..e3cb679 100644 --- a/ir.c +++ b/ir.c @@ -60,12 +60,12 @@ void node_kill(Node *n, Proc *p) { } void node_add_out(Proc *p, Node *a, Node *b) { - ZDA_PUSH(&p->arena, &a->out, b); + ZDA_PUSH(&p->perm, &a->out, b); if (b) b->refs++; } void node_add_in(Proc *p, Node *a, Node *b) { - ZDA_PUSH(&p->arena, &a->in, b); + ZDA_PUSH(&p->perm, &a->in, b); if (b) b->refs++; } @@ -113,7 +113,7 @@ Node *node_new_empty(Proc *p, NodeType t) { p->free_list = n->prev_free; memset(n, 0, sizeof(Node)); } else { - n = new(&p->arena, Node); + n = new(&p->perm, Node); } n->op = t; n->id = global_node_count++; @@ -180,7 +180,8 @@ void proc_init(Proc *proc, Str name) { } void proc_free(Proc *proc) { - arena_free(&proc->arena); + arena_free(&proc->perm); + arena_free(&proc->scratch); } /* scope */ @@ -203,7 +204,7 @@ ScopeFrame *scope_push(Scope *scope, Proc *proc) { *f = (ScopeFrame) { 0 }; scope->free_scope = f->prev; } else { - f = new(&proc->arena, ScopeFrame); + f = new(&proc->perm, ScopeFrame); } f->prev = scope->tail; scope->tail = f; @@ -234,7 +235,7 @@ NameBinding *scope_bind(Scope *scope, Str name, Node *value, LexSpan pos, Proc * *b = (NameBinding) { 0 }; scope->free_bind = b->prev; } else { - b = new(&proc->arena, NameBinding); + b = new(&proc->perm, NameBinding); } b->name = name; b->prev = scope->tail->latest; diff --git a/ir.h b/ir.h index 8923607..0e30a06 100644 --- a/ir.h +++ b/ir.h @@ -169,8 +169,24 @@ typedef struct { typedef DYNARR(ScopeName) ScopeNameList; +/* + * TODO: move to having + typedef struct { + Arena *arena; + Node *start, *stop, *ctrl, *keepalive; + Node *free_list; + } Graph; + typedef struct { + Arena arena; + Str name; + Graph graph; + Scope scope; + } Proc; + * so that scope handling can be separated from the rest of IR + */ + typedef struct { - Arena arena; + Arena perm, scratch; Str name; Node *start, *stop, *ctrl, *keepalive; Node *free_list; diff --git a/main.c b/main.c index c83245b..1787245 100644 --- a/main.c +++ b/main.c @@ -75,7 +75,7 @@ Type parse_type(Lexer *l, Proc *proc) { if (l->tok == TOK_DEREF) { lex_next(l); t.t = T_PTR; - t.next = new(&proc->arena, Type); + t.next = new(&proc->perm, Type); *t.next = parse_type(l, proc); return t; } @@ -125,13 +125,14 @@ void parse_stmt(Lexer *l, Proc *p); /* TODO: return node from this! */ void parse_block(Lexer *l, Proc *p, ScopeNameList *nl) { lex_next(l); + arena_reset(&p->scratch); scope_push(&p->scope, p); while (l->tok != TOK_RBRACE) { lex_expected_not(l, TM_EOF); parse_stmt(l, p); } if (nl) { - scope_collect(&p->scope, p, nl, &p->arena); + scope_collect(&p->scope, p, nl, &p->scratch); } scope_pop(&p->scope, p); lex_expected(l, TM_RBRACE); @@ -150,12 +151,12 @@ void parse_assign(Lexer *l, Proc *p) { Node *e = parse_expr(l, p, &b->node->type); if (node_uninit(e)) { lex_error_at(l, e->src_pos, LE_ERROR, - str_fmt(&p->arena, "uninitialized %S", - type_desc(&e->type, &p->arena))); + str_fmt(&p->scratch, "uninitialized %S", + type_desc(&e->type, &p->scratch))); } else if (node_maybe_uninit(e)) { lex_error_at(l, e->src_pos, LE_WARN, - str_fmt(&p->arena, "possibly uninitialized %S", - type_desc(&e->type, &p->arena))); + str_fmt(&p->scratch, "possibly uninitialized %S", + type_desc(&e->type, &p->scratch))); } scope_update(b, e, p); } @@ -249,8 +250,8 @@ void parse_if(Lexer *l, Proc *p) { .type = { .lvl = T_TOP, .t = T_TUPLE }, .tuple = { 0 } }; - ZDA_PUSH(&p->arena, &if_node->val.tuple, (Value) { .type = { .lvl = T_CTRL, .t = T_NONE } }); - ZDA_PUSH(&p->arena, &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 } }); + 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); @@ -265,7 +266,7 @@ void parse_if(Lexer *l, Proc *p) { node_add(p, if_true, p->keepalive); node_add(p, if_false, p->keepalive); ScopeNameList scope_before = { 0 }, scope_true = { 0 }, scope_false = { 0 }; - scope_collect(&p->scope, p, &scope_before, &p->arena); + scope_collect(&p->scope, p, &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; @@ -373,7 +374,7 @@ void parse_args_list(Lexer *l, Proc *proc) { Node *proj = node_new(proc, N_PROJ, proc->start); proj->type = v.type; proj->val.i = i++; - ZDA_PUSH(&proc->arena, &start->val.tuple, v); + ZDA_PUSH(&proc->perm, &start->val.tuple, v); scope_bind(&proc->scope, idbuf[j].name, proj, idbuf[j].pos, proc); } id = 0; @@ -444,7 +445,7 @@ void proc_opt_fwd(Proc *p, Lexer *l, Node *n) { void proc_opt(Proc *p, Lexer *l) { if (p->stop->in.len == 0) { if (p->ret_type.t != T_NONE) { - lex_error(l, LE_ERROR, str_fmt(&p->arena, "no return statement in function expecting %S", type_desc(&p->ret_type, &p->arena))); + 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++) { @@ -489,12 +490,12 @@ Proc *parse_proc(Lexer *l, Unit *u) { void uninit_check(Lexer *l, Proc *p, Node *n, LexSpan pos) { if (node_uninit(n)) { lex_error_at(l, pos, LE_ERROR, - str_fmt(&p->arena, "uninitialized %S", - type_desc(&n->type, &p->arena))); + str_fmt(&p->scratch, "uninitialized %S", + type_desc(&n->type, &p->scratch))); } else if (node_maybe_uninit(n)) { lex_error_at(l, pos, LE_WARN, - str_fmt(&p->arena, "possibly uninitialized %S", - type_desc(&n->type, &p->arena))); + str_fmt(&p->scratch, "possibly uninitialized %S", + type_desc(&n->type, &p->scratch))); } } @@ -636,8 +637,8 @@ void node_print(Node *n, Proc *p) { int c = n->val.tuple.len; Value *v = n->val.tuple.data; for (int i = 0; i < c; i++) { - if (i > 0) str_cat(&s, S(", "), &p->arena); - str_cat(&s, type_desc(&v[i].type, &p->arena), &p->arena); + if (i > 0) str_cat(&s, S(", "), &p->scratch); + str_cat(&s, type_desc(&v[i].type, &p->scratch), &p->scratch); } printf("\t%d [label=\"start(%.*s)\"]", n->id, (int)s.n, s.s); } else if (n->op == N_LIT) { @@ -659,10 +660,10 @@ void node_print(Node *n, Proc *p) { break; } } else if (n->op == N_PROJ) { - Str d = type_desc(&n->in.data[0]->val.tuple.data[n->val.i].type, &p->arena); + Str d = type_desc(&n->in.data[0]->val.tuple.data[n->val.i].type, &p->scratch); printf("\t%d [label=\"%.*s(%ld)\", shape=record]", n->id, (int)d.n, d.s, n->val.i); } else if (n->op == N_UNINIT) { - Str s = type_desc(&n->type, &p->arena); + Str s = type_desc(&n->type, &p->scratch); printf("\t%d [label=\"uninitialized %.*s\", shape=record]", n->id, (int)s.n, s.s); } else { printf("\t%d [label=\"%s\", shape=record]", n->id, node_type_name(n->op)); @@ -689,7 +690,7 @@ void node_print(Node *n, Proc *p) { void proc_print(Proc *p) { if (p->start) { - Str d = type_desc(&p->ret_type, &p->arena); + 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); if (no_opt) { diff --git a/test.lang b/test.lang index 3448ea8..b59ffe0 100644 --- a/test.lang +++ b/test.lang @@ -1,11 +1,3 @@ -/*func main(a, b i64) i64 { - let x i64 = 0, y bool = true - if a <> 0 { - x := 1 - } - return x + a -}*/ - -func main(a, b i64) i64 { - return (a & b) & b & a +func main(a, b, c i64) i64 { + return b xor ((a xor b) xor (b xor c) xor b) } -- cgit v1.2.3