--interp and --jit

Both modes run a program without writing an image, and both exit with the program’s status. --jit compiles for the host in memory and calls main. --interp compiles for the target and runs the SSA IR in badc’s interpreter, which checks how the program uses pointers.

$ badc --interp hello.c; echo "status $?"
Hello 123
status 0

--jit

The JIT runs on Linux x86-64 and ARM64, macOS ARM64, and Windows x64 and ARM64. It runs host code only: --jit with another --target is an error. Library calls go to the host’s C library, as from a native image. -O applies as it does to an image.

The JIT refuses two constructs, each with B4001 unsupported:

--interp

--interp compiles for --target, by default the host, with that target’s type sizes, predefined macros and headers. Any host can interpret a program for any target.

The interpreter keeps the program’s data, a 256 KiB stack and the heap in one byte-addressed memory. Code is outside that memory: a function pointer is a tagged value, not an address. Loading or storing through a function pointer is an error, and so is calling through an integer that is not one:

int (*fp)(void) = (int (*)(void))42;
fp();   /* error: runtime: vm_ssa: CallIndirect: target raw=0x000000000000002a is not a code pointer */

Pointer tracking

--track-pointers checks every heap access and every free:

program does report
reads or writes a freed allocation use-after-free, with the allocation’s id
reads or writes outside every live allocation out-of-bounds
frees an allocation twice double free, with the allocation’s id
frees a pointer malloc did not return free of unknown pointer

The program stops at the first report. Native images and --jit make none of these checks.

--trace is accepted and is meant to print a per-instruction trace to stdout; at this commit it prints nothing.

Library

The interpreter has its own C library. It provides malloc, calloc, realloc, free, memcpy, memmove, memset, memcmp, printf, fprintf, fputs, puts, fputc, putc, putchar, fwrite, fflush, fileno, stdin, stdout, stderr, open, read, write, close, getenv, setenv, _putenv_s, exit, and the dlopen family. Calls that badc compiles to instructions, such as sqrt, fabs, floor and labs, also work. strlen and strcmp work only on string literals, which badc evaluates at compile time.

printf reads a long double in the target’s format and writes %a and %La as the target’s C library does: 0xcp-3 for 1.5L on linux-x64, 0x1.8p+0 on the AArch64 targets, 0x1.8000000000000p+0 on Windows.

Any other library call stops the program when it is reached:

error: runtime: vm_ssa: library call `sscanf` is not implemented under --interp

Among the calls not implemented are the scanf family, strtol, strtod and strtold, atoi, sprintf, snprintf and vsnprintf, fopen and fgets, strcpy, strchr, qsort, time, setjmp, signal and pthread_create.

Other limits

The programs test suite runs its fixtures in the interpreter with pointer tracking on. The native backends are checked against exit codes measured with gcc and clang, not against the interpreter; see testing.

^ To the top