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.

161 lines
3.9 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
if [[ $# -lt 1 || $# -gt 3 ]]; then
echo "用法: $0 <input.sy> [output_dir] [--run]" >&2
exit 1
fi
input=$1
out_dir="test/test_result/asm"
run_exec=false
input_dir=$(dirname "$input")
shift
while [[ $# -gt 0 ]]; do
case "$1" in
--run)
run_exec=true
;;
*)
out_dir="$1"
;;
esac
shift
done
if [[ ! -f "$input" ]]; then
echo "输入文件不存在: $input" >&2
exit 1
fi
# 查找编译器路径 (使用绝对路径)
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
compiler="$PROJECT_ROOT/build/bin/compiler"
if [[ ! -x "$compiler" ]]; then
echo "未找到编译器: $compiler ,请先构建。" >&2
exit 1
fi
now_ms() {
local ns
ns=$(date +%s%N 2>/dev/null || true)
if [[ "$ns" =~ ^[0-9]+$ ]]; then
printf '%s\n' "$((ns / 1000000))"
else
printf '%s000\n' "$(date +%s)"
fi
}
format_ms() {
local ms=$1
printf '%d.%03ds' "$((ms / 1000))" "$((ms % 1000))"
}
link_aarch64() {
local asm_file=$1
local sylib=$2
local exe=$3
if command -v aarch64-linux-gnu-gcc >/dev/null 2>&1; then
if [[ -f "$sylib" ]]; then
aarch64-linux-gnu-gcc "$asm_file" "$sylib" -o "$exe"
else
aarch64-linux-gnu-gcc "$asm_file" -o "$exe"
fi
return
fi
if command -v clang >/dev/null 2>&1; then
if [[ -f "$sylib" ]]; then
clang --target=aarch64-linux-gnu "$asm_file" "$sylib" -o "$exe"
else
clang --target=aarch64-linux-gnu "$asm_file" -o "$exe"
fi
return
fi
echo "未找到 AArch64 链接工具:需要 aarch64-linux-gnu-gcc或支持 --target=aarch64-linux-gnu 的 clang。" >&2
exit 1
}
mkdir -p "$out_dir"
base=$(basename "$input")
stem=${base%.sy}
asm_file="$out_dir/$stem.s"
exe="$out_dir/$stem"
stdin_file="$input_dir/$stem.in"
expected_file="$input_dir/$stem.out"
# 查找运行库路径
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SYLIB="$SCRIPT_DIR/../sylib/sylib.c"
"$compiler" --emit-asm "$input" > "$asm_file"
echo "汇编已生成: $asm_file"
link_aarch64 "$asm_file" "$SYLIB" "$exe"
echo "可执行文件已生成: $exe"
if [[ "$run_exec" == true ]]; then
if ! command -v qemu-aarch64 >/dev/null 2>&1; then
echo "未找到 qemu-aarch64无法运行生成的可执行文件。" >&2
exit 1
fi
stdout_file="$out_dir/$stem.stdout"
actual_file="$out_dir/$stem.actual.out"
run_timeout="${SY_QEMU_TIMEOUT:-600}"
echo "运行 $exe ... (timeout: ${run_timeout}s)"
set +e
ulimit -s unlimited 2>/dev/null || true
export QEMU_STACK_SIZE=67108864
run_start_ms=$(now_ms)
if command -v timeout >/dev/null 2>&1; then
if [[ -f "$stdin_file" ]]; then
timeout "${run_timeout}s" qemu-aarch64 -L /usr/aarch64-linux-gnu "$exe" < "$stdin_file" > "$stdout_file"
else
timeout "${run_timeout}s" qemu-aarch64 -L /usr/aarch64-linux-gnu "$exe" > "$stdout_file"
fi
else
if [[ -f "$stdin_file" ]]; then
qemu-aarch64 -L /usr/aarch64-linux-gnu "$exe" < "$stdin_file" > "$stdout_file"
else
qemu-aarch64 -L /usr/aarch64-linux-gnu "$exe" > "$stdout_file"
fi
fi
status=$?
run_end_ms=$(now_ms)
run_elapsed_ms=$((run_end_ms - run_start_ms))
set -e
if [[ $status -eq 124 ]]; then
echo "运行超时: ${run_timeout}s耗时: $(format_ms "$run_elapsed_ms")" >&2
exit 124
fi
echo "运行耗时: $(format_ms "$run_elapsed_ms")"
cat "$stdout_file"
echo "退出码: $status"
{
cat "$stdout_file"
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
if diff -u -b -w "$expected_file" "$actual_file"; then
echo "输出匹配: $expected_file"
else
echo "输出不匹配: $expected_file" >&2
echo "实际输出已保存: $actual_file" >&2
exit 1
fi
else
echo "未找到预期输出文件,跳过比对: $expected_file"
fi
fi