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

Compile NativeAOT on x86 #1531

Closed
wants to merge 9 commits into from

Conversation

kant2002
Copy link
Contributor

@kant2002 kant2002 commented Sep 8, 2021

Thanks to suggestions from dotnet/runtime#86573 I was able to compile NativeAOT on Windows x86.
I apply just USE_GC_INFO_DECODER for now.

@kant2002
Copy link
Contributor Author

kant2002 commented Sep 8, 2021

I need to uncomment parts of

;; Need some more write barriers to run CLR compiled MDIL on Redhawk - commented out for now
;; DEFINE_WRITE_BARRIER EDX, EAX
;; DEFINE_WRITE_BARRIER EDX, ECX
;; DEFINE_WRITE_BARRIER EDX, EBX
;; DEFINE_WRITE_BARRIER EDX, ESI
;; DEFINE_WRITE_BARRIER EDX, EDI
;; DEFINE_WRITE_BARRIER EDX, EBP
;; DEFINE_CHECKED_WRITE_BARRIER EDX, EAX
;; DEFINE_CHECKED_WRITE_BARRIER EDX, ECX
;; DEFINE_CHECKED_WRITE_BARRIER EDX, EBX
;; DEFINE_CHECKED_WRITE_BARRIER EDX, ESI
;; DEFINE_CHECKED_WRITE_BARRIER EDX, EDI
;; DEFINE_CHECKED_WRITE_BARRIER EDX, EBP

But still ILC fails to process CORINFO_HELP_ENDCATCH. I would need advice where I can take parts for that implementation in ASM or somewhere elese.

@kant2002
Copy link
Contributor Author

kant2002 commented Sep 8, 2021

Also do I send something like #1530 and #1509 so I would not think too much about ObjWriter?

@@ -1,4 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

// USE_GC_INFO_DECODER does not defined for Win-x86 in CoreCLR
Copy link
Member

Choose a reason for hiding this comment

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

This won't be enough. You will also need to define it when building RyuJIT.

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 assume this is NativeAOT specific customization to https://github.com/dotnet/runtimelab/blob/feature/NativeAOT/src/coreclr/jit/CMakeLists.txt

Also I did not see any reference to USE_GC_INFO_DECODER in jit folder. Are you talking that I need to use FEATURE_EH_FUNCLETS then how I make that change purely NativeAOT specific ?

Copy link
Member

Choose a reason for hiding this comment

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

I assume this is NativeAOT specific customization to https://github.com/dotnet/runtimelab/blob/feature/NativeAOT/src/coreclr/jit/CMakeLists.txt

Yes. It becomes tricky because it would mean that the JIT binary used by CoreCLR will be different from the JIT binary used by AOT. It is actually a bunch of binaries since we build multiple variants to support cross-compilation. There are short-term hacks possible in this branch. Once/if we move NativeAOT to dotnet/runtime, we will need to be able to use the same JIT binary for both regular CoreCLR and NativeAOT. If we keep the ABI differences, we may need to replace the ifdefs with dynamic checks in the JIT. Other option is to just stick with the same ABI as CoreCLR and clean it up as necessary (ie avoid forking the ABI for NativeAOT).

Also I did not see any reference to USE_GC_INFO_DECODER in jit folder

JIT has JIT32_GCENCODER. JIT32_GCENCODER = !USE_GC_INFO_DECODER

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 think I found a way how we can postpone decision temporary. Instead of this particular change, I remove these lines from .h files

#ifdef TARGET_X86
#define JIT32_GCENCODER
#endif

and

#if !defined(TARGET_X86)
#define USE_GC_INFO_DECODER
#endif

And will control these defines from CMake files. That change maybe be submitted to Runtime repo I think, and all hacks would be in CMake files in NativeAOT repo. That way we can explore all 3 options without too much commitment to either of them, if I only apply CMake hacks locally. What do you think?

Copy link
Member

Choose a reason for hiding this comment

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

I do not think that there is a big difference in controlling it in cmake files vs. in header files. Both of these are short-term hacks that would be ok in this branch, but not in dotnet/runtime. You end up with a JIT build that is different from regular CoreCLR JIT build in either case.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ok, will try that. I think about JIT as black box for now, so it was a scary change for me. I think I understand direction now.

@@ -172,7 +172,7 @@ REDHAWK_PALEXPORT int32_t PalGetModuleFileName(_Out_ const TCHAR** pModuleNameOu
return 0;
}

REDHAWK_PALEXPORT uint64_t __cdecl PalGetTickCount64()
REDHAWK_PALEXPORT uint64_t REDHAWK_PALAPI PalGetTickCount64()
Copy link
Member

Choose a reason for hiding this comment

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

PalGetTickCount64 is defined as cdecl in C#. It has to match.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

REDHAWK_PALAPI defined as StdCall on non-Unix, and empty value on Unix. Does this mean, that I should change to StdCall in C#?

Copy link
Member

Choose a reason for hiding this comment

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

You can add new RhpGetTickCount64 that is cdecl and call that from C# instead of PalGetTickCount64. And then this change can stay.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

