makepad/libs/relax/compiler/bench_rt/interp/unwind_cmp.py
Admin b22a714840 makepad run: the Rust JIT (libs/relax) and makepad-remote
The JIT that runs makepad apps from source: lexer, front end, type checker,
lazy borrow checker (Gandalf; `--check-first` opts in), codegen, session and
warm/cold caches keyed by compiler stamp, provided crates bound late,
startup images, live patching. User-facing name is `makepad run` (binary
`makepad`, MAKEPAD_RUN_* env, ~/.makepad-run); libs/relax stays the internal
library name. `makepad check` reports rustc-style diagnostics with rustc
error codes and checks a whole workspace (`--workspace`). Runs on macOS,
Linux, Windows and Android. makepad-remote: one tool schema for apps and the
WM (app/1): grabs, captures, traces, frame profiles and tweaks.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-13 12:26:21 +02:00

71 lines
3.6 KiB
Python

#!/usr/bin/env python3
"""Drop order of panics through interpreted / JIT / native frames, against rustc.
usage: unwind_cmp.py <makepad binary> [test file ...]
Default test files: the interp_unwind*.rs fixtures and the existing drop/unwind fixtures (relative to
libs/relax/compiler); files named *_abort_* must abort the process everywhere.
tests/interp_unwind_abort_ffi.rs: a panic leaving an `extern "C"` body that C called (qsort's
comparator) aborts, as under rustc (lower.rs abort_unwinding_calls). Each file is built with
`rustc --test` and run (the reference), then run by `makepad test` with the JIT and with the
interpreter in several mixes; the "| " lines must be identical (compared as sorted sets per run,
since test threads may interleave). Exit status 1 on any difference.
"""
import os, subprocess, sys, tempfile
here = os.path.dirname(os.path.abspath(__file__))
comp = os.path.normpath(os.path.join(here, "../.."))
mk = os.path.abspath(sys.argv[1])
files = sys.argv[2:] or ["tests/interp_unwind.rs", "tests/interp_unwind_abort_cleanup.rs", "tests/interp_unwind_abort_ffi.rs", "tests/unwind_drops.rs", "tests/drop_order_scopes.rs", "tests/let_chain_drops.rs", "tests/jump_temp_drops.rs", "tests/drop_elab_flags.rs", "tests/thread_panic.rs", "tests/unwind_nested_catch_restore.rs"]
MODES = [
("jit", {}),
("interp-all", {"MAKEPAD_RUN_INTERP": "all"}),
("interp-xi", {"MAKEPAD_RUN_INTERP": "::xi_"}),
("interp-xj", {"MAKEPAD_RUN_INTERP": "::xj_,{closure"}),
("interp-std", {"MAKEPAD_RUN_INTERP": "std::,core::,alloc::"}),
("nocodegen", {"MAKEPAD_RUN_NO_CODEGEN": "1"}),
]
if os.environ.get("MODES"):
MODES = [m for m in MODES if m[0] in os.environ["MODES"].split(",")]
def lines(text):
out = []
for l in text.splitlines():
k = l.find("| ")
if k >= 0 and not l.lstrip().startswith("report:"):
out.append(l[k:].rstrip())
return sorted(out)
bad = 0
tmp = tempfile.mkdtemp()
for f in files:
path = os.path.join(comp, f)
exe = os.path.join(tmp, os.path.basename(f)[:-3])
r = subprocess.run(["rustc", "--edition", "2021", "-O", "--test", path, "-o", exe], capture_output=True, text=True)
if r.returncode != 0 and "Rust 2024" in r.stderr:
r = subprocess.run(["rustc", "--edition", "2024", "-O", "--test", path, "-o", exe], capture_output=True, text=True)
if r.returncode != 0:
print("rustc failed for", f, r.stderr[-600:])
bad += 1
continue
rr = subprocess.run([exe, "--test-threads=1", "--nocapture"], capture_output=True, text=True)
ref = lines(rr.stdout)
# files named *_abort_*: the process must abort (SIGABRT) everywhere, without "| " lines
aborts = "_abort_" in os.path.basename(f)
if aborts and rr.returncode != -6:
print("%-42s rustc did not abort (rc %d)" % (f, rr.returncode))
bad += 1
for name, env in MODES:
e = dict(os.environ, MAKEPAD_RUN_CACHE="off", **env)
p = subprocess.run(["nice", "-n", "5", mk, "test", path], cwd=comp, env=e, capture_output=True, text=True, timeout=900)
got = lines(p.stdout + p.stderr)
ok = got == ref and (p.returncode in (-6, 134) if aborts else p.returncode == 0)
print("%-42s %-11s %s (%d lines, rc %d)" % (f, name, "SAME" if ok else "DIFF", len(got), p.returncode), flush=True)
if not ok:
bad += 1
for l in sorted(set(ref) - set(got)):
print(" rustc only:", l)
for l in sorted(set(got) - set(ref)):
print(" run only: ", l)
if p.returncode != 0:
print(" tail:", (p.stdout + p.stderr)[-800:].replace("\n", "\n "))
sys.exit(1 if bad else 0)