Skip to content
This repository has been archived by the owner on Jan 23, 2023. It is now read-only.

Correctly marshal structure return values in member functions on Win-x64 and Win-x86 #23145

Merged
merged 20 commits into from
Mar 29, 2019

Conversation

jkoritzinsky
Copy link
Member

@jkoritzinsky jkoritzinsky commented Mar 9, 2019

On Windows x86 and x64, if we have a native member function signature with a struct return type, we need to do a by-ref return.

Superscedes #19643
Fixes #19474.

…struct return type, we need to do a by-ref return.
src/vm/ilmarshalers.h Outdated Show resolved Hide resolved
src/vm/dllimport.cpp Outdated Show resolved Hide resolved
src/vm/dllimport.cpp Outdated Show resolved Hide resolved
src/vm/stubgen.h Show resolved Hide resolved
// code:MarshalInfo.MarhalInfo where we do the optimization on x86). We want to throw only if the structure
// is too big to be returned in registers.
if (marshalType != MarshalInfo::MARSHAL_TYPE_BLITTABLEVALUECLASS ||
IsUnmanagedValueTypeReturnedByRef(returnInfo.GetNativeArgSize()))
Copy link
Member Author

Choose a reason for hiding this comment

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

returnInfo.GetNativeArgSize() isn't set up before this, so it was always returning 0, which effectively made this condition equivalent to marshalType != MarshalInfo::MARSHAL_TYPE_BLITTABLEVALUECLASS. So I've simplified the condition and combined it with the below failure condition.

@jkoritzinsky jkoritzinsky changed the title Correctly marshal structure return values in member functions on Win-x64 Correctly marshal structure return values in member functions on Win-x64 and Win-x86 Mar 13, 2019
@jkoritzinsky
Copy link
Member Author

Apparently Ubuntu ARM32 treats returning pointer-to-member-functions differently than pointer-to-nonmember-functions, which is what is causing the Ubuntu ARM32 leg to fail.

Pointers to nonmember functions don't require a return buffer, but pointers to member functions do. I'll see if I can figure out a good way to fit the "is instance method" check in the right place without making the code significantly messy.

@jkoritzinsky
Copy link
Member Author

jkoritzinsky commented Mar 15, 2019

I had forgotten that pointer-to-member functions were really weird (i.e. they aren't actually functions or pointers but implementation-defined structs), which was causing the issue on Ubuntu ARM. So, I've changed the test to dereference into the native vtable of a native object so I can make sure I actually get a function pointer for the test.


bool isInstanceMethod = fStubNeedsCOM || fThisCall;
// We cannot just use pSig.GetReturnType() here since it will return ELEMENT_TYPE_VALUETYPE for enums.
bool isReturnTypeValueType = msig.GetRetTypeHandleThrowing().GetVerifierCorElementType() == ELEMENT_TYPE_VALUETYPE;
#if defined(_TARGET_X86_) || defined(_TARGET_ARM_)
// JIT32 has problems in generating code for pinvoke ILStubs which do a return in return buffer.
Copy link
Member

Choose a reason for hiding this comment

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

Have you looked at what it would take to fix the JIT (or whether the JIT got fixed since this comment was written originally)?

It does not feel right to have all these platform-specific calling convention details replicated here.

Copy link
Member Author

Choose a reason for hiding this comment

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

I have not looked into the JIT side of this yet. I'll investigate to see if RyuJIT fixed some of this.

Copy link
Member Author

Choose a reason for hiding this comment

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

RyuJIT has not done any work to fix this, presumably since the interop space was already working around the limitation when RyuJIT was created.

@dotnet/jit-contrib any ideas on what it would take to support the easy case of x86 return buffers for non-member functions?

@jkotas
Copy link
Member

jkotas commented Mar 16, 2019

Do we have ability to run IJW test suite from the C++ compiler team? It has extensive coverage for the thiscall calling convention. It may be worth running it on this change (on both x86 and x64).

@jkoritzinsky
Copy link
Member Author

We'd have to port over each test individually into our test tree and set it up to run like we currently run IJW tests. So it's possible, but not simple copy-paste.

@jkotas
Copy link
Member

jkotas commented Mar 18, 2019

I did not mean to port the tests over. I meant to run the tests from the managed C++ compiler test suite where they currently are. I believe the C++ compiler team has ability to do that - otherwise, they would not be able to sign off on .NET Core support for managed C++.

@jkoritzinsky
Copy link
Member Author

We can't run the managed C++ compiler test suite in mixed-mode currently until we get #22636 and dotnet/core-setup#5185 both merged in and the C++ compiler team updates the compiler to link to the new ijwhost.dll unless we want to bin-edit the test binaries to point to ijwhost instead of mscoree.

@jkoritzinsky
Copy link
Member Author

@dotnet-bot test Ubuntu x64 Checked Innerloop Build and Test (Jit - TieredCompilation=0)
@dotnet-bot test OSX10.12 x64 Checked Innerloop Build and Test

@jkoritzinsky
Copy link
Member Author

@dotnet-bot test OSX10.12 x64 Checked Innerloop Build and Test

@jkoritzinsky
Copy link
Member Author

Test failures are due to #23534 as far as I can tell.

I'm going to merge this in and file a tracking issue for moving some of the return-buffer logic to the JIT.

@jkoritzinsky jkoritzinsky merged commit 6b889ab into dotnet:master Mar 29, 2019
@jkoritzinsky jkoritzinsky deleted the coreclr/19474 branch March 29, 2019 16:49
buyaa-n pushed a commit to buyaa-n/coreclr that referenced this pull request Apr 1, 2019
…x64 and Win-x86 (dotnet#23145)

* In Windows-x64, if we have a native member function signature with a struct return type, we need to do a by-ref return.

* Implement support for marshalling structure return values via a return buffer argument correctly in instance signatures on AMD64-Windows.

* Change field initialization ordering to satisfy warning.

* Try to narrow down the conditions that trigger these changes to just COM methods.

* Don't bash the return type on AMD64 Windows. Only treat it as a byref return buffer.

* PR feedback.

* Enable returning structs from COM methods via a return buffer on x86 for structs <= 8 bytes.

* Add test for struct returns with ThisCall. Extend the "struct return buffer" fix to functions marked as unmanaged thiscall since they all must be instance methods

* Don't include the return-type-bashing switch on AMD64 platforms.

* Don't do the signature swapping/copy on non-instance functions with struct returns.

* Cast the return type of GetStubTargetCallingConv to the right calling convention enum type.

* If we're doing a thiscall, marshal the "this" parameter before the return buffer (if the return buffer exists) on all platforms.

* Remove temporary logging code I added in for debugging.

* Clean up class naming.

* Try using a vtable instead of a pointer-to-member-function.

* Remove delete of class with non-virtual destructor
picenka21 pushed a commit to picenka21/runtime that referenced this pull request Feb 18, 2022
…x64 and Win-x86 (dotnet/coreclr#23145)

* In Windows-x64, if we have a native member function signature with a struct return type, we need to do a by-ref return.

* Implement support for marshalling structure return values via a return buffer argument correctly in instance signatures on AMD64-Windows.

* Change field initialization ordering to satisfy warning.

* Try to narrow down the conditions that trigger these changes to just COM methods.

* Don't bash the return type on AMD64 Windows. Only treat it as a byref return buffer.

* PR feedback.

* Enable returning structs from COM methods via a return buffer on x86 for structs <= 8 bytes.

* Add test for struct returns with ThisCall. Extend the "struct return buffer" fix to functions marked as unmanaged thiscall since they all must be instance methods

* Don't include the return-type-bashing switch on AMD64 platforms.

* Don't do the signature swapping/copy on non-instance functions with struct returns.

* Cast the return type of GetStubTargetCallingConv to the right calling convention enum type.

* If we're doing a thiscall, marshal the "this" parameter before the return buffer (if the return buffer exists) on all platforms.

* Remove temporary logging code I added in for debugging.

* Clean up class naming.

* Try using a vtable instead of a pointer-to-member-function.

* Remove delete of class with non-virtual destructor




Commit migrated from dotnet/coreclr@6b889ab
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants