Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ BasedOnStyle: LLVM
IndentWidth: 2
ColumnLimit: 100
UseTab: Never
AllowShortIfStatementsOnASingleLine: false
AllowShortIfStatementsOnASingleLine: true
AllowShortLoopsOnASingleLine: true
AllowShortFunctionsOnASingleLine: Empty
BreakBeforeBraces: Allman
BreakBeforeBraces: Attach
SpaceBeforeParens: ControlStatements
6 changes: 6 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,12 @@ jobs:
${{ matrix.cc }} -std=c11 -O2 -Isrc tests/test_harness_builder.c src/ctx.c -o jit_tests_builder
./jit_tests_builder

- name: Build and run minilang example
timeout-minutes: 1
run: |
${{ matrix.cc }} -std=c11 -O2 -Isrc examples/minilang.c src/ctx.c -o minilang_example
./minilang_example "(def main (x) (add 10 (call dec x))) (def dec (y) (sub y 1))" 10

- name: Build and run SIMD example
run: |
${{ matrix.cc }} -std=c11 -O2 -Isrc examples/simd.c src/ctx.c -o simd_example
Expand Down
13 changes: 13 additions & 0 deletions docs/builder.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ around abi registers, stack setup, and label plumbing, and it looks less scary.

- `cj_builder_fn_prologue(cj, stack_bytes, &frame)`: create a frame and reserve
optional stack space (aligned for both arches).
- `cj_builder_fn_prologue_with_link_save(cj, stack_bytes, &frame)`: like above,
but on ARM64 it also saves/restores `x30` for non-leaf functions.
- `cj_builder_fn_epilogue(cj, &frame)` / `cj_builder_return(cj, &frame)`:
restore the frame and emit `ret`.

Expand All @@ -16,9 +18,20 @@ around abi registers, stack setup, and label plumbing, and it looks less scary.
- `cj_builder_arg_int(cj, index)`: returns the platform-specific argument
register.
- `cj_builder_scratch_reg(index)`: picks a caller-saved temporary.
- `cj_builder_scratch_init`, `cj_builder_scratch_acquire`,
`cj_builder_scratch_release`: managed stack of scratch registers for balanced
temporaries.
- `cj_builder_zero_operand()` + `cj_builder_clear(cj, dst)`: easy zeroing.
- `cj_builder_assign`, `cj_builder_add_assign`, `cj_builder_sub_assign`:
assignment sugar.
- `cj_builder_call(ctx, scratch, label, args, count)`: loads integer argument
registers (up to the ABI limit), emits the proper call/bl, and optionally
preserves the return value via the scratch stack.
- `cj_builder_call_unary(ctx, scratch, label, arg)`: loads the first argument
register, emits the right call/bl, and—when a scratch stack is supplied—moves
the return value into a fresh scratch slot.
- `cj_resolve_label(ctx, module, label)`: convert a recorded label to a
callable pointer after finalization.

## control flow

Expand Down
21 changes: 14 additions & 7 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@

Small programs that showcase `cj`:

- `simple.c` – minimal
program(nop &ret)
.- `add.c` – adds a constant to the first argument and returns it;
demonstrates register operands and constants.- `fibonacci.c` – full control -
flow example(labels, branches, loops) emitted with the low-level API.
- `hl_fibonacci.c` – fibonacci again, but built entirely with the builder helpers.
- `simd.c` – x86 and arm simd vector addition loops, exercising memory operands and floating-point registers.
- `simple.c`: minimal
program(nop &ret)
.- `add.c`: adds a constant to the first argument and returns it;
demonstrates register operands and constants.- `fibonacci.c`: full control -
flow example(labels, branches, loops) emitted
with the low-level API.
- `hl_fibonacci.c` – fibonacci again, but built entirely with the builder
helpers.
- `simd.c` – x86 and arm simd vector addition loops, exercising memory operands
and floating-point registers.
- `minilang.c` – a minimal Lisp (has addition, subtraction, functions).

## building

Expand All @@ -28,6 +32,9 @@ cc -std=c11 -O2 -Isrc examples/hl_fibonacci.c src/ctx.c -o hl_fibonacci_example

cc -std=c11 -O2 -Isrc examples/simd.c src/ctx.c -o simd_example
./simd_example

cc -std=c11 -O2 -Isrc examples/minilang.c src/ctx.c -o minilang
./minilang "(def main (x) (sub (call inc x) 3)) (def inc (x) (add x 1))" 10
```

alternatively build the library and then add `-lcj -Lbin/` instead of the c file.
3 changes: 1 addition & 2 deletions examples/add.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@

typedef int (*add_fn)(int);

int main(void)
{
int main(void) {
cj_ctx *cj = create_cj_ctx();

#ifdef __aarch64__
Expand Down
15 changes: 5 additions & 10 deletions examples/fibonacci.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,18 @@
typedef int (*fib_fn)(int);

// Reference implementation for comparison
int fib_c(int n)
{
if (n <= 1)
return n;
int fib_c(int n) {
if (n <= 1) return n;
int a = 0, b = 1;
for (int i = 2; i <= n; i++)
{
for (int i = 2; i <= n; i++) {
int temp = a + b;
a = b;
b = temp;
}
return b;
}

int main(void)
{
int main(void) {
// Create JIT context
cj_ctx *cj = create_cj_ctx();

Expand Down Expand Up @@ -173,8 +169,7 @@ int main(void)

// Test the JIT-compiled function
int all_pass = 1;
for (int i = 0; i <= 15; i++)
{
for (int i = 0; i <= 15; i++) {
int result = fib_jit(i);
int expected = fib_c(i);
int pass = (result == expected);
Expand Down
18 changes: 6 additions & 12 deletions examples/hl_fibonacci.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,19 @@

typedef int (*fib_fn)(int);

static int fib_c(int n)
{
if (n <= 1)
return n;
static int fib_c(int n) {
if (n <= 1) return n;
int a = 0;
int b = 1;
for (int i = 2; i <= n; ++i)
{
for (int i = 2; i <= n; ++i) {
int tmp = a + b;
a = b;
b = tmp;
}
return b;
}

int main(void)
{
int main(void) {
cj_ctx *cj = create_cj_ctx();

cj_builder_frame frame;
Expand Down Expand Up @@ -53,16 +49,14 @@ int main(void)
cj_builder_return_value(cj, &frame, acc_b);

fib_fn fib_jit = (fib_fn)create_cj_fn(cj);
if (!fib_jit)
{
if (!fib_jit) {
puts("failed to create jit function");
destroy_cj_ctx(cj);
return 1;
}

int all_pass = 1;
for (int idx = 0; idx <= 15; ++idx)
{
for (int idx = 0; idx <= 15; ++idx) {
int result = fib_jit(idx);
int expected = fib_c(idx);
int pass = (result == expected);
Expand Down
Loading