[clr-interp] Add Swift calling convention support to CoreCLR interpreter on arm64#123142
Merged
kotlarmilos merged 37 commits intodotnet:mainfrom Feb 5, 2026
Merged
Conversation
…ift calling convention
Contributor
|
Tagging subscribers to this area: @BrzVlad, @janvorli, @kg |
This was referenced Jan 14, 2026
Open
janvorli
reviewed
Jan 15, 2026
3 tasks
janvorli
reviewed
Jan 30, 2026
Member
Author
|
@davidwrighton @janvorli This PR is ready for review, please take a look |
janvorli
approved these changes
Feb 3, 2026
Member
janvorli
left a comment
There was a problem hiding this comment.
LGTM modulo the comments on adding some ifdefs.
davidwrighton
added a commit
that referenced
this pull request
Feb 4, 2026
## Description
Converts interpreter call stub logging from compile-time `#if
LOG_COMPUTE_CALL_STUB` blocks to runtime-controllable LOG2 facility.
These logging statements have proven valuable for debugging but required
recompilation to enable.
## Changes
- Added `LF2_INTERPRETER = 0x00000002` to LogFacility2 enum
- Converted 26 logging instances to `LOG2((LF2_INTERPRETER,
LL_INFO10000, ...))`
- Removed `#define LOG_COMPUTE_CALL_STUB 0`
- Updated `INVOKE_FUNCTION_PTR` and `RETURN_TYPE_HANDLER` macros
### Before
```cpp
#define LOG_COMPUTE_CALL_STUB 0
PCODE GetGPRegRangeRoutine(int r1, int r2)
{
#if LOG_COMPUTE_CALL_STUB
printf("GetGPRegRangeRoutine %d %d\n", r1, r2);
#endif
// ...
}
```
### After
```cpp
PCODE GetGPRegRangeRoutine(int r1, int r2)
{
LOG2((LF2_INTERPRETER, LL_INFO10000, "GetGPRegRangeRoutine %d %d\n", r1, r2));
// ...
}
```
Logging now enabled via: `DOTNET_LogFacility2=0x2 DOTNET_LogLevel=10000`
<!-- START COPILOT ORIGINAL PROMPT -->
<details>
<summary>Original prompt</summary>
>
> ----
>
> *This section details on the original issue you should resolve*
>
> <issue_title>[clr-interp] Convert logging in call stubs to use logging
facility</issue_title>
> <issue_description>I think we should convert it to the LOG mechanism.
When I wrote these logging statements, I had thought they would likely
be very temporary, but I've used them 4-5 times since then, so they have
some ongoing value. However, I'd like to see that work done in a
separate PR. We should convert them to using LOG statements probably
with a new LF enum value. Probably what should be done is add a new log
facility enum in log.h, call it LF2_INTERPRETER. And convert these log
statements to use the LOG2 macro, with info level LL_INFO10000 instead
of wrapping them in #if LOG_COMPUTE_CALL_STUB blocks.
>
> _Originally posted by @davidwrighton in
#123142 (comment)
> </issue_description>
>
> ## Comments on the Issue (you are @copilot in this section)
>
> <comments>
> </comments>
>
</details>
<!-- START COPILOT CODING AGENT SUFFIX -->
- Fixes #123272
<!-- START COPILOT CODING AGENT TIPS -->
---
✨ Let Copilot coding agent [set things up for
you](https://github.com/dotnet/runtime/issues/new?title=✨+Set+up+Copilot+instructions&body=Configure%20instructions%20for%20this%20repository%20as%20documented%20in%20%5BBest%20practices%20for%20Copilot%20coding%20agent%20in%20your%20repository%5D%28https://gh.io/copilot-coding-agent-tips%29%2E%0A%0A%3COnboard%20this%20repo%3E&assignees=copilot)
— coding agent works faster and does higher quality work when set up for
your repo.
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: davidwrighton <10779849+davidwrighton@users.noreply.github.com>
Co-authored-by: David Wrighton <davidwr@microsoft.com>
Member
Author
|
/ba-g ios-arm64 failure is #123796 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Swift uses a calling convention that differs from the standard arm64 ABI. This PR extends the CoreCLR interpreter so that it can correctly call Swift functions on arm64. The changes are limited to call stub generation and includes Swift-specific register usage, argument lowering, and return value lowering.
SwiftSelf and SwiftSelf<T>
Swift instance methods pass
selfin a dedicated register (x20on arm64) rather than as a regular argument. InComputeCallStubWorkerwhen SwiftSelf in encountered, it emits routine for loading argument intox20before the call.When SwiftSelf<T> is encountered and not lowered according to the Swift value type lowering, it emits routine for loading address of struct into
x20before the call. If struct T can be lowered, it is processed as normal lowered argument as described below.SwiftError
Swift error is returned via dedicated register (
x21on arm64) when a call returns. It is passed as byref argument where is expected to load error reg into that bytrerf arg when call returns. It is done by:SwiftIndirectResult
Swift returns non-lowered structs indirectly via a dedicated register (
x8on arm64). InComputeCallStubWorkerwhen SwiftIndirectResult in encountered, it emits routine for loading argument intox8before the call. Then the callee writes the return value to the memory provided in the argument.Lowering of value types in arguments
Swift lowers structs into individual primitive arguments when they fit within four machine words. Consider the following struct:
A Swift function
swiftFunc(int a, F3_S4 b, float c)is lowered toswiftFunc(int a, nuint b_0, float b_1, ushort b_2, float c)The signature is first rewritten into lowered form. This enables correct register and stack allocation, but introduces a problem. When loading lowered arguments into registers or stack, the standard routines assume 8-byte alignment on the interpreter stack, which is not always true for fields within lowered structs.
For example, the loader routine reads
F0into a register and advances the argument pointer by 8 bytes. It then loadsF1and again advances by 8 bytes (including 4 bytes of padding). This is incorrect becauseF1is at offset 8, andF2is at offset 12To fix that, new load routines are introduced for Swift-lowered arguments:
[x9 + offset]without advancing the interpreter argument pointerLowering of return value types
Swift lowers struct return values into multiple registers (both GP and FP). This is done by collecting return registers after the call and reconstructing the original struct layout. When a lowered struct return is detected in
ComputeCallStubWorker, additional post-call routines are emitted to load the return value into the managed return buffer. To implement this, a new return stubInterpreterStubRetSwiftLoweredis introduced. This stub stores the return registers (GP0–GP4 and FP0–FP4) into a contiguous temporary buffer immediately after the call returns.A new call stub
CallJittedMethodRetSwiftLoweredis introduced to allow for execution of routines after the target call. Based on the computed lowering, a sequence of post-call routines is emitted. These routines copy each lowered field from the temporary buffer into the return struct at the correct offsets. ASwiftLoweredReturnTerminatorroutine is added at the end to branch back to the epilog.Out of scope
x64andUnmanagedCallersOnlyare currently not supported and will be added in a follow-up.Contributes to #120049