kit

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

run.sh (8912B)


      1 #!/usr/bin/env bash
      2 # test/wasm-target/run.sh — Wasm-target structural-grep tests, on the shared
      3 # corpus harness (test/lib/kit_corpus.sh).
      4 #
      5 # Each check compiles a tiny C or toy fixture with `kit cc -target
      6 # wasm32-none -c` and asserts a structural property of the produced module:
      7 # opcode bytes, export names, or import declarations. The oracle is a
      8 # structural grep over the raw module bytes; the opcode magic numbers and
      9 # import (module, field) names live as metadata inside the lane bodies.
     10 #
     11 # Lanes (each is one structural check — there is no opt/tuple axis):
     12 #   ASM   inline-asm WAT template lowers to i32.popcnt (0x69), and an
     13 #         escaping `br 0` is rejected with a "wasm target:" diagnostic.
     14 #   IMP   extern C symbols emit (import ...) decls under the default `env`
     15 #         module and honor import_module/import_name attribute overrides.
     16 #   MCP   copy_bytes/set_bytes lower to memory.copy (0xfc 0x0a) and
     17 #         memory.fill (0xfc 0x0b), not byte-loops.
     18 #   MEX   the linear memory is exported under the conventional name "memory".
     19 #
     20 # All lane hooks write only under $KIT_WORK and record via kit_*, so the runner
     21 # is parallel-safe by construction; KIT_WASM_TARGET_PARALLEL flips dispatch.
     22 set -u
     23 
     24 ROOT=$(cd "$(dirname "$0")/../.." && pwd)
     25 export KIT_LIB_DIR="$ROOT/test/lib"
     26 . "$ROOT/test/lib/kit_corpus.sh"
     27 
     28 SRC_DIR="$ROOT/test/wasm-target"
     29 BUILD_DIR="$ROOT/build/test/wasm-target"
     30 KIT_BIN="${KIT:-$ROOT/build/kit}"
     31 mkdir -p "$BUILD_DIR"
     32 
     33 # Preserve the original per-script semantics: a missing-toolchain/missing-fixture
     34 # SKIP (was a per-check exit 2 that the old run.sh counted as skip but did NOT
     35 # let fail the run) must not gate this harness's exit. Override the corpus
     36 # engine's default (KIT_SKIP_IS_FAILURE=1) back to "skip is informational".
     37 KIT_SKIP_IS_FAILURE=0
     38 
     39 # Toy fixtures live in the shared toy corpus; allow override (preserves the
     40 # original TOY_FIXTURE knob from check_memory_{copy,export}.sh).
     41 TOY_MEMCPY_FIXTURE="${TOY_FIXTURE_MEMCPY:-$ROOT/test/toy/cases/131_memcpy_uses_bulk.toy}"
     42 TOY_EXPORT_FIXTURE="${TOY_FIXTURE_EXPORT:-$ROOT/test/toy/cases/01_return_const.toy}"
     43 
     44 PAR="${KIT_WASM_TARGET_PARALLEL:-1}"
     45 
     46 # Driver presence gates every check: a missing driver SKIPs (was exit 2 in the
     47 # per-script harnesses). Surfaced as a SKIP per lane via the hooks below.
     48 have_kit=0
     49 [ -x "$KIT_BIN" ] && have_kit=1
     50 
     51 # wasm32-none -c <src> -> <out>; logs KIT_WORK-confined. Returns nonzero on
     52 # compile failure (lane decides pass/skip/fail).
     53 wt_compile() {  # SRC OUT TAG
     54   "$KIT_BIN" cc -target wasm32-none -c "$1" -o "$2" \
     55     >"$KIT_WORK/$3.cc.out" 2>"$KIT_WORK/$3.cc.err"
     56 }
     57 
     58 # Hex-dump $1 with no whitespace, for opcode-byte greps. (od is universally
     59 # available; matches the original check_asm.sh / check_memory_copy.sh dumps.)
     60 wt_hex() { od -An -tx1 -v "$1" | tr -d ' \n'; }
     61 
     62 # ---- lane: inline-asm WAT template (check_asm.sh) --------------------------
     63 # i32.popcnt encodes as 0x69 in the wasm binary format; an escaping top-level
     64 # `br 0` must be rejected before emission with a "wasm target:" diagnostic.
     65 kit_lane_ASM() {
     66   if [ "$have_kit" -eq 0 ]; then kit_skip "wasm-target/asm" "kit driver missing at $KIT_BIN"; return; fi
     67 
     68   local out="$KIT_WORK/asm_popcnt.wasm"
     69   if ! wt_compile "$SRC_DIR/asm_popcnt.c" "$out" asm_popcnt; then
     70     kit_fail "wasm-target/asm-popcnt" "kit cc -target wasm32-none failed for asm_popcnt.c"
     71     sed 's/^/    | /' "$KIT_WORK/asm_popcnt.cc.err" >&2
     72     return
     73   fi
     74   if wt_hex "$out" | grep -q '69'; then kit_pass "wasm-target/asm-popcnt"
     75   else kit_fail "wasm-target/asm-popcnt" "missing i32.popcnt opcode (0x69)"; fi
     76 
     77   # Negative oracle: escaping `br 0` must be rejected (nonzero) with a
     78   # "wasm target:" stderr diagnostic.
     79   local neg="$KIT_WORK/asm_branch_escape.wasm"
     80   if wt_compile "$SRC_DIR/asm_branch_escape.c" "$neg" asm_branch_escape; then
     81     kit_fail "wasm-target/asm-branch-escape" "compiled but should have been rejected"
     82   elif grep -F "wasm target:" "$KIT_WORK/asm_branch_escape.cc.err" >/dev/null 2>&1; then
     83     kit_pass "wasm-target/asm-branch-escape"
     84   else
     85     kit_fail "wasm-target/asm-branch-escape" "rejection lacks 'wasm target:' diagnostic"
     86     sed 's/^/    | /' "$KIT_WORK/asm_branch_escape.cc.err" >&2
     87   fi
     88 }
     89 
     90 # ---- lane: import declarations (check_imports.sh) --------------------------
     91 # Wasm import sections encode (module, field) as length-prefixed UTF-8 plain
     92 # text, so a `grep -F` over the raw bytes is enough.
     93 _wt_check_strings() {  # LABEL WASM STR...
     94   local label=$1 wasm=$2; shift 2
     95   local s ok=1
     96   for s in "$@"; do
     97     if ! grep -F "$s" "$wasm" >/dev/null 2>&1; then
     98       ok=0
     99       printf 'expected substring %s in %s\n' "$s" "$wasm" >&2
    100     fi
    101   done
    102   [ "$ok" -eq 1 ] && kit_pass "$label" || kit_fail "$label" "missing expected import substring(s)"
    103 }
    104 kit_lane_IMP() {
    105   if [ "$have_kit" -eq 0 ]; then kit_skip "wasm-target/imports" "kit driver missing at $KIT_BIN"; return; fi
    106 
    107   # Default module/field: env / host_add.
    108   local out="$KIT_WORK/import_decl.wasm"
    109   if wt_compile "$SRC_DIR/import_decl.c" "$out" import_decl; then
    110     _wt_check_strings "wasm-target/import-default" "$out" "env" "host_add"
    111   else
    112     kit_fail "wasm-target/import-default" "kit cc -target wasm32-none failed for import_decl.c"
    113     sed 's/^/    | /' "$KIT_WORK/import_decl.cc.err" >&2
    114   fi
    115 
    116   # Attribute-override module/field: custom / add.
    117   out="$KIT_WORK/import_decl_attribute.wasm"
    118   if wt_compile "$SRC_DIR/import_decl_attribute.c" "$out" import_decl_attribute; then
    119     _wt_check_strings "wasm-target/import-attribute" "$out" "custom" "add"
    120   else
    121     kit_fail "wasm-target/import-attribute" "kit cc -target wasm32-none failed for import_decl_attribute.c"
    122     sed 's/^/    | /' "$KIT_WORK/import_decl_attribute.cc.err" >&2
    123   fi
    124 }
    125 
    126 # ---- lane: bulk-memory opcodes (check_memory_copy.sh) ----------------------
    127 # Magic numbers mirror the wasm spec opcode encoding (keep in sync with
    128 # WASM_INSN_MEMORY_{COPY,FILL} in src/wasm/insn.c):
    129 #   memory.copy = 0xfc 0x0a   memory.fill = 0xfc 0x0b
    130 kit_lane_MCP() {
    131   if [ "$have_kit" -eq 0 ]; then kit_skip "wasm-target/memory-copy" "kit driver missing at $KIT_BIN"; return; fi
    132   if [ ! -f "$TOY_MEMCPY_FIXTURE" ]; then kit_skip "wasm-target/memory-copy" "missing toy fixture $TOY_MEMCPY_FIXTURE"; return; fi
    133 
    134   local out="$KIT_WORK/$(basename "$TOY_MEMCPY_FIXTURE" .toy).wasm"
    135   if ! wt_compile "$TOY_MEMCPY_FIXTURE" "$out" memory_copy; then
    136     kit_fail "wasm-target/memory-copy" "kit cc -target wasm32-none failed for $TOY_MEMCPY_FIXTURE"
    137     sed 's/^/    | /' "$KIT_WORK/memory_copy.cc.err" >&2
    138     return
    139   fi
    140   local hex; hex=$(wt_hex "$out")
    141   local ok=1
    142   printf '%s' "$hex" | grep -q 'fc0a' || { ok=0; echo "memory.copy (0xfc 0x0a) not present in $out" >&2; }
    143   printf '%s' "$hex" | grep -q 'fc0b' || { ok=0; echo "memory.fill (0xfc 0x0b) not present in $out" >&2; }
    144   [ "$ok" -eq 1 ] && kit_pass "wasm-target/memory-copy" || kit_fail "wasm-target/memory-copy" "missing bulk-memory opcode(s)"
    145 }
    146 
    147 # ---- lane: memory export (check_memory_export.sh) --------------------------
    148 # The linear memory must be exported under the conventional name "memory" for
    149 # browser/wasmtime/wasmer/Node host runtimes.
    150 kit_lane_MEX() {
    151   if [ "$have_kit" -eq 0 ]; then kit_skip "wasm-target/memory-export" "kit driver missing at $KIT_BIN"; return; fi
    152   if [ ! -f "$TOY_EXPORT_FIXTURE" ]; then kit_skip "wasm-target/memory-export" "missing toy fixture $TOY_EXPORT_FIXTURE"; return; fi
    153 
    154   local out="$KIT_WORK/memory_export.wasm"
    155   if ! wt_compile "$TOY_EXPORT_FIXTURE" "$out" memory_export; then
    156     kit_fail "wasm-target/memory-export" "kit cc -target wasm32-none failed for $TOY_EXPORT_FIXTURE"
    157     sed 's/^/    | /' "$KIT_WORK/memory_export.cc.err" >&2
    158     return
    159   fi
    160   if grep -F "memory" "$out" >/dev/null 2>&1; then kit_pass "wasm-target/memory-export"
    161   else kit_fail "wasm-target/memory-export" "produced module does not contain export name 'memory'"; fi
    162 }
    163 
    164 # ---- drive the structural checks -------------------------------------------
    165 # A single synthetic case fans the checks out across lanes (no opt/tuple axis).
    166 # Use this dir's fixture .c files as the corpus glob (the engine needs >=1
    167 # match); KIT_READ_CASE collapses to one driving case so each lane fires once.
    168 printf 'test-wasm-target target=wasm32-none\n'
    169 
    170 # Single-item corpus: pick exactly one fixture as the matrix driver so every
    171 # lane runs exactly once. The lane bodies reference fixtures by absolute path,
    172 # not via KIT_SRC, since one check may touch several fixtures.
    173 wt_pick_one() { [ "$KIT_BASE" = "asm_popcnt" ] || KIT_SKIP_NA_CASE=1; }
    174 
    175 KIT_LABEL=test-wasm-target KIT_BUILD_DIR="$BUILD_DIR" \
    176   KIT_CORPUS_GLOBS="$SRC_DIR/*.c" KIT_CORPUS_EXT=c KIT_SIDECAR_DIR="$SRC_DIR" \
    177   KIT_LANES="ASM IMP MCP MEX" KIT_OPT_LEVELS="" KIT_TUPLES="wasm32-none" \
    178   KIT_TARGETS_EXT="" KIT_READ_CASE=wt_pick_one KIT_PARALLELIZABLE="$PAR" \
    179   kit_corpus_run
    180 
    181 kit_summary test-wasm-target
    182 kit_exit