kit

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

regen.sh (5393B)


      1 #!/usr/bin/env bash
      2 # test/asm/regen.sh — regenerate the smoke goldens from the host
      3 # `as` / `objdump` (via clang as the cross driver). Maintainer aid: NOT
      4 # run by CI. Commit the refreshed goldens alongside the case changes.
      5 #
      6 # Usage:
      7 #   ./regen.sh                   regenerate every case
      8 #   ./regen.sh <name>            regenerate just one case (substring match)
      9 #
     10 # Requires:
     11 #   clang  --target=aarch64-linux-gnu or --target=x86_64-linux-gnu
     12 #   llvm-objdump or a target objdump
     13 #   xxd                                  (for hex dumps)
     14 
     15 set -eu
     16 
     17 ROOT="$(cd "$(dirname "$0")/../.." && pwd)"
     18 TEST_DIR="$ROOT/test/asm"
     19 FILTER="${1:-}"
     20 KIT_TEST_ARCH="${KIT_TEST_ARCH:-aa64}"
     21 ASM_RUNNER="$ROOT/build/test/asm-runner"
     22 
     23 case "$KIT_TEST_ARCH" in
     24     aa64|aarch64|arm64)
     25         TEST_ARCH=aa64
     26         CLANG_TARGET="--target=aarch64-linux-gnu"
     27         OBJDUMP_MACHINE="aarch64"
     28         TARGET_OBJDUMP="aarch64-linux-gnu-objdump"
     29         ;;
     30     x64|x86_64|amd64)
     31         TEST_ARCH=x64
     32         CLANG_TARGET="--target=x86_64-linux-gnu"
     33         OBJDUMP_MACHINE="i386:x86-64"
     34         TARGET_OBJDUMP="x86_64-linux-gnu-objdump"
     35         ;;
     36     *)
     37         printf 'regen.sh: unknown KIT_TEST_ARCH=%s (want aa64|x64)\n' "$KIT_TEST_ARCH" >&2
     38         exit 2
     39         ;;
     40 esac
     41 
     42 OBJDUMP="$(command -v llvm-objdump 2>/dev/null || command -v "$TARGET_OBJDUMP" 2>/dev/null || true)"
     43 if [ -z "$OBJDUMP" ]; then
     44     printf 'regen.sh: no llvm-objdump / %s on PATH\n' "$TARGET_OBJDUMP" >&2
     45     exit 1
     46 fi
     47 
     48 tmp="$(mktemp -d)"
     49 trap 'rm -rf "$tmp"' EXIT
     50 
     51 case_applies() {
     52     local dir="$1" name="$2" targets tuple
     53     targets="$dir/$name.targets"
     54     [ -f "$targets" ] || return 0
     55     for tuple in $(cat "$targets"); do
     56         case "$tuple:$TEST_ARCH" in
     57             aa64:aa64|aarch64:aa64|arm64:aa64) return 0 ;;
     58             x64:x64|x86_64:x64|amd64:x64) return 0 ;;
     59         esac
     60     done
     61     return 1
     62 }
     63 
     64 regen_encode() {
     65     local src="$1" name out_obj out_hex
     66     name="$(basename "$src" .s)"
     67     [ -n "$FILTER" ] && [[ "$name" != *"$FILTER"* ]] && return 0
     68     case_applies "$TEST_DIR/encode" "$name" || return 0
     69     out_obj="$tmp/$name.o"
     70     out_hex="$TEST_DIR/encode/$name.expected.hex"
     71     clang $CLANG_TARGET -c "$src" -o "$out_obj"
     72     # Dump every executable section (smoke only inspects .text; this is
     73     # tight enough for now). For multi-section cases we'll pivot to a
     74     # per-section dump alongside phase 3.
     75     "$OBJDUMP" -h -j .text "$out_obj" >/dev/null 2>&1
     76     "$OBJDUMP" --full-contents -j .text "$out_obj" \
     77         | awk '/^Contents of section/ {next} /^$/ {next}
     78                { for (i=2; i<=5; i++) if ($i ~ /^[0-9a-f]+$/) printf "%s", $i; printf "\n" }' \
     79         | tr -d '\n' \
     80         | { cat; printf '\n'; } >"$out_hex"
     81     printf '  regen encode/%s\n' "$name"
     82 }
     83 
     84 regen_decode() {
     85     local hexfile="$1" name out_txt
     86     name="$(basename "$hexfile" .hex)"
     87     [ -n "$FILTER" ] && [[ "$name" != *"$FILTER"* ]] && return 0
     88     case_applies "$TEST_DIR/decode" "$name" || return 0
     89     out_txt="$TEST_DIR/decode/$name.expected.txt"
     90     # Mirror asm-runner --decode output exactly: vaddr:\tmnemonic\toperands.
     91     # objdump's listing format differs (it interleaves addresses + raw hex);
     92     # rebuild a minimal line per insn via awk so the goldens match the
     93     # runner's exact-match expectation.
     94     local raw="$tmp/$name.bin" bytes_s="$tmp/$name.bytes.s" bytes_o="$tmp/$name.bytes.o"
     95     xxd -r -p "$hexfile" "$raw"
     96     {
     97         printf '.text\n'
     98         od -An -tx1 -v "$raw" \
     99             | awk '{ for (i=1; i<=NF; i++) printf ".byte 0x%s\n", $i }'
    100     } >"$bytes_s"
    101     clang $CLANG_TARGET -c "$bytes_s" -o "$bytes_o"
    102     "$OBJDUMP" -d --no-show-raw-insn "$bytes_o" \
    103         | awk '/^[ ]*[0-9a-f]+:/ {
    104                sub(/:/, "", $1);
    105                addr = $1;
    106                # fields: addr  mnemonic  operands...
    107                mnem = $2;
    108                ops = "";
    109                for (i=3; i<=NF; i++) ops = (ops=="" ? $i : ops " " $i);
    110                if (mnem == "lock") {
    111                    lock_addr = addr;
    112                    pending_lock = 1;
    113                    next;
    114                }
    115                if (pending_lock) {
    116                    addr = lock_addr;
    117                    mnem = "lock " mnem;
    118                    pending_lock = 0;
    119                }
    120                if (ops == "")
    121                    printf "%s:\t%s\n", addr, mnem;
    122                else
    123                    printf "%s:\t%s\t%s\n", addr, mnem, ops;
    124            }' >"$out_txt"
    125     printf '  regen decode/%s\n' "$name"
    126 }
    127 
    128 regen_listing() {
    129     local bin="$1" name out_lst
    130     name="$(basename "$bin" .in.bin)"
    131     [ -n "$FILTER" ] && [[ "$name" != *"$FILTER"* ]] && return 0
    132     case_applies "$TEST_DIR/listing" "$name" || return 0
    133     out_lst="$TEST_DIR/listing/$name.expected.lst"
    134     if [ -x "$ASM_RUNNER" ]; then
    135         KIT_TEST_ARCH="$TEST_ARCH" "$ASM_RUNNER" --listing "$bin" "$out_lst"
    136     else
    137         "$OBJDUMP" -d "$bin" \
    138             | awk '/^Disassembly of section/ || /^[0-9a-f]+ </ || /^[ ]+[0-9a-f]+:/ || /^$/' \
    139             >"$out_lst"
    140     fi
    141     printf '  regen listing/%s\n' "$name"
    142 }
    143 
    144 printf 'Regenerating goldens...\n'
    145 for src in "$TEST_DIR"/encode/*.s;      do [ -e "$src" ] && regen_encode  "$src"; done
    146 for src in "$TEST_DIR"/decode/*.hex;    do [ -e "$src" ] && regen_decode  "$src"; done
    147 for src in "$TEST_DIR"/listing/*.in.bin; do [ -e "$src" ] && regen_listing "$src"; done
    148 printf 'Done.\n'