So you propose declare RhpGetTickCount64 in c++, for which I would add corresponding C# function, and use that function instead of PalGetTickCount64? I probably can just define __cdecl to nothing for TARGET_X86 in that file then.

Copy link
Member

Choose a reason for hiding this comment

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

Yes. There is number of methods like that (e.g. RhpReleaseCastCacheLock). They are using __cdecl already.

#if CALLDESCR_FPARGREGSARERETURNREGS
out CommonInputThunkStub
#else
Copy link
Member

Choose a reason for hiding this comment

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

I do not see why this change is needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is purely to satisfy style cop. I may suppress it on these code. It did not like comma before other parameters.

Copy link
Member

Choose a reason for hiding this comment

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

Suppressing the warning would be better. The ifdefs do not make logical sense with this change.

@jkotas
Copy link
Member

jkotas commented Sep 8, 2021

Also do I send something like #1530 and #1509 so I would not think too much about ObjWriter?

I would not want to add x86 to the official builds until it is close to working.

@jkotas
Copy link
Member

jkotas commented Sep 8, 2021

CORINFO_HELP_ENDCATCH

This helper is only needed for !FEATURE_EH_FUNCLETS. If you plan to go with FEATURE_EH_FUNCLETS, it won't be needed.

@kant2002
Copy link
Contributor Author

kant2002 commented Sep 9, 2021

There bunch of assertions with only 2 kinds of them during ILC run with latest changes. Not sure if this is indication that I have to do something extra, or this is indication that I do something wrong

assert(genRegPtrTemp->rpdGCtypeGet() != GCT_NONE);

and

_ASSERTE( m_SizeOfStackOutgoingAndScratchArea != (UINT32)-1 );

Last one has additional information in form of this text message Assertion failed 'genRegPtrTemp->rpdGCtypeGet() != GCT_NONE' in 'System.IO.StreamWriter:.cctor()' during 'Emit GC+EH tables' (IL size 27)

@kant2002
Copy link
Contributor Author

kant2002 commented Sep 9, 2021

At least

_ASSERTE( m_SizeOfStackOutgoingAndScratchArea != (UINT32)-1 );

related to #define FEATURE_FIXED_OUT_ARGS 0 on x86.
If I define #define FEATURE_FIXED_OUT_ARGS 1 on x86.
next assertion is

assert(arg->TypeGet() != TYP_STRUCT);

Which seems to be related to FEATURE_PUT_STRUCT_ARG_STK being defined. If I undefine it for Win-x86 configuration, then src\coreclr\jit\codegenxarch.cpp does not ready for this challenge now. I was try to add missing #ifdefs but next issues start appear in src\coreclr\jit\lowerxarch.cpp and I think rabbit hole is too deep. Maybe I miss something simple

@kant2002
Copy link
Contributor Author

Let's start with IL

IL to import:
IL_0000  16                ldc.i4.0    
IL_0001  6a                conv.i8     
IL_0002  7e 23 04 00 04    ldsfld       0x4000423
IL_0007  73 37 0a 00 06    newobj       0x6000A37
IL_000c  80 9d 01 00 04    stsfld       0x400019D

Which translated to following statements

***** BB01
STMT00001 (IL   ???...  ???)
               [000011] I-CXG-------              *  CALL      void   System.DateTimeOffset..ctor (exactContextHnd=0x4000000000420029)
               [000010] ------------ this in ecx  +--*  ADDR      byref 
               [000009] -------N----              |  \--*  LCL_VAR   struct<System.DateTimeOffset, 12> V01 tmp1         
               [000001] ------------ arg1         +--*  CNS_LNG   long   0x0000000000000000
               [000005] --CXG------- arg2         \--*  OBJ       struct<System.TimeSpan, 8>
               [000004] --CXG-------                 \--*  ADD       byref 
               [000002] H-CXG-------                    +--*  CALL help byref  HELPER.CORINFO_HELP_READYTORUN_STATIC_BASE
               [000003] ------------                    \--*  CNS_INT   int    0 Fseq[Zero]

***** BB01
STMT00002 (IL 0x00C...  ???)
               [000018] -ACXG-------              *  ASG       struct (copy)
               [000017] --CXG-------              +--*  BLK       struct<System.DateTimeOffset, 12>
               [000015] --CXG-------              |  \--*  ADD       byref 
               [000013] H-CXG-------              |     +--*  CALL help byref  HELPER.CORINFO_HELP_READYTORUN_STATIC_BASE
               [000014] ------------              |     \--*  CNS_INT   int    0 Fseq[MinValue]
               [000012] ------------              \--*  LCL_VAR   struct<System.DateTimeOffset, 12> V01 tmp1         

Eventually it transformed to

***** BB01
STMT00000 (IL 0x000...0x00C)
N003 (  5,  4) [000008] IA--G---R---              *  ASG       struct (init) $VN.Void
N002 (  3,  2) [000006] D---G--N----              +--*  LCL_VAR   struct<System.DateTimeOffset, 12>(AX) V01 tmp1         
N001 (  1,  1) [000007] ------------              \--*  CNS_INT   int    0 $41

***** BB01
STMT00001 (IL   ???...  ???)
N014 ( 47, 27) [000011] -ACXG-------               *  CALL      void   System.DateTimeOffset..ctor $VN.Void
N010 ( 22, 11) [000058] -ACXG---R-L- arg2 SETUP    +--*  ASG       struct (copy) $VN.Void
N009 (  3,  2) [000056] D------N----               |  +--*  LCL_VAR   struct<System.TimeSpan, 8> V04 tmp4         d:1
N008 ( 18,  8) [000005] -ACXG--N----               |  \--*  IND       struct <l:$285, c:$284>
N007 ( 15,  6) [000077] -ACXG-------               |     \--*  COMMA     byref  $240
N005 ( 14,  5) [000075] -ACXG---R---               |        +--*  ASG       byref  $VN.Void
N004 (  1,  1) [000074] D------N----               |        |  +--*  LCL_VAR   byref  V07 cse0         d:1 $240
N003 ( 14,  5) [000002] H-CXG-------               |        |  \--*  CALL help byref  HELPER.CORINFO_HELP_READYTORUN_STATIC_BASE Zero Fseq[Zero] $240
N006 (  1,  1) [000076] ------------               |        \--*  LCL_VAR   byref  V07 cse0         u:1 Zero Fseq[Zero] $240
N011 (  3,  2) [000059] ------------ arg2 in out+08+--*  LCL_VAR   struct<System.TimeSpan, 8> V04 tmp4         u:1 (last use) $2c2
N012 (  3,  3) [000010] ------------ this in ecx   +--*  LCL_VAR_ADDR byref  V01 tmp1          $102
N013 (  2,  2) [000001] ------------ arg1 in out+00\--*  CNS_LNG   long   0x0000000000000000 $300

And this is last state of this part of tree before it start asserting. I mark argument which lowering complains about.

lowering call (before):
N006 (  1,  1) [000076] ------------        t76 =    LCL_VAR   byref  V07 cse0         u:1 Zero Fseq[Zero] $240
                                                  /--*  t76    byref  
N008 ( 18,  8) [000005] -c-XG--N----         t5 = *  IND       struct <l:$285, c:$284>
               [000100] Dc-----N----       t100 =    LCL_VAR_ADDR byref  V04 tmp4         
                                                  /--*  t100   byref  
                                                  +--*  t5     struct 
N010 ( 22, 11) [000058] sA--------L-              *  STORE_BLK struct<System.TimeSpan, 8> (copy) (Unroll)
N011 (  3,  2) [000059] ------------        t59 =    LCL_VAR   struct<System.TimeSpan, 8> V04 tmp4         u:1 (last use) $2c2
N012 (  3,  3) [000010] ------------        t10 =    LCL_VAR_ADDR byref  V01 tmp1          $102
N013 (  2,  2) [000001] ------------         t1 =    CNS_INT   int    0
               [000093] ------------        t93 =    CNS_INT   int    0
                                                  /--*  t1     int    
                                                  +--*  t93    int    
               [000094] ------------        t94 = *  LONG      long  
                                                  /--*  t59    struct arg2 in out+08  <-- !!!!!  ASSERT ON THIS ARG !!!!!
                                                  +--*  t10    byref  this in ecx
                                                  +--*  t94    long   arg1 in out+00
N014 ( 47, 27) [000011] --CXG-------              *  CALL      void   System.DateTimeOffset..ctor $VN.Void

My understanding that assert do not like that "local variable" passed as struct, and this should be "morphed" earlier. If morphing is indeed proper place for turning structs into I will look there. I also will re-read responsibilities of each phase, so maybe I will get better understanding what's going on.

@unofficialdev
Copy link

Has this pull request been merged into the master branch?

@kant2002
Copy link
Contributor Author

@unofficialdev I was stuck with that. I do not have enough cycles to make that work properly, as such this is only half done. I still have appetite for that, just delay this excercise. If you want to pursue, you are free base that on current work,

kant2002 added a commit to kant2002/runtime that referenced this pull request Dec 29, 2021
jkotas pushed a commit to dotnet/runtime that referenced this pull request Dec 30, 2021
@jkotas
Copy link
Member

jkotas commented Feb 1, 2022

This work should continue in dotnet/runtime repo.

@jkotas jkotas closed this Feb 1, 2022
@yowl
Copy link
Contributor

yowl commented Dec 12, 2022

Why was RhpGetTickCount64 added as void not uint64_t ? wasm-ld doesn't like the mismatch between the c# declaration in InternalCalls.cs of ulong .

@jkotas
Copy link
Member

jkotas commented Dec 12, 2022

It was an oversight. Would you like to submit a PR with a fix?

@yowl
Copy link
Contributor

yowl commented Dec 12, 2022

Thanks: dotnet/runtime#79538

@dadavadd
Copy link

dadavadd commented Apr 18, 2024

Could you tell us how you were able to achieve NativeAOT compilation in x86? I want to link a C++ static library to my x86 project.

@yowl
Copy link
Contributor

yowl commented Apr 18, 2024

Could you tell us how you were able to achieve NativeAOT compilation in x86? I want to link a C++ static library to my x86 project.

Hi, work for x86 continues in the runtime repo, not here in runtimelab.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants