Skip to content

Commit fa74058

Browse files
authored
Add minilang (#4)
1 parent 6a19ed2 commit fa74058

17 files changed

Lines changed: 903 additions & 583 deletions

File tree

.clang-format

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ BasedOnStyle: LLVM
22
IndentWidth: 2
33
ColumnLimit: 100
44
UseTab: Never
5-
AllowShortIfStatementsOnASingleLine: false
5+
AllowShortIfStatementsOnASingleLine: true
6+
AllowShortLoopsOnASingleLine: true
67
AllowShortFunctionsOnASingleLine: Empty
7-
BreakBeforeBraces: Allman
8+
BreakBeforeBraces: Attach
89
SpaceBeforeParens: ControlStatements

.github/workflows/ci.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,12 @@ jobs:
9797
${{ matrix.cc }} -std=c11 -O2 -Isrc tests/test_harness_builder.c src/ctx.c -o jit_tests_builder
9898
./jit_tests_builder
9999
100+
- name: Build and run minilang example
101+
timeout-minutes: 1
102+
run: |
103+
${{ matrix.cc }} -std=c11 -O2 -Isrc examples/minilang.c src/ctx.c -o minilang_example
104+
./minilang_example "(def main (x) (add 10 (call dec x))) (def dec (y) (sub y 1))" 10
105+
100106
- name: Build and run SIMD example
101107
run: |
102108
${{ matrix.cc }} -std=c11 -O2 -Isrc examples/simd.c src/ctx.c -o simd_example

docs/builder.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ around abi registers, stack setup, and label plumbing, and it looks less scary.
88

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

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

2336
## control flow
2437

examples/README.md

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,17 @@
22

33
Small programs that showcase `cj`:
44

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

1317
## building
1418

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

2933
cc -std=c11 -O2 -Isrc examples/simd.c src/ctx.c -o simd_example
3034
./simd_example
35+
36+
cc -std=c11 -O2 -Isrc examples/minilang.c src/ctx.c -o minilang
37+
./minilang "(def main (x) (sub (call inc x) 3)) (def inc (x) (add x 1))" 10
3138
```
3239

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

examples/add.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,7 @@
44

55
typedef int (*add_fn)(int);
66

7-
int main(void)
8-
{
7+
int main(void) {
98
cj_ctx *cj = create_cj_ctx();
109

1110
#ifdef __aarch64__

examples/fibonacci.c

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,22 +25,18 @@
2525
typedef int (*fib_fn)(int);
2626

2727
// Reference implementation for comparison
28-
int fib_c(int n)
29-
{
30-
if (n <= 1)
31-
return n;
28+
int fib_c(int n) {
29+
if (n <= 1) return n;
3230
int a = 0, b = 1;
33-
for (int i = 2; i <= n; i++)
34-
{
31+
for (int i = 2; i <= n; i++) {
3532
int temp = a + b;
3633
a = b;
3734
b = temp;
3835
}
3936
return b;
4037
}
4138

42-
int main(void)
43-
{
39+
int main(void) {
4440
// Create JIT context
4541
cj_ctx *cj = create_cj_ctx();
4642

@@ -173,8 +169,7 @@ int main(void)
173169

174170
// Test the JIT-compiled function
175171
int all_pass = 1;
176-
for (int i = 0; i <= 15; i++)
177-
{
172+
for (int i = 0; i <= 15; i++) {
178173
int result = fib_jit(i);
179174
int expected = fib_c(i);
180175
int pass = (result == expected);

examples/hl_fibonacci.c

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,23 +4,19 @@
44

55
typedef int (*fib_fn)(int);
66

7-
static int fib_c(int n)
8-
{
9-
if (n <= 1)
10-
return n;
7+
static int fib_c(int n) {
8+
if (n <= 1) return n;
119
int a = 0;
1210
int b = 1;
13-
for (int i = 2; i <= n; ++i)
14-
{
11+
for (int i = 2; i <= n; ++i) {
1512
int tmp = a + b;
1613
a = b;
1714
b = tmp;
1815
}
1916
return b;
2017
}
2118

22-
int main(void)
23-
{
19+
int main(void) {
2420
cj_ctx *cj = create_cj_ctx();
2521

2622
cj_builder_frame frame;
@@ -53,16 +49,14 @@ int main(void)
5349
cj_builder_return_value(cj, &frame, acc_b);
5450

5551
fib_fn fib_jit = (fib_fn)create_cj_fn(cj);
56-
if (!fib_jit)
57-
{
52+
if (!fib_jit) {
5853
puts("failed to create jit function");
5954
destroy_cj_ctx(cj);
6055
return 1;
6156
}
6257

6358
int all_pass = 1;
64-
for (int idx = 0; idx <= 15; ++idx)
65-
{
59+
for (int idx = 0; idx <= 15; ++idx) {
6660
int result = fib_jit(idx);
6761
int expected = fib_c(idx);
6862
int pass = (result == expected);

0 commit comments

Comments
 (0)