| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Sorry, something went wrong.
|
/azp run runtime-extra-platforms |
Sorry, something went wrong.
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
Sorry, something went wrong.
|
Azure Pipelines: Successfully started running 3 pipeline(s). 13 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
Sorry, something went wrong.
|
Tagging subscribers to this area: @steveisok, @vitek-karas |
Sorry, something went wrong.
There was a problem hiding this comment.
This PR expands the existing Swift interop test asset to add additional ABI/calling-convention stress cases around SwiftError placement, and wires them up from C# via Swift-callconv P/Invokes with new xUnit tests to exercise those scenarios on Apple platforms.
Changes:
| File | Description |
|---|---|
| src/tests/Interop/Swift/SwiftErrorHandling/SwiftErrorHandling.swift | Adds new exported Swift entry points and hashing helpers to exercise ABI argument placement while still returning a deterministic value. |
| src/tests/Interop/Swift/SwiftErrorHandling/SwiftErrorHandling.cs | Adds marshaling types, new Swift-callconv P/Invokes, and new xUnit tests to validate the ABI scenarios end-to-end. |
Sorry, something went wrong.
|
/azp run runtime-extra-platforms |
Sorry, something went wrong.
|
Azure Pipelines: Successfully started running 1 pipeline(s). |
Sorry, something went wrong.
There was a problem hiding this comment.
src/tests/Interop/Swift/SwiftErrorHandling/SwiftErrorHandling.cs:173
[Fact]
public static unsafe void TestSwiftErrorInFirstStackSlotNotThrown()
{
SwiftError error = new SwiftError();
int i = 0;
int result = (int)conditionallyThrowErrorInFirstStackSlot(0, i + 1, i + 2, i + 3, i + 4, i + 5, i + 6, i + 7, ref error);
Assert.True(error.Value == null, "No Swift error was expected to be thrown.");
Assert.True(result == 42, "The result from Swift does not match the expected value.");
}
src/tests/Interop/Swift/SwiftErrorHandling/SwiftErrorHandling.cs:178
byte* values = stackalloc byte[6];
Sorry, something went wrong.
There was a problem hiding this comment.
src/tests/Interop/Swift/SwiftErrorHandling/SwiftErrorHandling.cs:177
[Fact]
public static unsafe void TestSwiftErrorInFirstStackSlotNotThrown()
{
SwiftError error = new SwiftError();
int i = 0;
int result = (int)conditionallyThrowErrorInFirstStackSlot(0, i + 1, i + 2, i + 3, i + 4, i + 5, i + 6, i + 7, ref error);
Assert.True(error.Value == null, "No Swift error was expected to be thrown.");
Assert.True(result == 42, "The result from Swift does not match the expected value.");
}
src/tests/Interop/Swift/SwiftErrorHandling/SwiftErrorHandling.cs:210
byte* values = stackalloc byte[6];
src/mono/mono/mini/mini-amd64.c:1134
if (sig->pinvoke) {
ainfo->reg = GINT32_TO_UINT8 (AMD64_R12);
ainfo->swift_error_in_reg = TRUE;
} else {
add_general (&gr, &stack_size, ainfo);
ainfo->swift_error_in_reg = ainfo->storage == ArgInIReg;
}
ainfo->storage = ArgSwiftError;
Sorry, something went wrong.
|
Azure Pipelines: Successfully started running 4 pipeline(s). 12 pipeline(s) were filtered out due to trigger conditions. There may be pipelines that require an authorized user to comment /azp run to run. |
Sorry, something went wrong.
|
@BrzVlad @matouskozak can one you please review? |
Sorry, something went wrong.
There was a problem hiding this comment.
Overall looking good to me, just one question around the new ArgInfo field.
I've run it locally on arm64 macOS and without this change I'm getting NullReferenceException and passes with this change.
fyi: @dalexsoto since you're now working on this domain
Sorry, something went wrong.
| Back | FazBrowse Home | New Git URL |
There appear to be two problems with the Swift calling convention implementation in Mono for how it handles SwiftError.
On x64, structs can spill to the stack while a later scalar argument still has an available register. Consequently, SwiftError can be register passed while carrying a nonzero accumulated stack offset. Mono mistakes that offset for a stack location and reads an invalid pointer.
On ARM64, the first argument placed on the stack naturally has offset zero. Mono mistakes that stack location for a register passed argument and uses the wrong value. offset == 0 is ambiguous: it can mean either "passed in a register" or "passed in the first stack slot." Right now it doesn't look like it can tell the difference.
The fix records whether SwiftError was originally passed in a register before replacing its argument classification with ArgSwiftError, rather than inferring its location from the stack offset. On x64, stack-passed SwiftError arguments also disable frame-pointer omission so their incoming stack slots remain addressable.
The tests that have been added would fail without the fixes, and I confirmed this locally on an x64 macOS 26 machine.
This was originally found in #131630, where changes at the p/invoke boundary caused the SwiftError to be identified as register passed but carried a nonzero accumulated stack offset because preceding two word buffer structs had spilled.
This is a follow up to #103043, where it appears the fix was incomplete.