Build Linux altjit for x86 and amd64 (dotnet/coreclr#10120)
authorBruce Forstall <brucefo@microsoft.com>
Mon, 13 Mar 2017 23:32:15 +0000 (16:32 -0700)
committerGitHub <noreply@github.com>
Mon, 13 Mar 2017 23:32:15 +0000 (16:32 -0700)
Enable Windows hosted, Linux target amd64 altjit

With this change, we build a JIT that runs on Windows amd64
and targets Linux amd64, as an altjit named linuxnonjit.dll.
This is useful for debugging, or generating asm code or diffs.
You can even easily create Windows/non-Windows asm diffs
(either to compare the asm, or compare the generated code size).

For this to work, the JIT-EE interface method
getSystemVAmd64PassStructInRegisterDescriptor() was changed
to always be built in, by defining `FEATURE_UNIX_AMD64_STRUCT_PASSING_ITF`
in all AMD64 builds. The `_ITF` suffix indicates that this is
functionality specific to implementing the JIT-EE interface
contract. There were many places in the VM that used this
interchangeably with `FEATURE_UNIX_AMD64_STRUCT_PASSING`. Now,
`FEATURE_UNIX_AMD64_STRUCT_PASSING` means code in the VM needed
to implement this feature, but not required to implement the
JIT-EE interface contract. In particular, MethodTables compute
and cache the "eightbyte" info of structs when loading a type.
This is not done when only `FEATURE_UNIX_AMD64_STRUCT_PASSING_ITF`
is set, to avoid altering MethodTable behavior on non-Unix
AMD64 builds. Instead, if `getSystemVAmd64PassStructInRegisterDescriptor()`
is called on a non-Unix build (by the altjit), the `ClassifyEightBytes()`
function is called, and nothing is cached. Hopefully (though it was
hard for me to guarantee by observation), calling `ClassifyEightBytes()`
does not have any side effects on MethodTables. It doesn't really matter,
since if called for altjit, we don't care too much about running.

The previously used `PLATFORM_UNIX` define is now insufficient.
I introduced the `#define` macros `_HOST_UNIX_` to indicate the
JIT being built will run on Unix, and `_TARGET_UNIX_` to indicate
the JIT is generating code targeting Unix. Some things were
converted to use the `UNIX_AMD64_ABI` define, which makes more
sense.

Commit migrated from https://github.com/dotnet/coreclr/commit/ad8afe4f8c9537e8652ae35b301366d737bc1e04

25 files changed:
src/coreclr/CMakeLists.txt
src/coreclr/clrdefinitions.cmake
src/coreclr/src/debug/daccess/nidump.cpp
src/coreclr/src/jit/CMakeLists.txt
src/coreclr/src/jit/codegencommon.cpp
src/coreclr/src/jit/codegenlinear.h
src/coreclr/src/jit/codegenxarch.cpp
src/coreclr/src/jit/compiler.cpp
src/coreclr/src/jit/dll/CMakeLists.txt
src/coreclr/src/jit/ee_il_dll.cpp
src/coreclr/src/jit/emitxarch.cpp
src/coreclr/src/jit/jit.h
src/coreclr/src/jit/jitstd/type_traits.h
src/coreclr/src/jit/linuxnonjit/CMakeLists.txt [new file with mode: 0644]
src/coreclr/src/jit/target.h
src/coreclr/src/jit/unwindamd64.cpp
src/coreclr/src/jit/utils.cpp
src/coreclr/src/jit/valuenum.h
src/coreclr/src/vm/callhelpers.cpp
src/coreclr/src/vm/class.h
src/coreclr/src/vm/jitinterface.cpp
src/coreclr/src/vm/methodtable.cpp
src/coreclr/src/vm/methodtable.h
src/coreclr/src/vm/methodtablebuilder.cpp
src/coreclr/src/vm/methodtablebuilder.h

index 0e1e623..b371432 100644 (file)
@@ -294,7 +294,6 @@ set(CMAKE_CXX_FLAGS_CHECKED ${CLR_CXX_FLAGS_CHECKED_INIT} CACHE STRING "Flags us
 set(CMAKE_EXE_LINKER_FLAGS_CHECKED "")
 set(CMAKE_SHARED_LINKER_FLAGS_CHECKED "")
 
-# Disable the following line for UNIX altjit on Windows
 set(CMAKE_CXX_STANDARD_LIBRARIES "") # do not link against standard win32 libs i.e. kernel32, uuid, user32, etc.
 
 if (WIN32)
@@ -315,7 +314,6 @@ if (WIN32)
 
   # Linker flags
   #
-  # Disable the following line for UNIX altjit on Windows
   set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /MANIFEST:NO") #Do not create Side-by-Side Assembly Manifest
 
   if (CLR_CMAKE_PLATFORM_ARCH_ARM)
@@ -521,9 +519,6 @@ else ()
     clr_unknown_arch()
 endif ()
 
-# Enable for UNIX altjit on Windows - set(CLR_CMAKE_PLATFORM_UNIX_AMD64 1)
-# Enable for UNIX altjit on Windows - add_definitions(-DCLR_CMAKE_PLATFORM_UNIX=1)
-
 #--------------------------------------
 # Compile Options
 #--------------------------------------
index 05f4140..49db1fd 100644 (file)
@@ -145,7 +145,6 @@ endif(NOT CLR_CMAKE_PLATFORM_UNIX)
 add_definitions(-DFEATURE_MANAGED_ETW_CHANNELS)
 
 if(FEATURE_MERGE_JIT_AND_ENGINE)
-  # Disable the following for UNIX altjit on Windows
   add_definitions(-DFEATURE_MERGE_JIT_AND_ENGINE)
 endif(FEATURE_MERGE_JIT_AND_ENGINE)
 add_definitions(-DFEATURE_MULTICOREJIT)
@@ -175,10 +174,13 @@ if (CLR_CMAKE_PLATFORM_UNIX OR CLR_CMAKE_TARGET_ARCH_ARM64)
 endif ()
 add_definitions(-DFEATURE_SVR_GC)
 add_definitions(-DFEATURE_SYMDIFF)
+if (CLR_CMAKE_PLATFORM_ARCH_AMD64)
+  # Enable the AMD64 Unix struct passing JIT-EE interface for all AMD64 platforms, to enable altjit.
+  add_definitions(-DFEATURE_UNIX_AMD64_STRUCT_PASSING_ITF)
+endif (CLR_CMAKE_PLATFORM_ARCH_AMD64)
 if(CLR_CMAKE_PLATFORM_UNIX_AMD64)
   add_definitions(-DFEATURE_MULTIREG_RETURN)
   add_definitions(-DFEATURE_UNIX_AMD64_STRUCT_PASSING)
-  add_definitions(-DFEATURE_UNIX_AMD64_STRUCT_PASSING_ITF)
 endif (CLR_CMAKE_PLATFORM_UNIX_AMD64)
 add_definitions(-DFEATURE_USE_ASM_GC_WRITE_BARRIERS)
 if(CLR_CMAKE_PLATFORM_ARCH_AMD64 AND NOT WIN32)
index b2663fe..77c05b5 100644 (file)
@@ -5549,9 +5549,9 @@ NativeImageDumper::EnumMnemonics s_MTFlagsLow[] =
 #if defined(FEATURE_HFA)
     MTFLAG_ENTRY(IsHFA),
 #endif // FEATURE_HFA
-#if defined(FEATURE_UNIX_AMD64_STRUCT_PASSING_ITF)
+#if defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
     MTFLAG_ENTRY(IsRegStructPassed),
-#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING_ITF
+#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
     MTFLAG_ENTRY(IsByRefLike),
     MTFLAG_ENTRY(UNUSED_ComponentSize_5),
     MTFLAG_ENTRY(UNUSED_ComponentSize_6),
index ea7de57..8f2170d 100644 (file)
@@ -4,9 +4,6 @@ set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
 include_directories("./jitstd")
 include_directories("../inc")
 
-# Enable the following for UNIX altjit on Windows
-# add_definitions(-DALT_JIT)
-
 if (CLR_CMAKE_TARGET_ARCH_AMD64 OR (CLR_CMAKE_TARGET_ARCH_I386 AND NOT CLR_CMAKE_PLATFORM_UNIX))
   add_definitions(-DFEATURE_SIMD)
   add_definitions(-DFEATURE_AVX_SUPPORT)
@@ -225,6 +222,10 @@ if ((CLR_CMAKE_PLATFORM_ARCH_I386 OR CLR_CMAKE_PLATFORM_ARCH_AMD64) AND WIN32)
     # On x86, build RyuJIT/ARM32 cross-compiling altjit.
     # On amd64, build RyuJIT/ARM64 cross-compiling altjit.
     add_subdirectory(protononjit)
+
+    # Build Linux/x86-running-on-Windows altjit or
+    # Linux/AMD64-running-on-Windows altjit..
+    add_subdirectory(linuxnonjit)
 endif ()
 
 if (CLR_CMAKE_PLATFORM_ARCH_I386 AND WIN32)
index fde4a67..4a70b96 100644 (file)
@@ -9683,7 +9683,7 @@ void CodeGen::genFnEpilog(BasicBlock* block)
                                        addrInfo.addr,
                                        0,                                                      // argSize
                                        EA_UNKNOWN                                              // retSize
-                                       FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(EA_UNKNOWN), // secondRetSize
+                                       MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(EA_UNKNOWN),        // secondRetSize
                                        gcInfo.gcVarPtrSetCur,
                                        gcInfo.gcRegGCrefSetCur,
                                        gcInfo.gcRegByrefSetCur,
index af545fe..52b1f9e 100644 (file)
@@ -183,10 +183,10 @@ void genPutArgStkFieldList(GenTreePutArgStk* putArgStk);
 
 void genPutStructArgStk(GenTreePutArgStk* treeNode);
 
-int genMove8IfNeeded(unsigned size, regNumber tmpReg, GenTree* srcAddr, unsigned offset);
-int genMove4IfNeeded(unsigned size, regNumber tmpReg, GenTree* srcAddr, unsigned offset);
-int genMove2IfNeeded(unsigned size, regNumber tmpReg, GenTree* srcAddr, unsigned offset);
-int genMove1IfNeeded(unsigned size, regNumber tmpReg, GenTree* srcAddr, unsigned offset);
+unsigned genMove8IfNeeded(unsigned size, regNumber tmpReg, GenTree* srcAddr, unsigned offset);
+unsigned genMove4IfNeeded(unsigned size, regNumber tmpReg, GenTree* srcAddr, unsigned offset);
+unsigned genMove2IfNeeded(unsigned size, regNumber tmpReg, GenTree* srcAddr, unsigned offset);
+unsigned genMove1IfNeeded(unsigned size, regNumber tmpReg, GenTree* srcAddr, unsigned offset);
 void genStructPutArgRepMovs(GenTreePutArgStk* putArgStkNode);
 void genStructPutArgUnroll(GenTreePutArgStk* putArgStkNode);
 void genStoreRegToStackArg(var_types type, regNumber reg, int offset);
index 7639e8b..4917e2c 100644 (file)
@@ -3225,7 +3225,7 @@ void CodeGen::genCodeForCpBlkRepMovs(GenTreeBlk* cpBlkNode)
 //    On x86, longTmpReg must be an xmm reg; on x64 it must be an integer register.
 //    This is checked by genStoreRegToStackArg.
 //
-int CodeGen::genMove8IfNeeded(unsigned size, regNumber longTmpReg, GenTree* srcAddr, unsigned offset)
+unsigned CodeGen::genMove8IfNeeded(unsigned size, regNumber longTmpReg, GenTree* srcAddr, unsigned offset)
 {
 #ifdef _TARGET_X86_
     instruction longMovIns = INS_movq;
@@ -3259,7 +3259,7 @@ int CodeGen::genMove8IfNeeded(unsigned size, regNumber longTmpReg, GenTree* srcA
 //    intTmpReg must be an integer register.
 //    This is checked by genStoreRegToStackArg.
 //
-int CodeGen::genMove4IfNeeded(unsigned size, regNumber intTmpReg, GenTree* srcAddr, unsigned offset)
+unsigned CodeGen::genMove4IfNeeded(unsigned size, regNumber intTmpReg, GenTree* srcAddr, unsigned offset)
 {
     if ((size & 4) != 0)
     {
@@ -3288,7 +3288,7 @@ int CodeGen::genMove4IfNeeded(unsigned size, regNumber intTmpReg, GenTree* srcAd
 //    intTmpReg must be an integer register.
 //    This is checked by genStoreRegToStackArg.
 //
-int CodeGen::genMove2IfNeeded(unsigned size, regNumber intTmpReg, GenTree* srcAddr, unsigned offset)
+unsigned CodeGen::genMove2IfNeeded(unsigned size, regNumber intTmpReg, GenTree* srcAddr, unsigned offset)
 {
     if ((size & 2) != 0)
     {
@@ -3317,7 +3317,7 @@ int CodeGen::genMove2IfNeeded(unsigned size, regNumber intTmpReg, GenTree* srcAd
 //    intTmpReg must be an integer register.
 //    This is checked by genStoreRegToStackArg.
 //
-int CodeGen::genMove1IfNeeded(unsigned size, regNumber intTmpReg, GenTree* srcAddr, unsigned offset)
+unsigned CodeGen::genMove1IfNeeded(unsigned size, regNumber intTmpReg, GenTree* srcAddr, unsigned offset)
 {
 
     if ((size & 1) != 0)
@@ -3354,7 +3354,7 @@ void CodeGen::genStructPutArgUnroll(GenTreePutArgStk* putArgNode)
     GenTreePtr dstAddr = putArgNode;
     GenTreePtr src     = putArgNode->gtOp.gtOp1;
 
-    size_t size = putArgNode->getArgSize();
+    unsigned size = putArgNode->getArgSize();
     assert(size <= CPBLK_UNROLL_LIMIT);
 
     emitter* emit         = getEmitter();
@@ -7183,7 +7183,7 @@ int CodeGenInterface::genSPtoFPdelta()
 {
     int delta;
 
-#ifdef PLATFORM_UNIX
+#ifdef UNIX_AMD64_ABI
 
     // We require frame chaining on Unix to support native tool unwinding (such as
     // unwinding by the native debugger). We have a CLR-only extension to the
@@ -7191,7 +7191,7 @@ int CodeGenInterface::genSPtoFPdelta()
     // If Unix ever supports EnC, the RSP == RBP assumption will have to be reevaluated.
     delta = genTotalFrameSize();
 
-#else // !PLATFORM_UNIX
+#else // !UNIX_AMD64_ABI
 
     // As per Amd64 ABI, RBP offset from initial RSP can be between 0 and 240 if
     // RBP needs to be reported in unwind codes.  This case would arise for methods
@@ -7217,7 +7217,7 @@ int CodeGenInterface::genSPtoFPdelta()
         delta = genTotalFrameSize();
     }
 
-#endif // !PLATFORM_UNIX
+#endif // !UNIX_AMD64_ABI
 
     return delta;
 }
@@ -8525,7 +8525,7 @@ void CodeGen::genEmitHelperCall(unsigned helper, int argSize, emitAttr retSize,
                                INDEBUG_LDISASM_COMMA(nullptr) addr,
                                argSize,
                                retSize
-                               FEATURE_UNIX_AMD64_STRUCT_PASSING_ONLY_ARG(EA_UNKNOWN),
+                               MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(EA_UNKNOWN),
                                gcInfo.gcVarPtrSetCur,
                                gcInfo.gcRegGCrefSetCur,
                                gcInfo.gcRegByrefSetCur,
index 423a044..4e9c4b3 100644 (file)
@@ -4990,11 +4990,11 @@ int Compiler::compCompile(CORINFO_METHOD_HANDLE methodHnd,
     // with an ARM-targeting "altjit").
     info.compMatchedVM = IMAGE_FILE_MACHINE_TARGET == info.compCompHnd->getExpectedTargetArchitecture();
 
-#if defined(ALT_JIT) && defined(UNIX_AMD64_ABI)
-    // ToDo: This code is to allow us to run UNIX codegen on Windows for now. Remove when appropriate.
-    // Make sure that the generated UNIX altjit code is skipped on Windows. The static jit codegen is used to run.
+#if (defined(_TARGET_UNIX_) && !defined(_HOST_UNIX_)) || (!defined(_TARGET_UNIX_) && defined(_HOST_UNIX_))
+    // The host and target platforms don't match. This info isn't handled by the existing
+    // getExpectedTargetArchitecture() JIT-EE interface method.
     info.compMatchedVM = false;
-#endif // UNIX_AMD64_ABI
+#endif
 
 #if COR_JIT_EE_VERSION > 460
     compMaxUncheckedOffsetForNullObject = eeGetEEInfo()->maxUncheckedOffsetForNullObject;
@@ -5418,7 +5418,7 @@ void Compiler::compCompileFinish()
     {
         if (compJitHaltMethod())
         {
-#if !defined(_TARGET_ARM64_) && !defined(PLATFORM_UNIX)
+#if !defined(_TARGET_ARM64_) && !defined(_HOST_UNIX_)
             // TODO-ARM64-NYI: re-enable this when we have an OS that supports a pop-up dialog
 
             // Don't do an assert, but just put up the dialog box so we get just-in-time debugger
index 0e8f5bd..6d247fe 100644 (file)
@@ -4,7 +4,6 @@ if(CLR_CMAKE_TARGET_ARCH_ARM)
     add_definitions(-DLEGACY_BACKEND)
 endif(CLR_CMAKE_TARGET_ARCH_ARM)
 
-# Disable the following for UNIX altjit on Windows
 if(CLR_CMAKE_PLATFORM_UNIX)
     add_compile_options(-fPIC)
 
@@ -19,19 +18,4 @@ else()
       ${SHARED_LIB_SOURCES}
       ${JIT_ARCH_SOURCES}
     )
-# Disable up to here (see above) the following for UNIX altjit on Windows 
-# Enable the following for UNIX altjit on Windows
-#    add_library_clr(ClrJit
-#       SHARED
-#       ${SHARED_LIB_SOURCES}
-#    )
-
-# Enable the following for UNIX altjit on Windows
-#target_link_libraries(ClrJit
-#      utilcode
-#      gcinfo
-#      runtime_library
-#    )
-
-# Disable the following for UNIX altjit on Windows
 endif(CLR_CMAKE_PLATFORM_UNIX)
index a29a3ef..cfbc44c 100644 (file)
@@ -20,7 +20,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 #include "emit.h"
 #include "corexcep.h"
 
-#if !defined(PLATFORM_UNIX)
+#if !defined(_HOST_UNIX_)
 #include <io.h>    // For _dup, _setmode
 #include <fcntl.h> // For _O_TEXT
 #include <errno.h> // For EINVAL
@@ -66,9 +66,9 @@ extern "C" void __stdcall jitStartup(ICorJitHost* jitHost)
     assert(!JitConfig.isInitialized());
     JitConfig.initialize(jitHost);
 
-#if defined(PLATFORM_UNIX)
+#if defined(_HOST_UNIX_)
     jitstdout = procstdout();
-#else
+#else  // !_HOST_UNIX_
     if (jitstdout == nullptr)
     {
         int stdoutFd = _fileno(procstdout());
@@ -99,7 +99,7 @@ extern "C" void __stdcall jitStartup(ICorJitHost* jitHost)
     {
         jitstdout = procstdout();
     }
-#endif // PLATFORM_UNIX
+#endif // !_HOST_UNIX_
 
 #ifdef FEATURE_TRACELOGGING
     JitTelemetry::NotifyDllProcessAttach();
index f672913..7d3b615 100644 (file)
@@ -1665,7 +1665,7 @@ inline UNATIVE_OFFSET emitter::emitInsSizeSV(code_t code, int var, int dsp)
 
             if (EBPbased)
             {
-#if defined(_TARGET_AMD64_) && !defined(PLATFORM_UNIX)
+#if defined(_TARGET_AMD64_) && !defined(UNIX_AMD64_ABI)
                 // If localloc is not used, then ebp chaining is done and hence
                 // offset of locals will be at negative offsets, Otherwise offsets
                 // will be positive.  In future, when RBP gets positioned in the
index 05b154e..916b680 100644 (file)
 #define _TARGET_ARMARCH_
 #endif
 
+// If the UNIX_AMD64_ABI is defined make sure that _TARGET_AMD64_ is also defined.
+#if defined(UNIX_AMD64_ABI)
+#if !defined(_TARGET_AMD64_)
+#error When UNIX_AMD64_ABI is defined you must define _TARGET_AMD64_ defined as well.
+#endif
+#endif
+
+// If the UNIX_X86_ABI is defined make sure that _TARGET_X86_ is also defined.
+#if defined(UNIX_X86_ABI)
+#if !defined(_TARGET_X86_)
+#error When UNIX_X86_ABI is defined you must define _TARGET_X86_ defined as well.
+#endif
+#endif
+
+#if defined(PLATFORM_UNIX)
+#define _HOST_UNIX_
+#endif
+
+// Are we generating code to target Unix? This is true if we will run on Unix (_HOST_UNIX_ is defined).
+// It's also true if we are building an altjit targetting Unix, which we determine by checking if either
+// UNIX_AMD64_ABI or UNIX_X86_ABI is defined.
+#if defined(_HOST_UNIX_) || ((defined(UNIX_AMD64_ABI) || defined(UNIX_X86_ABI)) && defined(ALT_JIT))
+#define _TARGET_UNIX_
+#endif
+
 // --------------------------------------------------------------------------------
 // IMAGE_FILE_MACHINE_TARGET
 // --------------------------------------------------------------------------------
 
 // Include the AMD64 unwind codes when appropriate.
 #if defined(_TARGET_AMD64_)
+// We need to temporarily set PLATFORM_UNIX, if necessary, to get the Unix-specific unwind codes.
+#if defined(_TARGET_UNIX_) && !defined(_HOST_UNIX_)
+#define PLATFORM_UNIX
+#endif
 #include "win64unwind.h"
+#if defined(_TARGET_UNIX_) && !defined(_HOST_UNIX_)
+#undef PLATFORM_UNIX
+#endif
 #endif
 
 // Macros for defining strongly-typed enums. Use as follows:
index 1e853e8..f0f8518 100644 (file)
@@ -178,14 +178,15 @@ struct make_unsigned<int>
     typedef unsigned int type;
 };
 
-#ifndef PLATFORM_UNIX
+#ifndef _HOST_UNIX_
 
 template<>
 struct make_unsigned<long>
 {
     typedef unsigned long type;
 };
-#endif // PLATFORM_UNIX
+
+#endif // !_HOST_UNIX_
 
 template<>
 struct make_unsigned<__int64>
diff --git a/src/coreclr/src/jit/linuxnonjit/CMakeLists.txt b/src/coreclr/src/jit/linuxnonjit/CMakeLists.txt
new file mode 100644 (file)
index 0000000..87ec1e4
--- /dev/null
@@ -0,0 +1,71 @@
+project(linuxnonjit)
+
+add_definitions(-DALT_JIT)
+add_definitions(-DFEATURE_NO_HOST)
+add_definitions(-DSELF_NO_HOST)
+add_definitions(-DFEATURE_READYTORUN_COMPILER)
+remove_definitions(-DFEATURE_MERGE_JIT_AND_ENGINE)
+
+if (CLR_CMAKE_PLATFORM_ARCH_I386)
+    remove_definitions(-DFEATURE_SIMD)
+    remove_definitions(-DFEATURE_AVX_SUPPORT)
+    add_definitions(-DUNIX_X86_ABI)
+    set(JIT_ARCH_ALTJIT_SOURCES ${JIT_I386_SOURCES})
+elseif(CLR_CMAKE_PLATFORM_ARCH_AMD64)
+    add_definitions(-DUNIX_AMD64_ABI)
+    add_definitions(-DFEATURE_UNIX_AMD64_STRUCT_PASSING)
+    set(JIT_ARCH_ALTJIT_SOURCES ${JIT_AMD64_SOURCES})
+else()
+    clr_unknown_arch()
+endif()
+
+if(WIN32)
+  add_definitions(-DFX_VER_INTERNALNAME_STR=linuxnonjit.dll)
+endif(WIN32)
+
+add_library_clr(linuxnonjit
+   SHARED
+   ${SHARED_LIB_SOURCES}
+   ${JIT_ARCH_ALTJIT_SOURCES}
+)
+
+add_dependencies(linuxnonjit jit_exports)
+
+set_property(TARGET linuxnonjit APPEND_STRING PROPERTY LINK_FLAGS ${JIT_EXPORTS_LINKER_OPTION})
+set_property(TARGET linuxnonjit APPEND_STRING PROPERTY LINK_DEPENDS ${JIT_EXPORTS_FILE})
+
+set(RYUJIT_LINK_LIBRARIES
+   utilcodestaticnohost
+   gcinfo
+)
+
+if(CLR_CMAKE_PLATFORM_UNIX)
+    list(APPEND RYUJIT_LINK_LIBRARIES
+       mscorrc_debug
+       coreclrpal
+       palrt
+    )
+else()
+    list(APPEND RYUJIT_LINK_LIBRARIES
+       ${STATIC_MT_CRT_LIB}
+       ${STATIC_MT_VCRT_LIB}
+       kernel32.lib
+       advapi32.lib
+       ole32.lib
+       oleaut32.lib
+       uuid.lib
+       user32.lib
+       version.lib
+       shlwapi.lib
+       bcrypt.lib
+       crypt32.lib
+       RuntimeObject.lib
+    )
+endif(CLR_CMAKE_PLATFORM_UNIX)
+
+target_link_libraries(linuxnonjit
+   ${RYUJIT_LINK_LIBRARIES}
+)
+
+# add the install targets
+install_clr(linuxnonjit)
index 2cee2c8..a775186 100644 (file)
@@ -6,25 +6,11 @@
 #ifndef _TARGET_H_
 #define _TARGET_H_
 
-// If the UNIX_AMD64_ABI is defined make sure that _TARGET_AMD64_ is also defined.
-#if defined(UNIX_AMD64_ABI)
-#if !defined(_TARGET_AMD64_)
-#error When UNIX_AMD64_ABI is defined you must define _TARGET_AMD64_ defined as well.
-#endif
-#endif
-
-// If the UNIX_X86_ABI is defined make sure that _TARGET_X86_ is also defined.
-#if defined(UNIX_X86_ABI)
-#if !defined(_TARGET_X86_)
-#error When UNIX_X86_ABI is defined you must define _TARGET_X86_ defined as well.
-#endif
-#endif
-
-#if (defined(FEATURE_CORECLR) && defined(PLATFORM_UNIX))
+#if defined(FEATURE_CORECLR) && defined(_TARGET_UNIX_)
 #define FEATURE_VARARG 0
-#else // !(defined(FEATURE_CORECLR) && defined(PLATFORM_UNIX))
+#else // !(defined(FEATURE_CORECLR) && defined(_TARGET_UNIX_))
 #define FEATURE_VARARG 1
-#endif // !(defined(FEATURE_CORECLR) && defined(PLATFORM_UNIX))
+#endif // !(defined(FEATURE_CORECLR) && defined(_TARGET_UNIX_))
 
 /*****************************************************************************/
 // The following are human readable names for the target architectures
index 14eba8c..1b2baf6 100644 (file)
@@ -448,7 +448,7 @@ void Compiler::unwindSetFrameRegWindows(regNumber reg, unsigned offset)
 
     func->unwindHeader.FrameRegister = (BYTE)reg;
 
-#ifdef PLATFORM_UNIX
+#ifdef UNIX_AMD64_ABI
     if (offset > 240)
     {
         // On Unix only, we have a CLR-only extension to the AMD64 unwind codes: UWOP_SET_FPREG_LARGE.
@@ -467,7 +467,7 @@ void Compiler::unwindSetFrameRegWindows(regNumber reg, unsigned offset)
         func->unwindHeader.FrameOffset = 15;
     }
     else
-#endif // PLATFORM_UNIX
+#endif // UNIX_AMD64_ABI
     {
         assert(func->unwindCodeSlot > sizeof(UNWIND_CODE));
         UNWIND_CODE* code = (UNWIND_CODE*)&func->unwindCodes[func->unwindCodeSlot -= sizeof(UNWIND_CODE)];
@@ -697,7 +697,7 @@ void DumpUnwindInfo(bool                     isHotCode,
                        pCode->CodeOffset, pCode->UnwindOp, pCode->OpInfo); // This should be zero
                 break;
 
-#ifdef PLATFORM_UNIX
+#ifdef UNIX_AMD64_ABI
 
             case UWOP_SET_FPREG_LARGE:
                 printf("    CodeOffset: 0x%02X UnwindOp: UWOP_SET_FPREG_LARGE (%u) OpInfo: Unused (%u)\n",
@@ -712,7 +712,7 @@ void DumpUnwindInfo(bool                     isHotCode,
                 }
                 break;
 
-#endif // PLATFORM_UNIX
+#endif // UNIX_AMD64_ABI
 
             case UWOP_SAVE_NONVOL:
                 printf("    CodeOffset: 0x%02X UnwindOp: UWOP_SAVE_NONVOL (%u)     OpInfo: %s (%u)\n",
@@ -858,7 +858,7 @@ void Compiler::unwindReserveFuncHelper(FuncInfoDsc* func, bool isHotCode)
 #ifdef UNIX_AMD64_ABI
         if (generateCFIUnwindCodes())
         {
-            unwindCodeBytes = func->cfiCodes->size() * sizeof(CFI_CODE);
+            unwindCodeBytes = (DWORD)(func->cfiCodes->size() * sizeof(CFI_CODE));
         }
         else
 #endif // UNIX_AMD64_ABI
@@ -956,7 +956,7 @@ void Compiler::unwindEmitFuncHelper(FuncInfoDsc* func, void* pHotCode, void* pCo
 #ifdef UNIX_AMD64_ABI
         if (generateCFIUnwindCodes())
         {
-            int size = func->cfiCodes->size();
+            DWORD size = (DWORD)func->cfiCodes->size();
             if (size > 0)
             {
                 unwindCodeBytes = size * sizeof(CFI_CODE);
index bb76a73..e3654b0 100644 (file)
@@ -25,13 +25,13 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 // same code for all platforms, hence it is here instead of in the targetXXX.cpp
 // files.
 
-#ifdef PLATFORM_UNIX
+#ifdef _TARGET_UNIX_
 // Should we distinguish Mac? Can we?
 // Should we distinguish flavors of Unix? Can we?
 const char* Target::g_tgtPlatformName = "Unix";
-#else  // !PLATFORM_UNIX
+#else  // !_TARGET_UNIX_
 const char* Target::g_tgtPlatformName = "Windows";
-#endif // !PLATFORM_UNIX
+#endif // !_TARGET_UNIX_
 
 /*****************************************************************************/
 
index d434b81..2be4849 100644 (file)
@@ -678,9 +678,13 @@ private:
                 __fallthrough;
 
             case TYP_BYREF:
-#ifndef PLATFORM_UNIX
+
+#ifdef _MSC_VER
+
                 assert(&typeid(T) == &typeid(size_t)); // We represent ref/byref constants as size_t's.
-#endif                                                 // PLATFORM_UNIX
+
+#endif // _MSC_VER
+
                 __fallthrough;
 
             case TYP_INT:
index 18c935a..c575ee6 100644 (file)
@@ -434,7 +434,7 @@ void MethodDescCallSite::CallTargetWorker(const ARG_SLOT *pArguments, ARG_SLOT *
 
 #ifdef _DEBUG
         {
-#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING_ITF
+#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
             // Validate that the return value is not too big for the buffer passed
             if (m_pMD->GetMethodTable()->IsRegPassedStruct())
             {
@@ -444,7 +444,7 @@ void MethodDescCallSite::CallTargetWorker(const ARG_SLOT *pArguments, ARG_SLOT *
                     _ASSERTE(cbReturnValue >= thReturnValueType.GetSize());
                 }
             }
-#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING_ITF
+#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
 
             // The metasig should be reset
             _ASSERTE(m_methodSig.GetArgNum() == 0);
index 756f6d5..6c74377 100644 (file)
@@ -416,12 +416,12 @@ class EEClassLayoutInfo
             e_ZERO_SIZED                =   0x04,
             // The size of the struct is explicitly specified in the meta-data.
             e_HAS_EXPLICIT_SIZE         = 0x08,
-#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING_ITF
+#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
 #ifdef FEATURE_HFA
-#error Can't have FEATURE_HFA and FEATURE_UNIX_AMD64_STRUCT_PASSING_ITF defined at the same time.
+#error Can't have FEATURE_HFA and FEATURE_UNIX_AMD64_STRUCT_PASSING defined at the same time.
 #endif // FEATURE_HFA
             e_NATIVE_PASS_IN_REGISTERS  = 0x10, // Flag wheter a native struct is passed in registers.
-#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING_ITF
+#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
 #ifdef FEATURE_HFA
             // HFA type of the unmanaged layout
             e_R4_HFA                    = 0x10,
@@ -510,13 +510,13 @@ class EEClassLayoutInfo
             return m_cbPackingSize;
         }
 
-#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING_ITF
+#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
         bool IsNativeStructPassedInRegisters()
         {
             LIMITED_METHOD_CONTRACT;
             return (m_bFlags & e_NATIVE_PASS_IN_REGISTERS) != 0;
         }
-#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING_ITF
+#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
 
 #ifdef FEATURE_HFA
         bool IsNativeHFA()
@@ -570,13 +570,13 @@ class EEClassLayoutInfo
             m_bFlags |= (hfaType == ELEMENT_TYPE_R4) ? e_R4_HFA : e_R8_HFA;
         }
 #endif
-#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING_ITF
+#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
         void SetNativeStructPassedInRegisters()
         {
             LIMITED_METHOD_CONTRACT;
             m_bFlags |= e_NATIVE_PASS_IN_REGISTERS;
         }
-#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING_ITF
+#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
 
 };
 
index 45239c4..bdccdef 100644 (file)
@@ -2448,15 +2448,28 @@ bool CEEInfo::getSystemVAmd64PassStructInRegisterDescriptor(
         }
         _ASSERTE(methodTablePtr != nullptr);
 
+        // If we have full support for FEATURE_UNIX_AMD64_STRUCT_PASSING, and not just the interface,
+        // then we've cached whether this is a reg passed struct in the MethodTable, computed during
+        // MethodTable construction. Otherwise, we are just building in the interface, and we haven't
+        // computed or cached anything, so we need to compute it now.
+#if defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
         bool canPassInRegisters = useNativeLayout ? methodTablePtr->GetLayoutInfo()->IsNativeStructPassedInRegisters()
-                                                : methodTablePtr->IsRegPassedStruct();
+                                                  : methodTablePtr->IsRegPassedStruct();
+#else // !defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
+        SystemVStructRegisterPassingHelper helper((unsigned int)th.GetSize());
+        bool canPassInRegisters = methodTablePtr->ClassifyEightBytes(&helper, 0, 0, useNativeLayout);
+#endif // !defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
+
         if (canPassInRegisters)
         {
+#if defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
             SystemVStructRegisterPassingHelper helper((unsigned int)th.GetSize());
             bool result = methodTablePtr->ClassifyEightBytes(&helper, 0, 0, useNativeLayout);
 
             // The answer must be true at this point.
             _ASSERTE(result);
+#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
+
             structPassInRegDescPtr->passedInRegisters = true;
 
             structPassInRegDescPtr->eightByteCount = helper.eightByteCount;
index 2cc2ffe..21fab72 100644 (file)
@@ -2980,7 +2980,7 @@ bool MethodTable::ClassifyEightBytesWithNativeLayout(SystemVStructRegisterPassin
 }
 
 // Assigns the classification types to the array with eightbyte types.
-void  MethodTable::AssignClassifiedEightByteTypes(SystemVStructRegisterPassingHelperPtr helperPtr, unsigned int nestingLevel)
+void  MethodTable::AssignClassifiedEightByteTypes(SystemVStructRegisterPassingHelperPtr helperPtr, unsigned int nestingLevel) const
 {
     static const size_t CLR_SYSTEMV_MAX_BYTES_TO_PASS_IN_REGISTERS = CLR_SYSTEMV_MAX_EIGHTBYTES_COUNT_TO_PASS_IN_REGISTERS * SYSTEMV_EIGHT_BYTE_SIZE_IN_BYTES;
     static_assert_no_msg(CLR_SYSTEMV_MAX_BYTES_TO_PASS_IN_REGISTERS == SYSTEMV_MAX_NUM_FIELDS_IN_REGISTER_PASSED_STRUCT);
index 6e04b8a..d5cb5ba 100644 (file)
@@ -1070,7 +1070,7 @@ public:
 private:
 
 #if defined(FEATURE_UNIX_AMD64_STRUCT_PASSING_ITF)
-    void AssignClassifiedEightByteTypes(SystemVStructRegisterPassingHelperPtr helperPtr, unsigned int nestingLevel);
+    void AssignClassifiedEightByteTypes(SystemVStructRegisterPassingHelperPtr helperPtr, unsigned int nestingLevel) const;
     // Builds the internal data structures and classifies struct eightbytes for Amd System V calling convention.
     bool ClassifyEightBytesWithManagedLayout(SystemVStructRegisterPassingHelperPtr helperPtr, unsigned int nestingLevel, unsigned int startOffsetOfStruct, bool isNativeStruct);
     bool ClassifyEightBytesWithNativeLayout(SystemVStructRegisterPassingHelperPtr helperPtr, unsigned int nestingLevel, unsigned int startOffsetOfStruct, bool isNativeStruct);
@@ -2012,7 +2012,7 @@ public:
     }
 #endif // FEATURE_HFA
 
-#if defined(FEATURE_UNIX_AMD64_STRUCT_PASSING_ITF)
+#if defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
     inline bool IsRegPassedStruct()
     {
         LIMITED_METHOD_CONTRACT;
@@ -2024,7 +2024,7 @@ public:
         LIMITED_METHOD_CONTRACT;
         SetFlag(enum_flag_IsRegStructPassed);
     }
-#endif // defined(FEATURE_UNIX_AMD64_STRUCT_PASSING_ITF)
+#endif // defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
 
 #ifdef FEATURE_HFA
 
@@ -3801,18 +3801,18 @@ private:
         enum_flag_HasPreciseInitCctors      = 0x00000400,   // Do we need to run class constructors at allocation time? (Not perf important, could be moved to EEClass
 
 #if defined(FEATURE_HFA)
-#if defined(FEATURE_UNIX_AMD64_STRUCT_PASSING_ITF)
-#error Can't define both FEATURE_HFA and FEATURE_UNIX_AMD64_STRUCT_PASSING_ITF
+#if defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
+#error Can't define both FEATURE_HFA and FEATURE_UNIX_AMD64_STRUCT_PASSING
 #endif
         enum_flag_IsHFA                     = 0x00000800,   // This type is an HFA (Homogenous Floating-point Aggregate)
 #endif // FEATURE_HFA
 
-#if defined(FEATURE_UNIX_AMD64_STRUCT_PASSING_ITF)
+#if defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
 #if defined(FEATURE_HFA)
-#error Can't define both FEATURE_HFA and FEATURE_UNIX_AMD64_STRUCT_PASSING_ITF
+#error Can't define both FEATURE_HFA and FEATURE_UNIX_AMD64_STRUCT_PASSING
 #endif
         enum_flag_IsRegStructPassed         = 0x00000800,   // This type is a System V register passed struct.
-#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING_ITF
+#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
 
         enum_flag_IsByRefLike               = 0x00001000,
 
index fbf9246..7de3510 100644 (file)
@@ -1839,23 +1839,23 @@ MethodTableBuilder::BuildMethodTableThrowing(
 #ifdef FEATURE_HFA
         CheckForHFA(pByValueClassCache);
 #endif
-#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING_ITF
+#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
 #ifdef FEATURE_HFA
-#error Can't have FEATURE_HFA and FEATURE_UNIX_AMD64_STRUCT_PASSING_ITF defined at the same time.
+#error Can't have FEATURE_HFA and FEATURE_UNIX_AMD64_STRUCT_PASSING defined at the same time.
 #endif // FEATURE_HFA
         SystemVAmd64CheckForPassStructInRegister();
-#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING_ITF
+#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
     }
 
-#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING_ITF
+#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
 #ifdef FEATURE_HFA
-#error Can't have FEATURE_HFA and FEATURE_UNIX_AMD64_STRUCT_PASSING_ITF defined at the same time.
+#error Can't have FEATURE_HFA and FEATURE_UNIX_AMD64_STRUCT_PASSING defined at the same time.
 #endif // FEATURE_HFA
     if (HasLayout())
     {
         SystemVAmd64CheckForPassNativeStructInRegister();
     }
-#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING_ITF
+#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
 #ifdef FEATURE_HFA
     if (HasLayout())
     {
@@ -8224,7 +8224,7 @@ DWORD MethodTableBuilder::GetFieldSize(FieldDesc *pFD)
     return (1 << (DWORD)(DWORD_PTR&)(pFD->m_pMTOfEnclosingClass));
 }
 
-#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING_ITF
+#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
 // checks whether the struct is enregisterable.
 void MethodTableBuilder::SystemVAmd64CheckForPassStructInRegister()
 {
@@ -8309,7 +8309,7 @@ void MethodTableBuilder::StoreEightByteClassification(SystemVStructRegisterPassi
     eeClass->SetEightByteClassification(helper->eightByteCount, helper->eightByteClassifications, helper->eightByteSizes);
 }
 
-#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING_ITF
+#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
 
 #ifdef FEATURE_HFA
 //---------------------------------------------------------------------------------------
index 8bfffcc..2aa3683 100644 (file)
@@ -2925,14 +2925,14 @@ private:
 
     VOID    CheckForNativeHFA();
 
-#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING_ITF
+#ifdef FEATURE_UNIX_AMD64_STRUCT_PASSING
     // checks whether the struct is enregisterable.
     void SystemVAmd64CheckForPassStructInRegister();
     void SystemVAmd64CheckForPassNativeStructInRegister();
     // Store the eightbyte classification into the EEClass
     void StoreEightByteClassification(SystemVStructRegisterPassingHelper* helper);
 
-#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING_ITF
+#endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
 
     // this accesses the field size which is temporarily stored in m_pMTOfEnclosingClass
     // during class loading. Don't use any other time