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

[wasm] p/invoke and interop improvements #94446

Merged
merged 38 commits into from
Feb 9, 2024
Merged

[wasm] p/invoke and interop improvements #94446

merged 38 commits into from
Feb 9, 2024

Conversation

kg
Copy link
Contributor

@kg kg commented Nov 7, 2023

  • 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

@kg
Copy link
Contributor Author

kg commented Nov 7, 2023

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
@kg
Copy link
Contributor Author

kg commented Jan 18, 2024

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.

@kg
Copy link
Contributor Author

kg commented Feb 2, 2024

@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.

Copy link
Member

@kotlarmilos kotlarmilos left a 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";
Copy link
Member

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?

Comment on lines +19 to +26
/**
* 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);
Copy link
Member

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 ?

Copy link
Member

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.

Copy link
Member

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.

@lewing
Copy link
Member

lewing commented Feb 9, 2024

@kg please double check the conflict resolution with https://github.com/dotnet/runtime/pull/97643/files#r1483684742 in mind

@kg
Copy link
Contributor Author

kg commented Feb 9, 2024

@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

@kg
Copy link
Contributor Author

kg commented Feb 9, 2024

S.T.J failures are known, merging

@kg kg merged commit ed9f475 into dotnet:main Feb 9, 2024
188 of 191 checks passed
<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>
Copy link
Member

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).

Copy link
Contributor Author

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?

Copy link
Contributor Author

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.

Copy link
Member

@lewing lewing Feb 10, 2024

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.

cc @ViktorHofer @marcpopMSFT

Copy link
Member

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).

Copy link
Member

@ViktorHofer ViktorHofer Feb 11, 2024

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?

Copy link
Member

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.

Copy link
Member

@ViktorHofer ViktorHofer Feb 12, 2024

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.

Copy link
Member

Choose a reason for hiding this comment

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

Looks like it worked :)

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.

10 participants