--interp and --jitBoth 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
--jitThe 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:
_Thread_local object;__try) on Windows.--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 */
--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.
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.
asm goto, vector registers, condition-flag outputs and
system registers are refused at the asm statement.__try) is refused with B4001
unsupported.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.