From 2019ff866bf3660a35eaa4b20941b87295e93e7f Mon Sep 17 00:00:00 2001 From: seedds Date: Mon, 26 Oct 2026 14:46:10 +0800 Subject: [PATCH] Recognize framed pointer tail calls safely (#256) Preserve the existing terminal-tail recognizer and accept a contiguous framed method-pointer thunk followed by its separate null-error call. Reject stores that overwrite saved FP/LR, unproven store addresses and stack/frame/link-register clobbers, including WSP. Stores are limited to fixed caller stack-argument slots above the saved frame. Keep the fallback narrower than #188's proposed unframed block recognition. Add synthetic AArch64 regressions and document the rule beside the other tail-call findings; no game-specific IDs, fixed addresses or profile changes. Validation: 179 tool tests run, 174 passed and 5 skipped; 10 tail-call tests pass; the legacy terminal recognizer is AST-identical to main; git diff --check passes. Real game modules were not rewritten for this integration. Co-authored-by: chengjie --- dm/tools/patch_nso.py | 38 ++++++++++- dm/tools/tests/test_tail_call.py | 108 +++++++++++++++++++++++++++++++ docs/agents/symptoms.md | 1 + docs/reference/rewriter.md | 8 +++ 4 files changed, 154 insertions(+), 1 deletion(-) create mode 100644 dm/tools/tests/test_tail_call.py diff --git a/dm/tools/patch_nso.py b/dm/tools/patch_nso.py index 7b2f2eb..f0b6bf8 100644 --- a/dm/tools/patch_nso.py +++ b/dm/tools/patch_nso.py @@ -738,7 +738,7 @@ def jump_masked_pred(insl, j): t = [tb + struct.unpack_from('