From c0f397aedd9b84f8d0ab19bea2a5068111166e8a Mon Sep 17 00:00:00 2001 From: Bruce Forstall Date: Mon, 13 Mar 2017 16:32:15 -0700 Subject: [PATCH] Build Linux altjit for x86 and amd64 (dotnet/coreclr#10120) 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 --- src/coreclr/CMakeLists.txt | 5 -- src/coreclr/clrdefinitions.cmake | 6 ++- src/coreclr/src/debug/daccess/nidump.cpp | 4 +- src/coreclr/src/jit/CMakeLists.txt | 7 +-- src/coreclr/src/jit/codegencommon.cpp | 2 +- src/coreclr/src/jit/codegenlinear.h | 8 +-- src/coreclr/src/jit/codegenxarch.cpp | 18 +++---- src/coreclr/src/jit/compiler.cpp | 10 ++-- src/coreclr/src/jit/dll/CMakeLists.txt | 16 ------ src/coreclr/src/jit/ee_il_dll.cpp | 8 +-- src/coreclr/src/jit/emitxarch.cpp | 2 +- src/coreclr/src/jit/jit.h | 32 ++++++++++++ src/coreclr/src/jit/jitstd/type_traits.h | 5 +- src/coreclr/src/jit/linuxnonjit/CMakeLists.txt | 71 ++++++++++++++++++++++++++ src/coreclr/src/jit/target.h | 20 ++------ src/coreclr/src/jit/unwindamd64.cpp | 12 ++--- src/coreclr/src/jit/utils.cpp | 6 +-- src/coreclr/src/jit/valuenum.h | 8 ++- src/coreclr/src/vm/callhelpers.cpp | 4 +- src/coreclr/src/vm/class.h | 14 ++--- src/coreclr/src/vm/jitinterface.cpp | 15 +++++- src/coreclr/src/vm/methodtable.cpp | 2 +- src/coreclr/src/vm/methodtable.h | 16 +++--- src/coreclr/src/vm/methodtablebuilder.cpp | 16 +++--- src/coreclr/src/vm/methodtablebuilder.h | 4 +- 25 files changed, 200 insertions(+), 111 deletions(-) create mode 100644 src/coreclr/src/jit/linuxnonjit/CMakeLists.txt diff --git a/src/coreclr/CMakeLists.txt b/src/coreclr/CMakeLists.txt index 0e1e623..b371432 100644 --- a/src/coreclr/CMakeLists.txt +++ b/src/coreclr/CMakeLists.txt @@ -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 #-------------------------------------- diff --git a/src/coreclr/clrdefinitions.cmake b/src/coreclr/clrdefinitions.cmake index 05f4140..49db1fd 100644 --- a/src/coreclr/clrdefinitions.cmake +++ b/src/coreclr/clrdefinitions.cmake @@ -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) diff --git a/src/coreclr/src/debug/daccess/nidump.cpp b/src/coreclr/src/debug/daccess/nidump.cpp index b2663fe..77c05b5 100644 --- a/src/coreclr/src/debug/daccess/nidump.cpp +++ b/src/coreclr/src/debug/daccess/nidump.cpp @@ -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), diff --git a/src/coreclr/src/jit/CMakeLists.txt b/src/coreclr/src/jit/CMakeLists.txt index ea7de57..8f2170d 100644 --- a/src/coreclr/src/jit/CMakeLists.txt +++ b/src/coreclr/src/jit/CMakeLists.txt @@ -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) diff --git a/src/coreclr/src/jit/codegencommon.cpp b/src/coreclr/src/jit/codegencommon.cpp index fde4a67..4a70b96 100644 --- a/src/coreclr/src/jit/codegencommon.cpp +++ b/src/coreclr/src/jit/codegencommon.cpp @@ -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, diff --git a/src/coreclr/src/jit/codegenlinear.h b/src/coreclr/src/jit/codegenlinear.h index af545fe..52b1f9e 100644 --- a/src/coreclr/src/jit/codegenlinear.h +++ b/src/coreclr/src/jit/codegenlinear.h @@ -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); diff --git a/src/coreclr/src/jit/codegenxarch.cpp b/src/coreclr/src/jit/codegenxarch.cpp index 7639e8b..4917e2c 100644 --- a/src/coreclr/src/jit/codegenxarch.cpp +++ b/src/coreclr/src/jit/codegenxarch.cpp @@ -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, diff --git a/src/coreclr/src/jit/compiler.cpp b/src/coreclr/src/jit/compiler.cpp index 423a0447..4e9c4b3 100644 --- a/src/coreclr/src/jit/compiler.cpp +++ b/src/coreclr/src/jit/compiler.cpp @@ -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 diff --git a/src/coreclr/src/jit/dll/CMakeLists.txt b/src/coreclr/src/jit/dll/CMakeLists.txt index 0e8f5bd3..6d247fe 100644 --- a/src/coreclr/src/jit/dll/CMakeLists.txt +++ b/src/coreclr/src/jit/dll/CMakeLists.txt @@ -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) diff --git a/src/coreclr/src/jit/ee_il_dll.cpp b/src/coreclr/src/jit/ee_il_dll.cpp index a29a3ef..cfbc44c 100644 --- a/src/coreclr/src/jit/ee_il_dll.cpp +++ b/src/coreclr/src/jit/ee_il_dll.cpp @@ -20,7 +20,7 @@ XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX #include "emit.h" #include "corexcep.h" -#if !defined(PLATFORM_UNIX) +#if !defined(_HOST_UNIX_) #include // For _dup, _setmode #include // For _O_TEXT #include // 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(); diff --git a/src/coreclr/src/jit/emitxarch.cpp b/src/coreclr/src/jit/emitxarch.cpp index f672913..7d3b615 100644 --- a/src/coreclr/src/jit/emitxarch.cpp +++ b/src/coreclr/src/jit/emitxarch.cpp @@ -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 diff --git a/src/coreclr/src/jit/jit.h b/src/coreclr/src/jit/jit.h index 05b154e..916b680 100644 --- a/src/coreclr/src/jit/jit.h +++ b/src/coreclr/src/jit/jit.h @@ -172,6 +172,31 @@ #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 // -------------------------------------------------------------------------------- @@ -190,7 +215,14 @@ // 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: diff --git a/src/coreclr/src/jit/jitstd/type_traits.h b/src/coreclr/src/jit/jitstd/type_traits.h index 1e853e8..f0f8518 100644 --- a/src/coreclr/src/jit/jitstd/type_traits.h +++ b/src/coreclr/src/jit/jitstd/type_traits.h @@ -178,14 +178,15 @@ struct make_unsigned typedef unsigned int type; }; -#ifndef PLATFORM_UNIX +#ifndef _HOST_UNIX_ template<> struct make_unsigned { 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 index 0000000..87ec1e4 --- /dev/null +++ b/src/coreclr/src/jit/linuxnonjit/CMakeLists.txt @@ -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) diff --git a/src/coreclr/src/jit/target.h b/src/coreclr/src/jit/target.h index 2cee2c8..a775186 100644 --- a/src/coreclr/src/jit/target.h +++ b/src/coreclr/src/jit/target.h @@ -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 diff --git a/src/coreclr/src/jit/unwindamd64.cpp b/src/coreclr/src/jit/unwindamd64.cpp index 14eba8c..1b2baf6 100644 --- a/src/coreclr/src/jit/unwindamd64.cpp +++ b/src/coreclr/src/jit/unwindamd64.cpp @@ -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); diff --git a/src/coreclr/src/jit/utils.cpp b/src/coreclr/src/jit/utils.cpp index bb76a73..e3654b0 100644 --- a/src/coreclr/src/jit/utils.cpp +++ b/src/coreclr/src/jit/utils.cpp @@ -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_ /*****************************************************************************/ diff --git a/src/coreclr/src/jit/valuenum.h b/src/coreclr/src/jit/valuenum.h index d434b81..2be4849 100644 --- a/src/coreclr/src/jit/valuenum.h +++ b/src/coreclr/src/jit/valuenum.h @@ -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: diff --git a/src/coreclr/src/vm/callhelpers.cpp b/src/coreclr/src/vm/callhelpers.cpp index 18c935a..c575ee6 100644 --- a/src/coreclr/src/vm/callhelpers.cpp +++ b/src/coreclr/src/vm/callhelpers.cpp @@ -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); diff --git a/src/coreclr/src/vm/class.h b/src/coreclr/src/vm/class.h index 756f6d5..6c74377 100644 --- a/src/coreclr/src/vm/class.h +++ b/src/coreclr/src/vm/class.h @@ -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 }; diff --git a/src/coreclr/src/vm/jitinterface.cpp b/src/coreclr/src/vm/jitinterface.cpp index 45239c4..bdccdef 100644 --- a/src/coreclr/src/vm/jitinterface.cpp +++ b/src/coreclr/src/vm/jitinterface.cpp @@ -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; diff --git a/src/coreclr/src/vm/methodtable.cpp b/src/coreclr/src/vm/methodtable.cpp index 2cc2ffe..21fab72 100644 --- a/src/coreclr/src/vm/methodtable.cpp +++ b/src/coreclr/src/vm/methodtable.cpp @@ -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); diff --git a/src/coreclr/src/vm/methodtable.h b/src/coreclr/src/vm/methodtable.h index 6e04b8a..d5cb5ba 100644 --- a/src/coreclr/src/vm/methodtable.h +++ b/src/coreclr/src/vm/methodtable.h @@ -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, diff --git a/src/coreclr/src/vm/methodtablebuilder.cpp b/src/coreclr/src/vm/methodtablebuilder.cpp index fbf9246..7de3510 100644 --- a/src/coreclr/src/vm/methodtablebuilder.cpp +++ b/src/coreclr/src/vm/methodtablebuilder.cpp @@ -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 //--------------------------------------------------------------------------------------- diff --git a/src/coreclr/src/vm/methodtablebuilder.h b/src/coreclr/src/vm/methodtablebuilder.h index 8bfffcc..2aa3683 100644 --- a/src/coreclr/src/vm/methodtablebuilder.h +++ b/src/coreclr/src/vm/methodtablebuilder.h @@ -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 -- 2.7.4