You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
nudt-compiler-cpp/scripts/test_compiler.sh

156 lines
4.4 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#!/usr/bin/env bash
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
COMPILER="$ROOT_DIR/build/bin/compiler"
TMP_DIR="$ROOT_DIR/build/test_compiler"
TEST_DIRS=("$ROOT_DIR/test/test_case/functional" "$ROOT_DIR/test/test_case/performance")
if [[ ! -x "$COMPILER" ]]; then
echo "未找到编译器: $COMPILER"
echo "请先构建编译器,例如: mkdir -p build && cd build && cmake .. && make -j"
exit 1
fi
mkdir -p "$TMP_DIR"
ir_total=0
ir_pass=0
result_total=0
result_pass=0
ir_failures=()
result_failures=()
function normalize_file() {
sed 's/\r$//' "$1"
}
for test_dir in "${TEST_DIRS[@]}"; do
if [[ ! -d "$test_dir" ]]; then
echo "跳过不存在的测试目录: $test_dir"
continue
fi
shopt -s nullglob
for input in "$test_dir"/*.sy; do
ir_total=$((ir_total+1))
base=$(basename "$input")
stem=${base%.sy}
out_dir="$TMP_DIR/$(basename "$test_dir")"
mkdir -p "$out_dir"
ll_file="$out_dir/$stem.ll"
stdout_file="$out_dir/$stem.stdout"
expected_file="$test_dir/$stem.out"
stdin_file="$test_dir/$stem.in"
echo "[TEST] $input"
# 编译并捕获所有输出
compiler_status=0
compiler_output=""
compiler_output=$("$COMPILER" --emit-ir "$input" 2>&1) || compiler_status=$?
# 临时文件存储原始输出
raw_ll="$out_dir/$stem.raw.ll"
printf '%s\n' "$compiler_output" > "$raw_ll"
# 检查编译是否成功
if [[ $compiler_status -ne 0 ]]; then
echo " [IR] 编译失败: 返回码 $compiler_status"
ir_failures+=("$input: compiler failed ($compiler_status)")
# 失败:保留原始输出(包含所有调试信息)
cp "$raw_ll" "$ll_file"
rm -f "$raw_ll"
continue
fi
# 检查是否生成了有效的函数定义(在过滤后的内容中检查)
# 先过滤一下看看是否有define
filtered_content=$(sed -E '/^\[DEBUG\]|^SymbolTable::|^Check|^绑定|^保存|^dim_count:/d' "$raw_ll")
if ! echo "$filtered_content" | grep -qE '^define '; then
echo " [IR] 失败: 未生成有效函数定义"
ir_failures+=("$input: invalid IR output")
# 失败:保留原始输出
cp "$raw_ll" "$ll_file"
rm -f "$raw_ll"
continue
fi
# 编译成功过滤掉所有调试输出只保留IR
# 过滤规则:
# 1. 以 [DEBUG] 开头的行
# 2. SymbolTable:: 开头的行
# 3. CheckLValue: 开头的行
# 4. 绑定变量: 开头的行
# 5. dim_count: 开头的行
# 6. 空行(可选)
sed -E '/^(\[DEBUG|SymbolTable::|Check|绑定|保存|dim_)/d' "$raw_ll" > "$ll_file"
# 可选:删除多余的空行
sed -i '/^$/N;/\n$/D' "$ll_file"
rm -f "$raw_ll"
ir_pass=$((ir_pass+1))
echo " [IR] 生成成功 (IR已保存到: $ll_file)"
# 运行测试
if [[ -f "$expected_file" ]]; then
result_total=$((result_total+1))
# 运行LLVM IR
run_status=0
if [[ -f "$stdin_file" ]]; then
lli "$ll_file" < "$stdin_file" > "$stdout_file" 2>&1 || run_status=$?
else
lli "$ll_file" > "$stdout_file" 2>&1 || run_status=$?
fi
# 读取预期返回值
expected=$(normalize_file "$expected_file")
# 比较返回值
if [[ "$run_status" -eq "$expected" ]]; then
result_pass=$((result_pass+1))
echo " [RUN] 返回值匹配: $run_status"
# 成功:保留已清理的.ll文件删除输出文件
rm -f "$stdout_file"
else
echo " [RUN] 返回值不匹配: got $run_status, expected $expected"
result_failures+=("$input: exit code mismatch (got $run_status, expected $expected)")
# 失败:.ll文件已经保留输出文件也保留用于调试
fi
else
echo " [RUN] 未找到预期返回值文件 $expected_file,跳过结果验证"
fi
done
shopt -u nullglob
done
# 输出统计
cat <<EOF
测试完成。
IR 生成: $ir_pass / $ir_total
结果匹配: $result_pass / $result_total
EOF
# 输出失败列表
if [[ ${#ir_failures[@]} -gt 0 ]]; then
echo ""
echo "IR 失败列表:"
for item in "${ir_failures[@]}"; do
echo " $item"
done
fi
if [[ ${#result_failures[@]} -gt 0 ]]; then
echo ""
echo "结果失败列表:"
for item in "${result_failures[@]}"; do
echo " $item"
done
echo ""
echo "失败的测试文件已保留在: $TMP_DIR"
echo "可以查看对应的.ll文件进行调试"
fi