65816-llvm-mos/scripts/ccRegallocFallback.sh
2026-06-30 13:07:45 -05:00

54 lines
2 KiB
Bash
Executable file

#!/usr/bin/env bash
# Compile one W65816 translation unit, automatically falling back to the
# `basic` register allocator if the default `greedy` allocator hits the
# single-accumulator deadlock ("ran out of registers during register
# allocation").
#
# Why this exists: the 65816 has exactly one accumulator (the Acc16
# register class has a single physreg, A). greedy's region-splitting
# heuristic can manufacture two A-pinned live ranges it cannot then
# unspill, and aborts. This is a genuine hardware constraint, not a bug
# we can cheaply fix in the backend (the deadlocking vregs are greedy's
# own split products, so no pre-RA pass prevents them; verified
# 2026-06-29). `basic` regalloc serializes the two values correctly.
#
# greedy stays the default because its codegen is smaller/faster
# everywhere it succeeds; basic is used ONLY for the rare function greedy
# cannot allocate, and ONLY for that translation unit. This replaces the
# old hand-maintained per-file list (tests/lua/build.sh SLOW_FILES) so a
# newly-added register-heavy TU can never silently break the build.
#
# Usage: ccRegallocFallback.sh <clang> <clang-args...>
# The args are a normal clang `-c file -o out` compile command.
set -u
if [ "$#" -lt 1 ]; then
echo "usage: ccRegallocFallback.sh <clang> <clang-args...>" >&2
exit 2
fi
clang="$1"
shift
# First attempt with the default (greedy) allocator. Capture combined
# output so we can inspect it; a single-TU compile is quick, so buffering
# until completion is fine.
out="$("$clang" "$@" 2>&1)"
status=$?
if [ "$status" -eq 0 ]; then
# Success: pass through any warnings clang produced.
[ -n "$out" ] && printf '%s\n' "$out" >&2
exit 0
fi
# Retry with basic regalloc ONLY for the single-accumulator deadlock.
# Any other compile error is surfaced as-is.
if printf '%s' "$out" | grep -q 'ran out of registers'; then
echo " (regalloc: greedy ran out of registers; retrying with -regalloc=basic)" >&2
exec "$clang" "$@" -mllvm -regalloc=basic
fi
printf '%s\n' "$out" >&2
exit "$status"