#!/bin/bash PROJECT_ROOT=$(cd "$(dirname "$0")/.." ; pwd) COMPILER="$PROJECT_ROOT/build/bin/compiler" TEST_CASE_DIR="$PROJECT_ROOT/test/test_case" TEST_RESULT_DIR="$PROJECT_ROOT/test/test_result/mir" SYLIB_C="$PROJECT_ROOT/sylib/sylib.c" SYLIB_O="/tmp/sylib.o" RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' if [ ! -x "$COMPILER" ]; then echo "错误:编译器不存在或不可执行: $COMPILER" exit 1 fi # 编译 sylib 运行时库 echo "编译运行时库..." if [ ! -f "$SYLIB_O" ]; then riscv64-linux-gnu-gcc -c "$SYLIB_C" -o "$SYLIB_O" 2>/dev/null if [ $? -ne 0 ]; then echo "警告:无法编译 sylib.c,部分测试可能链接失败" fi fi echo "" mkdir -p "$TEST_RESULT_DIR" echo "==========================================" echo "RISC-V 后端测试" echo "==========================================" echo "" # 收集测试用例 mapfile -t test_files < <(find "$TEST_CASE_DIR" -name "*.sy" -not -path '*/*performance*/*' | sort) total=${#test_files[@]} pass_gen=0 fail_gen=0 pass_run=0 fail_run=0 timeout_cnt=0 echo "=== 阶段1:汇编生成 ===" echo "" for test_file in "${test_files[@]}"; do relative_path=$(realpath --relative-to="$TEST_CASE_DIR" "$test_file") output_file="$TEST_RESULT_DIR/${relative_path%.sy}.s" mkdir -p "$(dirname "$output_file")" "$COMPILER" --emit-asm "$test_file" 2>/dev/null > "$output_file" if [ $? -eq 0 ] && [ -s "$output_file" ]; then echo -e " ${GREEN}✓${NC} $relative_path" ((pass_gen++)) else echo -e " ${RED}✗${NC} $relative_path" ((fail_gen++)) fi done echo "" echo "--- 汇编生成: 通过 $pass_gen / 失败 $fail_gen / 总计 $total ---" echo "" for test_file in "${test_files[@]}"; do relative_path=$(realpath --relative-to="$TEST_CASE_DIR" "$test_file") stem="${relative_path%.sy}" asm_file="$TEST_RESULT_DIR/${stem}.s" exe_file="$TEST_RESULT_DIR/${stem}" expected_file="${test_file%.sy}.out" if [ ! -s "$asm_file" ]; then echo -e " ${YELLOW}⚠${NC} $relative_path (跳过)" continue fi # 链接 if [ -f "$SYLIB_O" ]; then riscv64-linux-gnu-gcc -static "$asm_file" "$SYLIB_O" -o "$exe_file" -no-pie 2>/dev/null else riscv64-linux-gnu-gcc -static "$asm_file" -o "$exe_file" -no-pie 2>/dev/null fi if [ $? -ne 0 ]; then echo -e " ${RED}✗${NC} $relative_path (链接失败)" ((fail_run++)) continue fi # 运行程序 - 修改:丢弃 stderr,只捕获 stdout input_file="${test_file%.sy}.in" tmp_out=$(mktemp) if [ -f "$input_file" ]; then timeout 10 qemu-riscv64 "$exe_file" < "$input_file" > "$tmp_out" 2>/dev/null else timeout 10 qemu-riscv64 "$exe_file" > "$tmp_out" 2>/dev/null fi exit_code=$? if [ $exit_code -eq 124 ]; then echo -e " ${YELLOW}⚠${NC} $relative_path (超时)" ((timeout_cnt++)) rm -f "$tmp_out" continue fi # 直接读取输出文件,不做任何处理 program_output=$(cat "$tmp_out" | tr -d '\n') rm -f "$tmp_out" if [ -f "$expected_file" ]; then expected=$(cat "$expected_file" | tr -d '\n') if [[ "$expected" =~ ^[0-9]+$ ]] && [ "$expected" -ge 0 ] && [ "$expected" -le 255 ] && [ -z "$program_output" ]; then # 期望退出码(且没有输出) if [ $exit_code -eq "$expected" ] 2>/dev/null; then echo -e " ${GREEN}✓${NC} $relative_path (退出码: $exit_code)" ((pass_run++)) else echo -e " ${RED}✗${NC} $relative_path (退出码: 期望 $expected, 实际 $exit_code)" ((fail_run++)) fi else # 期望输出内容 if [ "$program_output" = "$expected" ]; then echo -e " ${GREEN}✓${NC} $relative_path (输出匹配)" ((pass_run++)) else echo -e " ${RED}✗${NC} $relative_path (输出不匹配: 期望 '$expected', 实际 '$program_output')" ((fail_run++)) fi fi else # 没有期望文件 echo -e " ${GREEN}✓${NC} $relative_path (退出码: $exit_code, 输出: '$program_output')" ((pass_run++)) fi done echo "" echo "--- 运行验证: 通过 $pass_run / 失败 $fail_run / 超时 $timeout_cnt ---" echo "" echo "==========================================" echo "测试完成" echo "汇编生成: 通过 $pass_gen / 失败 $fail_gen" echo "运行验证: 通过 $pass_run / 失败 $fail_run / 超时 $timeout_cnt" echo "=========================================="