#!/usr/bin/env bash # ./scripts/verify_ir.sh test/test_case/functional/simple_add.sy test/test_result/function/ir --run set -euo pipefail if [[ $# -lt 1 ]]; then echo "用法: $0 [output_dir] [--run] [-O]" >&2 exit 1 fi out_dir="test/test_result/ir" run_exec=false optimize=false input="" while [[ $# -gt 0 ]]; do case "$1" in --run) run_exec=true ;; -O|--optimize) optimize=true ;; -*) echo "未知选项: $1" >&2 exit 1 ;; *) if [[ -z "$input" ]]; then input="$1" else out_dir="$1" fi ;; esac shift done if [[ -z "$input" ]]; then echo "未指定输入文件" >&2 exit 1 fi input_dir=$(dirname "$input") 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 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" # 记录编译开始时间 compile_start=$(date +%s%N) if [[ "$optimize" == true ]]; then "$compiler" -O --emit-ir "$input" > "$out_file" else "$compiler" --emit-ir "$input" > "$out_file" fi # 记录编译结束时间 compile_end=$(date +%s%N) compile_time=$(( ($compile_end - $compile_start) / 1000000 )) if [[ "$run_exec" == true ]]; then if ! command -v llc >/dev/null 2>&1; then echo "未找到 llc,无法运行 IR。请安装 LLVM。" >&2 exit 1 fi if ! command -v clang >/dev/null 2>&1; then echo "未找到 clang,无法链接可执行文件。请安装 LLVM/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" sylib_obj="$out_dir/sylib.o" # 记录链接开始时间 link_start=$(date +%s%N) if [[ ! -f "$sylib_obj" ]]; then gcc -c sylib/sylib.c -o "$sylib_obj" fi llc -O0 -filetype=obj "$out_file" -o "$obj" clang "$obj" "$sylib_obj" -o "$exe" # 记录链接结束时间 link_end=$(date +%s%N) link_time=$(( ($link_end - $link_start) / 1000000 )) # 记录执行开始时间 exec_start=$(date +%s%N) set +e if [[ -f "$stdin_file" ]]; then (ulimit -s 65536 && "$exe" < "$stdin_file" > "$stdout_file") else (ulimit -s 65536 && "$exe" > "$stdout_file") fi status=$? set -e # 记录执行结束时间 exec_end=$(date +%s%N) exec_time=$(( ($exec_end - $exec_start) / 1000000 )) # 保存运行时间到文件(只保存执行时间,不包含编译和链接时间) time_file="$out_dir/${stem}_time.txt" echo "$exec_time" > "$time_file" # 保存输出(用于比对) { cat "$stdout_file" # 确保 stdout 以换行结尾 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 temp_expected="$out_dir/$stem.expected.tmp" temp_actual="$out_dir/$stem.actual.tmp" tr -d '\r' < "$expected_file" > "$temp_expected" tr -d '\r' < "$actual_file" > "$temp_actual" if [[ -s "$temp_expected" ]] && (( $(tail -c 1 "$temp_expected" | wc -l) == 0 )); then if [[ -s "$temp_actual" ]] && (( $(tail -c 1 "$temp_actual" | wc -l) == 1 )); then truncate -s -1 "$temp_actual" fi fi if diff -u "$temp_expected" "$temp_actual" > /dev/null 2>&1; then rm -f "$temp_expected" "$temp_actual" else echo "输出不匹配: $expected_file" >&2 rm -f "$temp_expected" "$temp_actual" exit 1 fi fi fi