kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

commit a9e0c865122ac82d5b27160ac10ad0ec53fa4dd2
parent c6e10c46a421a8e9127fdb5b284aad2537aaf592
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Tue, 16 Jun 2026 19:00:40 -0700

arm32 Phase 2: DEPTH=full corpus lanes (toy X + parse E, bare-metal)

cross_one_arm32 in test/toy/run.sh (opt-in via KIT_TOY_CROSS_ARCHS=arm32, not
the default set — no test-toy disruption) + the parse E-lane arm32 branch
(test/parse/run.sh + kit_test_target.h) + the arm32 case in cross_test.sh's
freestanding full lane. Both run bare-metal under qemu-system-arm via exec_bare,
mirroring rv32; real gaps (i64 atomics, TLS, __int128) are left RED on purpose.

Diffstat:
Mscripts/cross_test.sh | 3+++
Mtest/lib/kit_test_target.h | 16+++++++++++++++-
Mtest/parse/run.sh | 28++++++++++++++++++++++++++++
Mtest/toy/run.sh | 33+++++++++++++++++++++++++++++++++
4 files changed, 79 insertions(+), 1 deletion(-)

diff --git a/scripts/cross_test.sh b/scripts/cross_test.sh @@ -291,6 +291,9 @@ full_token() { rv32) _full_lane "$t:toy" env KIT="$KIT" KIT_TOY_CROSS_ARCHS=rv32 KIT_TEST_PATHS=X bash "$ROOT/test/toy/run.sh" _full_lane "$t:parse" env KIT="$KIT" KIT_TEST_ARCH=rv32 KIT_TEST_PATHS=E bash "$ROOT/test/parse/run.sh" ;; + arm32) + _full_lane "$t:toy" env KIT="$KIT" KIT_TOY_CROSS_ARCHS=arm32 KIT_TEST_PATHS=X bash "$ROOT/test/toy/run.sh" + _full_lane "$t:parse" env KIT="$KIT" KIT_TEST_ARCH=arm32 KIT_TEST_PATHS=E bash "$ROOT/test/parse/run.sh" ;; *) printf 'cross: NOTE %s — full-corpus bare-metal not yet wired for %s (smoke only); see doc/plan/PORT.md\n' "$t" "$arch" ;; esac diff --git a/test/lib/kit_test_target.h b/test/lib/kit_test_target.h @@ -85,9 +85,23 @@ static inline int kit_test_target_init(KitTargetSpec* t) { t->float_abi = KIT_FLOAT_ABI_SINGLE; return 0; } + if (!strcmp(a, "arm32") || !strcmp(a, "arm")) { + if (t->os == KIT_OS_MACOS) { + fprintf(stderr, "kit_test_target: arm32 has no macOS target\n"); + return -1; + } + /* arm-none-eabi: freestanding Cortex-M, 4-byte pointers, soft-float (float + * + double via the AEABI/compiler-rt helpers). */ + t->arch = KIT_ARCH_ARM_32; + t->os = KIT_OS_FREESTANDING; + t->ptr_size = 4; + t->ptr_align = 4; + t->float_abi = KIT_FLOAT_ABI_SOFT; + return 0; + } fprintf(stderr, "kit_test_target: unrecognized KIT_TEST_ARCH=\"%s\" " - "(expected aa64/x64/rv64/rv32)\n", + "(expected aa64/x64/rv64/rv32/arm32)\n", a); return -1; } diff --git a/test/parse/run.sh b/test/parse/run.sh @@ -92,6 +92,9 @@ case "$KIT_TEST_ARCH" in # via exec_bare (rv32), not exec_target's qemu-user path. CLANG_TRIPLE is # only for clang probes; the kit target comes from KIT_TEST_ARCH. rv32|riscv32) TEST_ARCH=rv32; CLANG_TRIPLE=riscv32-unknown-elf; EXEC_ARCH=rv32 ;; + # arm32 is freestanding too: the E lane runs bare-metal under qemu-system-arm + # via exec_bare (arm32), mirroring rv32. + arm32|arm) TEST_ARCH=arm32; CLANG_TRIPLE=arm-none-eabi; EXEC_ARCH=arm32 ;; *) printf 'unknown KIT_TEST_ARCH=%s\n' "$KIT_TEST_ARCH" >&2; exit 2 ;; esac export KIT_TEST_ARCH @@ -101,6 +104,7 @@ case "$TEST_ARCH" in x64) RT_AR="$ROOT/build/rt/x86_64-linux/libkit_rt.a" ;; rv64) RT_AR="$ROOT/build/rt/riscv64-linux/libkit_rt.a" ;; rv32) RT_AR="$ROOT/build/rt/riscv32-elf-hardfloat/libkit_rt.a" ;; # used by exec_bare (rv32) + arm32) RT_AR="$ROOT/build/rt/arm-eabi-thumb2/libkit_rt.a" ;; # used by exec_bare (arm32) esac RT_LINK_ARGS=() if [ -f "$RT_AR" ]; then @@ -192,6 +196,9 @@ if [ "$TEST_ARCH" = "rv32" ]; then # The parse corpus's entry is test_main() (path C bridges main->test_main). if exec_bare_setup rv32 "$BUILD_DIR/rv32" test_main; then RV32_BARE_OK=1; else RV32_BARE_OK=0; fi fi +if [ "$TEST_ARCH" = "arm32" ]; then + if exec_bare_setup arm32 "$BUILD_DIR/arm32" test_main; then ARM32_BARE_OK=1; else ARM32_BARE_OK=0; fi +fi # ---- harness binaries ------------------------------------------------------ @@ -379,6 +386,27 @@ kit_lane_E() { else kit_fail "$KIT_NAME/E" "expected $exp_byte got $rc (qemu-system-riscv32), ${dt}ms"; fi return fi + if [ "$TEST_ARCH" = "arm32" ]; then + # arm32: freestanding bare-metal, same shape as rv32 but under + # qemu-system-arm (ARM semihosting exit). Gaps stay RED. + local exp_byte rc reason t0 dt run_rc + if [ "${ARM32_BARE_OK:-0}" -ne 1 ]; then + kit_skip "$KIT_NAME/E" "no arm32 runner (qemu-system-arm)" + return + fi + _parse_emit_obj || return + exp_byte=$(( KIT_EXPECTED & 0xff )) + t0=$(kit_now_ms) + reason="$(exec_bare_run arm32 "$PARSE_OBJ" "$KIT_WORK" "$KIT_WORK/exec.rc")" + run_rc=$? + dt=$(( $(kit_now_ms) - t0 )) + kit_time E "$dt" + if [ "$run_rc" -eq 2 ]; then kit_fail "$KIT_NAME/E" "$reason, ${dt}ms"; return; fi + rc="$(cat "$KIT_WORK/exec.rc" 2>/dev/null || echo 99)" + if [ "$rc" -eq "$exp_byte" ]; then kit_pass "$KIT_NAME/E (${dt}ms)" + else kit_fail "$KIT_NAME/E" "expected $exp_byte got $rc (qemu-system-arm), ${dt}ms"; fi + return + fi if [ $have_exe_runner -ne 1 ] || [ $have_clang_cross -ne 1 ] || [ $have_start_obj -ne 1 ]; then kit_skip "$KIT_NAME/E" "no link-exe-runner, $TEST_ARCH clang, or start.o" return diff --git a/test/toy/run.sh b/test/toy/run.sh @@ -408,10 +408,39 @@ cross_one_rv32() { else kit_fail "$label" "expected rc $exp, got $rc (qemu-system-riscv32)"; fi } +# arm32 cross arch: freestanding (arm-none-eabi, Cortex-M), bare-metal under +# qemu-system-arm via exec_bare — same model as rv32. Real arm32 gaps (i64 +# atomics, TLS needing a thread pointer, __int128) are left RED on purpose, not +# skipped, so they are not silently hidden. +cross_one_arm32() { + local label="$KIT_BASE/X-O$KIT_OPT:arm32" rc reason exp obj cc_err + local skip="${KIT_SRC%.toy}.arm32.skip" + if [ -e "$skip" ]; then kit_skip "$label" "$(head -n1 "$skip")"; return; fi + if [ "${ARM32_BARE_OK:-0}" -ne 1 ]; then + kit_skip "$label" "no arm32 runner (qemu-system-arm)"; return; fi + if grep -q 'asmnop' "$KIT_SRC" 2>/dev/null; then + kit_skip "$label" "asmnop is target-specific before toy asm selectors"; return; fi + obj="$KIT_WORK/$KIT_BASE.O$KIT_OPT.arm32.o"; cc_err="$KIT_WORK/arm32.cc.err" + if ! "$KIT" cc "-O$KIT_OPT" -target arm-none-eabi -mcpu=cortex-m3 \ + -mfloat-abi=soft -ffreestanding \ + -c "$KIT_SRC" -o "$obj" > "$KIT_WORK/arm32.cc.out" 2> "$cc_err"; then + kit_fail "$label" "kit cc -target arm-none-eabi failed" + sed 's/^/ | /' "$cc_err"; return + fi + if [ -s "$cc_err" ]; then + kit_fail "$label" "kit cc arm32 wrote stderr"; sed 's/^/ | /' "$cc_err"; return; fi + reason="$(exec_bare_run arm32 "$obj" "$KIT_WORK" "$KIT_WORK/arm32.rc")" + if [ $? -eq 2 ]; then kit_skip "$label" "$reason"; return; fi + rc="$(cat "$KIT_WORK/arm32.rc" 2>/dev/null || echo 99)"; exp=$(( KIT_EXPECTED & 255 )) + if [ "$rc" -eq "$exp" ]; then kit_pass "$label" + else kit_fail "$label" "expected rc $exp, got $rc (qemu-system-arm)"; fi +} + cross_one() { local arch="$1" local triple tag obj exe start_obj cc_err ld_err out err label if [ "$arch" = "rv32" ]; then cross_one_rv32; return; fi + if [ "$arch" = "arm32" ]; then cross_one_arm32; return; fi triple="$(cross_triple_for "$arch")" || { kit_skip "$KIT_BASE/X-O$KIT_OPT:$arch" "unknown cross arch" return @@ -670,6 +699,10 @@ if [ "$RUN_X" -eq 1 ]; then *" rv32 "*) if exec_bare_setup rv32 "$BUILD_DIR/rv32"; then RV32_BARE_OK=1; else RV32_BARE_OK=0; fi ;; esac + case " $TOY_CROSS_ARCHS " in + *" arm32 "*) + if exec_bare_setup arm32 "$BUILD_DIR/arm32"; then ARM32_BARE_OK=1; else ARM32_BARE_OK=0; fi ;; + esac fi # ---- drive the corpora -----------------------------------------------------