test.mk (52696B)
1 # Data-driven tests. Included from the top-level Makefile. 2 # 3 # - test-driver: aggregate alias that runs all test-driver-* targets. 4 # - test-driver-cc: narrow CLI behavior checks that do not belong to a specific 5 # frontend/linker corpus. Depends on the kit driver binary. 6 # - test-pp: aggregate alias that runs test-pp-ok and test-pp-err. 7 # - test-pp-ok: C preprocessor success cases; depends on the kit driver binary. 8 # - test-elf: ELF roundtrip harness in test/elf/; depends only on 9 # libkit.a and compiles its own test binaries against it. Skipped 10 # layers are reported (set KIT_TEST_ALLOW_SKIP=1 to allow skips). 11 # - test-ar: in-process ar reader/writer tests; depends only on 12 # libkit.a. Set KIT_AR_TEST_HOST=1 to also dump produced bytes 13 # to /tmp and run the host's `ar t` / `nm --print-armap` as a 14 # cross-check. 15 # - test-driver-ar: scenario-driven CLI harness for `kit ar`. Each 16 # case under test/ar/cases/ runs a small script and diffs stdout. 17 # Depends on the kit driver binary. 18 # - test-link: linker + JIT behavioral harness in test/link/; three paths 19 # per case (roundtrip R, ELF exec E, JIT J). Depends only on libkit.a. 20 # Set KIT_TEST_ALLOW_SKIP=1 to allow skipped layers. 21 # - test-macho: Mach-O variant of test-link; defaults to roundtrip+JIT 22 # paths because hosted Mach-O executable execution is target/SDK-specific. 23 # - test-parse: aggregate alias that runs test-parse-ok and test-parse-err. 24 # - test-parse-ok: file-driven C parser success harness in test/parse/; each 25 # case is a .c source file. Built against the public kit.h surface; 26 # reuses kit-roundtrip, link-exe-runner, and jit-runner. 27 # - test-asm: aggregate alias over the per-arch asm lanes test-asm-aa64, 28 # test-asm-x64 and test-asm-rv64. The file-driven assembler/disassembler 29 # harness in test/asm/ runs one arch per invocation (KIT_TEST_ARCH) over 30 # three sub-corpora (encode/, decode/, listing/), one mode per sub-dir. 31 # aa64 runs the full path set (incl. native exec on aa64 hosts); x64/rv64 32 # run the host-independent encode/decode/listing lanes only. See doc/ASM.md. 33 34 TEST_TARGETS = \ 35 test-cf-corpus-selftest \ 36 test-aa64-inline \ 37 test-abi-classify \ 38 test-ar \ 39 test-asm \ 40 test-asm-aa64 \ 41 test-asm-x64 \ 42 test-asm-rv64 \ 43 test-asm-rv32 \ 44 test-toy-rv32 \ 45 test-parse-rv32 \ 46 test-disasm-complete \ 47 test-asm-roundtrip \ 48 test-asm-roundtrip-exec \ 49 test-asm-symmetry \ 50 test-asm-roundtrip-toy \ 51 test-hostas-toy \ 52 test-hostas-cross \ 53 test-diff-llvm \ 54 test-bootstrap-toy \ 55 test-bootstrap-toy-debug \ 56 test-bootstrap-toy-release \ 57 test-bounce \ 58 test-cbackend \ 59 test-cg-api \ 60 test-coff \ 61 test-coff-mingw-import \ 62 test-coff-windows-o1-abi \ 63 test-coff-windows-ucrt \ 64 test-debug \ 65 test-dbg \ 66 test-driver \ 67 test-driver-ar \ 68 test-driver-cas \ 69 test-driver-cc \ 70 test-driver-build \ 71 test-driver-lsan \ 72 test-driver-objcopy \ 73 test-driver-objdump \ 74 test-driver-pkg \ 75 test-driver-strings \ 76 test-driver-tools \ 77 test-driver-wasm \ 78 test-hash \ 79 test-driver-strip \ 80 test-dwarf \ 81 test-elf \ 82 test-emu \ 83 test-emu-unit \ 84 test-interp \ 85 test-interp-emu \ 86 test-interp-toy \ 87 test-ir-recorder \ 88 test-isa \ 89 test-lib-deps \ 90 test-libc \ 91 test-libc-glibc \ 92 test-libc-glibc-rv64 \ 93 test-libc-musl \ 94 test-libc-musl-rv64 \ 95 test-link \ 96 test-link-reloc-uleb128 \ 97 test-link-reloc-desc \ 98 test-link-reloc-apply \ 99 test-link-jit-tls-relax \ 100 test-link-coff-weak-alias \ 101 test-macho \ 102 test-native-direct-target \ 103 test-opt \ 104 test-parse \ 105 test-parse-err \ 106 test-parse-ok \ 107 test-parse-rv64-wide \ 108 test-pp \ 109 test-pp-err \ 110 test-pp-ok \ 111 test-pp-file-escape \ 112 test-rt-headers \ 113 test-rt-runtime \ 114 test-rt-backtrace \ 115 test-link-x64 \ 116 test-rv64-inline \ 117 test-rv64-jit \ 118 test-rv32-jit \ 119 test-rv64-tls-link \ 120 test-smoke-rv64 \ 121 test-smoke-rv32 \ 122 test-smoke-x64 \ 123 test-toy \ 124 test-wasm \ 125 test-wasm-c \ 126 test-wasm-front \ 127 test-wasm-target \ 128 test-wasm-toy \ 129 test-x64-dbg \ 130 test-x64-inline 131 132 DEFAULT_TEST_TARGETS = \ 133 test-cf-corpus-selftest \ 134 test-driver \ 135 test-pp \ 136 test-elf \ 137 test-coff \ 138 test-ar \ 139 test-link \ 140 test-toy \ 141 test-dwarf \ 142 test-debug \ 143 test-parse \ 144 test-asm \ 145 test-asm-roundtrip \ 146 test-isa \ 147 test-aa64-inline \ 148 test-rv64-inline \ 149 test-rv64-jit \ 150 test-rv32-jit \ 151 test-rv64-tls-link \ 152 test-emu \ 153 test-emu-unit \ 154 test-interp \ 155 test-interp-emu \ 156 test-x64-inline \ 157 test-x64-dbg \ 158 test-rt-headers \ 159 test-lib-deps \ 160 test-cg-api \ 161 test-abi-classify \ 162 test-ir-recorder \ 163 test-native-direct-target \ 164 test-opt \ 165 test-asm-symmetry \ 166 test-link-reloc-uleb128 \ 167 test-link-reloc-desc \ 168 test-link-reloc-apply \ 169 test-link-jit-tls-relax \ 170 test-link-coff-weak-alias \ 171 test-dbg \ 172 test-disasm-complete \ 173 test-macho \ 174 test-interp-toy \ 175 test-wasm \ 176 test-libc \ 177 test-link-x64 \ 178 test-rt-runtime \ 179 test-rt-backtrace \ 180 test-bounce \ 181 bootstrap \ 182 test-bootstrap-toy 183 184 .PHONY: test $(TEST_TARGETS) windows-ucrt-sysroots \ 185 test-toy-vm test-toy-freebsd-vm test-toy-windows-vm \ 186 test-hosted test-hosted-vm hosted-glibc-images 187 188 test: $(DEFAULT_TEST_TARGETS) 189 190 # Unit-test binary build rules: two regimes (public vs internal interface). 191 include mk/test_unit.mk 192 193 # Provision the pinned per-arch container rootfs images that exec_target.sh runs 194 # kit-emitted binaries inside. This is the ONLY test step that touches the 195 # network: the cross-arch exec harnesses (toy/parse/link ... path X/E/L) run with 196 # `podman run --pull=never`, so without these images those paths SKIP. Run once, 197 # and again only after the pin in test/lib/test_images.sh changes. FORCE=1 198 # re-pulls. The images are pinned per-arch by content digest, so they coexist in 199 # local storage and can never clobber one another. 200 .PHONY: test-images 201 test-images: 202 @bash test/lib/pull_test_images.sh 203 204 # Hermetic self-test of the shared corpus harness engine (test/lib/kit_corpus.sh): 205 # asserts serial==parallel determinism, SKIP-NA, and the parallel-safety 206 # invariant (exec_target queued only on the parent, never in a worker). No 207 # kit binary / podman / qemu needed. 208 test-cf-corpus-selftest: 209 @bash test/lib/kit_corpus_selftest.sh 210 211 test-driver: test-driver-cc test-driver-build test-driver-ar test-driver-cas test-driver-strip test-driver-objcopy test-driver-objdump test-driver-pkg test-driver-strings test-driver-tools test-driver-wasm 212 213 test-driver-cc: bin 214 @KIT=$(abspath $(BIN)) sh test/driver/run.sh 215 216 test-driver-build: bin 217 @KIT=$(abspath $(BIN)) sh test/buildcmds/run.sh 218 219 ifeq ($(HOST_OS),linux) 220 test-driver-lsan: 221 @$(MAKE) test-driver RELEASE=0 BUILD_DIR=build/lsan \ 222 ASAN_OPTIONS=detect_leaks=1:halt_on_error=1:abort_on_error=1 223 else 224 test-driver-lsan: 225 @printf '%s\n' 'SKIP test-driver-lsan: LeakSanitizer requires HOST_OS=linux' 226 endif 227 228 # test-cbackend: --emit=c C-source backend, driven through three 229 # frontends — parse-runner (C), toy-runner (toy), wasm-runner (wat/wasm). 230 # Each invokes its existing runner with paths=C so a single corpus per 231 # frontend exercises both the existing backends and the C backend. 232 # Together they prove the CGTarget seam is frontend-agnostic. 233 # Unimplemented CGTarget methods report as SKIP; see doc/CBACKEND.md. 234 KIT_CBACKEND_TEST_JOBS ?= $(if $(KIT_TEST_JOBS),$(KIT_TEST_JOBS),1) 235 test-cbackend: bin 236 @KIT_TEST_JOBS=$(KIT_CBACKEND_TEST_JOBS) KIT_TEST_PATHS=C KIT_TEST_ALLOW_SKIP=1 sh test/parse/run.sh 237 @KIT_TEST_JOBS=$(KIT_CBACKEND_TEST_JOBS) KIT_TEST_PATHS=C KIT=$(abspath $(BIN)) sh test/toy/run.sh 238 @KIT_TEST_JOBS=$(KIT_CBACKEND_TEST_JOBS) KIT_TEST_PATHS=C KIT=$(abspath $(BIN)) bash test/wasm/run.sh 239 240 # test-wasm-toy: opt-in Toy -> Wasm -> JIT roundtrip. Runs the toy corpus 241 # under the W path (compile -target wasm32-none, then `kit run` the .wasm, 242 # which routes back through the lang/wasm frontend to native CG). Most cases 243 # will fail or skip today; the target exists so progress on the Wasm CGTarget 244 # is visible without putting noise into the default `test` summary. 245 # Drop `KIT_TEST_ALLOW_SKIP=1` once the corpus is mostly green. 246 test-wasm-toy: bin 247 @KIT_TEST_PATHS=W KIT_TEST_ALLOW_SKIP=1 KIT=$(abspath $(BIN)) sh test/toy/run.sh 248 249 # test-wasm-c: opt-in C -> Wasm -> JIT roundtrip, the C-frontend analogue of 250 # test-wasm-toy. Runs the test/parse corpus under the W path (compile 251 # -target wasm32-none, then `kit run -e test_main` the .wasm, which routes 252 # back through the lang/wasm frontend to native CG). The C corpus exercises 253 # far more of the language than the toy corpus, so expect many SKIPs for 254 # not-yet-implemented Wasm lowerings; the target makes that progress visible 255 # without adding noise to the default `test` summary. Drop 256 # `KIT_TEST_ALLOW_SKIP=1` once the corpus is mostly green. 257 test-wasm-c: bin $(PARSE_RUNNER) 258 @KIT_TEST_PATHS=W KIT_TEST_ALLOW_SKIP=1 KIT=$(abspath $(BIN)) bash test/parse/run.sh 259 260 test-pp: test-pp-ok test-pp-err test-pp-file-escape 261 262 test-pp-ok: bin 263 @KIT=$(abspath $(BIN)) test/pp/run.sh 264 265 test-pp-err: bin 266 @KIT=$(abspath $(BIN)) test/pp/run_errors.sh 267 268 test-pp-file-escape: bin 269 @KIT=$(abspath $(BIN)) bash test/pp/run_file_escape.sh 270 271 # Best-effort kit binary build: Layer D needs build/kit, but the 272 # binary may not link until enough libkit symbols exist. The harness 273 # detects a missing binary and skips that layer; don't break test-elf 274 # when bin fails. 275 .PHONY: bin-soft 276 bin-soft: 277 -@$(MAKE) bin 2>/dev/null || true 278 279 AR_TEST_BIN = build/test/ar_test 280 281 test-ar: $(AR_TEST_BIN) 282 $(AR_TEST_BIN) 283 284 285 test-driver-ar: bin 286 @KIT=$(abspath $(BIN)) test/ar/run.sh 287 288 test-driver-cas: bin 289 @KIT=$(abspath $(BIN)) sh test/cas/run.sh 290 291 test-driver-strip: bin 292 @KIT=$(abspath $(BIN)) test/strip/run.sh 293 294 test-driver-objcopy: bin 295 @KIT=$(abspath $(BIN)) test/objcopy/run.sh 296 297 test-driver-objdump: bin 298 @KIT=$(abspath $(BIN)) sh test/objdump/run.sh 299 300 test-driver-pkg: bin 301 @KIT=$(abspath $(BIN)) sh test/pkg/run.sh 302 303 test-driver-strings: bin 304 @KIT=$(abspath $(BIN)) sh test/strings/run.sh 305 306 test-driver-tools: bin 307 @KIT=$(abspath $(BIN)) sh test/tools/run.sh 308 309 test-driver-wasm: bin 310 @KIT=$(abspath $(BIN)) sh test/driver-wasm/run.sh 311 312 # DWARF consumer unit test: builds a hand-crafted DWARF-bearing ELF in 313 # memory and exercises every kit_dwarf_* entry. It reaches into the 314 # internal object builder to synthesize the fixture, so link individual 315 # lib objects rather than libkit.a (which hides internal symbols). 316 DWARF_TEST_BIN = build/test/dwarf_test 317 318 test-dwarf: $(DWARF_TEST_BIN) 319 $(DWARF_TEST_BIN) 320 321 322 # DWARF producer self-roundtrip unit test. Drives Debug directly, calls 323 # debug_emit, asserts the produced sections have valid DWARF 5 structure 324 # (length fields, version, address sizes, expected relocations against 325 # function symbol). Deliberately bypasses the consumer (kit_dwarf_open) 326 # so encoder bugs aren't masked by matching decoder bugs. 327 DEBUG_TEST_BIN = build/test/debug_roundtrip_unit 328 CFI_TEST_BIN = build/test/debug_cfi_unit 329 330 test-debug: $(DEBUG_TEST_BIN) $(CFI_TEST_BIN) 331 $(DEBUG_TEST_BIN) 332 $(CFI_TEST_BIN) 333 334 335 # CFI/.eh_frame producer roundtrip for aa64/rv64/x64 (validates the per-arch 336 # CIE template: code/data-align, return-address reg, CFA-init reg). 337 338 test-dbg: bin 339 @KIT=$(abspath $(BIN)) sh test/dbg/run.sh 340 341 .PHONY: test-dbg-red 342 test-dbg-red: bin 343 @KIT=$(abspath $(BIN)) DBG_STRICT_XFAIL=1 sh test/dbg/run.sh 344 345 # aa64 ISA descriptor-table unit test (doc/ASM.md phase 2). Covers 346 # every AA64Format the table maps and the alias-precedence invariant 347 # (first-match disasm picks the alias spelling over the canonical 348 # form). Internal arch/ surface — needs -Isrc. 349 AA64_ISA_TEST_BIN = build/test/aa64_isa_test 350 RV64_DECODE_TEST_BIN = build/test/rv64_decode_test 351 RV32_DECODE_TEST_BIN = build/test/rv32_decode_test 352 353 test-isa: $(AA64_ISA_TEST_BIN) $(RV64_DECODE_TEST_BIN) $(RV32_DECODE_TEST_BIN) 354 $(AA64_ISA_TEST_BIN) 355 $(RV64_DECODE_TEST_BIN) 356 $(RV32_DECODE_TEST_BIN) 357 358 359 360 # aa64_sweep_gen: emits one representative encoding per disasm-table row for the 361 # asm<->disasm self-symmetry sweep (test/asm/symmetry.sh). Needs the internal 362 # arch/aa64/isa.h surface, so -Isrc + LIB_OBJS like the ISA unit test. 363 AA64_SWEEP_GEN = build/test/aa64_sweep_gen 364 365 # test-emu: emulator end-to-end integration test. Builds tiny in-memory rv64 366 # ELFs and runs them to their exit syscall, asserting the exit code — entirely 367 # through the PUBLIC kit_emu_* API, so it links the public archive ($(LIB_AR), 368 # whose `ld -r` step localizes internal symbols). -Isrc is only for the 369 # header-only rv64 encoders / ELF constants the in-memory ELF builders use. 370 EMU_RV64_TEST_BIN = build/test/emu_rv64_test 371 372 test-emu: $(EMU_RV64_TEST_BIN) 373 $(EMU_RV64_TEST_BIN) 374 375 $(EMU_RV64_TEST_BIN): test/emu/rv64_smoke_test.c $(UNIT_HDR_DEPS) $(LIB_AR) 376 @mkdir -p $(dir $@) 377 $(CC) $(HOST_CFLAGS) -Iinclude -Isrc -Itest test/emu/rv64_smoke_test.c $(LIB_AR) -o $@ 378 379 # RISC-V ULEB128 diff-reloc application unit test. link_reloc_apply is an 380 # internal (hidden) symbol, so link the raw lib objects like the other 381 # internal-surface unit tests rather than libkit.a. 382 RELOC_ULEB128_TEST_BIN = build/test/reloc_uleb128_unit 383 384 test-link-reloc-uleb128: $(RELOC_ULEB128_TEST_BIN) 385 $(RELOC_ULEB128_TEST_BIN) 386 387 # Relocation-descriptor migration guard (doc/plan/RELOC.md, WS-B): pins 388 # reloc_desc()/reloc_kind_* to the frozen pre-refactor width + classification 389 # behaviour across every backend arch. Internal-surface, so links the raw lib 390 # objects like the other internal unit tests. 391 RELOC_DESC_TEST_BIN = build/test/reloc_desc_test 392 393 test-link-reloc-desc: $(RELOC_DESC_TEST_BIN) 394 $(RELOC_DESC_TEST_BIN) 395 396 # Relocation byte-encoder migration guard (doc/plan/RELOC.md, WS-C): pins 397 # link_reloc_apply to the frozen pre-refactor patched bytes for every 398 # instruction-immediate kind, so partitioning the encoders per-arch stays 399 # byte-identical. Internal-surface, so links the raw lib objects. 400 RELOC_APPLY_TEST_BIN = build/test/reloc_apply_test 401 402 test-link-reloc-apply: $(RELOC_APPLY_TEST_BIN) 403 $(RELOC_APPLY_TEST_BIN) 404 405 # In-process JIT TLS Local-Exec relaxation for the Windows (COFF) TEB idiom: 406 # pins the per-arch byte rewrite (jit_tls_le_relax) for x86-64 and aarch64. The 407 # aarch64 path is also covered end-to-end on the Windows VM; this is the only 408 # automated guard for the x86-64 idiom. Internal-surface (raw lib objects). 409 JIT_TLS_RELAX_TEST_BIN = build/test/jit_tls_relax_test 410 411 test-link-jit-tls-relax: $(JIT_TLS_RELAX_TEST_BIN) 412 $(JIT_TLS_RELAX_TEST_BIN) 413 414 # COFF WEAK_EXTERNAL alias capture in read_coff: pins the aux-TagIndex decode 415 # that lets the linker resolve mingw x86_64's `_setjmp` -> `__intrinsic_setjmp` 416 # alias (the x64-windows cross-link blocker). Internal-surface (raw lib objects). 417 COFF_WEAK_ALIAS_TEST_BIN = build/test/coff_weak_alias_test 418 419 test-link-coff-weak-alias: $(COFF_WEAK_ALIAS_TEST_BIN) 420 $(COFF_WEAK_ALIAS_TEST_BIN) 421 422 # test-emu-unit: white-box unit tests for the emulator's INTERNAL units (rv64 423 # decoder, EmuAddrSpace, Linux syscall handler) that have no public API. Reaches 424 # internal symbols -> links $(LIB_OBJS) (mirrors test-interp), not the archive. 425 EMU_RV64_UNIT_TEST_BIN = build/test/emu_rv64_unit_test 426 427 test-emu-unit: $(EMU_RV64_UNIT_TEST_BIN) 428 $(EMU_RV64_UNIT_TEST_BIN) 429 430 431 # test-interp: threaded-bytecode interpreter unit smoke test. Builds tiny CG IR 432 # by hand, runs opt_run_o1_interp + interp_lower + the engine, asserts the 433 # returned value. Reaches internal opt/interp symbols -> links $(LIB_OBJS) and 434 # needs -Isrc (mirrors test-opt). 435 INTERP_SMOKE_TEST_BIN = build/test/interp_smoke_test 436 437 test-interp: $(INTERP_SMOKE_TEST_BIN) 438 $(INTERP_SMOKE_TEST_BIN) 439 440 441 # test-interp-emu: differential test of the emulator's INTERP execution mode 442 # (doc/INTERPRETER.md Phase 4). Builds a tiny rv64 ELF with SD/LD/ecall and runs 443 # it through kit_emu_run in JIT and INTERP modes (both -O1), asserting the exit 444 # codes match. Public-API only, but links $(LIB_OBJS) like test-interp to dodge 445 # the visibility-hidden archive's localized internals. 446 INTERP_EMU_TEST_BIN = build/test/rv64_interp_smoke_test 447 448 test-interp-emu: $(INTERP_EMU_TEST_BIN) 449 $(INTERP_EMU_TEST_BIN) 450 451 452 # test-interp-toy: run the toy suite's interpreter (--no-jit) path only, 453 # asserting it matches the golden exit codes (and SKIPping unimplemented ops). 454 test-interp-toy: bin 455 @KIT=$(abspath $(BIN)) KIT_TEST_PATHS=I bash test/toy/run.sh 456 457 CG_API_TEST_BIN = build/test/cg_api_test 458 CG_SWITCH_TEST_BIN = build/test/cg_switch_test 459 CG_FP_CMP_TEST_BIN = build/test/cg_fp_cmp_test 460 CG_CONTROL_TEST_BIN = build/test/cg_control_test 461 STRENGTH_REDUCE_TEST_BIN = build/test/strength_reduce_test 462 TARGET_TEST_BIN = build/test/target_test 463 HASH_TEST_BIN = build/test/hash_test 464 PANIC_RECOVERY_TEST_BIN = build/test/panic_recovery_test 465 ABI_CLASSIFY_TEST_BIN = build/test/abi_classify_test 466 IR_RECORDER_TEST_BIN = build/test/ir_recorder_test 467 NATIVE_DIRECT_TARGET_TEST_BIN = build/test/native_direct_target_test 468 469 test-cg-api: $(TARGET_TEST_BIN) $(CG_API_TEST_BIN) $(CG_SWITCH_TEST_BIN) \ 470 $(CG_FP_CMP_TEST_BIN) $(CG_CONTROL_TEST_BIN) \ 471 $(STRENGTH_REDUCE_TEST_BIN) \ 472 $(PANIC_RECOVERY_TEST_BIN) 473 $(TARGET_TEST_BIN) 474 $(CG_API_TEST_BIN) 475 $(CG_SWITCH_TEST_BIN) 476 $(CG_FP_CMP_TEST_BIN) 477 $(CG_CONTROL_TEST_BIN) 478 $(STRENGTH_REDUCE_TEST_BIN) 479 $(PANIC_RECOVERY_TEST_BIN) 480 481 test-hash: $(HASH_TEST_BIN) 482 $(HASH_TEST_BIN) 483 484 test-abi-classify: $(ABI_CLASSIFY_TEST_BIN) 485 $(ABI_CLASSIFY_TEST_BIN) 486 487 488 489 490 test-ir-recorder: $(IR_RECORDER_TEST_BIN) 491 $(IR_RECORDER_TEST_BIN) 492 493 494 test-native-direct-target: $(NATIVE_DIRECT_TARGET_TEST_BIN) 495 $(NATIVE_DIRECT_TARGET_TEST_BIN) 496 497 498 test-toy: bin 499 @KIT=$(abspath $(BIN)) test/toy/run.sh 500 501 # Opt-in: run the Toy corpus as real hosted programs inside the FreeBSD and 502 # Windows VMs (test/toy/vm.sh), asserting each case's .expected exit code on the 503 # genuine OS — the hosted counterpart to run.sh's freestanding-Linux X lane. 504 # Not in the default set (needs provisioned VMs + cross sysroots; amd64/riscv64 505 # FreeBSD run under slow TCG). The FreeBSD script lazily builds its base.txz 506 # sysroots and self-skips arches whose VM/sysroot is absent; the Windows target 507 # carries the same rt + UCRT-sysroot deps as test-coff-windows-vm. 508 test-toy-freebsd-vm: bin 509 @KIT=$(abspath $(BIN)) bash test/toy/vm.sh freebsd 510 511 test-toy-windows-vm: bin rt-x86_64-pc-windows rt-aarch64-windows windows-ucrt-sysroots 512 @KIT=$(abspath $(BIN)) bash test/toy/vm.sh windows 513 514 test-toy-vm: test-toy-freebsd-vm test-toy-windows-vm 515 516 # test-bootstrap-toy: run the Toy corpus through the bootstrapped (self-built) 517 # stage3 kit instead of the host-built binary, so the self-hosted compiler is 518 # exercised on real codegen (not just self-reproduction like `make bootstrap`). 519 # Split per build mode: -debug runs the debug stage3, -release the release 520 # (-O1) stage3; the aggregate target runs both. 521 test-bootstrap-toy: test-bootstrap-toy-debug test-bootstrap-toy-release 522 523 test-bootstrap-toy-debug: bootstrap-debug 524 @KIT='$(abspath $(BUILD_DIR)/debug/bootstrap/stage3/kit)' test/toy/run.sh 525 526 test-bootstrap-toy-release: bootstrap-release 527 @KIT='$(abspath $(BUILD_DIR)/release/bootstrap/stage3/kit)' test/toy/run.sh 528 529 530 # Public-API inline-asm backend tests. These emit a tiny function through CG, 531 # reopen the object through the public object reader, and assert the expected 532 # instruction bytes are present in .text. 533 AA64_INLINE_TEST_BIN = build/test/aa64_inline_test 534 535 test-aa64-inline: $(AA64_INLINE_TEST_BIN) 536 $(AA64_INLINE_TEST_BIN) 537 538 539 RV64_INLINE_TEST_BIN = build/test/rv64_inline_test 540 541 test-rv64-inline: $(RV64_INLINE_TEST_BIN) 542 $(RV64_INLINE_TEST_BIN) 543 544 545 # rv64 JIT smoke test. Builds a tiny rv64 ELF .o in memory, runs it 546 # through kit_link_session in JIT-output mode, and skips native execution 547 # on non-riscv64 hosts after exercising the JIT mapping/reloc path. 548 RV64_JIT_TEST_BIN = build/test/rv64_jit_test 549 550 test-rv64-jit: $(RV64_JIT_TEST_BIN) 551 @$(RV64_JIT_TEST_BIN); rc=$$?; \ 552 if [ $$rc -eq 77 ]; then \ 553 echo " (rv64_jit_test SKIPPED on non-rv64 host)"; \ 554 exit 0; \ 555 else \ 556 exit $$rc; \ 557 fi 558 559 # rv32 JIT smoke test. Mirror of test-rv64-jit: builds a tiny rv32 ELF .o in 560 # memory, runs it through kit_link_session in JIT-output mode, and skips native 561 # execution on non-riscv32 hosts after exercising the JIT mapping/reloc path. 562 RV32_JIT_TEST_BIN = build/test/rv32_jit_test 563 564 test-rv32-jit: $(RV32_JIT_TEST_BIN) 565 @$(RV32_JIT_TEST_BIN); rc=$$?; \ 566 if [ $$rc -eq 77 ]; then \ 567 echo " (rv32_jit_test SKIPPED on non-rv32 host)"; \ 568 exit 0; \ 569 else \ 570 exit $$rc; \ 571 fi 572 573 574 # Link-only regression for rv64 TLS Local-Exec lowering (runs on any host). 575 test-rv64-tls-link: bin 576 @KIT='$(abspath $(BIN))' bash test/smoke/rv64_tls_link.sh 577 578 X64_INLINE_TEST_BIN = build/test/x64_inline_test 579 580 test-x64-inline: $(X64_INLINE_TEST_BIN) 581 $(X64_INLINE_TEST_BIN) 582 583 584 X64_DBG_TEST_BIN = build/test/x64_dbg_test 585 586 test-x64-dbg: $(X64_DBG_TEST_BIN) 587 $(X64_DBG_TEST_BIN) 588 589 # Reaches the internal arch/arch.h surface (arch_lookup, ArchDbgOps) -> links 590 # $(LIB_OBJS), not the archive, whose relocatable merge localizes non-public 591 # symbols (mirrors the aa64/rv64 arch unit tests above). 592 593 RT_HEADER_TEST_TARGETS = \ 594 aarch64-linux-gnu \ 595 x86_64-linux-gnu \ 596 riscv64-linux-gnu \ 597 aarch64-apple-darwin \ 598 x86_64-apple-darwin 599 600 test-rt-headers: bin 601 @set -e; \ 602 for target in $(RT_HEADER_TEST_TARGETS); do \ 603 out="build/test/rt-headers/$$target/smoke.o"; \ 604 mkdir -p "$$(dirname "$$out")"; \ 605 $(BIN) cc -target "$$target" -Werror -c test/rt/smoke.c -o "$$out"; \ 606 done 607 608 # Arch token -> linux rt variant target. The cross-target test harnesses link 609 # the matching LINUX runtime archive (compiler-rt-style helpers like 610 # __kit_sext64ti, __kit_assert_fail) rather than the native `rt` target, 611 # which builds only the host's own variant. Shared by the single-arch 612 # parse/asm/macho/link tests (via KIT_TEST_ARCH/TEST_RT_DEP) and by 613 # test-rt-runtime, which sweeps several arches at once. 614 KIT_TEST_ARCH ?= aa64 615 _TEST_RT_aa64 = rt-aarch64-linux 616 _TEST_RT_aarch64 = rt-aarch64-linux 617 _TEST_RT_arm64 = rt-aarch64-linux 618 _TEST_RT_x64 = rt-x86_64-linux 619 _TEST_RT_x86_64 = rt-x86_64-linux 620 _TEST_RT_amd64 = rt-x86_64-linux 621 _TEST_RT_rv64 = rt-riscv64-linux 622 _TEST_RT_riscv64 = rt-riscv64-linux 623 TEST_RT_DEP = $(_TEST_RT_$(KIT_TEST_ARCH)) 624 625 # test-rt-runtime compiles each case for the configured arches and links it 626 # against that arch's LINUX runtime archive, so it must depend on each variant 627 # (not the host `rt`). A stale per-arch archive otherwise silently breaks the 628 # link — e.g. a dropped __kit_assert_fail weak def surfaces as an undefined 629 # reference. KIT_RT_RUNTIME_ARCHES mirrors the default in test/rt/run.sh. 630 KIT_RT_RUNTIME_ARCHES ?= aa64 x64 rv64 631 RT_RUNTIME_DEPS := $(foreach a,$(KIT_RT_RUNTIME_ARCHES),$(_TEST_RT_$(a))) 632 LINK_EXE_RUNNER = build/test/link-exe-runner 633 634 test-rt-runtime: bin $(RT_RUNTIME_DEPS) $(LINK_EXE_RUNNER) 635 @bash test/rt/run.sh 636 637 # L3a backtrace round-trip: run a kit-compiled program that prints its own 638 # backtrace, then symbolize the captured addresses two ways — `kit addr2line` 639 # (bare addresses) and `kit symbolize` (the raw "#N 0xADDR" stream, annotated 640 # in place). Same per-arch deps as test-rt-runtime (each arch's linux rt 641 # archive + the Path-E link runner). See test/rt/addr2line.sh and 642 # doc/plan/BACKTRACE.md (L3a / WS5). 643 test-rt-backtrace: bin $(RT_RUNTIME_DEPS) $(LINK_EXE_RUNNER) 644 @bash test/rt/addr2line.sh 645 646 # Test harness binaries shared by test-elf and test-link. 647 # Declared as Make targets (not built by the run.sh scripts) so they pick 648 # up libkit.a changes deterministically. 649 # 650 # HARNESS_CFLAGS drops -Wpedantic from the normal host flags; the runners cast 651 # kit_jit_lookup's void* to a function pointer, which pedantic rejects under 652 # C11. 653 HARNESS_CFLAGS = $(filter-out -Wpedantic,$(HOST_CFLAGS)) -Iinclude -Itest 654 655 ROUNDTRIP_BIN = build/test/kit-roundtrip 656 ROUNDTRIP_BIN_MACHO = build/test/kit-roundtrip-macho 657 ROUNDTRIP_BIN_COFF = build/test/kit-roundtrip-coff 658 COFF_IMPORT_SMOKE_BIN = build/test/pe-import-smoke 659 COFF_IMPORT_MINGW_BIN = build/test/pe-import-mingw 660 COFF_DSO_FORWARDER_BIN = build/test/pe-dso-forwarder 661 COFF_MIXED_ARCHIVE_BIN = build/test/pe-mixed-archive 662 COFF_IMAGE_READ_BIN = build/test/pe-image-read 663 LLVM_MINGW_SYSROOT_X64_MARKER = build/llvm-mingw/20260602/ucrt/x86_64-w64-mingw32/PROVENANCE 664 LLVM_MINGW_SYSROOT_AARCH64_MARKER = build/llvm-mingw/20260602/ucrt/aarch64-w64-mingw32/PROVENANCE 665 JIT_RUNNER = build/test/jit-runner 666 PARSE_RUNNER = build/test/parse-runner 667 ASM_RUNNER = build/test/asm-runner 668 WASM_TOOL = build/test/wasm-tool 669 670 $(ROUNDTRIP_BIN): test/elf/kit-roundtrip.c $(LIB_AR) 671 @mkdir -p $(dir $@) 672 $(CC) $(HARNESS_CFLAGS) test/elf/kit-roundtrip.c $(LIB_AR) -o $@ 673 674 # Mach-O peer of kit-roundtrip — read_macho + emit_macho. Used by 675 # test-link's path R when KIT_TEST_OBJ=macho. 676 $(ROUNDTRIP_BIN_MACHO): test/macho/kit-roundtrip-macho.c $(LIB_AR) 677 @mkdir -p $(dir $@) 678 $(CC) $(HARNESS_CFLAGS) -Isrc test/macho/kit-roundtrip-macho.c $(LIB_AR) -o $@ 679 680 # PE/COFF round-trip harness (test/coff/). All-in-one binary: builds 681 # hand-crafted ObjBuilders and asserts emit_coff/read_coff round-trip 682 # stability for both x86_64-windows and aarch64-windows. 683 $(ROUNDTRIP_BIN_COFF): test/coff/kit-roundtrip-coff.c $(LIB_OBJS) 684 @mkdir -p $(dir $@) 685 $(CC) $(HARNESS_CFLAGS) -Isrc test/coff/kit-roundtrip-coff.c $(LIB_OBJS) -o $@ 686 687 # PE import-directory smoke test (test/coff/pe-import-smoke.c). 688 # Exercises the full chain: short-import shim bytes -> link_add_obj_bytes 689 # (reclassified as DSO) -> link_resolve -> link_emit_coff. Verifies the 690 # produced PE32+ via x86_64-w64-mingw32-objdump; skips cleanly if absent. 691 $(COFF_IMPORT_SMOKE_BIN): test/coff/pe-import-smoke.c $(LIB_OBJS) 692 @mkdir -p $(dir $@) 693 $(CC) $(HARNESS_CFLAGS) -Isrc test/coff/pe-import-smoke.c $(LIB_OBJS) -o $@ 694 695 # PE import test against a real mingw archive (test/coff/pe-import-mingw.c). 696 # Exercises the long-form import-archive absorption path 697 # (link_add_archive_bytes -> classify_coff_archive_member). Skips cleanly 698 # when the mingw toolchain isn't installed. 699 $(COFF_IMPORT_MINGW_BIN): test/coff/pe-import-mingw.c $(LIB_OBJS) 700 @mkdir -p $(dir $@) 701 $(CC) $(HARNESS_CFLAGS) -Isrc test/coff/pe-import-mingw.c $(LIB_OBJS) -o $@ 702 703 # read_coff_dso forwarder-export contract (test/coff/pe-dso-forwarder.c). 704 # Synthesizes a tiny PE32+ DLL with one direct and one forwarder export 705 # and asserts both surface as OBJ_SEC_NONE globals on the ObjBuilder. 706 $(COFF_DSO_FORWARDER_BIN): test/coff/pe-dso-forwarder.c $(LIB_OBJS) 707 @mkdir -p $(dir $@) 708 $(CC) $(HARNESS_CFLAGS) -Isrc test/coff/pe-dso-forwarder.c $(LIB_OBJS) -o $@ 709 710 # Mixed-member archive (test/coff/pe-mixed-archive.c). Verifies that 711 # one archive containing both a short-import member and a long-form 712 # COFF object with a defined data symbol satisfies references through 713 # both shapes — the same composition libucrt.a uses (API-set imports 714 # alongside lib64_libucrt_extra_a-*.o helpers). 715 $(COFF_MIXED_ARCHIVE_BIN): test/coff/pe-mixed-archive.c $(LIB_OBJS) 716 @mkdir -p $(dir $@) 717 $(CC) $(HARNESS_CFLAGS) -Isrc test/coff/pe-mixed-archive.c $(LIB_OBJS) -o $@ 718 719 # PE32+ linked-image reader round-trip (test/coff/pe-image-read.c). Links a 720 # tiny PIE .exe in memory (import + base reloc), re-opens it via kit_obj_open, 721 # and asserts the neutral image view + raw escape hatch. Needs no external 722 # toolchain — runs on every host. 723 $(COFF_IMAGE_READ_BIN): test/coff/pe-image-read.c $(LIB_OBJS) 724 @mkdir -p $(dir $@) 725 $(CC) $(HARNESS_CFLAGS) -Isrc test/coff/pe-image-read.c $(LIB_OBJS) -o $@ 726 727 $(LLVM_MINGW_SYSROOT_X64_MARKER): scripts/llvm_mingw_sysroot.sh 728 @bash scripts/llvm_mingw_sysroot.sh prepare x64 729 730 $(LLVM_MINGW_SYSROOT_AARCH64_MARKER): scripts/llvm_mingw_sysroot.sh 731 @bash scripts/llvm_mingw_sysroot.sh prepare aarch64 732 733 windows-ucrt-sysroots: $(LLVM_MINGW_SYSROOT_X64_MARKER) $(LLVM_MINGW_SYSROOT_AARCH64_MARKER) 734 735 $(LINK_EXE_RUNNER): test/link/harness/link_exe_runner.c $(LIB_AR) 736 @mkdir -p $(dir $@) 737 $(CC) $(HARNESS_CFLAGS) test/link/harness/link_exe_runner.c $(LIB_AR) -o $@ 738 739 $(JIT_RUNNER): test/link/harness/jit_runner.c $(LIB_AR) 740 @mkdir -p $(dir $@) 741 $(CC) $(HARNESS_CFLAGS) test/link/harness/jit_runner.c $(LIB_AR) -o $@ 742 743 $(PARSE_RUNNER): test/parse/harness/parse_runner.c $(LIB_AR) 744 @mkdir -p $(dir $@) 745 $(CC) $(HARNESS_CFLAGS) test/parse/harness/parse_runner.c $(LIB_AR) -o $@ 746 747 $(ASM_RUNNER): test/asm/harness/asm_runner.c $(LIB_AR) 748 @mkdir -p $(dir $@) 749 $(CC) $(HARNESS_CFLAGS) test/asm/harness/asm_runner.c $(LIB_AR) -o $@ 750 751 $(WASM_TOOL): test/wasm/harness/wasm_tool.c $(LIB_AR) 752 @mkdir -p $(dir $@) 753 $(CC) $(HARNESS_CFLAGS) -I. test/wasm/harness/wasm_tool.c $(LIB_AR) -o $@ 754 755 test-elf: lib bin-soft $(ROUNDTRIP_BIN) 756 KIT_ELF_UNIT_CFLAGS='$(HOST_MODE_CFLAGS)' \ 757 KIT_ELF_UNIT_LDFLAGS='$(HOST_MODE_LDFLAGS)' \ 758 bash test/elf/run.sh 759 760 # PE/COFF round-trip harness plus optional hosted Windows smoke. The 761 # UCRT smoke self-skips when llvm-mingw is not installed. 762 test-coff: lib bin rt-aarch64-windows $(ROUNDTRIP_BIN_COFF) $(COFF_IMPORT_SMOKE_BIN) $(COFF_DSO_FORWARDER_BIN) $(COFF_MIXED_ARCHIVE_BIN) $(COFF_IMAGE_READ_BIN) 763 $(ROUNDTRIP_BIN_COFF) 764 $(COFF_IMPORT_SMOKE_BIN) 765 $(COFF_DSO_FORWARDER_BIN) 766 $(COFF_MIXED_ARCHIVE_BIN) 767 $(COFF_IMAGE_READ_BIN) 768 bash test/coff/windows-ucrt-hosted-smoke.sh 769 bash test/coff/windows-system-dlls-smoke.sh 770 771 # Separate target so it can be skipped gracefully if mingw isn't 772 # installed. The test itself self-skips on missing tooling, but the 773 # build target only fires when explicitly requested. 774 test-coff-mingw-import: lib $(COFF_IMPORT_MINGW_BIN) 775 $(COFF_IMPORT_MINGW_BIN) 776 777 test-coff-windows-ucrt: bin rt-x86_64-pc-windows rt-aarch64-windows windows-ucrt-sysroots 778 KIT_SYSROOT=$(abspath build/llvm-mingw/20260602/ucrt) bash test/coff/windows-ucrt-hosted-smoke.sh 779 KIT_SYSROOT=$(abspath build/llvm-mingw/20260602/ucrt) bash test/coff/windows-system-dlls-smoke.sh 780 KIT_SYSROOT=$(abspath build/llvm-mingw/20260602/ucrt) bash test/coff/windows-o1-abi-smoke.sh 781 782 test-coff-windows-o1-abi: bin rt-x86_64-pc-windows rt-aarch64-windows windows-ucrt-sysroots 783 KIT_SYSROOT=$(abspath build/llvm-mingw/20260602/ucrt) bash test/coff/windows-o1-abi-smoke.sh 784 785 # Opt-in: run the COFF/PE hosted smokes against a real Windows 11 ARM64 VM, so 786 # their per-program run lanes execute for real instead of self-skipping. On 787 # Apple Silicon a single hvf-accelerated VM serves both targets: aarch64-windows 788 # runs natively and x86_64-windows runs via the in-box x64 emulator, so both run 789 # lanes point at the same endpoint. Requires a provisioned VM and a user-supplied 790 # Windows ISO (see doc/WINDOWS.md), then boots it, waits for SSH, and runs the 791 # smokes against it. 792 KIT_WINDOWS_VM_USER ?= kit 793 KIT_WINDOWS_VM_PORT ?= 2227 794 # SSH key is left unset so windows_vm.sh uses its default in the durable cache 795 # (~/.cache/kit/windows-vm/ssh/id_ed25519); the working disk auto-restores from 796 # the cached golden, so a clean build/ still finds a ready VM. 797 _WIN_VM_ENV = KIT_SYSROOT=$(abspath build/llvm-mingw/20260602/ucrt) \ 798 KIT_WINDOWS_VM_AARCH64=$(KIT_WINDOWS_VM_USER)@127.0.0.1 KIT_WINDOWS_VM_AARCH64_PORT=$(KIT_WINDOWS_VM_PORT) \ 799 KIT_WINDOWS_VM_X64=$(KIT_WINDOWS_VM_USER)@127.0.0.1 KIT_WINDOWS_VM_X64_PORT=$(KIT_WINDOWS_VM_PORT) 800 801 test-coff-windows-vm: bin rt-x86_64-pc-windows rt-aarch64-windows windows-ucrt-sysroots 802 bash scripts/windows_vm.sh boot 803 bash scripts/windows_vm.sh wait-ssh 600 804 $(_WIN_VM_ENV) bash test/coff/windows-ucrt-hosted-smoke.sh 805 $(_WIN_VM_ENV) bash test/coff/windows-system-dlls-smoke.sh 806 $(_WIN_VM_ENV) bash test/coff/windows-o1-abi-smoke.sh 807 808 # The parse/asm/macho harnesses select a cross-target via KIT_TEST_ARCH 809 # (default aa64); the link rt dependency is resolved through the shared 810 # _TEST_RT_<arch> map defined above (near test-rt-runtime). 811 test-link: lib $(ROUNDTRIP_BIN) $(ROUNDTRIP_BIN_MACHO) $(LINK_EXE_RUNNER) $(JIT_RUNNER) 812 bash test/link/run.sh 813 814 # x64 ELF link/reloc-application coverage. test-link defaults to aa64, so 815 # kit's x64 static-link reloc fixups (R_X64_PLT32/GOTPCREL/TPOFF/...) were 816 # only ever run via a manual KIT_TEST_ARCH=x64 override. Opt-in (not in the 817 # default set) because the E path links + runs under podman/qemu-x86_64; the R 818 # path (roundtrip + reloc layout) runs on any host. 819 test-link-x64: lib rt-x86_64-linux $(ROUNDTRIP_BIN) $(LINK_EXE_RUNNER) $(JIT_RUNNER) 820 @KIT_TEST_ARCH=x64 KIT_TEST_PATHS=RE bash test/link/run.sh 821 822 test-macho: lib $(TEST_RT_DEP) $(ROUNDTRIP_BIN_MACHO) $(LINK_EXE_RUNNER) $(JIT_RUNNER) 823 KIT_TEST_OBJ=macho \ 824 KIT_TEST_ARCH=$${KIT_TEST_ARCH:-aa64} \ 825 KIT_TEST_PATHS=$${KIT_TEST_PATHS:-RJ} \ 826 KIT_TEST_ALLOW_SKIP=$${KIT_TEST_ALLOW_SKIP:-1} \ 827 bash test/link/run.sh 828 829 OPT_TEST_BIN = build/test/cg_ir_lower_test 830 TINY_INLINE_TEST_BIN = build/test/tiny_inline_test 831 832 test-opt: bin $(OPT_TEST_BIN) test-opt-tiny-inline test-opt-inline test-opt-zero-arg test-opt-static-prune-aa64 test-opt-aa64-tail test-opt-x64-win-tail-sret test-opt-prologue-tier test-opt-whole-program-inline test-opt-lto-phase1 833 $(OPT_TEST_BIN) 834 835 836 test-opt-tiny-inline: bin $(TINY_INLINE_TEST_BIN) 837 $(TINY_INLINE_TEST_BIN) 838 839 840 # Behavioral disasm check: tiny callee `bl` disappears from its caller at -O1. 841 test-opt-inline: bin 842 @KIT=$(abspath $(BIN)) bash test/opt/run.sh 843 844 # Behavioral disasm check: a pointer-typed null call arg is not routed through 845 # a scratch temp at -O1 (PERCALL.md item 3, "zero through a temp"). 846 test-opt-zero-arg: bin 847 @KIT=$(abspath $(BIN)) bash test/opt/zero_arg.sh 848 849 .PHONY: test-opt-static-prune-aa64 850 test-opt-static-prune-aa64: bin 851 @KIT=$(abspath $(BIN)) bash test/opt/static_prune_aa64.sh 852 853 .PHONY: test-opt-aa64-tail 854 test-opt-aa64-tail: bin 855 @KIT=$(abspath $(BIN)) bash test/opt/aa64_tail_call.sh 856 857 .PHONY: test-opt-x64-win-tail-sret 858 test-opt-x64-win-tail-sret: bin 859 @KIT=$(abspath $(BIN)) bash test/opt/x64_win_tail_sret.sh 860 861 # Structural disasm check: the -O1 known-frame prologue cost-model tiers 862 # (aa64 reference + ported x64 slim/red-zone and rv64 leaf shapes). 863 .PHONY: test-opt-prologue-tier 864 test-opt-prologue-tier: bin 865 @KIT=$(abspath $(BIN)) bash test/opt/prologue_tier.sh 866 867 # Whole-program (LTO Phase 0) cross-function inlining: a small static callee 868 # fuses into its caller at -O1 on every arch, and opt_inline actually fires. 869 .PHONY: test-opt-whole-program-inline 870 test-opt-whole-program-inline: bin 871 @KIT=$(abspath $(BIN)) bash test/opt/whole_program_inline.sh 872 873 .PHONY: test-opt-lto-phase1 874 test-opt-lto-phase1: bin 875 @KIT=$(abspath $(BIN)) bash test/opt/lto_phase1.sh 876 877 test-parse: test-parse-ok test-parse-err 878 879 test-parse-ok: lib $(TEST_RT_DEP) $(PARSE_RUNNER) $(ROUNDTRIP_BIN) $(LINK_EXE_RUNNER) $(JIT_RUNNER) 880 bash test/parse/run.sh 881 882 test-parse-err: lib $(PARSE_RUNNER) 883 sh test/parse/run_errors.sh 884 885 # test-asm: aggregate alias running every per-arch asm lane (aa64 + x64 + rv64) 886 # so `make test` covers all three through one target. The harness runs one arch 887 # per invocation (KIT_TEST_ARCH); each lane scopes its scratch per arch, so 888 # the prerequisites are safe to run in parallel under `make -j`. 889 test-asm: test-asm-aa64 test-asm-x64 test-asm-rv64 test-asm-rv32 890 891 # test-asm-aa64: the reference lane. aa64 is the default cross-target, and on 892 # aa64 hosts the exec paths (D/E/J) run natively, so it uses the full default 893 # path set (HTLDJE). The Makefile owns the harness binaries so they inherit host 894 # flags consistently with the rest of the test suite. 895 test-asm-aa64: lib $(TEST_RT_DEP) $(ASM_RUNNER) $(LINK_EXE_RUNNER) $(JIT_RUNNER) 896 @KIT_TEST_ARCH=aa64 bash test/asm/run.sh 897 898 # x64/rv64 exercise the encode (H), decode (T) and listing (L) corpora on any 899 # host: H/T/L need no native execution (they only produce/compare bytes), so the 900 # exec paths (D/E/J) are deliberately excluded and left to the smoke/qemu 901 # targets. 902 test-asm-x64: lib $(ASM_RUNNER) 903 @KIT_TEST_ARCH=x64 KIT_TEST_PATHS=HTL bash test/asm/run.sh 904 test-asm-rv64: lib $(ASM_RUNNER) 905 @KIT_TEST_ARCH=rv64 KIT_TEST_PATHS=HT bash test/asm/run.sh 906 # riscv32-none-elf is freestanding (no qemu-user exec lane), so like rv64 it 907 # runs the host-independent encode (H) + decode (T) lanes only. The rv32_* 908 # goldens use a no-compressed ISA so encodings stay a stable 4 bytes. 909 test-asm-rv32: lib $(ASM_RUNNER) 910 @KIT_TEST_ARCH=rv32 KIT_TEST_PATHS=HT bash test/asm/run.sh 911 912 # test-toy-rv32: the rv32 cross lane (path X) of the Toy corpus, scoped to the 913 # rv32 arch only. test/toy/run.sh's cross_one_rv32 compiles each case with 914 # `kit cc -target riscv32-none-elf` and runs the freestanding ELF bare-metal 915 # under qemu-system-riscv32 via test/lib/exec_rv32_bare.sh (the qemu exit code 916 # is the exit-code oracle). Self-skips per case when the rv32 toolchain 917 # (clang riscv32 + qemu-system-riscv32) is absent. The corpus is green; this 918 # lane is opt-in (not in DEFAULT_TEST_TARGETS) because it needs that toolchain, 919 # matching the rv64 cross lanes. The only non-passing cases are intentionally 920 # unsupported on rv32 (__int128, binary128 long double, LP64-data-model 921 # assumptions, aa64-only intrinsics) and carry committed .rv32.skip sidecars. 922 test-toy-rv32: bin rt-riscv32-elf-hardfloat 923 @KIT=$(abspath $(BIN)) KIT_TOY_CROSS_ARCHS=rv32 KIT_TEST_PATHS=X \ 924 test/toy/run.sh 925 926 # test-parse-rv32: the C-parser corpus run for riscv32-none-elf, exec lane (E) 927 # only. parse-runner --emit -> kit ld + start crt -> qemu-system-riscv32 928 # (test/parse/run.sh's rv32 freestanding E path via exec_rv32_bare.sh). Models 929 # test-parse-rv64-wide; opt-in (needs the rv32 toolchain/qemu), so excluded 930 # from DEFAULT_TEST_TARGETS, matching test-parse-rv64-wide. The corpus is green; 931 # the only skips are intentionally-unsupported cases (__int128, binary128 long 932 # double, LP64-data-model assumptions) with committed .rv32.skip sidecars. 933 test-parse-rv32: lib rt-riscv32-elf-hardfloat $(PARSE_RUNNER) $(ROUNDTRIP_BIN) \ 934 $(LINK_EXE_RUNNER) 935 @KIT_TEST_ARCH=rv32 KIT_TEST_PATHS=E bash test/parse/run.sh 936 937 # Codegen round-trip completeness (doc/ASM_ROUNDTRIP_TESTING.md). These drive 938 # the `kit` binary itself (cc -S / as / objdump) over a C corpus rather than 939 # a hand-written asm corpus, so coverage tracks codegen automatically. 940 # 941 # test-disasm-complete L0: cc -S must decode every in-function word 942 # (no `.inst` markers). Host-independent, no exec. 943 # test-asm-roundtrip L0+L1: also assert cc -c bytes/relocs == cc -S | as. 944 # test-asm-roundtrip-exec L0+L1+L2: also run direct vs round-tripped object 945 # and compare exit codes (native arch; opt-in). 946 # 947 # Vertical slice: aa64 only for now; L1/L2 run at -O1 (branch-free), L0 at both 948 # opt levels. Broadening to -O0, other arches, and the default suite is tracked 949 # in doc/ASM_ROUNDTRIP_TESTING.md once -S symbolization (Phase 2) lands. 950 test-disasm-complete: bin 951 @KIT_TEST_ARCH=aa64 KIT_TEST_OPTS="O0 O1" KIT_TEST_PATHS=0 \ 952 bash test/asm/roundtrip.sh 953 test-asm-roundtrip: bin 954 @KIT_TEST_ARCH=aa64 KIT_TEST_OPTS="O0 O1" KIT_TEST_PATHS=01 \ 955 bash test/asm/roundtrip.sh 956 test-asm-roundtrip-exec: bin $(JIT_RUNNER) 957 @KIT_TEST_ARCH=aa64 KIT_TEST_OPTS="O0 O1" KIT_TEST_PATHS=012 \ 958 bash test/asm/roundtrip.sh 959 960 # test-asm-symmetry: asm<->disasm self-symmetry sweep (aa64). Decode-side sweeps 961 # every disasm-table form (decode->encode->decode fixed point); encode-side 962 # asserts every byte the assembler emits over the encode corpus is decodable. 963 # Catches encode/decode asymmetries the codegen round-trip can't reach (e.g. a 964 # form one tool handles and the other doesn't). Host-independent, no exec. 965 test-asm-symmetry: $(ASM_RUNNER) $(AA64_SWEEP_GEN) 966 @bash test/asm/symmetry.sh 967 968 # test-diff-llvm: differential cross-check of kit against llvm (aa64), as a 969 # second oracle. Encode lane: kit as vs llvm-mc bytes over the encode corpus. 970 # Disasm lane: cc -c bytes vs llvm-mc of cc -S (validates kit's disassembler; 971 # the benign same-section-call reloc-vs-resolve difference is recognized). 972 # Opt-in; skips cleanly when llvm-mc is absent. 973 test-diff-llvm: bin 974 @KIT_TEST_OPTS="O0 O1" bash test/asm/diff_llvm.sh 975 976 # test-asm-roundtrip-toy: L2 exec round-trip over the Toy corpus (native arch). 977 # Reuses the ~150 toy cases (full CG op set, exit-code oracle) for free 978 # round-trip coverage: kit cc -S | kit as | kit run, exit must match. 979 # Opt-in; native target. Found a real miscompile (dropped .inst) the hand 980 # corpus never reached. 981 test-asm-roundtrip-toy: bin 982 @bash test/asm/roundtrip_toy.sh 983 984 # test-hostas-toy: feed one native `cc -S` to BOTH kit's own `as` and clang (a 985 # third-party host assembler), link + run each, and assert the toy exit-code 986 # oracle. Only the assembler differs between the two lanes, so the clang lane is 987 # the real test: a standard assembler can't paper over a private-dialect quirk 988 # the way kit's own `as` can (cf. test/asm/diff_llvm.sh, but by execution). 989 # cc -S is now object-format-aware, so the native Mach-O clang lane GATES by 990 # default (both lanes 312/0); KIT_HOSTAS_ENFORCE_CLANG=0 demotes it to XFAIL. 991 # Opt-in; skips cleanly if clang is absent. 992 test-hostas-toy: bin 993 @bash test/asm/hostas_toy.sh 994 995 # test-hostas-cross: the same two-assembler-by-execution idea as test-hostas-toy, 996 # but CROSS — `cc -S -target <triple>` for ELF Linux arches (aarch64/x86_64/ 997 # riscv64), assembled by kit-as AND clang, linked static (+ the start.c crt) 998 # with kit ld, and run under podman/qemu via test/lib/exec_target.sh. Each 999 # target self-skips unless the host has a clang cross target, a runner, a 1000 # working `cc -S | kit as` for that arch, and a passing bounded exec smoke — 1001 # so it runs green on whatever the host supports (aarch64-linux today; x86_64 1002 # pends the x64 cc -S symbolizer, riscv64 pends a working rv64 user-mode 1003 # emulator). Opt-in; skips cleanly if clang/podman are absent. 1004 test-hostas-cross: bin 1005 @bash test/asm/hostas_cross.sh 1006 1007 test-wasm: test-wasm-front test-wasm-target test-wasm-toy 1008 1009 test-wasm-front: bin $(WASM_TOOL) $(LINK_EXE_RUNNER) $(JIT_RUNNER) 1010 bash test/wasm/run.sh 1011 1012 # test-wasm-target: structural checks on `kit cc -target wasm32-none` 1013 # output. test/wasm-target/run.sh is a Type C corpus harness whose lanes each 1014 # compile a tiny C or toy fixture and assert a property of the produced module 1015 # bytes (inline-asm opcodes, memory.copy/fill opcodes, exported "memory", 1016 # (import ...) decls). Opt-in: not in the default `test` target because the 1017 # checks depend on the bulk-memory + (import ...) backend work landing first. 1018 test-wasm-target: bin 1019 @KIT=$(abspath $(BIN)) bash test/wasm-target/run.sh 1020 1021 # test-smoke-x64: phase-1 sanity check for the multi-arch bring-up. Builds a 1022 # tiny freestanding x86_64 ELF with clang --target=x86_64-linux-gnu and 1023 # runs it through test/lib/exec_target.sh's podman/qemu pipeline, 1024 # proving the harness end-to-end before any kit-emitted x64 bytes 1025 # exist. Excluded from the default `test` target because it needs 1026 # podman + lld; opt-in via `make test-smoke-x64`. 1027 test-smoke-x64: 1028 bash test/smoke/x64.sh 1029 1030 # test-smoke-rv64: phase-2 counterpart of test-smoke-x64. Builds a 1031 # tiny freestanding riscv64 ELF with clang --target=riscv64-linux-gnu 1032 # and runs it through test/lib/exec_target.sh, proving the rv64 lane 1033 # of the harness end-to-end before any kit-emitted rv64 bytes 1034 # exist. Excluded from the default `test` target because it needs 1035 # qemu-riscv64 (or podman with riscv64 emulation) + lld; opt-in via 1036 # `make test-smoke-rv64`. 1037 test-smoke-rv64: 1038 bash test/smoke/rv64.sh 1039 1040 # test-smoke-rv32: behavioral oracle for riscv32-none-elf codegen under 1041 # qemu-system-riscv32 (ilp32f + ilp32 lanes, i64 + soft-float). Skips if the 1042 # rv32 toolchain/qemu prerequisites are absent (see test/lib/check_rv32_env.sh). 1043 test-smoke-rv32: 1044 bash test/smoke/rv32.sh 1045 1046 # test-smoke-freestanding-system: whole-toolchain bare-metal smoke for 1047 # aarch64/x86_64/riscv64/riscv32 under qemu-system. Each lane compiles with kit, 1048 # assembles its reset stub with kit, links with kit ld -T, then boots the image 1049 # under the matching qemu-system binary. rv32 may need compiler-rt-style helpers 1050 # for 64-bit operations, so build that freestanding runtime variant with kit too. 1051 test-smoke-freestanding-system: bin rt-riscv32-elf-hardfloat 1052 bash test/smoke/freestanding_system.sh 1053 1054 # test-parse-rv64-wide: end-to-end coverage of the rv64 128-bit scalar types 1055 # — __int128 (i128_*) and IEEE-754 binary128 long double (ldbl128_*) — built 1056 # with kit and run on riscv64. Exercises the soft-float / i128 lowering to 1057 # the compiler-rt-style runtime (fp_tf, fp_ti, int64), the LP64D register-pair 1058 # ABI for 16-byte scalars, and the conditional-branch range fix that large 1059 # soft-float helpers depend on. Opt-in (needs qemu-riscv64 or podman with 1060 # riscv64 emulation), so excluded from the default `test` target; mirrors 1061 # test-smoke-rv64. Run a single case with 1062 # KIT_TEST_ARCH=rv64 bash test/parse/run.sh ldbl128_03_arith 1063 test-parse-rv64-wide: lib rt-riscv64-linux $(PARSE_RUNNER) $(ROUNDTRIP_BIN) \ 1064 $(LINK_EXE_RUNNER) 1065 @KIT_TEST_ARCH=rv64 KIT_TEST_PATHS=RE bash test/parse/run.sh 128 1066 1067 # test-bounce: format-bounce stress test. Compiles small programs with 1068 # kit, then bounces each object through chains of format conversions 1069 # (ELF<->Mach-O<->COFF), partial links (ld -r), strip, and archive 1070 # round-trips, relinks, and runs the result, asserting the exit code 1071 # matches a host-cc reference. Stresses obj read/write/reloc, ar, and 1072 # partial-link paths rather than the arches. Defaults to the host-native 1073 # Linux arch (no emulation); sweep others with 1074 # KIT_BOUNCE_ARCHES="aarch64 x64 rv64". Excluded from the default `test` 1075 # target because it needs podman/qemu + a host cc; opt-in via 1076 # `make test-bounce`. 1077 test-bounce: $(BIN) 1078 bash test/bounce/bounce.sh 1079 1080 # test-libc: aggregate alias that runs test-libc-musl and test-libc-glibc. 1081 # test-libc-musl / test-libc-glibc: end-to-end static + dynamic libc link/run 1082 # on aarch64. Each variant pulls its own pinned sysroot (podman, ~30s on 1083 # first run) and shares the same case files under test/libc/cases/: 1084 # 1085 # test-libc-musl — Alpine 3.20 + musl 1.2.5 (test/libc/musl/) 1086 # test-libc-glibc — Debian bookworm + glibc 2.36 (test/libc/glibc/) 1087 # 1088 # Both build build/rt/aarch64-linux/libkit_rt.a for soft-float / TF 1089 # builtins, and run `kit ld` against the real libc.a (static) and 1090 # libc.so / libc.so.6 (dynamic). Excluded from the 1091 # default `test` target because they need podman; opt-in via 1092 # `make test-libc-musl` / `make test-libc-glibc` (or `make test-libc` for both). 1093 # 1094 # Each sysroot is treated as a real prerequisite via its PROVENANCE 1095 # marker so subsequent runs skip extraction and re-extract only when 1096 # the file is removed (or extract.sh -f forces a rebuild). 1097 MUSL_SYSROOT_MARKER = build/musl-sysroot/PROVENANCE 1098 MUSL_SYSROOT_X64_MARKER = build/musl-sysroot-x64/PROVENANCE 1099 MUSL_SYSROOT_RV64_MARKER = build/musl-sysroot-rv64/PROVENANCE 1100 GLIBC_SYSROOT_MARKER = build/glibc-sysroot/PROVENANCE 1101 GLIBC_SYSROOT_X64_MARKER = build/glibc-sysroot-x64/PROVENANCE 1102 GLIBC_SYSROOT_RV64_MARKER = build/glibc-sysroot-rv64/PROVENANCE 1103 1104 $(MUSL_SYSROOT_MARKER): test/libc/musl/extract.sh test/libc/musl/Containerfile 1105 @bash test/libc/musl/extract.sh 1106 1107 $(MUSL_SYSROOT_X64_MARKER): test/libc/musl/extract.sh test/libc/musl/Containerfile.x64 1108 @bash test/libc/musl/extract.sh -a x64 1109 1110 $(MUSL_SYSROOT_RV64_MARKER): test/libc/musl/extract.sh test/libc/musl/Containerfile.rv64 1111 @bash test/libc/musl/extract.sh -a rv64 1112 1113 $(GLIBC_SYSROOT_MARKER): test/libc/glibc/extract.sh test/libc/glibc/Containerfile 1114 @bash test/libc/glibc/extract.sh 1115 1116 $(GLIBC_SYSROOT_X64_MARKER): test/libc/glibc/extract.sh test/libc/glibc/Containerfile.x64 1117 @bash test/libc/glibc/extract.sh -a x64 1118 1119 $(GLIBC_SYSROOT_RV64_MARKER): test/libc/glibc/extract.sh test/libc/glibc/Containerfile.rv64 1120 @bash test/libc/glibc/extract.sh -a rv64 1121 1122 # test-libc-musl / test-libc-glibc honor KIT_LIBC_ARCHES (default "aa64"; 1123 # values: aa64, x64, rv64). Each enabled arch contributes its sysroot 1124 # PROVENANCE marker and its rt archive to the prerequisite list, so 1125 # `KIT_LIBC_ARCHES="aa64 x64" make test-libc-musl` builds both sysroots 1126 # + both rt archives before the runner script picks them up. 1127 KIT_LIBC_ARCHES ?= aa64 1128 1129 # Map an arch token to its musl/glibc sysroot marker and rt target. 1130 _LIBC_MUSL_SYSROOT_aa64 = $(MUSL_SYSROOT_MARKER) 1131 _LIBC_MUSL_SYSROOT_x64 = $(MUSL_SYSROOT_X64_MARKER) 1132 _LIBC_MUSL_SYSROOT_rv64 = $(MUSL_SYSROOT_RV64_MARKER) 1133 _LIBC_GLIBC_SYSROOT_aa64 = $(GLIBC_SYSROOT_MARKER) 1134 _LIBC_GLIBC_SYSROOT_x64 = $(GLIBC_SYSROOT_X64_MARKER) 1135 _LIBC_GLIBC_SYSROOT_rv64 = $(GLIBC_SYSROOT_RV64_MARKER) 1136 _LIBC_RT_aa64 = rt-aarch64-linux 1137 _LIBC_RT_x64 = rt-x86_64-linux 1138 _LIBC_RT_rv64 = rt-riscv64-linux 1139 1140 LIBC_MUSL_DEPS = $(foreach a,$(KIT_LIBC_ARCHES),$(_LIBC_MUSL_SYSROOT_$(a)) $(_LIBC_RT_$(a))) 1141 LIBC_GLIBC_DEPS = $(foreach a,$(KIT_LIBC_ARCHES),$(_LIBC_GLIBC_SYSROOT_$(a)) $(_LIBC_RT_$(a))) 1142 1143 test-libc: test-libc-musl test-libc-glibc 1144 1145 test-libc-musl: bin $(LIBC_MUSL_DEPS) 1146 @KIT_LIBC_ARCHES="$(KIT_LIBC_ARCHES)" bash test/libc/musl/run.sh 1147 1148 test-libc-glibc: bin $(LIBC_GLIBC_DEPS) 1149 @KIT_LIBC_ARCHES="$(KIT_LIBC_ARCHES)" bash test/libc/glibc/run.sh 1150 1151 # FreeBSD hosted executable smoke (static + dynamic). Sysroots come from 1152 # scripts/freebsd_sysroot.sh (cached base.txz extracts under ~/.cache/kit). By 1153 # default these validate compile/link + ELF metadata; set KIT_FREEBSD_RUN_VM=1 1154 # to boot the cached FreeBSD VMs and execute each binary under real FreeBSD. 1155 test-freebsd: bin 1156 @KIT_FREEBSD_LINK=both bash test/libc/freebsd/run.sh 1157 1158 test-freebsd-static: bin 1159 @KIT_FREEBSD_LINK=static bash test/libc/freebsd/run.sh 1160 1161 test-freebsd-dynamic: bin 1162 @KIT_FREEBSD_LINK=dynamic bash test/libc/freebsd/run.sh 1163 1164 test-libc-musl-rv64: 1165 @$(MAKE) test-libc-musl KIT_LIBC_ARCHES=rv64 1166 1167 test-libc-glibc-rv64: 1168 @$(MAKE) test-libc-glibc KIT_LIBC_ARCHES=rv64 1169 1170 # Hosted test suite (test/hosted/run.sh): build each C case for every 1171 # (target, link-mode) config in the support set via scripts/hosted.sh and run it 1172 # through the shared exec seam, checking exit code + stdout. Opt-in (not in the 1173 # default set). The default config set is Linux (musl static+dynamic + glibc, 1174 # all 3 arches) + macOS; it provisions the linux sysroots + rt + the per-arch 1175 # run images (alpine for musl, debian for glibc) here. test-hosted-vm adds the 1176 # FreeBSD + Windows VM configs. 1177 HOSTED_LINUX_DEPS = \ 1178 $(MUSL_SYSROOT_MARKER) $(MUSL_SYSROOT_X64_MARKER) $(MUSL_SYSROOT_RV64_MARKER) \ 1179 $(GLIBC_SYSROOT_MARKER) $(GLIBC_SYSROOT_X64_MARKER) $(GLIBC_SYSROOT_RV64_MARKER) \ 1180 rt-aarch64-linux rt-x86_64-linux rt-riscv64-linux 1181 1182 # Per-arch glibc (Debian) run images for the linux-glibc configs. musl uses the 1183 # pinned alpine images from `make test-images`. Best-effort pull (idempotent). 1184 HOSTED_GLIBC_IMAGES = \ 1185 docker.io/arm64v8/debian:bookworm-slim \ 1186 docker.io/amd64/debian:bookworm-slim \ 1187 docker.io/riscv64/debian:trixie-slim 1188 1189 hosted-glibc-images: 1190 @for img in $(HOSTED_GLIBC_IMAGES); do \ 1191 podman image exists "$$img" 2>/dev/null || podman pull "$$img" || \ 1192 echo "warn: could not pull $$img (linux-glibc run lanes will SKIP)"; \ 1193 done 1194 1195 test-hosted: bin $(HOSTED_LINUX_DEPS) test-images hosted-glibc-images 1196 @KIT=$(abspath $(BIN)) bash test/hosted/run.sh 1197 1198 test-hosted-vm: bin $(HOSTED_LINUX_DEPS) test-images hosted-glibc-images rt-x86_64-pc-windows rt-aarch64-windows windows-ucrt-sysroots 1199 @KIT=$(abspath $(BIN)) KIT_HOSTED_VM=1 bash test/hosted/run.sh 1200 1201 # Fail if libkit.a depends on any external symbol not in the allowlist, or 1202 # if a relocatable link exposes non-public global definitions. 1203 # External dependency drift in either direction (new dep, or stale entry) is a 1204 # failure. 1205 # 1206 # Inspect the RELEASE artifacts only: the debug build is ASan/UBSan-instrumented 1207 # and pulls in __asan_*/__ubsan_* externals that are not part of the shipped 1208 # library's dependency surface. 1209 LIB_DEPS_RELEASE_DIR = build/release 1210 LIB_DEPS_AR = $(LIB_DEPS_RELEASE_DIR)/libkit.a 1211 LIB_DEPS_ACTUAL = $(LIB_DEPS_RELEASE_DIR)/libkit.deps.txt 1212 LIB_RELOC = $(LIB_DEPS_RELEASE_DIR)/libkit.reloc.o 1213 LIB_RELOC_BAD = $(LIB_DEPS_RELEASE_DIR)/libkit.reloc.bad-symbols.txt 1214 1215 test-lib-deps: 1216 @$(MAKE) lib RELEASE=1 1217 @mkdir -p $(dir $(LIB_DEPS_ACTUAL)) 1218 @python3 scripts/lib_external_deps.py $(LIB_DEPS_AR) > $(LIB_DEPS_ACTUAL) 1219 @diff -u scripts/lib_deps.allowlist $(LIB_DEPS_ACTUAL) \ 1220 || { echo "libkit.a external symbol set drifted from scripts/lib_deps.allowlist"; exit 1; } 1221 @python3 scripts/lib_reloc_defined_prefixes.py $(LIB_DEPS_AR) \ 1222 --output $(LIB_RELOC) --ar $(AR) --cc $(CC) > $(LIB_RELOC_BAD) 1223 @test ! -s $(LIB_RELOC_BAD) \ 1224 || { echo "libkit relocatable link exposes non-public symbols"; cat $(LIB_RELOC_BAD); exit 1; }