Skip to content

Commit 321f7e9

Browse files
committed
extract calls into builder
1 parent f56d599 commit 321f7e9

File tree

3 files changed

+70
-10
lines changed

3 files changed

+70
-10
lines changed

docs/builder.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ around abi registers, stack setup, and label plumbing, and it looks less scary.
2222
- `cj_builder_zero_operand()` + `cj_builder_clear(cj, dst)`: easy zeroing.
2323
- `cj_builder_assign`, `cj_builder_add_assign`, `cj_builder_sub_assign`:
2424
assignment sugar.
25+
- `cj_builder_call(ctx, scratch, label, args, count)`: loads integer argument
26+
registers (up to the ABI limit), emits the proper call/bl, and optionally
27+
preserves the return value via the scratch stack.
28+
- `cj_builder_call_unary(ctx, scratch, label, arg)`: loads the first argument
29+
register, emits the right call/bl, and—when a scratch stack is supplied—moves
30+
the return value into a fresh scratch slot.
2531

2632
## control flow
2733

examples/minilang.c

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -323,16 +323,7 @@ static cj_operand emit_expr(codegen *cg, node *n)
323323
case NODE_CALL:
324324
{
325325
cj_operand arg = emit_expr(cg, n->arg);
326-
cj_builder_assign(cg->cj, cj_builder_arg_int(cg->cj, 0), arg);
327-
cj_builder_scratch_release(&cg->scratch);
328-
#if defined(__aarch64__) || defined(_M_ARM64)
329-
cj_bl(cg->cj, cg->functions[n->target].entry);
330-
#else
331-
cj_call(cg->cj, cg->functions[n->target].entry);
332-
#endif
333-
cj_operand dst = cj_builder_scratch_acquire(&cg->scratch);
334-
cj_builder_assign(cg->cj, dst, cj_builder_return_reg());
335-
return dst;
326+
return cj_builder_call_unary(cg->cj, &cg->scratch, cg->functions[n->target].entry, arg);
336327
}
337328
}
338329
fprintf(stderr, "unsupported node kind\n");

src/builder.h

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,13 @@ static inline unsigned cj_builder_scratch_capacity(void);
7676
static inline void cj_builder_scratch_init(cj_builder_scratch *scratch);
7777
static inline cj_operand cj_builder_scratch_acquire(cj_builder_scratch *scratch);
7878
static inline void cj_builder_scratch_release(cj_builder_scratch *scratch);
79+
static inline unsigned cj_builder_arg_int_capacity(void);
80+
static inline void cj_builder_call_label(cj_ctx *ctx, cj_label target);
81+
static inline cj_operand
82+
cj_builder_call(cj_ctx *ctx, cj_builder_scratch *scratch, cj_label target,
83+
const cj_operand *args, size_t arg_count);
84+
static inline cj_operand cj_builder_call_unary(cj_ctx *ctx, cj_builder_scratch *scratch,
85+
cj_label target, cj_operand arg0);
7986

8087
#include <assert.h>
8188
#include <stdint.h>
@@ -587,6 +594,15 @@ static inline unsigned cj_builder_scratch_capacity(void)
587594
#endif
588595
}
589596

597+
static inline unsigned cj_builder_arg_int_capacity(void)
598+
{
599+
#if defined(__x86_64__) || defined(_M_X64)
600+
return 6;
601+
#elif defined(__aarch64__) || defined(_M_ARM64)
602+
return 8;
603+
#endif
604+
}
605+
590606
static inline void cj_builder_scratch_init(cj_builder_scratch *scratch)
591607
{
592608
if (!scratch)
@@ -608,3 +624,50 @@ static inline void cj_builder_scratch_release(cj_builder_scratch *scratch)
608624
assert(scratch->depth > 0);
609625
scratch->depth--;
610626
}
627+
628+
static inline void cj_builder_call_label(cj_ctx *ctx, cj_label target)
629+
{
630+
#if defined(__x86_64__) || defined(_M_X64)
631+
cj_call(ctx, target);
632+
#elif defined(__aarch64__) || defined(_M_ARM64)
633+
cj_bl(ctx, target);
634+
#endif
635+
}
636+
637+
static inline cj_operand cj_builder_call_unary(cj_ctx *ctx, cj_builder_scratch *scratch,
638+
cj_label target, cj_operand arg0)
639+
{
640+
const cj_operand args[] = {arg0};
641+
return cj_builder_call(ctx, scratch, target, args, 1);
642+
}
643+
644+
static inline cj_operand
645+
cj_builder_call(cj_ctx *ctx, cj_builder_scratch *scratch, cj_label target,
646+
const cj_operand *args, size_t arg_count)
647+
{
648+
if (!ctx)
649+
return cj_builder_return_reg();
650+
651+
unsigned capacity = cj_builder_arg_int_capacity();
652+
assert(arg_count <= capacity);
653+
654+
for (size_t i = 0; i < arg_count; ++i)
655+
{
656+
cj_operand reg = cj_builder_arg_int(ctx, (unsigned)i);
657+
cj_builder_assign(ctx, reg, args[i]);
658+
}
659+
660+
if (scratch)
661+
cj_builder_scratch_release(scratch);
662+
663+
cj_builder_call_label(ctx, target);
664+
665+
if (scratch)
666+
{
667+
cj_operand dst = cj_builder_scratch_acquire(scratch);
668+
cj_builder_assign(ctx, dst, cj_builder_return_reg());
669+
return dst;
670+
}
671+
672+
return cj_builder_return_reg();
673+
}

0 commit comments

Comments
 (0)