|
|
#!/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/ir"
|
|
|
VERIFY_SCRIPT="$PROJECT_ROOT/scripts/verify_ir.sh"
|
|
|
PARALLEL=${PARALLEL:-$(nproc)}
|
|
|
LOG_FILE="$TEST_RESULT_DIR/verify.log"
|
|
|
|
|
|
if [ ! -x "$COMPILER" ]; then
|
|
|
echo "错误:编译器不存在或不可执行: $COMPILER"
|
|
|
echo "请先构建项目:cmake --build build -j\$(nproc)"
|
|
|
exit 1
|
|
|
fi
|
|
|
|
|
|
mkdir -p "$TEST_RESULT_DIR"
|
|
|
> "$LOG_FILE"
|
|
|
|
|
|
# ── 阶段1:IR 生成(并行)────────────────────────────────────────────────────
|
|
|
echo "=== 阶段1:IR 生成 ===" | tee -a "$LOG_FILE"
|
|
|
echo "" | tee -a "$LOG_FILE"
|
|
|
|
|
|
GEN_TMPDIR=$(mktemp -d)
|
|
|
|
|
|
gen_one() {
|
|
|
test_file="$1"
|
|
|
relative_path=$(realpath --relative-to="$TEST_CASE_DIR" "$test_file")
|
|
|
output_file="$TEST_RESULT_DIR/${relative_path%.sy}.ll"
|
|
|
mkdir -p "$(dirname "$output_file")"
|
|
|
"$COMPILER" --emit-ir "$test_file" > "$output_file" 2>&1
|
|
|
exit_code=$?
|
|
|
# Use a per-case tmp file to avoid concurrent write issues
|
|
|
case_id=$(echo "$relative_path" | tr '/' '_')
|
|
|
if [ $exit_code -eq 0 ] && [ -s "$output_file" ] && ! grep -q '\[error\]' "$output_file"; then
|
|
|
echo "通过: $relative_path" > "$GEN_TMPDIR/pass_${case_id}"
|
|
|
else
|
|
|
echo "$relative_path" > "$GEN_TMPDIR/fail_${case_id}"
|
|
|
echo "失败: $relative_path" > "$GEN_TMPDIR/line_fail_${case_id}"
|
|
|
fi
|
|
|
}
|
|
|
export -f gen_one
|
|
|
export COMPILER TEST_CASE_DIR TEST_RESULT_DIR GEN_TMPDIR
|
|
|
|
|
|
find "$TEST_CASE_DIR" -name "*.sy" -not -path '*/*performance*/*' | sort | \
|
|
|
xargs -P "$PARALLEL" -I{} bash -c 'gen_one "$@"' _ {}
|
|
|
|
|
|
# Collect results in sorted order
|
|
|
failed_cases=()
|
|
|
for f in $(find "$TEST_CASE_DIR" -name "*.sy" | sort); do
|
|
|
relative_path=$(realpath --relative-to="$TEST_CASE_DIR" "$f")
|
|
|
case_id=$(echo "$relative_path" | tr '/' '_')
|
|
|
if [ -f "$GEN_TMPDIR/pass_${case_id}" ]; then
|
|
|
cat "$GEN_TMPDIR/pass_${case_id}" | tee -a "$LOG_FILE"
|
|
|
elif [ -f "$GEN_TMPDIR/fail_${case_id}" ]; then
|
|
|
cat "$GEN_TMPDIR/line_fail_${case_id}" | tee -a "$LOG_FILE"
|
|
|
failed_cases+=("$relative_path")
|
|
|
fi
|
|
|
done
|
|
|
|
|
|
pass_count=$(ls "$GEN_TMPDIR"/pass_* 2>/dev/null | wc -l)
|
|
|
fail_count=${#failed_cases[@]}
|
|
|
rm -rf "$GEN_TMPDIR"
|
|
|
|
|
|
echo "" | tee -a "$LOG_FILE"
|
|
|
echo "--- 生成完成: 通过 $pass_count / 失败 $fail_count ---" | tee -a "$LOG_FILE"
|
|
|
|
|
|
# ── 阶段2:IR 运行验证(并行,需要 llc + clang)──────────────────────────────
|
|
|
if ! command -v llc >/dev/null 2>&1 || ! command -v clang >/dev/null 2>&1; then
|
|
|
echo "" | tee -a "$LOG_FILE"
|
|
|
echo "=== 跳过阶段2:未找到 llc 或 clang,无法运行 IR ===" | tee -a "$LOG_FILE"
|
|
|
else
|
|
|
echo "" | tee -a "$LOG_FILE"
|
|
|
echo "=== 阶段2:IR 运行验证 ===" | tee -a "$LOG_FILE"
|
|
|
echo "" | tee -a "$LOG_FILE"
|
|
|
|
|
|
VRF_TMPDIR=$(mktemp -d)
|
|
|
|
|
|
verify_one() {
|
|
|
test_file="$1"
|
|
|
relative_path=$(realpath --relative-to="$TEST_CASE_DIR" "$test_file")
|
|
|
relative_dir=$(dirname "$relative_path")
|
|
|
out_dir="$TEST_RESULT_DIR/$relative_dir"
|
|
|
stem=$(basename "${test_file%.sy}")
|
|
|
case_log="$out_dir/$stem.verify.log"
|
|
|
case_id=$(echo "$relative_path" | tr '/' '_')
|
|
|
if bash "$VERIFY_SCRIPT" "$test_file" "$out_dir" --run > "$case_log" 2>&1; then
|
|
|
echo "通过: $relative_path" > "$VRF_TMPDIR/pass_${case_id}"
|
|
|
else
|
|
|
extra=$(grep -E '(退出码|输出不匹配|错误)' "$case_log" | head -3 | sed 's/^/ /' || true)
|
|
|
{ echo "失败: $relative_path"; [ -n "$extra" ] && echo "$extra"; } > "$VRF_TMPDIR/fail_${case_id}"
|
|
|
echo "$relative_path" > "$VRF_TMPDIR/failname_${case_id}"
|
|
|
fi
|
|
|
}
|
|
|
export -f verify_one
|
|
|
export TEST_CASE_DIR TEST_RESULT_DIR VERIFY_SCRIPT VRF_TMPDIR
|
|
|
|
|
|
find "$TEST_CASE_DIR" -name "*.sy" -not -path '*/*performance*/*' | sort | \
|
|
|
xargs -P "$PARALLEL" -I{} bash -c 'verify_one "$@"' _ {}
|
|
|
|
|
|
# Collect results in sorted order
|
|
|
verify_failed_cases=()
|
|
|
for f in $(find "$TEST_CASE_DIR" -name "*.sy" | sort); do
|
|
|
relative_path=$(realpath --relative-to="$TEST_CASE_DIR" "$f")
|
|
|
case_id=$(echo "$relative_path" | tr '/' '_')
|
|
|
if [ -f "$VRF_TMPDIR/pass_${case_id}" ]; then
|
|
|
cat "$VRF_TMPDIR/pass_${case_id}" | tee -a "$LOG_FILE"
|
|
|
elif [ -f "$VRF_TMPDIR/fail_${case_id}" ]; then
|
|
|
cat "$VRF_TMPDIR/fail_${case_id}" | tee -a "$LOG_FILE"
|
|
|
verify_failed_cases+=("$relative_path")
|
|
|
fi
|
|
|
done
|
|
|
|
|
|
verify_pass=$(ls "$VRF_TMPDIR"/pass_* 2>/dev/null | wc -l)
|
|
|
verify_fail=${#verify_failed_cases[@]}
|
|
|
rm -rf "$VRF_TMPDIR"
|
|
|
|
|
|
echo "" | tee -a "$LOG_FILE"
|
|
|
echo "--- 验证完成: 通过 $verify_pass / 失败 $verify_fail ---" | tee -a "$LOG_FILE"
|
|
|
|
|
|
if [ ${#verify_failed_cases[@]} -gt 0 ]; then
|
|
|
echo "" | tee -a "$LOG_FILE"
|
|
|
echo "=== 验证失败的用例 ===" | tee -a "$LOG_FILE"
|
|
|
for f in "${verify_failed_cases[@]}"; do
|
|
|
[ -n "$f" ] && echo " - $f" | tee -a "$LOG_FILE"
|
|
|
done
|
|
|
fi
|
|
|
fi
|
|
|
|
|
|
# ── 汇总 ─────────────────────────────────────────────────────────────────────
|
|
|
echo "" | tee -a "$LOG_FILE"
|
|
|
echo "=== 测试完成 ===" | tee -a "$LOG_FILE"
|
|
|
echo "IR生成 通过: $pass_count 失败: $fail_count" | tee -a "$LOG_FILE"
|
|
|
echo "结果保存在: $TEST_RESULT_DIR" | tee -a "$LOG_FILE"
|
|
|
echo "日志保存在: $LOG_FILE" | tee -a "$LOG_FILE"
|
|
|
|
|
|
if [ ${#failed_cases[@]} -gt 0 ]; then
|
|
|
echo "" | tee -a "$LOG_FILE"
|
|
|
echo "=== IR生成失败的用例 ===" | tee -a "$LOG_FILE"
|
|
|
for f in "${failed_cases[@]}"; do
|
|
|
[ -n "$f" ] && echo " - $f" | tee -a "$LOG_FILE"
|
|
|
done
|
|
|
exit 1
|
|
|
fi
|