Skip to content

Conversation

@davidwrighton
Copy link
Member

call.tail in the interpreter isn't guaranteed to tail-call in some cases, so we need to put in a ret instruction after the tail-call to ensure that the runtime doesn't execute invalid code. The code for doing a ret is extracted into a helper routine, and now called from both the CEE_JMP and CEE_RET pathways. The only change made to the code was to unify where the ip adjustment was to not happen in the EmitRet logic and instead keep it all in the same place in CEE_RET handling case.

This fixes these test cases on Windows Arm64
JIT/Directed/pinvoke/jump
JIT/Directed/pinvoke/tail_pinvoke

…ling to actually tail call

call.tail in the interpreter isn't guaranteed to tail-call in some cases, so we need to put in a ret instruction after the tail-call to ensure that the runtime doesn't execute invalid code
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adjusts the CLR interpreter’s handling of CEE_RET and CEE_JMP to ensure correct behavior when call.tail does not actually result in a tail call, particularly fixing Windows Arm64 P/Invoke jump/tailcall tests.

Changes:

  • Refactors return emission logic into a shared InterpCompiler::EmitRet helper used by both CEE_RET and CEE_JMP handling.
  • Updates the CEE_RET opcode handling to delegate all return-related code generation to EmitRet, keeping IP and block-linking logic in one place.
  • Tightens CEE_JMP semantics by disallowing its use in synchronized/async methods and by emitting a ret after the tailcall to guard against non-tail-call behavior in the interpreter.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
src/coreclr/interpreter/compiler.h Declares the new EmitRet(CORINFO_METHOD_INFO* methodInfo) helper to centralize return emission logic.
src/coreclr/interpreter/compiler.cpp Implements EmitRet, refactors CEE_RET to use it, and updates CEE_JMP to forbid use in synchronized/async methods and to emit a post-call return to ensure valid control flow even if the tailcall is not honored.

Copy link
Member

@janvorli janvorli left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thank you!

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants