#!/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" RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' if [ ! -x "$COMPILER" ]; then echo "错误:编译器不存在或不可执行: $COMPILER" exit 1 fi 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 "" echo "=== 阶段2:运行验证 ===" 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 riscv64-linux-gnu-gcc -static "$asm_file" -o "$exe_file" -no-pie 2>/dev/null if [ $? -ne 0 ]; then echo -e " ${RED}✗${NC} $relative_path (链接失败)" ((fail_run++)) continue fi # 运行程序,设置超时 5 秒 timeout 5 qemu-riscv64 "$exe_file" 2>/dev/null exit_code=$? # 检查是否超时 if [ $exit_code -eq 124 ]; then echo -e " ${YELLOW}⚠${NC} $relative_path (超时)" ((timeout_cnt++)) continue fi # 获取程序输出(需要单独捕获,因为 timeout 会改变输出) program_output=$(timeout 5 qemu-riscv64 "$exe_file" 2>/dev/null) if [ $? -eq 124 ]; then echo -e " ${YELLOW}⚠${NC} $relative_path (超时)" ((timeout_cnt++)) continue fi if [ -f "$expected_file" ]; then expected=$(cat "$expected_file" | tr -d '\n') # 判断期望文件是输出内容还是退出码 if [ -z "$expected" ] || [[ "$expected" =~ ^[0-9]+$ ]]; 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 (输出不匹配)" ((fail_run++)) fi fi else # 没有期望文件,默认通过 echo -e " ${GREEN}✓${NC} $relative_path (退出码: $exit_code)" ((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 "=========================================="