#!/usr/bin/env bash # ./scripts/verify_ir.sh test/test_case/functional/simple_add.sy test/test_result/function/ir --run set -euo pipefail now_ns() { date +%s%N } format_ns() { local ns=$1 local ms=$((ns / 1000000)) local sec=$((ms / 1000)) local rem_ms=$((ms % 1000)) printf '%d.%03ds' "$sec" "$rem_ms" } if [[ $# -lt 1 || $# -gt 3 ]]; then echo "用法: $0 [output_dir] [--run]" >&2 exit 1 fi input=$1 out_dir="test/test_result/ir" run_exec=false input_dir=$(dirname "$input") shift while [[ $# -gt 0 ]]; do case "$1" in --run) run_exec=true ;; *) out_dir="$1" ;; esac shift done if [[ ! -f "$input" ]]; then echo "输入文件不存在: $input" >&2 exit 1 fi compiler="./build/bin/compiler" if [[ ! -x "$compiler" ]]; then echo "未找到编译器: $compiler ,请先构建(如: mkdir -p build && cd build && cmake .. && make -j)" >&2 exit 1 fi find_tool() { local name for name in "$@"; do if command -v "$name" >/dev/null 2>&1; then command -v "$name" return 0 fi done return 1 } llc_cmd=$(find_tool llc llc-20 || true) clang_cmd=$(find_tool clang clang-20 || true) mkdir -p "$out_dir" base=$(basename "$input") stem=${base%.sy} out_file="$out_dir/$stem.ll" stdin_file="$input_dir/$stem.in" expected_file="$input_dir/$stem.out" total_start_ns=$(now_ns) emit_start_ns=$(now_ns) "$compiler" --emit-ir "$input" > "$out_file" emit_elapsed_ns=$(( $(now_ns) - emit_start_ns )) echo "IR 已生成: $out_file" echo "IR 生成耗时: $(format_ns "$emit_elapsed_ns")" if [[ "$run_exec" == true ]]; then if [[ -z "$llc_cmd" ]]; then echo "未找到 llc 或 llc-20,无法运行 IR。请安装 LLVM。" >&2 exit 1 fi if [[ -z "$clang_cmd" ]]; then echo "未找到 clang 或 clang-20,无法链接可执行文件。请安装 Clang。" >&2 exit 1 fi obj="$out_dir/$stem.o" exe="$out_dir/$stem" stdout_file="$out_dir/$stem.stdout" actual_file="$out_dir/$stem.actual.out" lower_link_start_ns=$(now_ns) "$llc_cmd" -filetype=obj "$out_file" -o "$obj" "$clang_cmd" -no-pie "$obj" sylib/sylib.c -o "$exe" -lm -pthread lower_link_elapsed_ns=$(( $(now_ns) - lower_link_start_ns )) echo "IR 落地/链接耗时: $(format_ns "$lower_link_elapsed_ns")" echo "运行 $exe ..." run_start_ns=$(now_ns) set +e if [[ -f "$stdin_file" ]]; then "$exe" < "$stdin_file" > "$stdout_file" else "$exe" > "$stdout_file" fi status=$? set -e run_elapsed_ns=$(( $(now_ns) - run_start_ns )) cat "$stdout_file" echo "退出码: $status" echo "运行耗时: $(format_ns "$run_elapsed_ns")" { cat "$stdout_file" if [[ -s "$stdout_file" ]] && (( $(tail -c 1 "$stdout_file" | wc -l) == 0 )); then printf '\n' fi printf '%s\n' "$status" } > "$actual_file" if [[ -f "$expected_file" ]]; then if diff -u <(sed -e 's/\r$//' -e '$a\\' "$expected_file") <(sed -e 's/\r$//' -e '$a\\' "$actual_file"); then echo "输出匹配: $expected_file" else echo "输出不匹配: $expected_file" >&2 echo "实际输出已保存: $actual_file" >&2 exit 1 fi else echo "未找到预期输出文件,跳过比对: $expected_file" fi fi total_elapsed_ns=$(( $(now_ns) - total_start_ns )) echo "总耗时: $(format_ns "$total_elapsed_ns")"