kit

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

run.sh (19455B)


      1 #!/usr/bin/env bash
      2 # test/wasm/run.sh — Wasm frontend end-to-end tests, on the shared corpus
      3 # harness (test/lib/kit_corpus.sh). Lanes (KIT_TEST_PATHS, default WDNOJE):
      4 #   W  wat2wasm (wasm-tool)
      5 #   D  kit run (JIT)            — wat + wasm inputs
      6 #   N  kit run --no-jit (interp; SKIPs ops it does not implement)
      7 #   O  kit cc -c (object out)   — wat + wasm inputs
      8 #   J  jit-runner against the obj — wat + wasm inputs
      9 #   E  link + native exec (synchronous exec_target_run)
     10 #   C  --emit=c + host cc + exec  (opt-in; C-source backend, doc/CBACKEND.md)
     11 # Plus three diagnostic corpora (trap/err/meta) when any of W/D/O is enabled.
     12 # All lane hooks write only under KIT_WORK and record via kit_*, so the runner is
     13 # parallel-safe; KIT_WASM_PARALLEL flips dispatch.
     14 set -u
     15 
     16 ROOT=$(cd "$(dirname "$0")/../.." && pwd)
     17 export KIT_LIB_DIR="$ROOT/test/lib"
     18 . "$ROOT/test/lib/kit_corpus.sh"
     19 
     20 BUILD_DIR="$ROOT/build/test/wasm"
     21 CASES_DIR="$ROOT/test/wasm/cases"
     22 ERR_DIR="$ROOT/test/wasm/err"
     23 TRAP_DIR="$ROOT/test/wasm/trap"
     24 META_DIR="$ROOT/test/wasm/meta"
     25 KIT_BIN="${KIT:-$ROOT/build/kit}"
     26 WASM_TOOL="$ROOT/build/test/wasm-tool"
     27 JIT_RUNNER="$ROOT/build/test/jit-runner"
     28 LINK_EXE_RUNNER="$ROOT/build/test/link-exe-runner"
     29 TEST_ARCH="${KIT_TEST_ARCH:-aa64}"
     30 TEST_OBJ="${KIT_TEST_OBJ:-macho}"
     31 HOST_CC="${CC:-cc}"
     32 mkdir -p "$BUILD_DIR"
     33 
     34 PATHS="${KIT_TEST_PATHS:-WDNOJE}"
     35 case "$PATHS" in *W*) RUN_W=1;; *) RUN_W=0;; esac
     36 case "$PATHS" in *D*) RUN_D=1;; *) RUN_D=0;; esac
     37 case "$PATHS" in *N*) RUN_N=1;; *) RUN_N=0;; esac
     38 case "$PATHS" in *O*) RUN_O=1;; *) RUN_O=0;; esac
     39 case "$PATHS" in *J*) RUN_J=1;; *) RUN_J=0;; esac
     40 case "$PATHS" in *E*) RUN_E=1;; *) RUN_E=0;; esac
     41 case "$PATHS" in *C*) RUN_C=1;; *) RUN_C=0;; esac
     42 
     43 case "$TEST_ARCH" in
     44   aa64|aarch64|arm64) TEST_ARCH=aa64; EXEC_ARCH="aarch64" ;;
     45   x64|x86_64|amd64)   TEST_ARCH=x64;  EXEC_ARCH="x64" ;;
     46   rv64|riscv64)       TEST_ARCH=rv64; EXEC_ARCH="rv64" ;;
     47   *)                  TEST_ARCH=aa64; EXEC_ARCH="aarch64" ;;
     48 esac
     49 host_arch=$(uname -m); host_matches=0
     50 case "$TEST_ARCH:$host_arch" in
     51   aa64:arm64|aa64:aarch64) host_matches=1 ;;
     52   x64:x86_64) host_matches=1 ;;
     53 esac
     54 case "$TEST_OBJ" in
     55   macho) EXEC_OS="macos"
     56     case "$TEST_ARCH" in
     57       aa64) target_triple="aarch64-macos"; clang_triple="arm64-apple-macos" ;;
     58       x64)  target_triple="x86_64-macos";  clang_triple="x86_64-apple-macos" ;;
     59       *)    target_triple="aarch64-macos"; clang_triple="arm64-apple-macos" ;;
     60     esac ;;
     61   elf) EXEC_OS="linux"
     62     case "$TEST_ARCH" in
     63       aa64) target_triple="aarch64-linux"; clang_triple="aarch64-linux-gnu" ;;
     64       x64)  target_triple="x86_64-linux";  clang_triple="x86_64-linux-gnu" ;;
     65       rv64) target_triple="riscv64-linux"; clang_triple="riscv64-linux-gnu" ;;
     66       *)    target_triple="aarch64-linux"; clang_triple="aarch64-linux-gnu" ;;
     67     esac ;;
     68   *) target_triple="aarch64-macos"; clang_triple="arm64-apple-macos"; EXEC_OS="macos" ;;
     69 esac
     70 EXEC_TAG="$EXEC_ARCH-$EXEC_OS"
     71 export KIT_TEST_ARCH="$TEST_ARCH" KIT_TEST_OBJ="$TEST_OBJ"
     72 WASM_RUN_TEST_IMPORTS=(--wasm-imports=test)
     73 
     74 have_wasm_tool=0;  [ -x "$WASM_TOOL" ] && have_wasm_tool=1
     75 have_jit_runner=0; [ -x "$JIT_RUNNER" ] && [ "$host_matches" -eq 1 ] && have_jit_runner=1
     76 have_link_runner=0;[ -x "$LINK_EXE_RUNNER" ] && have_link_runner=1
     77 
     78 # exec_target wiring (lane E runs SYNCHRONOUSLY via exec_target_run).
     79 have_qemu=0; have_podman=0; is_aarch64=0
     80 QEMU_BIN="$(command -v qemu-aarch64-static 2>/dev/null || command -v qemu-aarch64 2>/dev/null || true)"
     81 [ -n "$QEMU_BIN" ] && have_qemu=1
     82 command -v podman >/dev/null 2>&1 && have_podman=1
     83 { [ "$host_arch" = "aarch64" ] || [ "$host_arch" = "arm64" ]; } && is_aarch64=1
     84 EXEC_TARGET_MOUNT_ROOT="$BUILD_DIR"
     85 export have_qemu have_podman is_aarch64 QEMU_BIN EXEC_TARGET_MOUNT_ROOT
     86 . "$ROOT/test/lib/exec_target.sh"
     87 
     88 WASM_START_OBJ="$BUILD_DIR/start-wasm.o"
     89 have_wasm_start_obj=0
     90 if clang --target="$clang_triple" -ffreestanding -fno-stack-protector \
     91     -fno-builtin -nostdlib -c "$ROOT/test/wasm/harness/start_wasm.c" \
     92     -o "$WASM_START_OBJ" >"$BUILD_DIR/start-wasm.out" 2>"$BUILD_DIR/start-wasm.err"; then
     93   have_wasm_start_obj=1
     94 fi
     95 
     96 MACHO_DSO_ARGS=()
     97 if [ "$TEST_OBJ" = "macho" ] && command -v xcrun >/dev/null 2>&1; then
     98   sdk="$(xcrun --show-sdk-path 2>/dev/null || true)"
     99   if [ -n "$sdk" ] && [ -f "$sdk/usr/lib/libSystem.tbd" ]; then
    100     MACHO_DSO_ARGS=(--dso "$sdk/usr/lib/libSystem.tbd")
    101   fi
    102 fi
    103 
    104 # Path C wrapper: bridges the emitted C's test_main(instance) to int main(void).
    105 C_WRAPPER_SRC="$BUILD_DIR/wasm_c_wrapper.c"
    106 C_WRAPPER_OBJ="$BUILD_DIR/wasm_c_wrapper.o"
    107 have_c_wrapper=0
    108 if [ "$RUN_C" -eq 1 ]; then
    109   cat > "$C_WRAPPER_SRC" <<'EOF'
    110 #include <stdint.h>
    111 #include <stdlib.h>
    112 #include <string.h>
    113 extern void __kit_wasm_init(void *);
    114 extern int32_t test_main(void *);
    115 
    116 /* Canned host import, mirroring jit_runner.c / start_wasm.c / driver/run.c. */
    117 static int32_t test_host_add(void *inst, int32_t a, int32_t b) {
    118   (void)inst;
    119   return a + b;
    120 }
    121 
    122 /* Import descriptors emitted by lang/wasm/cg.c. The C lane compiles for the
    123  * native target (aarch64/x86_64-*), so this is the 64-bit layout used by
    124  * start_wasm.c, with full module/field name pointers — match by name and bind
    125  * the canned host function into the instance import slot before
    126  * __kit_wasm_init. Weak DEFAULTS (not weak externs): a module with imports
    127  * emits its own strong __kit_wasm_imports/__kit_wasm_nimports that override
    128  * these; a module with none falls back to nimports=0. (A weak *undefined* ref
    129  * would be rejected by the Mach-O static linker.) */
    130 typedef struct {
    131   const char *module;
    132   const char *field;
    133   unsigned int kind;
    134   unsigned int desc_index;
    135   unsigned int slot_offset;
    136   unsigned int reserved;
    137 } WasmImportDesc;
    138 __attribute__((weak)) const unsigned int __kit_wasm_nimports = 0;
    139 __attribute__((weak)) const WasmImportDesc __kit_wasm_imports[1] = {{0, 0, 0, 0, 0, 0}};
    140 
    141 static int bind_canned_imports(void *instance) {
    142   for (unsigned int i = 0; i < __kit_wasm_nimports; ++i) {
    143     const WasmImportDesc *d = &__kit_wasm_imports[i];
    144     if (d->kind == 0 && strcmp(d->module, "env") == 0 &&
    145         strcmp(d->field, "host_add") == 0)
    146       *(void **)((unsigned char *)instance + d->slot_offset) =
    147           (void *)(uintptr_t)test_host_add;
    148     else
    149       return 0;
    150   }
    151   return 1;
    152 }
    153 
    154 typedef struct { unsigned char *data; unsigned long long pages;
    155   unsigned long long max_pages; unsigned int flags; } WasmStartMemoryPrefix;
    156 #define WASM_START_MEMORY_PREFIX_COUNT 8u
    157 #define WASM_START_INSTANCE_SIZE (64u * 1024u)
    158 #define WASM_START_MEMORY_SIZE (16u * 1024u * 1024u)
    159 int main(void) {
    160   void *instance = calloc(1, WASM_START_INSTANCE_SIZE);
    161   unsigned char *memory = calloc(1, WASM_START_MEMORY_SIZE);
    162   if (!instance || !memory) return 1;
    163   for (unsigned int i = 0; i < WASM_START_MEMORY_PREFIX_COUNT; ++i)
    164     ((WasmStartMemoryPrefix *)instance)[i].data =
    165         memory + i * (WASM_START_MEMORY_SIZE / WASM_START_MEMORY_PREFIX_COUNT);
    166   /* After the memory prefix (which can overlap import slots for memory-less
    167    * modules), before init (which consumes the bound slots). */
    168   if (!bind_canned_imports(instance)) return 1;
    169   __kit_wasm_init(instance);
    170   return (int)test_main(instance);
    171 }
    172 EOF
    173   $HOST_CC -std=gnu99 -c "$C_WRAPPER_SRC" -o "$C_WRAPPER_OBJ" \
    174       2>"$BUILD_DIR/wasm_c_wrapper.err" && have_c_wrapper=1
    175 fi
    176 
    177 # ---- per-result oracle helpers (KIT_WORK-confined -> parallel-safe) ---------
    178 _wf_base() { printf '%s/%s' "$KIT_WORK" "$(printf '%s' "$1" | tr '/ ' '__')"; }
    179 wf_rc() {            # LABEL EXPECTED CMD...
    180   local label=$1 exp=$2 b; b=$(_wf_base "$1"); shift 2
    181   "$@" >"$b.out" 2>"$b.err"; local rc=$?
    182   if [ "$rc" -eq "$exp" ]; then kit_pass "$label"; else kit_fail "$label" "expected $exp got $rc"; fi
    183 }
    184 wf_rc_interp() {     # LABEL EXPECTED CMD...  (--no-jit; SKIP on "interp: ..not supported")
    185   local label=$1 exp=$2 b; b=$(_wf_base "$1"); shift 2
    186   "$@" >"$b.out" 2>"$b.err"; local rc=$? miss
    187   miss=$(grep -oE 'interp: .*not supported' "$b.err" 2>/dev/null | head -n1 || true)
    188   if [ -n "$miss" ]; then kit_skip "$label" "$miss"
    189   elif [ "$rc" -eq "$exp" ]; then kit_pass "$label"
    190   else kit_fail "$label" "expected $exp got $rc"; fi
    191 }
    192 wf_zero() {          # LABEL CMD...
    193   local label=$1 b; b=$(_wf_base "$1"); shift
    194   if "$@" >"$b.out" 2>"$b.err"; then kit_pass "$label"; else kit_fail "$label"; fi
    195 }
    196 wf_fail() {          # LABEL CMD...  (expect nonzero)
    197   local label=$1 b; b=$(_wf_base "$1"); shift
    198   if "$@" >"$b.out" 2>"$b.err"; then kit_fail "$label" "expected failure"; else kit_pass "$label"; fi
    199 }
    200 wf_fail_grep() {     # LABEL SUBSTR CMD...  (expect failure + stderr contains SUBSTR)
    201   local label=$1 want=$2 b; b=$(_wf_base "$1"); shift 2
    202   if "$@" >"$b.out" 2>"$b.err"; then kit_fail "$label" "expected failure"
    203   elif grep -F "$want" "$b.err" >/dev/null 2>&1; then kit_pass "$label"
    204   else kit_fail "$label" "missing diagnostic: $want"; fi
    205 }
    206 
    207 # Build the wat->wasm intermediate once per case (idempotent). Sets WASM.
    208 wasm_build() {
    209   WASM="$KIT_WORK/$KIT_BASE.wasm"
    210   [ -f "$WASM" ] && return 0
    211   [ "$have_wasm_tool" -eq 1 ] || return 1
    212   "$WASM_TOOL" --wat2wasm "$KIT_SRC" "$WASM" >"$KIT_WORK/_w.out" 2>"$KIT_WORK/_w.err"
    213 }
    214 # Ensure the wat/wasm .o exists (O lane builds it; J/E build on demand if absent).
    215 _obj_wat()  { local o="$KIT_WORK/$KIT_BASE.wat.o";  [ -f "$o" ] || "$KIT_BIN" cc -target "$target_triple" -c "$KIT_SRC" -o "$o" >/dev/null 2>&1; printf '%s' "$o"; }
    216 _obj_wasm() { local o="$KIT_WORK/$KIT_BASE.wasm.o"; wasm_build || return 1; [ -f "$o" ] || "$KIT_BIN" cc -target "$target_triple" -c "$WASM" -o "$o" >/dev/null 2>&1; printf '%s' "$o"; }
    217 
    218 # ---- cases-corpus lanes ----------------------------------------------------
    219 kit_lane_W() {
    220   if [ "$have_wasm_tool" -eq 1 ]; then wf_zero "$KIT_NAME/W" "$WASM_TOOL" --wat2wasm "$KIT_SRC" "$KIT_WORK/$KIT_BASE.wasm"
    221   else kit_skip "$KIT_NAME/W" "no wasm-tool"; fi
    222 }
    223 kit_lane_D() {
    224   wf_rc "$KIT_NAME/D-wat" "$KIT_EXPECTED" "$KIT_BIN" run "${WASM_RUN_TEST_IMPORTS[@]}" -e test_main "$KIT_SRC"
    225   if wasm_build; then wf_rc "$KIT_NAME/D-wasm" "$KIT_EXPECTED" "$KIT_BIN" run "${WASM_RUN_TEST_IMPORTS[@]}" -e test_main "$WASM"
    226   else kit_skip "$KIT_NAME/D-wasm" "no wasm-tool"; fi
    227 }
    228 kit_lane_N() {
    229   wf_rc_interp "$KIT_NAME/N-wat" "$KIT_EXPECTED" "$KIT_BIN" run --no-jit "${WASM_RUN_TEST_IMPORTS[@]}" -e test_main "$KIT_SRC"
    230   if wasm_build; then wf_rc_interp "$KIT_NAME/N-wasm" "$KIT_EXPECTED" "$KIT_BIN" run --no-jit "${WASM_RUN_TEST_IMPORTS[@]}" -e test_main "$WASM"
    231   else kit_skip "$KIT_NAME/N-wasm" "no wasm-tool"; fi
    232 }
    233 kit_lane_O() {
    234   wf_zero "$KIT_NAME/O-wat" "$KIT_BIN" cc -target "$target_triple" -c "$KIT_SRC" -o "$KIT_WORK/$KIT_BASE.wat.o"
    235   if wasm_build; then wf_zero "$KIT_NAME/O-wasm" "$KIT_BIN" cc -target "$target_triple" -c "$WASM" -o "$KIT_WORK/$KIT_BASE.wasm.o"
    236   else kit_skip "$KIT_NAME/O-wasm" "no wasm-tool"; fi
    237 }
    238 kit_lane_J() {
    239   if [ "$have_jit_runner" -eq 0 ]; then kit_skip "$KIT_NAME/J" "host arch does not match target or no jit-runner"; return; fi
    240   wf_rc "$KIT_NAME/J-wat-obj" "$KIT_EXPECTED" env KIT_TEST_ARCH="$TEST_ARCH" KIT_TEST_OBJ="$TEST_OBJ" "$JIT_RUNNER" "$(_obj_wat)"
    241   local wo; if wo=$(_obj_wasm); then wf_rc "$KIT_NAME/J-wasm-obj" "$KIT_EXPECTED" env KIT_TEST_ARCH="$TEST_ARCH" KIT_TEST_OBJ="$TEST_OBJ" "$JIT_RUNNER" "$wo"
    242   else kit_skip "$KIT_NAME/J-wasm-obj" "no wasm-tool"; fi
    243 }
    244 kit_lane_E() {
    245   if [ "$have_link_runner" -eq 0 ] || [ "$have_wasm_start_obj" -eq 0 ]; then
    246     kit_skip "$KIT_NAME/E" "requires link runner and wasm start.o"; return
    247   fi
    248   local exe="$KIT_WORK/$KIT_BASE.exe"
    249   if "$LINK_EXE_RUNNER" -o "$exe" "${MACHO_DSO_ARGS[@]}" "$(_obj_wat)" "$WASM_START_OBJ" \
    250       >"$KIT_WORK/link.out" 2>"$KIT_WORK/link.err"; then
    251     if exec_target_supported "$EXEC_TAG"; then
    252       exec_target_run "$EXEC_TAG" "$exe" "$KIT_WORK/exec.out" "$KIT_WORK/exec.err"
    253       if [ "$RUN_RC" -eq "$KIT_EXPECTED" ]; then kit_pass "$KIT_NAME/E"
    254       else kit_fail "$KIT_NAME/E" "expected $KIT_EXPECTED got $RUN_RC"; fi
    255     else kit_skip "$KIT_NAME/E" "no execution support for $TEST_ARCH"; fi
    256   else kit_fail "$KIT_NAME/E" "link failed"; fi
    257 }
    258 kit_lane_C() {
    259   if [ "$have_c_wrapper" -eq 0 ]; then kit_skip "$KIT_NAME/C" "host CC wrapper unavailable"; return; fi
    260   if [ "$host_matches" -eq 0 ]; then kit_skip "$KIT_NAME/C" "host arch != $TEST_ARCH (C target is target-locked)"; return; fi
    261   local c_src="$KIT_WORK/$KIT_BASE.kit.c" c_bin="$KIT_WORK/$KIT_BASE.cbackend.bin" miss
    262   if ! "$KIT_BIN" cc -target "$target_triple" --emit=c "$KIT_SRC" -o "$c_src" \
    263         >"$KIT_WORK/c.emit.out" 2>"$KIT_WORK/c.emit.err"; then
    264     miss=$(grep -oE 'C target: .*(not implemented|not yet supported)' "$KIT_WORK/c.emit.err" 2>/dev/null | head -n1 || true)
    265     if [ -n "$miss" ]; then kit_skip "$KIT_NAME/C" "$miss"; else kit_fail "$KIT_NAME/C" "kit cc --emit=c failed"; fi
    266     return
    267   fi
    268   if ! $HOST_CC -std=gnu99 -Wno-main-return-type "$c_src" "$C_WRAPPER_OBJ" -o "$c_bin" \
    269         >"$KIT_WORK/c.cc.out" 2>"$KIT_WORK/c.cc.err"; then
    270     kit_fail "$KIT_NAME/C" "host cc rejected emitted source"; return
    271   fi
    272   "$c_bin" >"$KIT_WORK/c.run.out" 2>"$KIT_WORK/c.run.err"; local rc=$?
    273   if [ "$rc" -eq "$KIT_EXPECTED" ]; then kit_pass "$KIT_NAME/C"; else kit_fail "$KIT_NAME/C" "expected $KIT_EXPECTED got $rc"; fi
    274 }
    275 
    276 # ---- diagnostic-corpus lanes ----------------------------------------------
    277 kit_lane_T() {        # trap: build wasm (expect 0), then run expecting a trap (nonzero)
    278   if [ "$have_wasm_tool" -eq 1 ]; then wf_zero "trap/$KIT_BASE/W" "$WASM_TOOL" --wat2wasm "$KIT_SRC" "$KIT_WORK/$KIT_BASE.wasm"
    279   else kit_skip "trap/$KIT_BASE/W" "no wasm-tool"; return; fi
    280   wf_fail "trap/$KIT_BASE/D-wat"  "$KIT_BIN" run -e test_main "$KIT_SRC"
    281   wf_fail "trap/$KIT_BASE/D-wasm" "$KIT_BIN" run -e test_main "$KIT_WORK/$KIT_BASE.wasm"
    282 }
    283 kit_lane_ERR() {      # err: cc must fail
    284   wf_fail "err/$KIT_BASE/cc" "$KIT_BIN" cc -target "$target_triple" -c "$KIT_SRC" -o "$KIT_WORK/$KIT_BASE.o"
    285 }
    286 kit_lane_META() {     # meta: build wasm, then native cc per the expect whitelist
    287   wf_zero "meta/$KIT_BASE/W" "$WASM_TOOL" --wat2wasm "$KIT_SRC" "$KIT_WORK/$KIT_BASE.wasm"
    288   if [ "$KIT_BASE" = "type_custom" ] || [ "$KIT_BASE" = "import_table_global_start" ]; then
    289     wf_zero "meta/$KIT_BASE/native" "$KIT_BIN" cc -target "$target_triple" -c "$KIT_WORK/$KIT_BASE.wasm" -o "$KIT_WORK/$KIT_BASE.o"
    290   else
    291     wf_fail "meta/$KIT_BASE/native" "$KIT_BIN" cc -target "$target_triple" -c "$KIT_WORK/$KIT_BASE.wasm" -o "$KIT_WORK/$KIT_BASE.o"
    292   fi
    293 }
    294 
    295 # ---- drive the corpora -----------------------------------------------------
    296 printf 'test-wasm-front target=%s obj=%s\n' "$target_triple" "$TEST_OBJ"
    297 
    298 # cases corpus — active lanes in PATHS order.
    299 CASE_LANES=
    300 [ "$RUN_W" -eq 1 ] && CASE_LANES="$CASE_LANES W"
    301 [ "$RUN_D" -eq 1 ] && CASE_LANES="$CASE_LANES D"
    302 [ "$RUN_N" -eq 1 ] && CASE_LANES="$CASE_LANES N"
    303 [ "$RUN_O" -eq 1 ] && CASE_LANES="$CASE_LANES O"
    304 [ "$RUN_J" -eq 1 ] && CASE_LANES="$CASE_LANES J"
    305 [ "$RUN_E" -eq 1 ] && CASE_LANES="$CASE_LANES E"
    306 [ "$RUN_C" -eq 1 ] && CASE_LANES="$CASE_LANES C"
    307 PAR="${KIT_WASM_PARALLEL:-1}"
    308 KIT_LABEL=test-wasm-front KIT_BUILD_DIR="$BUILD_DIR/cases" \
    309   KIT_CORPUS_GLOBS="$CASES_DIR/*.wat" KIT_CORPUS_EXT=wat KIT_SIDECAR_DIR="$CASES_DIR" \
    310   KIT_LANES="$CASE_LANES" KIT_OPT_LEVELS="" KIT_TUPLES="$EXEC_TAG" \
    311   KIT_EXPECTED_EXT=.expect KIT_TARGETS_EXT="" KIT_PARALLELIZABLE="$PAR" \
    312   kit_corpus_run
    313 
    314 # trap/err/meta are diagnostics corpora, orthogonal to the C-emit path.
    315 RUN_DIAG=0
    316 { [ "$RUN_W" -eq 1 ] || [ "$RUN_D" -eq 1 ] || [ "$RUN_O" -eq 1 ]; } && RUN_DIAG=1
    317 
    318 if [ "$RUN_DIAG" -eq 1 ]; then
    319   KIT_LABEL=test-wasm-front KIT_BUILD_DIR="$BUILD_DIR/trap" \
    320     KIT_CORPUS_GLOBS="$TRAP_DIR/*.wat" KIT_CORPUS_EXT=wat KIT_SIDECAR_DIR="$TRAP_DIR" \
    321     KIT_LANES="T" KIT_OPT_LEVELS="" KIT_TUPLES="$EXEC_TAG" KIT_TARGETS_EXT="" \
    322     KIT_PARALLELIZABLE="$PAR" kit_corpus_run
    323 
    324   KIT_LABEL=test-wasm-front KIT_BUILD_DIR="$BUILD_DIR/err" \
    325     KIT_CORPUS_GLOBS="$ERR_DIR/*.wat" KIT_CORPUS_EXT=wat KIT_SIDECAR_DIR="$ERR_DIR" \
    326     KIT_LANES="ERR" KIT_OPT_LEVELS="" KIT_TUPLES="$EXEC_TAG" KIT_TARGETS_EXT="" \
    327     KIT_PARALLELIZABLE="$PAR" kit_corpus_run
    328 
    329   # Inline diagnostic cases (not file-glob corpora).
    330   KIT_WORK="$BUILD_DIR/err-inline"; rm -rf "$KIT_WORK"; mkdir -p "$KIT_WORK"
    331   KIT_NAME=err KIT_BASE=err
    332   wf_fail_grep "err/stack_underflow/loc" \
    333     "$ERR_DIR/stack_underflow.wat:3:5: fatal: wasm: operand stack underflow" \
    334     "$KIT_BIN" cc -target "$target_triple" -c "$ERR_DIR/stack_underflow.wat" -o "$KIT_WORK/su-loc.o"
    335 
    336   if [ "$have_wasm_tool" -eq 1 ]; then
    337     KIT_LABEL=test-wasm-front KIT_BUILD_DIR="$BUILD_DIR/meta" \
    338       KIT_CORPUS_GLOBS="$META_DIR/*.wat" KIT_CORPUS_EXT=wat KIT_SIDECAR_DIR="$META_DIR" \
    339       KIT_LANES="META" KIT_OPT_LEVELS="" KIT_TUPLES="$EXEC_TAG" KIT_TARGETS_EXT="" \
    340       KIT_PARALLELIZABLE="$PAR" kit_corpus_run
    341   else
    342     kit_skip "meta" "no wasm-tool"
    343   fi
    344 
    345   printf '\000asm\001\000\000\000\001\005\001\140' > "$KIT_WORK/malformed-section.wasm"
    346   wf_fail "err/malformed-section/wasm" "$KIT_BIN" cc -target "$target_triple" -c "$KIT_WORK/malformed-section.wasm" -o "$KIT_WORK/bad-section.o"
    347   printf '\000asm\001\000\000\000\001\200\200\200\200\020' > "$KIT_WORK/malformed-leb.wasm"
    348   wf_fail "err/malformed-leb/wasm" "$KIT_BIN" cc -target "$target_triple" -c "$KIT_WORK/malformed-leb.wasm" -o "$KIT_WORK/bad-leb.o"
    349 fi
    350 
    351 # ---- multi-source wasm (cross-TU call + cross-TU data reference) -----------
    352 if [ "$RUN_D" -eq 1 ] || [ "$RUN_N" -eq 1 ]; then
    353   KIT_WORK="$BUILD_DIR/multi-tu"; rm -rf "$KIT_WORK"; mkdir -p "$KIT_WORK"
    354   cat > "$KIT_WORK/mtu_helper.c" <<'EOF'
    355 int g_count = 0;
    356 int add_and_count(int a, int b) { g_count++; return a + b; }
    357 EOF
    358   cat > "$KIT_WORK/mtu_main.c" <<'EOF'
    359 extern int g_count;
    360 int add_and_count(int a, int b);
    361 int test_main(void) {
    362   int r = add_and_count(3, 4);
    363   return (r == 7 && g_count == 1) ? 0 : 1;
    364 }
    365 EOF
    366   _mtu_wasm="$KIT_WORK/multi_tu.wasm"
    367   if "$KIT_BIN" build-obj -target wasm32-none \
    368       "$KIT_WORK/mtu_main.c" "$KIT_WORK/mtu_helper.c" \
    369       -o "$_mtu_wasm" >"$KIT_WORK/build.out" 2>"$KIT_WORK/build.err"; then
    370     if [ "$RUN_N" -eq 1 ]; then
    371       wf_rc_interp "multi-tu/N" 0 \
    372         "$KIT_BIN" run --no-jit -e test_main "$_mtu_wasm"
    373     fi
    374     if [ "$RUN_D" -eq 1 ]; then
    375       wf_rc "multi-tu/D" 0 \
    376         "$KIT_BIN" run -e test_main "$_mtu_wasm"
    377     fi
    378   else
    379     kit_fail "multi-tu/build" "build-obj failed"
    380   fi
    381 fi
    382 
    383 # ---- wasm build-exe: DCE from entry point, runnable via kit run -------------
    384 if [ "$RUN_D" -eq 1 ] || [ "$RUN_N" -eq 1 ]; then
    385   KIT_WORK="$BUILD_DIR/wasm-exe"; rm -rf "$KIT_WORK"; mkdir -p "$KIT_WORK"
    386   cat > "$KIT_WORK/exe_add.c" <<'EOF'
    387 int add(int a, int b) { return a + b; }
    388 int dead_fn(void) { return 99; }
    389 EOF
    390   cat > "$KIT_WORK/exe_main.c" <<'EOF'
    391 int add(int a, int b);
    392 int test_main(void) { return add(2, 3) == 5 ? 0 : 1; }
    393 EOF
    394   _wasm_exe="$KIT_WORK/out.wasm"
    395   if "$KIT_BIN" build-exe -target wasm32-none \
    396       "$KIT_WORK/exe_main.c" "$KIT_WORK/exe_add.c" \
    397       -e test_main -o "$_wasm_exe" \
    398       >"$KIT_WORK/build.out" 2>"$KIT_WORK/build.err"; then
    399     [ "$RUN_D" -eq 1 ] && wf_rc "wasm-exe/D" 0 \
    400         "$KIT_BIN" run -e test_main "$_wasm_exe"
    401     [ "$RUN_N" -eq 1 ] && wf_rc_interp "wasm-exe/N" 0 \
    402         "$KIT_BIN" run --no-jit -e test_main "$_wasm_exe"
    403     [ "$RUN_D" -eq 1 ] && wf_rc "wasm-exe/D-autoentry" 0 \
    404         "$KIT_BIN" run "$_wasm_exe"
    405   else
    406     kit_fail "wasm-exe/build" "build-exe failed"
    407   fi
    408 fi
    409 
    410 kit_summary test-wasm-front
    411 kit_exit