aboutsummaryrefslogtreecommitdiff
path: root/tests/run_rv64_e2e.sh
blob: 7d515c03e90267e9e011e86afdf01602da189fdf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#!/bin/bash
# rcc end-to-end test: rcc backend → RV64 assembly → gcc → qemu
#
#   .sy --rcc -S--> .s --gcc--> ELF --qemu--> stdout/retcode
#
# Usage: ./tests/run_rv64_e2e.sh [test-dir]
# Default: functional
#
# Source code for RCC-Legacy.
# Copyright (C) 2026 Richard Qin
#
# This file is part of RCC.
#
# RCC is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free
# Software Foundation; either version 3, or (at your option) any later
# version.
#
# RCC is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
# for more details.
#
# You should have received a copy of the GNU General Public License
# along with RCC; see the file LICENSE.  If not see
# <http://www.gnu.org/licenses/>.

set -u
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
COMPILER="$PROJECT_DIR/../build-rcc-legacy/rcc"
SYLIB="$SCRIPT_DIR/runtime/sylib.c"
RV_GCC="/opt/riscv64-glibc/bin/riscv64-unknown-linux-gnu-gcc"
QEMU="/opt/riscv64-glibc/bin/qemu-riscv64"
TEST_DIR="${1:-$SCRIPT_DIR/functional}"
TIMEOUT=120  # seconds per test case

WORKDIR=$(mktemp -d /tmp/rcc_rv64_e2e_XXXXXX)
trap 'rm -rf "$WORKDIR"' EXIT

# Colors
RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[0;33m'; NC='\033[0m'

PASS=0; FAIL=0; ERROR=0; TOTAL=0; FAILURES=""

for sy in $(find "$TEST_DIR" -name '*.sy' | sort); do
    base="${sy%.sy}"; name=$(basename "$base")
    [ -f "$base.out" ] || continue
    TOTAL=$((TOTAL + 1))
    asm="$WORKDIR/$name.s"; elf="$WORKDIR/$name.elf"
    in=/dev/null; [ -f "$base.in" ] && in="$base.in"

    # 1. Compile .sy -> .s
    if ! timeout "$TIMEOUT" "$COMPILER" -S -o "$asm" "$sy" 2>"$WORKDIR/$name.err"; then
        ERROR=$((ERROR + 1))
        FAILURES="$FAILURES  ERROR(rcc): $name\n"
        echo -e "  ${YELLOW}[ERROR]${NC} $name  (rcc compile failed)"
        sed 's/^/         /' "$WORKDIR/$name.err"
        continue
    fi

    # 2. Assemble+link .s -> ELF
    if ! timeout "$TIMEOUT" "$RV_GCC" -static -march=rv64gc -o "$elf" "$asm" "$SYLIB" 2>"$WORKDIR/$name.gcc.err"; then
        ERROR=$((ERROR + 1))
        FAILURES="$FAILURES  ERROR(gcc): $name\n"
        echo -e "  ${YELLOW}[ERROR]${NC} $name  (gcc link failed)"
        sed 's/^/         /' "$WORKDIR/$name.gcc.err"
        continue
    fi

    # 3. Run under qemu with timeout
    actual_out=$(timeout "$TIMEOUT" "$QEMU" "$elf" < "$in" 2>/dev/null)
    actual_ret=$?

    # timeout returns 124 on timeout
    if [ "$actual_ret" -eq 124 ]; then
        ERROR=$((ERROR + 1))
        FAILURES="$FAILURES  ERROR(timeout): $name\n"
        echo -e "  ${YELLOW}[ERROR]${NC} $name  (qemu timeout ${TIMEOUT}s)"
        continue
    fi

    expected=$(cat "$base.out")
    expected_out=$(echo "$expected" | head -n -1)
    expected_ret=$(echo "$expected" | tail -n 1)

    if [ "$actual_out" = "$expected_out" ] && [ "$actual_ret" = "$expected_ret" ]; then
        PASS=$((PASS + 1))
        echo -e "  ${GREEN}[PASS]${NC}  $name"
    else
        FAIL=$((FAIL + 1))
        reason=""
        [ "$actual_ret" != "$expected_ret" ] && reason="ret: expected=$expected_ret got=$actual_ret"
        [ "$actual_out" != "$expected_out" ] && reason="${reason}${reason:+, }stdout mismatch"
        echo -e "  ${RED}[FAIL]${NC}  $name  ($reason)"
        if [ "$actual_out" != "$expected_out" ]; then
            echo "$expected_out" > "$WORKDIR/$name.expected"
            echo "$actual_out"   > "$WORKDIR/$name.actual"
            diff -u "$WORKDIR/$name.expected" "$WORKDIR/$name.actual" | head -20 | sed 's/^/         /'
        fi
        FAILURES="$FAILURES  FAIL: $name  $reason\n"
    fi
done

echo ""
echo "========================================"
echo -e "  TOTAL=$TOTAL  ${GREEN}PASS=$PASS${NC}  ${RED}FAIL=$FAIL${NC}  ${YELLOW}ERROR=$ERROR${NC}"
echo "========================================"
[ -n "$FAILURES" ] && echo -e "\nDetails:\n$FAILURES"