summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWormHeamer2025-08-27 19:00:27 -0400
committerWormHeamer2025-08-27 19:00:27 -0400
commit5e38aebb97048d9c634e88f1be02f825a93720fe (patch)
tree5a02ecbf4bb49a0173f80a9d8bdea9b6fadc41d7
parent8c0a2fa3efdaf100b7119649863ecc173236153a (diff)
add scratch arena to Proc
-rw-r--r--doc/xar.txt36
-rw-r--r--ir.c13
-rw-r--r--ir.h18
-rw-r--r--main.c41
-rw-r--r--test.lang12
5 files changed, 83 insertions, 37 deletions
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)
}