dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
14.87k stars 4.63k forks source link

NativeAOT: exportable static fields support #88598

Open RalfKornmannEnvision opened 1 year ago

RalfKornmannEnvision commented 1 year ago

To use the DirectX12 Agility SDK the executable needs to export two constants

https://devblogs.microsoft.com/directx/gettingstarted-dx12agility/#parametersa

Currently it is only possible to export methods by using the UnmanagedCallersOnly attribute

https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.unmanagedcallersonlyattribute?view=net-7.0

It's possible to export constants from a native AOT executable by linking it with a static lib that contains these. But you need to make sure that anything else in this lib is actually used so that the linker does not drop it.

It would be nice if there would be a way to have these constants directly in a C# code file instead.

teo-tsirpanis commented 1 year ago

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

ghost commented 1 year ago

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

Issue Details
To use the DirectX12 Agility SDK the executable needs to export two constants https://devblogs.microsoft.com/directx/gettingstarted-dx12agility/#parametersa Currently it is only possible to export methods by using the UnmanagedCallersOnly attribute https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.unmanagedcallersonlyattribute?view=net-7.0 It's possible to export constants from a native AOT executable by linking it with a static lib that contains these. But you need to make sure that anything else in this lib is actually used so that the linker does not drop it. It would be nice if there would be a way to have these constants directly in a C# code file instead.
Author: RalfKornmannEnvision
Assignees: -
Labels: `untriaged`, `area-NativeAOT-coreclr`
Milestone: -
MichalPetryka commented 1 year ago

Related to #60422.

MichalStrehovsky commented 1 year ago

I've had a need for something similar in the past. Ended up generating a synthetic RVA-static field within the compiler since that was an option.

One possible implementation approach would be to have an attribute one can put on a non-GC static field to have the compiler treat it as an RVA static (so that it doesn't participate in static layout) and give it a symbolic name.

This feels kind of similar to what FixedAddressValueType attribute does. Maybe we could use that and add a EntryPoint property.

jkotas commented 1 year ago

If we were to implement this, we should make sure that the same scheme can work on JIT-based runtime, so that our debugging story (debug on CoreCLR, deploy with AOT) holds.

MichalStrehovsky commented 1 year ago

This feels similar to setting EntryPoint on UnmanagedCallersOnly - it's a no-op when JIT is involved, unless one builds a custom host that interprets this, a la DNNE. Not sure if CoreCLR hosting APIs would allow emulating this for fields in their current form.

jkotas commented 1 year ago

Right, it is similar. The challenge is that it is not possible to lazy resolve and forward the fields access like it is possible for methods. It means that the unmanaged export would need to point directly at the field storage, and the type loader would need to call the host to get address of the storage assigned to the field and use that instead of allocating the storage.