Skip to content

Commit f56d599

Browse files
committed
extract scratch registers to builder
1 parent 5b6bdb8 commit f56d599

File tree

4 files changed

+55
-30
lines changed

4 files changed

+55
-30
lines changed

docs/builder.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ around abi registers, stack setup, and label plumbing, and it looks less scary.
1616
- `cj_builder_arg_int(cj, index)`: returns the platform-specific argument
1717
register.
1818
- `cj_builder_scratch_reg(index)`: picks a caller-saved temporary.
19+
- `cj_builder_scratch_init`, `cj_builder_scratch_acquire`,
20+
`cj_builder_scratch_release`: managed stack of scratch registers for balanced
21+
temporaries.
1922
- `cj_builder_zero_operand()` + `cj_builder_clear(cj, dst)`: easy zeroing.
2023
- `cj_builder_assign`, `cj_builder_add_assign`, `cj_builder_sub_assign`:
2124
assignment sugar.

examples/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ cc -std=c11 -O2 -Isrc examples/hl_fibonacci.c src/ctx.c -o hl_fibonacci_example
3131

3232
cc -std=c11 -O2 -Isrc examples/simd.c src/ctx.c -o simd_example
3333
./simd_example
34+
35+
cc -std=c11 -O2 -Isrc examples/minilang.c src/ctx.c -o minilang
36+
./minilang
3437
```
3538

3639
alternatively build the library and then add `-lcj -Lbin/` instead of the c file.

examples/minilang.c

Lines changed: 9 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -289,43 +289,22 @@ typedef struct
289289
{
290290
cj_ctx *cj;
291291
function *functions;
292-
int scratch_depth;
292+
cj_builder_scratch scratch;
293293
} codegen;
294294

295-
static cj_operand acquire_scratch(codegen *cg)
296-
{
297-
if (cg->scratch_depth >= 6)
298-
{
299-
fprintf(stderr, "scratch register exhausted\n");
300-
exit(1);
301-
}
302-
int idx = cg->scratch_depth++;
303-
return cj_builder_scratch_reg((unsigned)idx);
304-
}
305-
306-
static void release_scratch(codegen *cg)
307-
{
308-
if (cg->scratch_depth <= 0)
309-
{
310-
fprintf(stderr, "release underflow\n");
311-
exit(1);
312-
}
313-
cg->scratch_depth--;
314-
}
315-
316295
static cj_operand emit_expr(codegen *cg, node *n)
317296
{
318297
switch (n->kind)
319298
{
320299
case NODE_NUM:
321300
{
322-
cj_operand dst = acquire_scratch(cg);
301+
cj_operand dst = cj_builder_scratch_acquire(&cg->scratch);
323302
cj_builder_assign(cg->cj, dst, cj_make_constant((uint64_t)(uint32_t)n->value));
324303
return dst;
325304
}
326305
case NODE_PARAM:
327306
{
328-
cj_operand dst = acquire_scratch(cg);
307+
cj_operand dst = cj_builder_scratch_acquire(&cg->scratch);
329308
cj_builder_assign(cg->cj, dst, cj_builder_arg_int(cg->cj, 0));
330309
return dst;
331310
}
@@ -338,20 +317,20 @@ static cj_operand emit_expr(codegen *cg, node *n)
338317
cj_add(cg->cj, lhs, rhs);
339318
else
340319
cj_sub(cg->cj, lhs, rhs);
341-
release_scratch(cg);
320+
cj_builder_scratch_release(&cg->scratch);
342321
return lhs;
343322
}
344323
case NODE_CALL:
345324
{
346325
cj_operand arg = emit_expr(cg, n->arg);
347326
cj_builder_assign(cg->cj, cj_builder_arg_int(cg->cj, 0), arg);
348-
release_scratch(cg);
327+
cj_builder_scratch_release(&cg->scratch);
349328
#if defined(__aarch64__) || defined(_M_ARM64)
350329
cj_bl(cg->cj, cg->functions[n->target].entry);
351330
#else
352331
cj_call(cg->cj, cg->functions[n->target].entry);
353332
#endif
354-
cj_operand dst = acquire_scratch(cg);
333+
cj_operand dst = cj_builder_scratch_acquire(&cg->scratch);
355334
cj_builder_assign(cg->cj, dst, cj_builder_return_reg());
356335
return dst;
357336
}
@@ -362,7 +341,7 @@ static cj_operand emit_expr(codegen *cg, node *n)
362341

363342
static void emit_function(codegen *cg, function *fn)
364343
{
365-
cg->scratch_depth = 0;
344+
cj_builder_scratch_init(&cg->scratch);
366345
cj_mark_label(cg->cj, fn->entry);
367346
#if defined(__aarch64__) || defined(_M_ARM64)
368347
cj_operand sp = cj_make_register("sp");
@@ -382,7 +361,7 @@ static void emit_function(codegen *cg, function *fn)
382361
cj_operand result = emit_expr(cg, fn->body);
383362
cj_builder_return_value(cg->cj, &frame, result);
384363
#endif
385-
release_scratch(cg);
364+
cj_builder_scratch_release(&cg->scratch);
386365
}
387366

388367
static const char *program_source = "(def main (x) (sub (call inc x) 3))\n"
@@ -426,7 +405,7 @@ int main(void)
426405
for (int i = 0; i < function_count; i++)
427406
functions[i].entry = cj_create_label(cj);
428407

429-
codegen cg = {.cj = cj, .functions = functions, .scratch_depth = 0};
408+
codegen cg = {.cj = cj, .functions = functions};
430409
emit_function(&cg, &functions[main_idx]);
431410
for (int i = 0; i < function_count; i++)
432411
if (i != main_idx)

src/builder.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ typedef struct
3232
cj_condition exit_cond;
3333
} cj_builder_for_loop;
3434

35+
typedef struct
36+
{
37+
unsigned depth;
38+
} cj_builder_scratch;
39+
3540
static inline void cj_builder_fn_prologue(cj_ctx *ctx, size_t requested_stack_bytes,
3641
cj_builder_frame *frame);
3742
static inline void cj_builder_fn_epilogue(cj_ctx *ctx, const cj_builder_frame *frame);
@@ -67,6 +72,10 @@ static inline void cj_builder_return_value(cj_ctx *ctx, const cj_builder_frame *
6772
static inline cj_operand cj_builder_zero_operand(void);
6873
static inline void cj_builder_clear(cj_ctx *ctx, cj_operand dst);
6974
static inline cj_operand cj_builder_scratch_reg(unsigned index);
75+
static inline unsigned cj_builder_scratch_capacity(void);
76+
static inline void cj_builder_scratch_init(cj_builder_scratch *scratch);
77+
static inline cj_operand cj_builder_scratch_acquire(cj_builder_scratch *scratch);
78+
static inline void cj_builder_scratch_release(cj_builder_scratch *scratch);
7079

7180
#include <assert.h>
7281
#include <stdint.h>
@@ -568,3 +577,34 @@ static inline cj_operand cj_builder_scratch_reg(unsigned index)
568577
return cj_make_register(regs[index]);
569578
#endif
570579
}
580+
581+
static inline unsigned cj_builder_scratch_capacity(void)
582+
{
583+
#if defined(__x86_64__) || defined(_M_X64)
584+
return 6;
585+
#elif defined(__aarch64__) || defined(_M_ARM64)
586+
return 6;
587+
#endif
588+
}
589+
590+
static inline void cj_builder_scratch_init(cj_builder_scratch *scratch)
591+
{
592+
if (!scratch)
593+
return;
594+
scratch->depth = 0;
595+
}
596+
597+
static inline cj_operand cj_builder_scratch_acquire(cj_builder_scratch *scratch)
598+
{
599+
assert(scratch);
600+
assert(scratch->depth < cj_builder_scratch_capacity());
601+
unsigned index = scratch->depth++;
602+
return cj_builder_scratch_reg(index);
603+
}
604+
605+
static inline void cj_builder_scratch_release(cj_builder_scratch *scratch)
606+
{
607+
assert(scratch);
608+
assert(scratch->depth > 0);
609+
scratch->depth--;
610+
}

0 commit comments

Comments
 (0)