Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JIT: Support frozen structs for Swift pinvokes #99294

Merged
merged 33 commits into from
Mar 13, 2024

Conversation

jakobbotsch
Copy link
Member

@jakobbotsch jakobbotsch commented Mar 5, 2024

Add support for decomposing structs in Swift pinvokes. Reverse pinvokes are not yet handled, and multireg returns also aren't yet handled.

Also add 100 auto generated Swift ABI stress tests.

@dotnet-issue-labeler dotnet-issue-labeler bot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label Mar 5, 2024
@ghost ghost assigned jakobbotsch Mar 5, 2024
@ghost
Copy link

ghost commented Mar 5, 2024

Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
See info in area-owners.md if you want to be subscribed.

Issue Details

Add support for decomposing structs in Swift pinvokes. Reverse pinvokes are not yet handled, and multireg returns also aren't yet handled.

Only works with crossgen2/ILC since that's the only places getSwiftLowering has an implementation.

Also add a bunch of auto generated Swift ABI stress tests. Currently 5000 tests, but I plan to reduce it to a much smaller set once everything is passing (it currently isn't).

Author: jakobbotsch
Assignees: -
Labels:

area-CodeGen-coreclr

Milestone: -

@jakobbotsch

This comment was marked as outdated.

@jkoritzinsky
Copy link
Member

I put a PR out with the fix.

@jakobbotsch
Copy link
Member Author

Closing this temporarily to avoid running CI needlessly...

@jakobbotsch jakobbotsch closed this Mar 6, 2024
@jakobbotsch

This comment was marked as outdated.

@jakobbotsch
Copy link
Member Author

jakobbotsch commented Mar 6, 2024

@jkoritzinsky I auto generated 5000 tests in the ExpectedLowering format (structs passed by reference are represented without any elements): https://gist.github.com/jakobbotsch/675a9f8cf54ae5603b8fa258b6ae1e1d (has both a .cs and a .swift file that was used to extract swiftc's lowering)

@jkoritzinsky
Copy link
Member

I'll pull those into the unit testing harness and fix the failing cases. Thanks for generating them!

@jakobbotsch jakobbotsch reopened this Mar 11, 2024
{
SwiftLoweringInterval& lastInterval = mergedIntervals[mergedIntervals.Size() - 1];
lastInterval.size = interval.offset + interval.size - lastInterval.offset;
continue;
}
Copy link
Member Author

Choose a reason for hiding this comment

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

This logic didn't add any interval to mergedIntervals when this check failed.

}

// Now we have the intervals, we can calculate the lowering.
CorInfoType loweredTypes[MAX_SWIFT_LOWERED_ELEMENTS];
uint32_t offsets[MAX_SWIFT_LOWERED_ELEMENTS];
uint32_t numLoweredTypes = 0;

for (uint32_t i = 0; i < mergedIntervals.Size(); i++, numLoweredTypes++)
for (uint32_t i = 0; i < mergedIntervals.Size(); i++)
Copy link
Member Author

Choose a reason for hiding this comment

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

Incrementing numLoweredTypes here would result in one extra increment for the opaque intervals.

@jakobbotsch jakobbotsch marked this pull request as ready for review March 12, 2024 14:53
@jakobbotsch
Copy link
Member Author

cc @dotnet/jit-contrib PTAL @amanasifkhalid (JIT parts) @jkoritzinsky (VM changes)

FYI @kotlarmilos @matouskozak

I tested with 5000 auto generated tests and they all pass with this PR with both crossgen2 and corerun. The PR here includes only 100 of the stress tests to avoid checking in hundreds of thousands of lines of test code.

I added an IMPL_LIMITATION when we see SIMDs since they are unsupported for now (by both the JIT and the lowering).

The approach taken here is that we expand the frozen structs into the primitive arguments during import. In that way we guarantee no structs are left in the signature, and also that we are able to handle everything efficiently.

Frozen struct returns and reverse pinvokes also remain to be supported. I'm going to work on the returns next, but I want to do that in a separate PR.

Copy link
Member

@amanasifkhalid amanasifkhalid left a comment

Choose a reason for hiding this comment

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

JIT changes LGTM -- thanks for cleaning up the SwiftSelf quirks, too

arg.SetWellKnownArg(WellKnownArg::SwiftSelf);
CORINFO_SWIFT_LOWERING* lowering = lowerings[argIndex];

if (lowering == nullptr)
Copy link
Member

Choose a reason for hiding this comment

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

(lowering == nullptr) indicates that either the arg should be passed by reference, or that we never called getSwiftLowering for this arg (because it's a SwiftSelf, or it's not a value type), as the lowerings array is zero-initialized, right? It would sacrifice some perf, but this might read better if we always save the result of getSwiftLowering and check lowering->byReference here instead; that way, we know getSwiftLowering was never called for this arg if lowerings[argIndex] == nullptr, and can assert on it.

I don't have a strong preference on this, though.

Copy link
Member Author

Choose a reason for hiding this comment

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

The SwiftSelf case is handled before we get here, but other than that you're right, lowering == nullptr here means that the arg is passed by reference. I'll switch it to always save the lowerings for all the struct args and add an assert -- I agree that seems better.

Copy link
Member

@jkoritzinsky jkoritzinsky left a comment

Choose a reason for hiding this comment

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

CoreCLR changes look good. Some comments on test infrastructure.

using System.Runtime.InteropServices.Swift;
using Xunit;

public class SwiftAbiStress
Copy link
Member

Choose a reason for hiding this comment

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

Let's add this test to the Interop.csproj project directly and use the following attributes to do the correct test filtering (instead of issues.targets and the csproj filtering).

You'll also need to add a CMakeProjectReference to the CMakeLists..txt in this folder from Interop.csproj.

Suggested change
public class SwiftAbiStress
[PlatformSpecific(TestPlatforms.OSX | TestPlatforms.iOS | TestPlatforms.tvOS)]
[ActiveIssue("https://github.com/dotnet/runtime/issues/94081", TestRuntimes.Mono)]
public class SwiftAbiStress

Copy link
Member Author

Choose a reason for hiding this comment

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

Does it look good now?
I assume we'll want to put the other Swift tests under the same plan too (although let's do it separately from this PR).

Copy link
Member

Choose a reason for hiding this comment

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

The change looks great, but it looks like there's some issues with a folder that only has targets on some platforms. I don't want to make you do the infra work to make this work correctly, so you can revert these changes.

We'll do it (for these tests and the other Swift tests) in a follow-up PR.

@jakobbotsch jakobbotsch merged commit 9843659 into dotnet:main Mar 13, 2024
125 checks passed
@jakobbotsch jakobbotsch deleted the swift-abi branch March 13, 2024 10:15
@github-actions github-actions bot locked and limited conversation to collaborators Apr 13, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants