regen-rv32.sh (4418B)
1 #!/usr/bin/env bash 2 # test/asm/regen-rv32.sh — regenerate the rv32_* smoke goldens from 3 # clang + llvm-objdump targeting riscv32-unknown-elf. Maintainer aid: NOT 4 # run by CI. Commit the refreshed goldens alongside the case changes. 5 # 6 # Usage: 7 # ./regen-rv32.sh regenerate every rv32_* case 8 # ./regen-rv32.sh <name> regenerate just one rv32_* case (substring) 9 # 10 # Detects clang + llvm-objdump (or riscv32-unknown-elf-objdump). Exits 0 11 # with a SKIP-style message if either is missing — the script is intended 12 # to support cross-toolchain regen on machines that don't have a full 13 # riscv32 cross install. 14 15 set -u 16 17 ROOT="$(cd "$(dirname "$0")/../.." && pwd)" 18 TEST_DIR="$ROOT/test/asm" 19 FILTER="${1:-}" 20 21 # Use the no-C ISA so encode goldens match the existing 4-byte-per-insn 22 # fixtures (same no-compressed choice as regen-rv64.sh). ilp32f gives the 23 # F extension with single-precision float args in FP regs. Per-fixture 24 # .targets sidecars carry the canonical bytes the in-tree corpus has agreed 25 # to (asm-runner emits raw 32-bit encodings; turning on the C extension 26 # would shrink some forms to 16 bits). 27 CLANG_TARGET="--target=riscv32-unknown-elf -march=rv32imaf -mabi=ilp32f" 28 OBJDUMP="$(command -v llvm-objdump 2>/dev/null || command -v riscv32-unknown-elf-objdump 2>/dev/null || true)" 29 CLANG="$(command -v clang 2>/dev/null || true)" 30 31 if [ -z "$OBJDUMP" ] || [ -z "$CLANG" ]; then 32 printf 'regen-rv32.sh: SKIP — need clang and llvm-objdump (or riscv32-unknown-elf-objdump) on PATH\n' >&2 33 exit 0 34 fi 35 36 tmp="$(mktemp -d)" 37 trap 'rm -rf "$tmp"' EXIT 38 39 regen_encode() { 40 local src="$1" name out_obj out_hex 41 name="$(basename "$src" .s)" 42 case "$name" in rv32_*) ;; *) return 0 ;; esac 43 [ -n "$FILTER" ] && [[ "$name" != *"$FILTER"* ]] && return 0 44 out_obj="$tmp/$name.o" 45 out_hex="$TEST_DIR/encode/$name.expected.hex" 46 $CLANG $CLANG_TARGET -c "$src" -o "$out_obj" 47 "$OBJDUMP" --full-contents -j .text "$out_obj" \ 48 | awk '/^Contents of section/ {next} /^$/ {next} 49 { for (i=2; i<=5; i++) if ($i ~ /^[0-9a-f]+$/) printf "%s", $i; printf "\n" }' \ 50 | tr -d '\n' \ 51 | { cat; printf '\n'; } >"$out_hex" 52 printf ' regen encode/%s\n' "$name" 53 } 54 55 regen_decode() { 56 local hexfile="$1" name out_txt raw scratch 57 name="$(basename "$hexfile" .hex)" 58 case "$name" in rv32_*) ;; *) return 0 ;; esac 59 [ -n "$FILTER" ] && [[ "$name" != *"$FILTER"* ]] && return 0 60 out_txt="$TEST_DIR/decode/$name.expected.txt" 61 raw="$tmp/$name.bin" 62 scratch="$tmp/$name.decode.txt" 63 xxd -r -p "$hexfile" "$raw" 64 if ! "$OBJDUMP" -b binary -m riscv -M no-aliases -D "$raw" >"$scratch" 2>"$tmp/$name.decode.err"; then 65 return 1 66 fi 67 awk '/^[ ]+[0-9a-f]+:/ { 68 sub(/:/, "", $1); 69 addr = $1; 70 mnem = $3; 71 ops = ""; 72 for (i=4; i<=NF; i++) ops = (ops=="" ? $i : ops " " $i); 73 printf "%s:\t%s\t%s\n", addr, mnem, ops; 74 }' "$scratch" >"$out_txt" 75 printf ' regen decode/%s\n' "$name" 76 } 77 78 regen_listing() { 79 local bin="$1" name out_lst scratch 80 name="$(basename "$bin" .in.bin)" 81 case "$name" in rv32_*) ;; *) return 0 ;; esac 82 [ -n "$FILTER" ] && [[ "$name" != *"$FILTER"* ]] && return 0 83 out_lst="$TEST_DIR/listing/$name.expected.lst" 84 scratch="$tmp/$name.listing.txt" 85 if ! "$OBJDUMP" -d -m riscv "$bin" >"$scratch" 2>"$tmp/$name.listing.err"; then 86 return 1 87 fi 88 awk '/^Disassembly of section/ || /^[0-9a-f]+ </ || /^[ ]+[0-9a-f]+:/ || /^$/' \ 89 "$scratch" >"$out_lst" 90 printf ' regen listing/%s\n' "$name" 91 } 92 93 printf 'Regenerating rv32 goldens...\n' 94 # encode/ is portable across llvm-objdump versions (uses real .o input). 95 for src in "$TEST_DIR"/encode/*.s; do [ -e "$src" ] && regen_encode "$src"; done 96 # decode/ and listing/ pass raw bytes through `-b binary -m riscv` which 97 # some llvm-objdump builds (notably the macOS Homebrew build) do not 98 # support. Soft-fail per case so encode regen still completes. 99 for src in "$TEST_DIR"/decode/*.hex; do 100 [ -e "$src" ] || continue 101 regen_decode "$src" || printf ' skip decode/%s (objdump rejected raw binary)\n' "$(basename "$src" .hex)" 102 done 103 for src in "$TEST_DIR"/listing/*.in.bin; do 104 [ -e "$src" ] || continue 105 regen_listing "$src" || printf ' skip listing/%s (objdump rejected raw binary)\n' "$(basename "$src" .in.bin)" 106 done 107 printf 'Done.\n'