Skip to content

codegen: safety fallback + entry-slice boundary fix for truncated functions (#86)#109

Closed
jlsandri wants to merge 1 commit intoran-j:mainfrom
jlsandri:pr/codegen-truncated-function-fallback
Closed

codegen: safety fallback + entry-slice boundary fix for truncated functions (#86)#109
jlsandri wants to merge 1 commit intoran-j:mainfrom
jlsandri:pr/codegen-truncated-function-fallback

Conversation

@jlsandri
Copy link
Copy Markdown

@jlsandri jlsandri commented Apr 6, 2026

Addresses #86. Two small, independent fixes for functions whose last instruction is not jr \$ra — either because the source really lacks a tail return, or because the imported function boundary is wrong and the real jr \$ra lives past the reported end.

Fix 1 — Implicit safety fallback at function end (code_generator.cpp)

Emit an implicit

ctx->pc = GPR_U32(ctx, 31);
return;

at the end of every generated function body.

  • For well-formed functions this is unreachable dead code (the preceding jr \$ra already returned).
  • For functions with incorrect boundaries, it returns cleanly via \$ra instead of leaving ctx->pc at whatever value the last fall-through instruction set, which previously caused cascading wrong returns up the call chain.

Fix 2 — Skip boundary starts inside a containing parent (ps2_recompiler.cpp)

When reslicing entry functions, skip any boundary start that falls inside the range of the containing parent function.

Ghidra-style sub_xxx children inside a parent were creating "boundary" entries that truncated sibling entry slices before their jr \$ra, producing half-functions that would fall off the end at runtime.

Scope

  • ps2xRecomp/src/lib/code_generator.cpp: +6 / -0
  • ps2xRecomp/src/lib/ps2_recompiler.cpp: +13 / -1
  • No change in behaviour for correct inputs.

…y fix

Two fixes for functions that end without jr $ra (issue ran-j#86):

1. code_generator.cpp: Emit implicit `ctx->pc = GPR_U32(ctx, 31); return;`
   at end of every generated function. For correct functions this is
   unreachable dead code. For functions with wrong TOML/CSV boundaries, it
   returns via $ra instead of leaving ctx->pc in a bad state that cascades
   returns up the entire call chain.

2. ps2_recompiler.cpp: When reslicing entry functions, skip boundary starts
   that fall inside the containing parent function. Ghidra sub-functions
   (sub_xxx) inside a parent were creating false boundaries that truncated
   sibling entry slices before their jr $ra.
@jlsandri jlsandri force-pushed the pr/codegen-truncated-function-fallback branch from fcc74e6 to 2584583 Compare April 6, 2026 08:56
@jlsandri
Copy link
Copy Markdown
Author

jlsandri commented Apr 6, 2026

Closing as part of a batch cleanup after #107 landed. The runtime ecosystem refactor in #107 substantially reworked the files this PR touched, and I would like to re-audit the underlying fix against the new code structure before putting it back in front of you. If the fix is still needed after that re-audit, I will re-open as a focused PR rebased onto current main. Thanks for your patience.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant