-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
[wasm] p/invoke and interop improvements #94446
Conversation
kg
commented
Nov 7, 2023
•
edited
Loading
edited
- Refactor logging in the wasm build tasks to use a LogAdapter helper class that can either write to stdout/stderr or via the msbuild logging APIs
- Refactor ManagedToNativeGenerator so that it can run in either in-process or out-of-process modes (but it still runs in-process right now). This will enable us to pivot to out-of-process in order to pick up function pointer support later on.
- Add support for function pointer types via reflection (so that we can still build and run on net4x for visual studio). Right now the underlying libraries are too old for this support to work, but once the libraries are updated it will.
- Add basic support for structs as arguments
- Implement scalar struct behavior from the wasm C ABI (structs containing one scalar are passed by-value instead of by-reference) in various places in the build tasks, interpreter, and AOT compiler
- Remove a use of varargs pinvoke from SystemNative because it isn't compatible with the WASM C ABI (it's replaced with two non-varargs pinvokes)
- Generate more accurate C signatures for pinvokes
cc @lewing |
Checkpoint Checkpoint Checkpoint Update tests; make fn pointers explicitly blittable on net8 Checkpoint Checkpoint Update test assertions to handle out-of-process line breaking Csproj no longer needed Repair merge damage Blittable structs Fix broken WBT tests Checkpoint wasm ABI Wasm ABI in SignatureMapper Wasm ABI fixes Add test covering most of the weird parts of the wasm ABI (doesn't currently pass) Checkpoint (this is broken) Revert transform.c changes Split test into both AOT and interp variants Checkpoint Checkpoint: scalarized calls seem to work now but the return value causes crashes Update build_args_from_sig to properly support scalarized struct parameters on wasm Fix scalarized struct return values in interp Add missing file
…chitectures, so change to an approach that always works
It looks like SBRP hasn't updated since Jan 5. Is there something I need to do to make the flow happen? Should I just manually do it in this PR? #96989 happened, which I thought would have updated it to a more recent commit, but it didn't. @mthalman EDIT: Looking closer, it looks like the timing was just slightly off, so it missed two deps updates and my PR in SBRP, so I guess that flow was correct. |
@BrzVlad @kotlarmilos @vargaz Any of you feel comfortable reviewing the interp/type system changes here? They're nuanced enough I want to make sure someone with expertise looks them over. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
@@ -4948,6 +4948,8 @@ process_call (EmitContext *ctx, MonoBasicBlock *bb, LLVMBuilderRef *builder_ref, | |||
if (!addresses [call->inst.dreg]) | |||
addresses [call->inst.dreg] = build_alloca_address (ctx, sig->ret); | |||
emit_store (builder, lcall, convert_full (ctx, addresses [call->inst.dreg]->value, pointer_type (LLVMTypeOf (lcall)), FALSE), is_volatile); | |||
load_name = "wasm_vtype_as_scalar"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be WASM only?
/** | ||
* Two specialized overloads for use from Interop.Sys, because these two signatures are not equivalent | ||
* on some architectures (like 64-bit WebAssembly) | ||
*/ | ||
|
||
PALEXPORT int32_t SystemNative_SNPrintF_1S(char* string, int32_t size, const char* format, char* str); | ||
|
||
PALEXPORT int32_t SystemNative_SNPrintF_1I(char* string, int32_t size, const char* format, int arg); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@AaronRobinsonMSFT how did you handle this in runtimelab ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the correct way to handle this scenario. Native varargs at the interop boundary have narrow support in .NET and are exclusive to the Windows platform and typically only for the C++/CLI scenario. See #48796 for broader support.
The approach taken here is to provide an unmanaged export that managed code can call safely which then forwards to a native varargs function. This ensures the unmanaged calling convention is handled correctly during the P/Invoke and correctly at the dispatch to the unmanaged varargs.
It is ugly and not what anyone really wants, but the cost of supporting native varargs is expensive to support. This comes up rarely relative to other interop scenarios so just hasn't been prioritized. The aforementioned issue mentions some of the costs and relevant parties that would need to respond to support.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes perfect sense, just wanted to verify.
@kg please double check the conflict resolution with https://github.com/dotnet/runtime/pull/97643/files#r1483684742 in mind |
Looks right to me, and tests should fail if it's wrong. Thanks for sorting out the merge |
S.T.J failures are known, merging |
<SystemComponentModelAnnotationsVersion>5.0.0</SystemComponentModelAnnotationsVersion> | ||
<SystemDataSqlClientVersion>4.8.6</SystemDataSqlClientVersion> | ||
<SystemDrawingCommonVersion>8.0.0</SystemDrawingCommonVersion> | ||
<SystemIOFileSystemAccessControlVersion>5.0.0</SystemIOFileSystemAccessControlVersion> | ||
<SystemMemoryVersion>4.5.5</SystemMemoryVersion> | ||
<SystemReflectionMetadataVersion>9.0.0-alpha.1.24072.1</SystemReflectionMetadataVersion> | ||
<!-- Keep toolset versions in sync with dotnet/msbuild and dotnet/sdk --> | ||
<SystemReflectionMetadataToolsetVersion>7.0.0</SystemReflectionMetadataToolsetVersion> | ||
<SystemReflectionMetadataLoadContextVersion>7.0.0</SystemReflectionMetadataLoadContextVersion> | ||
<SystemReflectionMetadataToolsetVersion>8.0.0</SystemReflectionMetadataToolsetVersion> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Based on the comment above, this toolset version should not be updated without coordination with msbuild and sdk repos.
@ViktorHofer, FYI, this is blocking the codeflow dotnet/sdk#38665 (while previous change made it to the next phases without problems dotnet/sdk#38553). We can either revert this or update https://github.com/dotnet/sdk/blob/b32df9afff77e8f1afbd417e7c70841867cb6cdc/src/Tasks/Microsoft.NET.Build.Tasks/Microsoft.NET.Build.Tasks.csproj#L75 to 8.0 (if we choose the latter, we can close #96809).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I coordinated with people from the msbuild team at multiple points while developing this along with the SBRP team, so I'm sorry that something fell through the cracks here. Is there a specific step we missed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see now from looking through the replies to Larry's comment on this issue that you told us there. For some reason, GitHub did not send me a notification for your comment, so I didn't see it :( I guess in the future blocking issues like that need to be PR comments instead of replies.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My preference would definitely be to take the bump in the sdk. VS 17.9 is where these changes will ship and it has taken the update.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NP, #96809 is tracking it, but it seems (almost) resolved by your PR. Once confirmed, we can just update sdk's Microsoft.NET.Build.Tasks.csproj#L74-L76 to 8.0 (now that all the related toolings are using 8.0; msbuild, HostModel and VS).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think for this to work, sdk would need to upgrade its .NET Framework leg to a VS 17.9 Preview image (for the updated msbuild binding redirects that allow to unify to an 8.0.0.0 assembly version). I'm not sure if such an image is already available. Worst case, we would need to revert this dependency bump here. @lewing can you please make sure that this dependency flow issue gets resolved: dotnet/sdk#38665?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct me if I'm wrong but the sdk build should be fine, it'd just need the testing legs to use VS17.9 Preview right? That should already be the case: https://github.com/dotnet/sdk/blob/0962c1f89f5daf924a9fe876c80e80b0bde63b0d/.vsts-ci.yml#L108-L111
I'll try bumping the .csproj in the sdk PR and see what happens.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct. Binding redirect unification at run time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like it worked :)