dotnet / runtime

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

Support x86 for NativeAOT #86573

Closed kant2002 closed 3 months ago

kant2002 commented 3 years ago

I know that x86 is legacy right now, but come across person who what to write anti-cheat for x86 game using NativeAOT. I know that's fringe case, and I prefer to have better case asking for support me on this journey.

So my question would be following: If I put some efforts into this, would this be a burden for core team?

MichalStrehovsky commented 3 years ago

Anti-cheat... I assume you're asking x86 Windows specifically?

kant2002 commented 3 years ago

Yes, I was thinking about Windows x86.

MichalStrehovsky commented 3 years ago

So my question would be following: If I put some efforts into this, would this be a burden for core team?

I'll let @jkotas answer that. My estimate is that x86 Windows will be orders of magnitude more work than what was needed for ARM32 Linux (ARM32 Linux was already mostly there thanks to Samsung's work in the past). x86 in general is an unpleasant architecture to work with, possibly more so on Windows than Linux. A lot of legacy weird cruft was fixed with x86-64.

jkotas commented 3 years ago

x86 was done in the past for UWP. We have a lot of the x86 code there, so I would not say that fixing that code up and filling in the missing pieces would be a significant burden. I agree with @MichalStrehovsky that Windows x86 in general is an unpleasant architecture to work with and fixing it up is likely going to be much harder than fixing up ARM32.

kant2002 commented 3 years ago

I immediately hit something not very pleasant. The USE_GC_INFO_DECODER not defined on x86, so I have compilation errors in CoffNativeCodeManager::EnumGcRefs , CoffNativeCodeManager::GetConservativeUpperBoundForOutgoingArgs and CoffNativeCodeManager::UnwindStackFrame. From what I understand I need to reimplement methods from EECodeManager, but for example EnumGcRefs is quite a bit of code and I may need add eetwain.cpp to Runtime. Are there any better way?

Suchiman commented 3 years ago

Another thing i remember that also needs to be enabled for x86 is exception handling which is vastly different between x86 and x64 (at least in CoreCLR). IIRC the x86 mechanism is not implemented in CoreRT but the x64 mechanism could be used on x86 but it requires building the JIT with FEATURE_EH_FUNCLETS enabled which is untested for x86.

jkoritzinsky commented 3 years ago

It would be interesting to try to build Windows x86 on NativeAOT more like how CoreCLR's (unofficial, for Tizen only) x86 Linux support is built instead of how CoreCLR does Windows x86 support. x86 Linux is much more similar to the rest of the supported platforms than x86 Windows in terms of implementation.

kant2002 commented 3 years ago

It would be interesting to try to build Windows x86 on NativeAOT more like how CoreCLR's (unofficial, for Tizen only) x86 Linux support is built

@jkoritzinsky Can you feed me with details of differences, and how I may pursue that direction? If making Linux x86 works would be faster and pave road to Win x86, I may start even with that.

jkoritzinsky commented 3 years ago

So there's a few differences I know off the top of my head. I'll include a little table below with my recommendations for what to do for CoreRT Windows x86 support (note these are my gut recommendations and might be wrong or unneeded for NativeAOT).

Primarily, many of the Windows x86 differences aren't due to actual requirements, but due to the fact that the x86 models were the first designed in .NET Framework, and all the future architecture models learned from the mistakes of Windows x86.

Item CoreCLR Windows x86 CoreCLR Linux x86 NativeAOT x64 Suggestion
Calling Convention Fastcall-like Cdecl + extra registers + same limitations as fastcall-like platform default Fastcall-like
GC Info encoding custom encode/decode USE_GC_INFO_DECODER encode/decode USE_GC_INFO_DECODER encode/decode USE_GC_INFO_DECODER encode/decode
Exception handling !FEATURE_EH_FUNCLETS FEATURE_EH_FUNCLETS FEATURE_EH_FUNCLETS FEATURE_EH_FUNCLETS unless special handling is required for SEH-interop

Basically you should try just turning on the USE_GC_INFO_DECODER and FEATURE_EH_FUNCLETS defines for x86 and see how far you can get with x86 support. I think you'll be able to make a lot of progress by going in this direction instead of trying to port over CoreCLR's Windows x86's weirdness to NativeAOT.

kant2002 commented 3 years ago

Thanks a lot, that clarify all your point, and make my life so much easier. At least I now understand about why bifurcation happens, and what I have option to make small decisions my self, like if I encounter some wierdness, then I may check that this is x86 weirdness, and just try to go with different path.

Basically you should try just turning on the USE_GC_INFO_DECODER and FEATURE_EH_FUNCLETS defines for x86 and see how far you can get with x86 support

Will try it out, and see how it goes.

CeSun commented 1 year ago

A better option for developers maintaining old x86 projects? The exe of the program I am maintaining now has lost the source code, I can only develop dll, but I am tired of c++ and want to use c# to develop.

sweetjian commented 1 year ago

Support for x86 programs is expected

ThaDaVos commented 1 year ago

Any estimation as to when? I am trying to build a DLL for an old Clarion project where I work, Clarion is all 32-bit (x86) and as far as I can tell I can only use x86 architecture based DLL's there - in all the guides I could find (https://medium.com/@jsmckee100/net-and-clarion-c65bc91d1718) they are using Unmanaged Exports, sadly it doesn't compile any longer so after a long winding search, from Unmanaged Exports to DLLExport etc I eventually found that .NET has native options for stuff like this these days, sadly x86 isn't available - would love to test drive it if there is a way for it now.

Or if anyone can give a hint to what else to use so I can finish this off - maybe using something else to get DLL's which can be used in Clarion

kant2002 commented 1 year ago

I cannot have enough time for this, so nobody working on the matter right now from what I know. I would suggest you try different route then NativeAOT for x86

ThaDaVos commented 1 year ago

Any suggestions @kant2002 ?

NCLnclNCL commented 1 year ago

I cannot have enough time for this, so nobody working on the matter right now from what I know. I would suggest you try different route then NativeAOT for x86

i think you can refer to .net native x86 at uwp

lowleveldesign commented 9 months ago

Any suggestions @kant2002 ?

@ThaDaVos , if you're OK with loading .NET runtime libs into the target process, you could try the approach from the core hosting sample. I used it in my windbg extension template.

ThaDaVos commented 9 months ago

I am currently using a modified version of DNNE (https://github.com/AaronRobinsonMSFT/DNNE) to get it to work, it compiles a Native library which loads the runtime and my library - still sad it's not included in NativeOAT, but it's understandable after the explanations I've found

joeamnesiac commented 9 months ago

I am currently using a modified version of DNNE (https://github.com/AaronRobinsonMSFT/DNNE) to get it to work, it compiles a Native library which loads the runtime and my library - still sad it's not included in NativeOAT, but it's understandable after the explanations I've found

What did you have to change? Is there a branch or a clone with the changes needed?

ThaDaVos commented 9 months ago

@joeamnesiac - you can just use the normal DNNE version if you want a Native x86 library - my modified version contains some extra stuff for working with Clarion (automatic generation of some files)

DeafMan1983 commented 8 months ago

Why do we need x86 for Linux and Windows? I thought Windows won't drop 32 bit support. What is about win-x86?

NCLnclNCL commented 8 months ago

Why do we need x86 for Linux and Windows? I thought Windows won't drop 32 bit support. What is about win-x86?

i think window x64 will support 32 bit over wow64 forever until 128 bit comes out, linux x86 hasn't been supported for a long time

filipnavara commented 7 months ago

Initial support has landed with https://github.com/dotnet/runtime/pull/99372. There are still bugs that need to be solved. I expect to setup some test infrastructure in the coming days and file issues for specific failures.

filipnavara commented 7 months ago

Current list of known outstanding issues / tasks:

ThaDaVos commented 6 months ago

Initial support has landed with #99372. There are still bugs that need to be solved. I expect to setup some test infrastructure in the coming days and file issues for specific failures.

I guess that's in Dotnet 9? Or hasn't it be published yet? Would love to help by trying it out

MichalStrehovsky commented 6 months ago

A public preview with the support hasn't shipped yet, but if you get the latest installer bits from https://github.com/dotnet/installer?tab=readme-ov-file#installers-and-binaries, you can try it out. In the linked page, make sure to choose "Zip" or "Installer" from the column marked "main (9.0.x Runtime)". Make sure to read the instructions about nuget.config. Without that, you'll get restore errors.

nahakyuu commented 5 months ago

A public preview with the support hasn't shipped yet, but if you get the latest installer bits from https://github.com/dotnet/installer?tab=readme-ov-file#installers-and-binaries, you can try it out. In the linked page, make sure to choose "Zip" or "Installer" from the column marked "main (9.0.x Runtime)". Make sure to read the instructions about nuget.config. Without that, you'll get restore errors.

@MichalStrehovsky I use dotnet publish -r win-x86 and still get NETSDK1203 error

> dotnet --version
9.0.100-preview.5.24230.22
NativeLibrary.csproj
<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net9.0</TargetFramework>
  </PropertyGroup>

  <PropertyGroup>
    <PublishAot>true</PublishAot>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.DotNet.ILCompiler; runtime.win-x64.Microsoft.DotNet.ILCompiler" Version="9.0.0-preview.4.24251.3" />
  </ItemGroup>
</Project>
nuget.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <packageSources>
    <clear />
    <add key="dotnet9" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet9/nuget/v3/index.json" />
    <add key="nuget" value="https://api.nuget.org/v3/index.json" />
  </packageSources>
</configuration>
MichalStrehovsky commented 5 months ago

Is the project targeting net9.0? Also how did you end up with the ProjectReference to ILCompiler? You shouldn't need any. This should only require PublishAot=true in the project file.

nahakyuu commented 5 months ago

Is the project targeting net9.0? Also how did you end up with the ProjectReference to ILCompiler? You shouldn't need any. This should only require PublishAot=true in the project file.

@MichalStrehovsky I updated my original comment,The code used refers to this link and link2, update TargetFramework to net9.0

NCLnclNCL commented 5 months ago

Is the project targeting net9.0? Also how did you end up with the ProjectReference to ILCompiler? You shouldn't need any. This should only require PublishAot=true in the project file.

@MichalStrehovsky I updated my original comment,The code used refers to this link and link2, update TargetFramework to net9.0

There's something wrong with the new version, I'm using the old version so it's okay

nahakyuu commented 5 months ago

Is the project targeting net9.0? Also how did you end up with the ProjectReference to ILCompiler? You shouldn't need any. This should only require PublishAot=true in the project file.

@MichalStrehovsky I updated my original comment,The code used refers to this link and link2, update TargetFramework to net9.0

There's something wrong with the new version, I'm using the old version so it's okay

old version is ? I failed using 9.0.100-preview.3.24204.13

NCLnclNCL commented 5 months ago

Is the project targeting net9.0? Also how did you end up with the ProjectReference to ILCompiler? You shouldn't need any. This should only require PublishAot=true in the project file.

The latest version of dotnet, I can't run winform native aot though build successly, the build file is only 1 mb in size.

MichalStrehovsky commented 5 months ago

Is the project targeting net9.0? Also how did you end up with the ProjectReference to ILCompiler? You shouldn't need any. This should only require PublishAot=true in the project file.

@MichalStrehovsky I updated my original comment,The code used refers to this link and link2, update TargetFramework to net9.0

Delete the PackageReference. It should not be needed and it will only make things worse.

MichalStrehovsky commented 5 months ago

Is the project targeting net9.0? Also how did you end up with the ProjectReference to ILCompiler? You shouldn't need any. This should only require PublishAot=true in the project file.

The latest version of dotnet, I can't run winform native aot though build successly, the build file is only 1 mb in size.

It doesn't repro with:

D:\wftest>dotnet --info
.NET SDK:
 Version:           9.0.100-preview.4.24222.10
 Commit:            118dfc281e
 Workload version:  9.0.100-manifests.fb4db8ea
 MSBuild version:   17.11.0-preview-24218-01+195e9289b

My steps:

dotnet new winforms -o wftest
cd wftest
dotnet publish --arch x86 -p:_SuppressWinFormsTrimError=true -p:PublishAot=true

The output is a 21 MB exe and works.

NCLnclNCL commented 5 months ago

Is the project targeting net9.0? Also how did you end up with the ProjectReference to ILCompiler? You shouldn't need any. This should only require PublishAot=true in the project file.

The latest version of dotnet, I can't run winform native aot though build successly, the build file is only 1 mb in size.

It doesn't repro with:

D:\wftest>dotnet --info
.NET SDK:
 Version:           9.0.100-preview.4.24222.10
 Commit:            118dfc281e
 Workload version:  9.0.100-manifests.fb4db8ea
 MSBuild version:   17.11.0-preview-24218-01+195e9289b

My steps:

dotnet new winforms -o wftest
cd wftest
dotnet publish --arch x86 -p:_SuppressWinFormsTrimError=true -p:PublishAot=true

The output is a 21 MB exe and works.

Newest is dotnet 9 preview 5

MichalStrehovsky commented 5 months ago

Newest is dotnet 9 preview 5

I see the issue now, it is not x86 specific, not even native AOT specific. It is tracked at https://github.com/dotnet/winforms/issues/11282.

nomi-san commented 5 months ago

Any news? The latest dotnet 9 SDK preview-5 should work with win-x86 target but it raises error when compiling classlib due to missing some nuget dependencies that are only available in preview-3 🤔

MichalStrehovsky commented 5 months ago

Any news? The latest dotnet 9 SDK preview-5 should work with win-x86 target but it raises error when compiling classlib due to missing some nuget dependencies that are only available in preview-3 🤔

What's the error? Did you do the "Make sure to read the instructions about nuget.config. Without that, you'll get restore errors." part of my comment?

nomi-san commented 5 months ago

Make sure to read the instructions about nuget.config.

Thank you, now it works like a charm. Is there planned a date of publishing preview-5 prerelease?

MichalStrehovsky commented 5 months ago

Is there planned a date of publishing preview-5 prerelease?

Sometime in June based on past preview dates. I think Preview 4 will have this usable as well and that one should come out soon.

smoogipoo commented 4 months ago

Is this enabled in the latest previews? Would really like to test it (not a production app so it's no biggie if not): https://github.com/smoogipoo/osu-native-diffcalc/actions/runs/9474346123/job/26103751949

Run dotnet publish -c Release -r win-x86 -f net9.0 --self-contained Sources/osu.Game.Native.Desktop/osu.Game.Native.Desktop.csproj
  Determining projects to restore...

Error: C:\Program Files\dotnet\sdk\9.0.100-preview.5.24307.3\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(90,5): error NETSDK1203: Ahead-of-time compilation is not supported for the target runtime identifier 'win-x86'. [D:\a\osu-native-diffcalc\osu-native-diffcalc\Sources\osu.Game.Native.Desktop\osu.Game.Native.Desktop.csproj]
NCLnclNCL commented 4 months ago

Is this enabled in the latest previews? Would really like to test it (not a production app so it's no biggie if not): https://github.com/smoogipoo/osu-native-diffcalc/actions/runs/9474346123/job/26103751949

Run dotnet publish -c Release -r win-x86 -f net9.0 --self-contained Sources/osu.Game.Native.Desktop/osu.Game.Native.Desktop.csproj
  Determining projects to restore...

Error: C:\Program Files\dotnet\sdk\9.0.100-preview.5.24307.3\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(90,5): error NETSDK1203: Ahead-of-time compilation is not supported for the target runtime identifier 'win-x86'. [D:\a\osu-native-diffcalc\osu-native-diffcalc\Sources\osu.Game.Native.Desktop\osu.Game.Native.Desktop.csproj]

image add win-x86 to ILcompiler with path dotnet-sdk-9.0.100-preview.5.24267.1-win-x64\sdk\9.0.100-preview.5.24267.1\Microsoft.NETCoreSdk.BundledVersions.props

MichalStrehovsky commented 4 months ago

Is this enabled in the latest previews? Would really like to test it (not a production app so it's no biggie if not): https://github.com/smoogipoo/osu-native-diffcalc/actions/runs/9474346123/job/26103751949

Run dotnet publish -c Release -r win-x86 -f net9.0 --self-contained Sources/osu.Game.Native.Desktop/osu.Game.Native.Desktop.csproj
  Determining projects to restore...

Error: C:\Program Files\dotnet\sdk\9.0.100-preview.5.24307.3\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.FrameworkReferenceResolution.targets(90,5): error NETSDK1203: Ahead-of-time compilation is not supported for the target runtime identifier 'win-x86'. [D:\a\osu-native-diffcalc\osu-native-diffcalc\Sources\osu.Game.Native.Desktop\osu.Game.Native.Desktop.csproj]

Thanks for bringing this up. This is actually a recent regression. We lost the following line when dotnet/installer repo got folded into dotnet/sdk repo: https://github.com/dotnet/installer/blob/main/src/redist/targets/GenerateBundledVersions.targets#L380

(I'm starting an email thread with the people involved in the repo migration to make sure they investigate if this was the only thing we lost in the migration.)

Fix in https://github.com/dotnet/sdk/pull/41537. It will be in Preview 6 :(

MichalStrehovsky commented 3 months ago

This is done.