Docs updated.
This commit is contained in:
parent
d4e5c26fd6
commit
178ed633ee
11 changed files with 189 additions and 78 deletions
25
README.md
25
README.md
|
|
@ -60,6 +60,31 @@ bash scripts/runInMame.sh hello.bin --check 0x025000=0037
|
||||||
See [docs/USAGE.md](docs/USAGE.md) for a full walkthrough including
|
See [docs/USAGE.md](docs/USAGE.md) for a full walkthrough including
|
||||||
multi-segment builds and the Apple IIgs Toolbox.
|
multi-segment builds and the Apple IIgs Toolbox.
|
||||||
|
|
||||||
|
### Register-heavy code and the regalloc fallback
|
||||||
|
|
||||||
|
The 65816 has a single accumulator, so a few unusually register-heavy
|
||||||
|
functions exceed what LLVM's default `greedy` allocator can place and
|
||||||
|
abort with `ran out of registers during register allocation`. This is a
|
||||||
|
hardware constraint, not a miscompile; LLVM's `basic` allocator handles
|
||||||
|
those functions correctly (greedy stays the default everywhere else
|
||||||
|
because its codegen is smaller and faster).
|
||||||
|
|
||||||
|
The project build scripts handle this automatically via
|
||||||
|
`scripts/ccRegallocFallback.sh`, which compiles with greedy and silently
|
||||||
|
retries the affected translation unit with `-mllvm -regalloc=basic` only
|
||||||
|
when it hits that error. `tests/lua/build.sh`, `tests/coremark/build.sh`,
|
||||||
|
and `runtime/build.sh` route their compiles through it.
|
||||||
|
|
||||||
|
If you invoke `clang` directly and hit the error on your own
|
||||||
|
register-heavy code, either compile that file through the wrapper:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
./scripts/ccRegallocFallback.sh ./tools/llvm-mos-build/bin/clang \
|
||||||
|
--target=w65816 -O2 -c heavy.c -o heavy.o
|
||||||
|
```
|
||||||
|
|
||||||
|
or just add `-mllvm -regalloc=basic` to that one compile.
|
||||||
|
|
||||||
## Project layout
|
## Project layout
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -377,7 +377,7 @@ All under `/home/scott/claude/llvm816/tools/`:
|
||||||
| MAME 0.264 | `/usr/games/mame` (apt) | supports `-console` (Lua) |
|
| MAME 0.264 | `/usr/games/mame` (apt) | supports `-console` (Lua) |
|
||||||
| Apple IIgs ROMs | `tools/mame/roms/apple2gs.zip`, `apple2gsr1.zip` | from archive.org |
|
| Apple IIgs ROMs | `tools/mame/roms/apple2gs.zip`, `apple2gsr1.zip` | from archive.org |
|
||||||
| Calypsi 5.16 | `tools/calypsi/` | extracted .deb |
|
| Calypsi 5.16 | `tools/calypsi/` | extracted .deb |
|
||||||
| ORCA/C source | `tools/orca-c/` | reference only |
|
| Toolbox catalogue | `tools/nlist/NList.Data.txt` | Dave Lyons' NiftyList data; source for `scripts/genToolbox.py` |
|
||||||
|
|
||||||
`./setup.sh --verify-only` passed all checks as of the prior session.
|
`./setup.sh --verify-only` passed all checks as of the prior session.
|
||||||
|
|
||||||
|
|
@ -390,7 +390,7 @@ llvm816/ # git repo, branch main
|
||||||
├── setup.sh # tracked
|
├── setup.sh # tracked
|
||||||
├── scripts/ # tracked
|
├── scripts/ # tracked
|
||||||
│ ├── common.sh
|
│ ├── common.sh
|
||||||
│ ├── installDeps.sh installCalypsi.sh installOrcaC.sh
|
│ ├── installDeps.sh installCalypsi.sh installGno.sh
|
||||||
│ ├── installLlvmMos.sh # non-destructive (see §8)
|
│ ├── installLlvmMos.sh # non-destructive (see §8)
|
||||||
│ ├── installMame.sh verify.sh
|
│ ├── installMame.sh verify.sh
|
||||||
│ ├── applyBackend.sh # src/ + patches/ -> tools/llvm-mos/
|
│ ├── applyBackend.sh # src/ + patches/ -> tools/llvm-mos/
|
||||||
|
|
|
||||||
59
STATUS.md
59
STATUS.md
|
|
@ -332,8 +332,14 @@ which runs correctly under MAME (apple2gs).
|
||||||
| memcmp | 682 | 716 | 0.95× |
|
| memcmp | 682 | 716 | 0.95× |
|
||||||
| fib | 11594 | 10912 | 1.06× |
|
| fib | 11594 | 10912 | 1.06× |
|
||||||
|
|
||||||
**Geomean: 0.62× Calypsi.** 9 of 10 below 1.0×; only fib trails
|
**Geomean: 0.62× Calypsi.** 9 of 10 below 1.0×; only fib trails.
|
||||||
(recursive call overhead, structural). Speed is the optimization
|
The ~6% gap is the per-call defensive `REP #$30` mode-set our
|
||||||
|
FrameLowering emits at every function entry (Calypsi omits it via a
|
||||||
|
global M/X=16 invariant) plus a marginally larger stack frame. Both
|
||||||
|
are deliberate correctness choices; eliding the entry REP safely needs
|
||||||
|
the deferred per-region REP/SEP scheduling pass (design §3.3) -- a
|
||||||
|
naive global elision risks the silent i16-immediate-in-M=1 miscompile
|
||||||
|
documented in W65816FrameLowering.cpp. Speed is the optimization
|
||||||
priority, not size.
|
priority, not size.
|
||||||
|
|
||||||
- `compare/` holds three side-by-side C tests with our asm and
|
- `compare/` holds three side-by-side C tests with our asm and
|
||||||
|
|
@ -395,11 +401,12 @@ which runs correctly under MAME (apple2gs).
|
||||||
Resource Manager, MIDI, Video Overlay, TextEdit, Media
|
Resource Manager, MIDI, Video Overlay, TextEdit, Media
|
||||||
Control, Print Manager, Scheduler, Desk Manager, …). Names
|
Control, Print Manager, Scheduler, Desk Manager, …). Names
|
||||||
match Apple's IIgs Toolbox Reference exactly (TLStartUp,
|
match Apple's IIgs Toolbox Reference exactly (TLStartUp,
|
||||||
MMStartUp, NewWindow, SysBeep, …). 417 simple wrappers
|
MMStartUp, NewWindow, SysBeep, …). 495 simple wrappers
|
||||||
(zero/single-arg, i16-or-void return) inline in the header;
|
(zero/single-arg, i16-or-void return) inline in the header;
|
||||||
890 multi-arg ones live in `runtime/src/iigsToolbox.s`.
|
896 multi-arg ones live in `runtime/src/iigsToolbox.s`.
|
||||||
Generated by `scripts/genToolbox.py` from ORCA-C's
|
Generated by `scripts/genToolbox.py` from Dave Lyons'
|
||||||
`ORCACDefs/` (re-runnable when ORCA-C updates).
|
NiftyList database (`tools/nlist/NList.Data.txt`,
|
||||||
|
re-runnable when the catalogue updates).
|
||||||
|
|
||||||
## What's next
|
## What's next
|
||||||
|
|
||||||
|
|
@ -592,10 +599,11 @@ for the common-case C / minimal-C++ workload. Priority is speed
|
||||||
- **Lua 5.1.5 compiles cleanly** (2026-05-20). Reference C
|
- **Lua 5.1.5 compiles cleanly** (2026-05-20). Reference C
|
||||||
implementation (17K lines, 24 source files) builds + links into a
|
implementation (17K lines, 24 source files) builds + links into a
|
||||||
multi-segment binary. Loads in MAME. Lives under `tests/lua/`.
|
multi-segment binary. Loads in MAME. Lives under `tests/lua/`.
|
||||||
Three large functions (luaV_execute, symbexec, auxsort) hit
|
A few large functions (luaV_execute, symbexec, auxsort, and
|
||||||
greedy regalloc's complexity budget and need `-mllvm
|
lstrlib under --layer2) exceed what greedy regalloc can place
|
||||||
-regalloc=basic` (still at -O2 — basic-regalloc -O2 is ~3.5×
|
with the single accumulator; `build.sh` auto-falls-back to
|
||||||
smaller than fast-regalloc -O0). Largest "real-world C" test
|
`-mllvm -regalloc=basic` for just those TUs via
|
||||||
|
`scripts/ccRegallocFallback.sh` (still -O2). Largest "real-world C" test
|
||||||
in the project.
|
in the project.
|
||||||
|
|
||||||
**Open limitations:**
|
**Open limitations:**
|
||||||
|
|
@ -615,17 +623,28 @@ for the common-case C / minimal-C++ workload. Priority is speed
|
||||||
bank N needs the program to set DBR=N or use `sta long` via
|
bank N needs the program to set DBR=N or use `sta long` via
|
||||||
inline asm.
|
inline asm.
|
||||||
|
|
||||||
- **C++ exceptions absent from CI smoke.** The SJLJ runtime
|
- **C++ exceptions now run in CI smoke** (2026-06-30). Both the
|
||||||
round-trip is in smoke; the full clang++ → backend → MAME
|
pure-C SJLJ runtime round-trip AND the full clang++
|
||||||
execution path runs reliably interactively but is excluded
|
`-fsjlj-exceptions` → backend → MAME execution path are in smoke:
|
||||||
from automated smoke due to MAME-side I/O flakiness.
|
the latter throws an int across a recursive call boundary and
|
||||||
|
verifies the catch fired and the value propagated (407/0x0197).
|
||||||
|
The earlier -O2 call_site-store isel mis-route and the
|
||||||
|
"intermittent MAME crash" that previously kept this compile+link
|
||||||
|
only are resolved (verified 20/20 across -O0/-O2).
|
||||||
|
|
||||||
- **GS/OS validation uses a stub dispatcher.** The wrapper
|
- **GS/OS validated against BOTH a stub and a real bootable
|
||||||
contract (PHA + PEA 0 + LDX + JSL $E100A8 + post-call SP
|
volume.** The wrapper contract (PHA + PEA 0 + LDX + JSL $E100A8 +
|
||||||
fixup) is verified end-to-end in MAME against a stub
|
post-call SP fixup) is verified in MAME two ways: a fast isolated
|
||||||
(`scripts/runInMameWithGsosStub.sh`). Validation against a
|
stub round-trip (`scripts/runInMameWithGsosStub.sh`), and -- since
|
||||||
real bootable GS/OS volume is left out of CI as it needs a
|
the `runViaFinder` path landed -- end-to-end against a real booted
|
||||||
smartport hard-disk image and live Tool Locator init.
|
GS/OS. `scripts/runViaFinder.sh` boots real GS/OS 6.0.2
|
||||||
|
(`tools/gsos/sys602.po`) with live Tool Locator init and mounts a
|
||||||
|
cadius-built smartport data volume; the smoke check "GS/OS
|
||||||
|
fopen/fread reads /DATA/TESTFILE" drives `fopen`/`fread`/`fclose`
|
||||||
|
through the wrapper to real GS/OS on that volume and verifies the
|
||||||
|
content round-trips. ~15 further smoke checks run real GS/OS
|
||||||
|
6.0.2/6.0.4 (Resource Manager, StandardFile, Cursor Mgr, the
|
||||||
|
Loader's cINTERSEG + indirect dispatch, etc.).
|
||||||
|
|
||||||
- **VLAs work end-to-end** (2026-05-09). Backend Custom-lowers
|
- **VLAs work end-to-end** (2026-05-09). Backend Custom-lowers
|
||||||
`ISD::DYNAMIC_STACKALLOC` for both i16 and i32 result types.
|
`ISD::DYNAMIC_STACKALLOC` for both i16 and i32 result types.
|
||||||
|
|
|
||||||
|
|
@ -285,7 +285,7 @@ bash runtime/build.sh
|
||||||
# Compile + disassemble a small C demo
|
# Compile + disassemble a small C demo
|
||||||
bash scripts/cDemo.sh
|
bash scripts/cDemo.sh
|
||||||
|
|
||||||
# Run the full smoke test suite (~150 checks, takes ~3 min)
|
# Run the full smoke test suite (~175 checks, takes a few min)
|
||||||
bash scripts/smokeTest.sh
|
bash scripts/smokeTest.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -353,8 +353,9 @@ See [STATUS.md](../STATUS.md) for the full feature matrix.
|
||||||
## Linking — full reference
|
## Linking — full reference
|
||||||
|
|
||||||
`link816` produces a flat binary suitable for direct execution (loaded
|
`link816` produces a flat binary suitable for direct execution (loaded
|
||||||
into a fixed address) or, with `--omf`, an OMF binary that the GS/OS
|
into a fixed address). To get an OMF binary that the GS/OS Loader can
|
||||||
Loader can load and relocate.
|
load and relocate, pass `link816`'s output through the separate `omfEmit`
|
||||||
|
tool (see "Multi-segment OMF (for GS/OS Loader)" below).
|
||||||
|
|
||||||
### Raw binary (fixed-address load)
|
### Raw binary (fixed-address load)
|
||||||
|
|
||||||
|
|
@ -1161,10 +1162,14 @@ is a follow-up under the `cxxsmoke` GNO MAME harness.
|
||||||
trigger FP-relative addressing. Most programs fit under that limit.
|
trigger FP-relative addressing. Most programs fit under that limit.
|
||||||
See the `frame-rel` discussion in
|
See the `frame-rel` discussion in
|
||||||
[LLVM_65816_DESIGN.md](../LLVM_65816_DESIGN.md).
|
[LLVM_65816_DESIGN.md](../LLVM_65816_DESIGN.md).
|
||||||
- **Three Lua functions** (`luaV_execute`, `symbexec`, `auxsort`) hit
|
- **Register-heavy functions** (e.g. Lua's `luaV_execute`, `symbexec`,
|
||||||
the greedy register allocator's complexity budget. Workaround:
|
`auxsort`) can exceed what the `greedy` allocator places with the
|
||||||
compile those TUs with `-mllvm -regalloc=basic`. Documented in
|
65816's single accumulator and abort with `ran out of registers`.
|
||||||
[`tests/lua/README.md`](../tests/lua/README.md).
|
This is handled automatically by `scripts/ccRegallocFallback.sh`
|
||||||
|
(retries the TU with `-mllvm -regalloc=basic`); the project build
|
||||||
|
scripts route through it. For a direct `clang` invocation, use the
|
||||||
|
wrapper or add `-mllvm -regalloc=basic`. See the Quick start note in
|
||||||
|
[`../README.md`](../README.md) and [`tests/lua/README.md`](../tests/lua/README.md).
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,10 @@ cc() {
|
||||||
local o="$OUT/$(basename "${c%.c}").o"
|
local o="$OUT/$(basename "${c%.c}").o"
|
||||||
local extra=("${@:2}")
|
local extra=("${@:2}")
|
||||||
echo " CC $(basename "$c")"
|
echo " CC $(basename "$c")"
|
||||||
"$CLANG" -target w65816 -O2 -ffunction-sections \
|
# Route through the regalloc fallback so a register-heavy runtime TU
|
||||||
|
# auto-retries with basic regalloc instead of hard-failing the build.
|
||||||
|
"$PROJECT_ROOT/scripts/ccRegallocFallback.sh" "$CLANG" \
|
||||||
|
-target w65816 -O2 -ffunction-sections \
|
||||||
"${extra[@]}" \
|
"${extra[@]}" \
|
||||||
-I"$PROJECT_ROOT/runtime/include" \
|
-I"$PROJECT_ROOT/runtime/include" \
|
||||||
-c "$c" -o "$o"
|
-c "$c" -o "$o"
|
||||||
|
|
|
||||||
54
scripts/ccRegallocFallback.sh
Executable file
54
scripts/ccRegallocFallback.sh
Executable file
|
|
@ -0,0 +1,54 @@
|
||||||
|
#!/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"
|
||||||
|
|
@ -5003,26 +5003,32 @@ EOF
|
||||||
fi
|
fi
|
||||||
rm -f "$cSjeFile" "$oSjeFile" "$oSjeRt" "$oSjeAbi" "$binSjeFile"
|
rm -f "$cSjeFile" "$oSjeFile" "$oSjeRt" "$oSjeAbi" "$binSjeFile"
|
||||||
|
|
||||||
# C++ try/throw/catch via clang's -fsjlj-exceptions: COMPILE +
|
# C++ try/throw/catch via clang's -fsjlj-exceptions: full
|
||||||
# LINK only. We don't run the binary in MAME from smoke
|
# frontend → backend → SJLJ runtime → MAME execution. Throws an
|
||||||
# because MAME's apple2gs CPU emulation crashes intermittently
|
# int across a recursive call boundary and checks both that the
|
||||||
# on our SJLJ-prepared exception code (a MAME bug — same
|
# catch fired (caught=1) and that the thrown value propagated
|
||||||
# binary executes correctly when invoked outside the smoke
|
# intact (4*100+7 = 407 = 0x0197). This used to be compile+link
|
||||||
# harness's I/O environment). The pure-C SJLJ runtime test
|
# only: the earlier -O2 call_site-store isel mis-route and the
|
||||||
# above already exercises the full _Unwind_SjLj_* + __cxa_*
|
# "intermittent MAME crash" are both resolved, and the binary now
|
||||||
# surface end-to-end; this check just guards that the C++
|
# runs deterministically (verified 20/20 across -O0 and -O2).
|
||||||
# frontend → backend path produces a linkable binary.
|
log "check: MAME runs clang++ -fsjlj-exceptions C++ throw/catch across a call"
|
||||||
log "check: clang++ -fsjlj-exceptions compiles + links a C++ try/catch program"
|
|
||||||
cppExcFile="$(mktemp --suffix=.cpp)"
|
cppExcFile="$(mktemp --suffix=.cpp)"
|
||||||
oCppExcFile="$(mktemp --suffix=.o)"
|
oCppExcFile="$(mktemp --suffix=.o)"
|
||||||
oExcRt="$(mktemp --suffix=.o)"
|
oExcRt="$(mktemp --suffix=.o)"
|
||||||
oExcAbi="$(mktemp --suffix=.o)"
|
oExcAbi="$(mktemp --suffix=.o)"
|
||||||
binCppExcFile="$(mktemp --suffix=.bin)"
|
binCppExcFile="$(mktemp --suffix=.bin)"
|
||||||
cat > "$cppExcFile" <<'EOF'
|
cat > "$cppExcFile" <<'EOF'
|
||||||
|
__attribute__((noinline)) static int deep(int n) {
|
||||||
|
if (n > 3) throw (n * 100 + 7);
|
||||||
|
return deep(n + 1);
|
||||||
|
}
|
||||||
int main(void) {
|
int main(void) {
|
||||||
int ok = 0;
|
int caught = 0;
|
||||||
try { throw 42; } catch (int e) { if (e == 42) ok = 1; }
|
int val = 0;
|
||||||
*(volatile unsigned short *)0x025000 = (unsigned short)ok;
|
try { val = deep(0); }
|
||||||
|
catch (int e) { caught = 1; val = e; }
|
||||||
|
*(volatile unsigned short *)0x025000 = (unsigned short)caught;
|
||||||
|
*(volatile unsigned short *)0x025002 = (unsigned short)val;
|
||||||
while (1) {}
|
while (1) {}
|
||||||
}
|
}
|
||||||
EOF
|
EOF
|
||||||
|
|
@ -5040,6 +5046,10 @@ EOF
|
||||||
"$oExcAbi" "$oExcRt" "$oCppExcFile" >/dev/null 2>&1; then
|
"$oExcAbi" "$oExcRt" "$oCppExcFile" >/dev/null 2>&1; then
|
||||||
die "clang++ -fsjlj-exceptions: C++ try/catch failed to link"
|
die "clang++ -fsjlj-exceptions: C++ try/catch failed to link"
|
||||||
fi
|
fi
|
||||||
|
if ! bash "$PROJECT_ROOT/scripts/runInMame.sh" "$binCppExcFile" --check \
|
||||||
|
0x025000=0001 0x025002=0197 >/dev/null 2>&1; then
|
||||||
|
die "MAME: clang++ C++ throw/catch across a call failed (caught!=1 or value!=0x0197)"
|
||||||
|
fi
|
||||||
rm -f "$cppExcFile" "$oCppExcFile" "$oExcRt" "$oExcAbi" "$binCppExcFile"
|
rm -f "$cppExcFile" "$oCppExcFile" "$oExcRt" "$oExcAbi" "$binCppExcFile"
|
||||||
|
|
||||||
# Real-world: hex dumper using memory-backed file I/O. Reads
|
# Real-world: hex dumper using memory-backed file I/O. Reads
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,9 @@ PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||||
CM_SRC="$SCRIPT_DIR/coremark-src"
|
CM_SRC="$SCRIPT_DIR/coremark-src"
|
||||||
OUT="$SCRIPT_DIR/build"
|
OUT="$SCRIPT_DIR/build"
|
||||||
CLANG="$PROJECT_ROOT/tools/llvm-mos-build/bin/clang"
|
CLANG="$PROJECT_ROOT/tools/llvm-mos-build/bin/clang"
|
||||||
|
# Auto-fall-back to basic regalloc on the single-accumulator deadlock
|
||||||
|
# instead of hard-failing the build -- see scripts/ccRegallocFallback.sh.
|
||||||
|
CC="$PROJECT_ROOT/scripts/ccRegallocFallback.sh"
|
||||||
|
|
||||||
ITERATIONS="${ITERATIONS:-1}"
|
ITERATIONS="${ITERATIONS:-1}"
|
||||||
|
|
||||||
|
|
@ -36,11 +39,11 @@ CFLAGS=(--target=w65816 -O2 -ffunction-sections
|
||||||
CORE_FILES="core_list_join core_main core_matrix core_state core_util"
|
CORE_FILES="core_list_join core_main core_matrix core_state core_util"
|
||||||
for f in $CORE_FILES; do
|
for f in $CORE_FILES; do
|
||||||
echo " CC $f.c"
|
echo " CC $f.c"
|
||||||
"$CLANG" "${CFLAGS[@]}" -c "$CM_SRC/$f.c" -o "$OUT/$f.o"
|
"$CC" "$CLANG" "${CFLAGS[@]}" -c "$CM_SRC/$f.c" -o "$OUT/$f.o"
|
||||||
done
|
done
|
||||||
|
|
||||||
echo " CC core_portme.c"
|
echo " CC core_portme.c"
|
||||||
"$CLANG" "${CFLAGS[@]}" -c "$SCRIPT_DIR/core_portme.c" -o "$OUT/core_portme.o"
|
"$CC" "$CLANG" "${CFLAGS[@]}" -c "$SCRIPT_DIR/core_portme.c" -o "$OUT/core_portme.o"
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "CoreMark built: $(ls "$OUT"/*.o | wc -l) objects, $(du -sh "$OUT" | cut -f1) total"
|
echo "CoreMark built: $(ls "$OUT"/*.o | wc -l) objects, $(du -sh "$OUT" | cut -f1) total"
|
||||||
|
|
|
||||||
|
|
@ -22,17 +22,19 @@ bash tests/lua/runLuaTest.sh # build + link the test wrapper
|
||||||
|
|
||||||
## Caveats
|
## Caveats
|
||||||
|
|
||||||
Three functions (`symbexec` in ldebug.c, `auxsort` in ltablib.c,
|
A few functions (`symbexec` in ldebug.c, `auxsort` in ltablib.c,
|
||||||
`luaV_execute` in lvm.c) hit our greedy register allocator's complexity
|
`luaV_execute` in lvm.c, plus `lstrlib.c` under `--layer2`) exceed what
|
||||||
budget and fail with an `IndexedMap` assertion. Workaround: compile
|
LLVM's `greedy` allocator can place with the 65816's single accumulator
|
||||||
these specific TUs with `-mllvm -regalloc=basic` (the simpler-but-
|
and abort with `ran out of registers during register allocation`. This
|
||||||
slower allocator). Object size with basic-regalloc + -O2 is ~3.5×
|
is a hardware constraint, not a miscompile. `build.sh` handles it
|
||||||
smaller than -O0 (lvm.o: 220KB → 63KB), so this is the preferred
|
automatically: it compiles through `scripts/ccRegallocFallback.sh`, which
|
||||||
fallback over `-O0`.
|
retries an affected TU with `-mllvm -regalloc=basic` (the simpler,
|
||||||
|
always-terminating allocator) only when greedy fails. No per-file list
|
||||||
|
is maintained; a newly register-heavy TU is handled transparently.
|
||||||
|
|
||||||
These three functions are the largest in Lua and exhibit unusual
|
These functions are the largest in Lua and exhibit unusual register
|
||||||
register pressure (luaV_execute is a 30+ case VM dispatch). Greedy
|
pressure (luaV_execute is a 30+ case VM dispatch). See the regalloc
|
||||||
regalloc improvements may eventually handle them.
|
discussion in [`../../LLVM_65816_DESIGN.md`](../../LLVM_65816_DESIGN.md).
|
||||||
|
|
||||||
## Runtime execution status
|
## Runtime execution status
|
||||||
|
|
||||||
|
|
@ -48,7 +50,8 @@ plain shell.
|
||||||
## Files
|
## Files
|
||||||
|
|
||||||
- `lua-5.1.5/` — vendored Lua 5.1.5 source tree (from www.lua.org)
|
- `lua-5.1.5/` — vendored Lua 5.1.5 source tree (from www.lua.org)
|
||||||
- `build.sh` — compile script (handles per-file regalloc tuning)
|
- `build.sh` — compile script (auto-falls-back to basic regalloc via
|
||||||
|
`scripts/ccRegallocFallback.sh` when greedy can't place a TU)
|
||||||
- `luaStubs.c` — `strcoll`, `strxfrm`, `freopen` stubs for missing libc
|
- `luaStubs.c` — `strcoll`, `strxfrm`, `freopen` stubs for missing libc
|
||||||
- `luaTest.c` — minimal Lua API test (sentinel `0xC0DE` if pass)
|
- `luaTest.c` — minimal Lua API test (sentinel `0xC0DE` if pass)
|
||||||
- `runLuaTest.sh` — full build + run wrapper
|
- `runLuaTest.sh` — full build + run wrapper
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,11 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Build Lua 5.1.5 for the W65816 target. Most files compile at -O2;
|
# Build Lua 5.1.5 for the W65816 target. All files compile at -O2. A
|
||||||
# ldebug.c (symbexec) and ltablib.c (auxsort) hit a register-allocation
|
# few functions (symbexec in ldebug.c, auxsort in ltablib.c, luaV_execute
|
||||||
# limit at -O1+ and need -O0. Outputs object files under build/.
|
# in lvm.c, and luaO_str2d-class code in lstrlib.c under --layer2) exceed
|
||||||
|
# what greedy regalloc can do with the 65816's single accumulator and
|
||||||
|
# fall back to basic regalloc automatically -- see
|
||||||
|
# scripts/ccRegallocFallback.sh. No hand-maintained per-file list.
|
||||||
|
# Outputs object files under build/.
|
||||||
|
|
||||||
set -eu
|
set -eu
|
||||||
|
|
||||||
|
|
@ -23,15 +27,7 @@ done
|
||||||
CFLAGS=(-target w65816 -O2 -ffunction-sections -DLUA_USE_C89
|
CFLAGS=(-target w65816 -O2 -ffunction-sections -DLUA_USE_C89
|
||||||
-I "$PROJECT_ROOT/runtime/include" -I "$LUA_SRC"
|
-I "$PROJECT_ROOT/runtime/include" -I "$LUA_SRC"
|
||||||
"${LAYER2[@]}")
|
"${LAYER2[@]}")
|
||||||
# These functions exceed greedy regalloc's complexity budget — fall back
|
CC="$PROJECT_ROOT/scripts/ccRegallocFallback.sh"
|
||||||
# to basic regalloc which is simpler but always terminates. Code is
|
|
||||||
# slower but stays at -O2 so the resulting object is ~3.5× smaller
|
|
||||||
# than -O0 (lvm.o: 220KB → 63KB).
|
|
||||||
SLOW_FILES="ldebug ltablib lvm"
|
|
||||||
if [ ${#LAYER2[@]} -gt 0 ]; then
|
|
||||||
SLOW_FILES="$SLOW_FILES lstrlib"
|
|
||||||
fi
|
|
||||||
SLOW_FLAGS="-mllvm -regalloc=basic"
|
|
||||||
|
|
||||||
# Core Lua: VM, parser, GC, string/table libs. Skip: liolib (no FILE*
|
# Core Lua: VM, parser, GC, string/table libs. Skip: liolib (no FILE*
|
||||||
# backing in mfs-only mode), loslib (no time), loadlib (no dlsym),
|
# backing in mfs-only mode), loslib (no time), loadlib (no dlsym),
|
||||||
|
|
@ -43,19 +39,12 @@ CORE="lapi lcode ldebug ldo ldump lfunc lgc llex lmem lobject lopcodes
|
||||||
|
|
||||||
for f in $CORE; do
|
for f in $CORE; do
|
||||||
o="$OUT/${f}.o"
|
o="$OUT/${f}.o"
|
||||||
cflags=("${CFLAGS[@]}")
|
echo " CC $f.c"
|
||||||
if echo " $SLOW_FILES " | grep -q " $f "; then
|
"$CC" "$CLANG" "${CFLAGS[@]}" -c "$LUA_SRC/${f}.c" -o "$o"
|
||||||
# shellcheck disable=SC2206
|
|
||||||
cflags=("${cflags[@]}" $SLOW_FLAGS)
|
|
||||||
echo " CC $f.c (basic regalloc)"
|
|
||||||
else
|
|
||||||
echo " CC $f.c"
|
|
||||||
fi
|
|
||||||
"$CLANG" "${cflags[@]}" -c "$LUA_SRC/${f}.c" -o "$o"
|
|
||||||
done
|
done
|
||||||
|
|
||||||
# Stubs for libc functions Lua needs that our libc doesn't provide.
|
# Stubs for libc functions Lua needs that our libc doesn't provide.
|
||||||
"$CLANG" "${CFLAGS[@]}" -c "$SCRIPT_DIR/luaStubs.c" -o "$OUT/luaStubs.o"
|
"$CC" "$CLANG" "${CFLAGS[@]}" -c "$SCRIPT_DIR/luaStubs.c" -o "$OUT/luaStubs.o"
|
||||||
echo " CC luaStubs.c"
|
echo " CC luaStubs.c"
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue