diff --git a/src/coreclr/inc/corinfo.h b/src/coreclr/inc/corinfo.h index 59e65a5d41794d..ae313b4cbbe162 100644 --- a/src/coreclr/inc/corinfo.h +++ b/src/coreclr/inc/corinfo.h @@ -3197,6 +3197,10 @@ class ICorStaticInfo // Returns lowering info for fields of a RISC-V/LoongArch struct passed in registers according to // hardware floating-point calling convention. virtual void getFpStructLowering(CORINFO_CLASS_HANDLE structHnd, CORINFO_FPSTRUCT_LOWERING* pLowering) = 0; + + // Returns the primitive type for passing/returning a Wasm struct by value, + // or CORINFO_WASM_TYPE_VOID if passing/returning must be by reference. + virtual CorInfoWasmType getWasmLowering(CORINFO_CLASS_HANDLE structHnd) = 0; }; /***************************************************************************** diff --git a/src/coreclr/inc/icorjitinfoimpl_generated.h b/src/coreclr/inc/icorjitinfoimpl_generated.h index 600decea333c34..dcd0b89b491c56 100644 --- a/src/coreclr/inc/icorjitinfoimpl_generated.h +++ b/src/coreclr/inc/icorjitinfoimpl_generated.h @@ -535,6 +535,9 @@ void getFpStructLowering( CORINFO_CLASS_HANDLE structHnd, CORINFO_FPSTRUCT_LOWERING* pLowering) override; +CorInfoWasmType getWasmLowering( + CORINFO_CLASS_HANDLE structHnd) override; + uint32_t getThreadTLSIndex( void** ppIndirection) override; diff --git a/src/coreclr/inc/jiteeversionguid.h b/src/coreclr/inc/jiteeversionguid.h index c65beca168e933..709aff447c5e32 100644 --- a/src/coreclr/inc/jiteeversionguid.h +++ b/src/coreclr/inc/jiteeversionguid.h @@ -37,11 +37,11 @@ #include -constexpr GUID JITEEVersionIdentifier = { /* 868b8ae2-0000-410b-a9dc-38d9eda37d66 */ - 0x868b8ae2, - 0x0000, - 0x410b, - {0xa9, 0xdc, 0x38, 0xd9, 0xed, 0xa3, 0x7d, 0x66} +constexpr GUID JITEEVersionIdentifier = { /* 1774da53-2dcd-42cd-bb0f-ae7f66c79e8e */ + 0x1774da53, + 0x2dcd, + 0x42cd, + {0xbb, 0x0f, 0xae, 0x7f, 0x66, 0xc7, 0x9e, 0x8e} }; #endif // JIT_EE_VERSIONING_GUID_H diff --git a/src/coreclr/jit/ICorJitInfo_names_generated.h b/src/coreclr/jit/ICorJitInfo_names_generated.h index c221367761499c..f6d1edf75d754e 100644 --- a/src/coreclr/jit/ICorJitInfo_names_generated.h +++ b/src/coreclr/jit/ICorJitInfo_names_generated.h @@ -132,6 +132,7 @@ DEF_CLR_API(getMethodHash) DEF_CLR_API(getSystemVAmd64PassStructInRegisterDescriptor) DEF_CLR_API(getSwiftLowering) DEF_CLR_API(getFpStructLowering) +DEF_CLR_API(getWasmLowering) DEF_CLR_API(getThreadTLSIndex) DEF_CLR_API(getAddrOfCaptureThreadGlobal) DEF_CLR_API(getHelperFtn) diff --git a/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp b/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp index da6e7be4c998d4..34c2542d89e383 100644 --- a/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp +++ b/src/coreclr/jit/ICorJitInfo_wrapper_generated.hpp @@ -1262,6 +1262,15 @@ void WrapICorJitInfo::getFpStructLowering( API_LEAVE(getFpStructLowering); } +CorInfoWasmType WrapICorJitInfo::getWasmLowering( + CORINFO_CLASS_HANDLE structHnd) +{ + API_ENTER(getWasmLowering); + CorInfoWasmType temp = wrapHnd->getWasmLowering(structHnd); + API_LEAVE(getWasmLowering); + return temp; +} + uint32_t WrapICorJitInfo::getThreadTLSIndex( void** ppIndirection) { diff --git a/src/coreclr/jit/abi.h b/src/coreclr/jit/abi.h index 836540e1578b7c..08b9dcf5dcdc21 100644 --- a/src/coreclr/jit/abi.h +++ b/src/coreclr/jit/abi.h @@ -343,6 +343,8 @@ class WasmClassifier return 0; } + static var_types ToJitType(CorInfoWasmType wasmType); + ABIPassingInformation Classify(Compiler* comp, var_types type, ClassLayout* structLayout, diff --git a/src/coreclr/jit/codegencommon.cpp b/src/coreclr/jit/codegencommon.cpp index b7620a2d8e41e3..e866d340d317a1 100644 --- a/src/coreclr/jit/codegencommon.cpp +++ b/src/coreclr/jit/codegencommon.cpp @@ -1876,18 +1876,12 @@ void CodeGen::genGenerateMachineCode() } printf(" for "); + printf(Target::g_tgtCPUName); #if defined(TARGET_XARCH) -#if defined(TARGET_64BIT) - printf("generic X64"); -#else - printf("generic X86"); -#endif - // Check ISA directly here instead of using // compOpportunisticallyDependsOn to avoid JIT-EE calls that could make // us miss in SPMI - if (m_compiler->opts.compSupportsISA.HasInstructionSet(InstructionSet_AVX)) { printf(" + VEX"); @@ -1902,21 +1896,11 @@ void CodeGen::genGenerateMachineCode() { printf(" + APX"); } -#elif defined(TARGET_ARM) - printf("generic ARM"); #elif defined(TARGET_ARM64) - printf("generic ARM64"); - if (m_compiler->opts.compSupportsISA.HasInstructionSet(InstructionSet_Sve)) { printf(" + SVE"); } -#elif defined(TARGET_LOONGARCH64) - printf("generic LOONGARCH64"); -#elif defined(TARGET_RISCV64) - printf("generic RISCV64"); -#else - printf("unknown architecture"); #endif if (TargetOS::IsWindows) diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index 379c33ab5a5042..256c10457b7593 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -756,6 +756,38 @@ var_types Compiler::getReturnTypeForStruct(CORINFO_CLASS_HANDLE clsHnd, } assert(structSize > 0); +#if defined(TARGET_WASM) + CorInfoWasmType abiType = info.compCompHnd->getWasmLowering(clsHnd); + + if (abiType == CORINFO_WASM_TYPE_VOID) + { + howToReturnStruct = SPK_ByReference; + useType = TYP_UNKNOWN; + } + else + { + howToReturnStruct = SPK_ByValue; + useType = WasmClassifier::ToJitType(abiType); + } + + if (wbReturnStruct != nullptr) + { + *wbReturnStruct = howToReturnStruct; + } + + return useType; +#else +#ifdef DEBUG + // Extra query to facilitate wasm replay of native collections. + // TODO-WASM: delete once we can get a wasm collection. + // + if (JitConfig.EnableExtraSuperPmiQueries() && IsReadyToRun()) + { + info.compCompHnd->getWasmLowering(clsHnd); + } +#endif // DEBUG +#endif // defined(TARGET_WASM) + #ifdef SWIFT_SUPPORT if (callConv == CorInfoCallConvExtension::Swift) { diff --git a/src/coreclr/jit/lclvars.cpp b/src/coreclr/jit/lclvars.cpp index 0e9882e85b739b..6238a4883335aa 100644 --- a/src/coreclr/jit/lclvars.cpp +++ b/src/coreclr/jit/lclvars.cpp @@ -954,6 +954,20 @@ void Compiler::lvaClassifyParameterABI(Classifier& classifier) dsc->lvIsRegArg = numRegisters > 0; dsc->lvIsMultiRegArg = numRegisters > 1; + +#ifdef DEBUG + // Extra query to facilitate wasm replay of native collections. + // TODO-WASM: delete once we can get a wasm collection. + // + if (JitConfig.EnableExtraSuperPmiQueries() && IsReadyToRun() && (structLayout != nullptr)) + { + CORINFO_CLASS_HANDLE clsHnd = structLayout->GetClassHandle(); + if (clsHnd != NO_CLASS_HANDLE) + { + info.compCompHnd->getWasmLowering(clsHnd); + } + } +#endif // DEBUG } lvaParameterStackSize = classifier.StackSize(); diff --git a/src/coreclr/jit/targetwasm.cpp b/src/coreclr/jit/targetwasm.cpp index 56f342f3af3886..c396e9b602f3d1 100644 --- a/src/coreclr/jit/targetwasm.cpp +++ b/src/coreclr/jit/targetwasm.cpp @@ -27,6 +27,32 @@ WasmClassifier::WasmClassifier(const ClassifierInfo& info) { } +//----------------------------------------------------------------------------- +// ToJitType: translate CorInfoWasmType to var_types +// +// Parameters: +// wasmType -- wasm type to translate +// +var_types WasmClassifier::ToJitType(CorInfoWasmType wasmType) +{ + switch (wasmType) + { + case CORINFO_WASM_TYPE_I32: + return TYP_INT; + case CORINFO_WASM_TYPE_I64: + return TYP_LONG; + case CORINFO_WASM_TYPE_F32: + return TYP_FLOAT; + case CORINFO_WASM_TYPE_F64: + return TYP_DOUBLE; + case CORINFO_WASM_TYPE_V128: + // TODO-WASM: Simd support + unreached(); + default: + unreached(); + } +} + //----------------------------------------------------------------------------- // Classify: // Classify a parameter for the Wasm ABI. @@ -48,7 +74,25 @@ ABIPassingInformation WasmClassifier::Classify(Compiler* comp, { if (type == TYP_STRUCT) { - NYI_WASM("WasmClassifier::Classify - structs"); + CORINFO_CLASS_HANDLE clsHnd = structLayout->GetClassHandle(); + assert(clsHnd != NO_CLASS_HANDLE); + CorInfoWasmType wasmAbiType = comp->info.compCompHnd->getWasmLowering(clsHnd); + bool passByRef = false; + var_types abiType = TYP_UNDEF; + + if (wasmAbiType == CORINFO_WASM_TYPE_VOID) + { + abiType = TYP_I_IMPL; + passByRef = true; + } + else + { + abiType = ToJitType(wasmAbiType); + } + + regNumber reg = MakeWasmReg(m_localIndex++, genActualType(abiType)); + ABIPassingSegment seg = ABIPassingSegment::InRegister(reg, 0, genTypeSize(abiType)); + return ABIPassingInformation::FromSegment(comp, passByRef, seg); } regNumber reg = MakeWasmReg(m_localIndex++, genActualType(type)); diff --git a/src/coreclr/tools/Common/Compiler/ObjectWriter/Dwarf/DwarfHelper.cs b/src/coreclr/tools/Common/Compiler/ObjectWriter/Dwarf/DwarfHelper.cs index 68be8c292aac51..abea62e7ed90f9 100644 --- a/src/coreclr/tools/Common/Compiler/ObjectWriter/Dwarf/DwarfHelper.cs +++ b/src/coreclr/tools/Common/Compiler/ObjectWriter/Dwarf/DwarfHelper.cs @@ -7,7 +7,7 @@ namespace ILCompiler.ObjectWriter { - internal static class DwarfHelper + public static class DwarfHelper { public static uint SizeOfULEB128(ulong value) { diff --git a/src/coreclr/tools/Common/Compiler/ObjectWriter/WasmObjectWriter.cs b/src/coreclr/tools/Common/Compiler/ObjectWriter/WasmObjectWriter.cs index c3b677b9a9e08f..f69b003b0e9f91 100644 --- a/src/coreclr/tools/Common/Compiler/ObjectWriter/WasmObjectWriter.cs +++ b/src/coreclr/tools/Common/Compiler/ObjectWriter/WasmObjectWriter.cs @@ -68,7 +68,7 @@ private protected override void RecordMethodSignature(ISymbolDefinitionNode symb private void MaybeWriteType(MethodDesc desc) { - WasmFuncType signature = WasmAbiContext.GetSignature(desc); + WasmFuncType signature = Internal.JitInterface.WasmLowering.GetSignature(desc); if (_uniqueSignatures.ContainsKey(signature)) { return; @@ -89,7 +89,7 @@ private void WriteSignatureIndexForFunction(MethodDesc desc) { SectionWriter writer = GetOrCreateSection(WasmObjectNodeSection.FunctionSection); - WasmFuncType signature = WasmAbiContext.GetSignature(desc); + WasmFuncType signature = Internal.JitInterface.WasmLowering.GetSignature(desc); if (!_uniqueSignatures.TryGetValue(signature, out int signatureIndex)) { throw new InvalidOperationException($"Signature index not found for function: {desc.GetName()}"); @@ -385,103 +385,6 @@ private protected override void EmitSymbolTable(IDictionary - /// Gets the Wasm-level signature for a given MethodDesc. - /// - /// Parameters for managed Wasm calls have the following layout: - /// i32 (SP), loweredParam0, ..., loweredParamN, i32 (PE entrypoint) - /// - /// For unmanaged callers only (reverse P/Invoke), the layout is simply the native signature - /// which is just the lowered parameters+return. - /// - /// - /// - public static WasmFuncType GetSignature(MethodDesc method) - { - // TODO-WASM: handle struct by-value return (extra parameter pointing to buffer must be in signature) - // TODO-WASM: handle seemingly by-value struct arguments that are actually passed implicitly by reference - - MethodSignature signature = method.Signature; - TypeDesc returnType = signature.ReturnType; - Span wasmParameters, lowered; - if (method.IsUnmanagedCallersOnly) // reverse P/Invoke - { - wasmParameters = new WasmValueType[signature.Length]; - lowered = wasmParameters; - } - else // managed call - { - wasmParameters = new WasmValueType[signature.Length + 2]; - wasmParameters[0] = WasmValueType.I32; // Stack pointer parameter - wasmParameters[wasmParameters.Length - 1] = WasmValueType.I32; // PE entrypoint parameter - - lowered = wasmParameters.Slice(1, wasmParameters.Length - 2); - } - - Debug.Assert(lowered.Length == signature.Length); - for (int i = 0; i < signature.Length; i++) - { - lowered[i] = LowerType(signature[i]); - } - - WasmResultType ps = new(wasmParameters.ToArray()); - WasmResultType ret = signature.ReturnType.IsVoid ? new(Array.Empty()) - : new([LowerType(returnType)]); - - return new WasmFuncType(ps, ret); - } - } - internal class WasmSection { public WasmSectionType Type { get; } diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index 7391b3c64be4fe..e0943d3fb6c99d 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -31,6 +31,8 @@ using ILCompiler.DependencyAnalysis.ReadyToRun; #endif +using ILCompiler.ObjectWriter; + using DependencyList = ILCompiler.DependencyAnalysisFramework.DependencyNodeCore.DependencyList; #pragma warning disable IDE0060 @@ -3674,6 +3676,52 @@ private void getFpStructLowering(CORINFO_CLASS_STRUCT_* structHnd, ref CORINFO_F } } + private CorInfoWasmType getWasmLowering(CORINFO_CLASS_STRUCT_* structHnd) + { + TypeDesc type = HandleToObject(structHnd); + +#if READYTORUN + LayoutInt classSize = type.GetElementSize(); + + if (classSize.IsIndeterminate) + { + throw new RequiresRuntimeJitException(type); + } + + if (NeedsTypeLayoutCheck(type)) + { + ISymbolNode node = _compilation.SymbolNodeFactory.CheckTypeLayout(type); + AddPrecodeFixup(node); + } +#endif + + TypeDesc abiType = WasmLowering.LowerToAbiType(type); + + if (abiType == null) + { + // Indicate type should be passed by-ref. + return CorInfoWasmType.CORINFO_WASM_TYPE_VOID; + } + + WasmValueType wasmAbiType = WasmLowering.LowerType(abiType); + + switch (wasmAbiType) + { + case WasmValueType.I32: + return CorInfoWasmType.CORINFO_WASM_TYPE_I32; + case WasmValueType.I64: + return CorInfoWasmType.CORINFO_WASM_TYPE_I64; + case WasmValueType.F32: + return CorInfoWasmType.CORINFO_WASM_TYPE_F32; + case WasmValueType.F64: + return CorInfoWasmType.CORINFO_WASM_TYPE_F64; + default: + ThrowHelper.ThrowInvalidProgramException(); + return CorInfoWasmType.CORINFO_WASM_TYPE_I32; // unreachable + + } + } + private uint getThreadTLSIndex(ref void* ppIndirection) { throw new NotImplementedException("getThreadTLSIndex"); } diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs index 9ada9df6223120..0981c611697392 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl_generated.cs @@ -148,6 +148,7 @@ static ICorJitInfoCallbacks() s_callbacks.getSystemVAmd64PassStructInRegisterDescriptor = &_getSystemVAmd64PassStructInRegisterDescriptor; s_callbacks.getSwiftLowering = &_getSwiftLowering; s_callbacks.getFpStructLowering = &_getFpStructLowering; + s_callbacks.getWasmLowering = &_getWasmLowering; s_callbacks.getThreadTLSIndex = &_getThreadTLSIndex; s_callbacks.getAddrOfCaptureThreadGlobal = &_getAddrOfCaptureThreadGlobal; s_callbacks.getHelperFtn = &_getHelperFtn; @@ -328,6 +329,7 @@ static ICorJitInfoCallbacks() public delegate* unmanaged getSystemVAmd64PassStructInRegisterDescriptor; public delegate* unmanaged getSwiftLowering; public delegate* unmanaged getFpStructLowering; + public delegate* unmanaged getWasmLowering; public delegate* unmanaged getThreadTLSIndex; public delegate* unmanaged getAddrOfCaptureThreadGlobal; public delegate* unmanaged getHelperFtn; @@ -2273,6 +2275,21 @@ private static void _getFpStructLowering(IntPtr thisHandle, IntPtr* ppException, } } + [UnmanagedCallersOnly] + private static CorInfoWasmType _getWasmLowering(IntPtr thisHandle, IntPtr* ppException, CORINFO_CLASS_STRUCT_* structHnd) + { + var _this = GetThis(thisHandle); + try + { + return _this.getWasmLowering(structHnd); + } + catch (Exception ex) + { + *ppException = _this.AllocException(ex); + return default; + } + } + [UnmanagedCallersOnly] private static uint _getThreadTLSIndex(IntPtr thisHandle, IntPtr* ppException, void** ppIndirection) { diff --git a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt index fc15811ce83e67..53a90e73eb9ea8 100644 --- a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt +++ b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt @@ -301,6 +301,7 @@ FUNCTIONS bool getSystemVAmd64PassStructInRegisterDescriptor(CORINFO_CLASS_HANDLE structHnd, SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* structPassInRegDescPtr); void getSwiftLowering(CORINFO_CLASS_HANDLE structHnd, CORINFO_SWIFT_LOWERING* pLowering); void getFpStructLowering(CORINFO_CLASS_HANDLE structHnd, CORINFO_FPSTRUCT_LOWERING* pLowering); + CorInfoWasmType getWasmLowering(CORINFO_CLASS_HANDLE structHnd); uint32_t getThreadTLSIndex(void **ppIndirection); int32_t * getAddrOfCaptureThreadGlobal(void **ppIndirection); void getHelperFtn (CorInfoHelpFunc ftnNum, CORINFO_CONST_LOOKUP* pNativeEntrypoint, CORINFO_METHOD_HANDLE *pMethod); diff --git a/src/coreclr/tools/Common/JitInterface/WasmLowering.cs b/src/coreclr/tools/Common/JitInterface/WasmLowering.cs new file mode 100644 index 00000000000000..606c305a8a616e --- /dev/null +++ b/src/coreclr/tools/Common/JitInterface/WasmLowering.cs @@ -0,0 +1,219 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Diagnostics; +using Internal.TypeSystem; +using ILCompiler.ObjectWriter; + +namespace Internal.JitInterface +{ + public static class WasmLowering + { + // The Wasm "basic C ABI" passes structs that contain one + // primitive field as that primitive field. + // + // Analyze the type and determine if it should be passed + // as a primitive, and if so, which type. If not, return + // null. + + public static TypeDesc LowerToAbiType(TypeDesc type) + { + if (!(type.IsValueType && !type.IsPrimitive)) + { + return type; + } + + int size = type.GetElementSize().AsInt; + + while (true) + { + FieldDesc firstField = null; + int numIntroducedFields = 0; + foreach (FieldDesc field in type.GetFields()) + { + if (!field.IsStatic) + { + firstField ??= field; + numIntroducedFields++; + } + + if (numIntroducedFields > 1) + { + break; + } + } + + if (numIntroducedFields != 1) + { + return null; + } + + TypeDesc firstFieldElementType = firstField.FieldType; + + if (firstFieldElementType.GetElementSize().AsInt != size) + { + // One-field struct with padding. + return null; + } + + type = firstFieldElementType; + + if (type.IsValueType && !type.IsPrimitive) + { + continue; + } + + return type; + } + } + + public static WasmValueType LowerType(TypeDesc type) + { + WasmValueType pointerType = (type.Context.Target.PointerSize == 4) ? WasmValueType.I32 : WasmValueType.I64; + + TypeDesc abiType = LowerToAbiType(type); + + switch (abiType.UnderlyingType.Category) + { + case TypeFlags.Int32: + case TypeFlags.UInt32: + case TypeFlags.Boolean: + case TypeFlags.Char: + case TypeFlags.Byte: + case TypeFlags.SByte: + case TypeFlags.Int16: + case TypeFlags.UInt16: + return WasmValueType.I32; + + case TypeFlags.Int64: + case TypeFlags.UInt64: + return WasmValueType.I64; + + case TypeFlags.Single: + return WasmValueType.F32; + + case TypeFlags.Double: + return WasmValueType.F64; + + // Pointer and reference types + case TypeFlags.IntPtr: + case TypeFlags.UIntPtr: + case TypeFlags.Class: + case TypeFlags.Interface: + case TypeFlags.Array: + case TypeFlags.SzArray: + case TypeFlags.ByRef: + case TypeFlags.Pointer: + case TypeFlags.FunctionPointer: + return pointerType; + + default: + throw new NotSupportedException($"Unknown wasm mapping for type: {type.UnderlyingType.Category}"); + } + } + + /// + /// Gets the Wasm-level signature for a given MethodDesc. + /// + /// Parameters for managed Wasm calls have the following layout: + /// i32 (SP), loweredParam0, ..., loweredParamN, i32 (PE entrypoint) + /// + /// For unmanaged callers only (reverse P/Invoke), the layout is simply the native signature + /// which is just the lowered parameters+return. + /// + /// + /// + public static WasmFuncType GetSignature(MethodDesc method) + { + MethodSignature signature = method.Signature; + TypeDesc returnType = signature.ReturnType; + WasmValueType pointerType = (method.Context.Target.PointerSize == 4) ? WasmValueType.I32 : WasmValueType.I64; + + // Determine if the return value is via a return buffer + // + TypeDesc loweredReturnType = LowerToAbiType(returnType); + bool hasReturnBuffer = false; + bool returnIsVoid = false; + bool hasThis = false; + bool explicitThis = false; + + if (loweredReturnType == null) + { + hasReturnBuffer = true; + returnIsVoid = true; + } + else if (loweredReturnType.IsVoid) + { + returnIsVoid = true; + } + + int parameterCount = signature.Length; + + if (hasReturnBuffer) + { + parameterCount++; // return buffer + } + + if (!method.IsUnmanagedCallersOnly) + { + parameterCount += 2; // sp and pe + } + + if (!signature.IsStatic) + { + hasThis = true; + + if (signature.IsExplicitThis) + { + explicitThis = true; + } + else + { + parameterCount += 1; // implicit this + } + } + + Span wasmParameters = new WasmValueType[parameterCount]; + + int index = 0; + + if (method.IsUnmanagedCallersOnly) // reverse P/Invoke + { + if (hasReturnBuffer) + { + wasmParameters[index++] = pointerType; + } + } + else // managed call + { + wasmParameters[0] = pointerType; // Stack pointer parameter + + // Return buffer is first after this. + + if (hasThis) + { + wasmParameters[index++] = pointerType; + } + + if (hasReturnBuffer) + { + wasmParameters[index++] = pointerType; + } + + wasmParameters[wasmParameters.Length - 1] = pointerType; // PE entrypoint parameter + } + + for (int i = explicitThis ? 1 : 0; i < signature.Length; i++) + { + wasmParameters[index++] = LowerType(signature[i]); + } + + WasmResultType ps = new(wasmParameters.ToArray()); + WasmResultType ret = returnIsVoid ? new(Array.Empty()) + : new([LowerType(loweredReturnType)]); + + return new WasmFuncType(ps, ret); + } + } +} diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj index cb7b001082722b..1cff95dd437131 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj @@ -148,6 +148,7 @@ + diff --git a/src/coreclr/tools/aot/ILCompiler.RyuJit/ILCompiler.RyuJit.csproj b/src/coreclr/tools/aot/ILCompiler.RyuJit/ILCompiler.RyuJit.csproj index 8fa7b6865ae5ca..74cf5ecc08ad51 100644 --- a/src/coreclr/tools/aot/ILCompiler.RyuJit/ILCompiler.RyuJit.csproj +++ b/src/coreclr/tools/aot/ILCompiler.RyuJit/ILCompiler.RyuJit.csproj @@ -50,6 +50,9 @@ Compiler\JitHelper.cs + + ObjectWriter\WasmNative + IL\HelperExtensions.cs @@ -89,6 +92,9 @@ JitInterface\SwiftPhysicalLowering.cs + + JitInterface\WasmLowering.cs + Pgo\TypeSystemEntityOrUnknown.cs diff --git a/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h b/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h index 94f4bd19349961..9d66ed8ac70f86 100644 --- a/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h +++ b/src/coreclr/tools/aot/jitinterface/jitinterface_generated.h @@ -139,6 +139,7 @@ struct JitInterfaceCallbacks bool (* getSystemVAmd64PassStructInRegisterDescriptor)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE structHnd, SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* structPassInRegDescPtr); void (* getSwiftLowering)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE structHnd, CORINFO_SWIFT_LOWERING* pLowering); void (* getFpStructLowering)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE structHnd, CORINFO_FPSTRUCT_LOWERING* pLowering); + CorInfoWasmType (* getWasmLowering)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE structHnd); uint32_t (* getThreadTLSIndex)(void * thisHandle, CorInfoExceptionClass** ppException, void** ppIndirection); int32_t* (* getAddrOfCaptureThreadGlobal)(void * thisHandle, CorInfoExceptionClass** ppException, void** ppIndirection); void (* getHelperFtn)(void * thisHandle, CorInfoExceptionClass** ppException, CorInfoHelpFunc ftnNum, CORINFO_CONST_LOOKUP* pNativeEntrypoint, CORINFO_METHOD_HANDLE* pMethod); @@ -1442,6 +1443,15 @@ class JitInterfaceWrapper : public ICorJitInfo if (pException != nullptr) throw pException; } + virtual CorInfoWasmType getWasmLowering( + CORINFO_CLASS_HANDLE structHnd) +{ + CorInfoExceptionClass* pException = nullptr; + CorInfoWasmType temp = _callbacks->getWasmLowering(_thisHandle, &pException, structHnd); + if (pException != nullptr) throw pException; + return temp; +} + virtual uint32_t getThreadTLSIndex( void** ppIndirection) { diff --git a/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h b/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h index 1ddd421e1e5cd3..9240baa75f0d69 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h @@ -127,6 +127,7 @@ LWM(GetStringConfigValue, DWORD, DWORD) LWM(GetSystemVAmd64PassStructInRegisterDescriptor, DWORDLONG, Agnostic_GetSystemVAmd64PassStructInRegisterDescriptor) LWM(GetSwiftLowering, DWORDLONG, Agnostic_GetSwiftLowering) LWM(GetFpStructLowering, DWORDLONG, Agnostic_GetFpStructLowering) +LWM(GetWasmLowering, DWORDLONG, DWORD) LWM(GetTailCallHelpers, Agnostic_GetTailCallHelpers, Agnostic_CORINFO_TAILCALL_HELPERS) LWM(GetAsyncResumptionStub, DWORD, DLDL) LWM(GetContinuationType, Agnostic_GetContinuationTypeIn, DWORDLONG) diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp index bfc8aeecfaa774..61d85acbda1c0e 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp @@ -6447,6 +6447,26 @@ void MethodContext::repGetFpStructLowering(CORINFO_CLASS_HANDLE structHnd, CORIN } } +void MethodContext::recGetWasmLowering(CORINFO_CLASS_HANDLE structHnd, CorInfoWasmType value) +{ + if (GetWasmLowering == nullptr) + GetWasmLowering = new LightWeightMap(); + DWORDLONG key = CastHandle(structHnd); + GetWasmLowering->Add(key, (DWORD) value); + DEBUG_REC(dmpGetWasmLowering(key, value)); +} +void MethodContext::dmpGetWasmLowering(DWORDLONG key, DWORD value) +{ + printf("GetWasmLowering key structHnd-%016" PRIX64 ", value %d ", key, value); +} +CorInfoWasmType MethodContext::repGetWasmLowering(CORINFO_CLASS_HANDLE structHnd) +{ + DWORDLONG key = CastHandle(structHnd); + DWORD value = LookupByKeyOrMiss(GetWasmLowering, key, ": key %016" PRIX64 "", key); + DEBUG_REP(dmpGetWasmLowering(key, value)); + return (CorInfoWasmType) value; +} + void MethodContext::recGetRelocTypeHint(void* target, CorInfoReloc result) { if (GetRelocTypeHint == nullptr) diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h index cdabbf70947647..7b19b948b26316 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h @@ -786,6 +786,10 @@ class MethodContext void dmpGetFpStructLowering(DWORDLONG key, const Agnostic_GetFpStructLowering& value); void repGetFpStructLowering(CORINFO_CLASS_HANDLE structHnd, CORINFO_FPSTRUCT_LOWERING* pLowering); + void recGetWasmLowering(CORINFO_CLASS_HANDLE structHnd, CorInfoWasmType wasmType); + void dmpGetWasmLowering(DWORDLONG key, DWORD value); + CorInfoWasmType repGetWasmLowering(CORINFO_CLASS_HANDLE structHnd); + void recGetRelocTypeHint(void* target, CorInfoReloc result); void dmpGetRelocTypeHint(DWORDLONG key, DWORD value); CorInfoReloc repGetRelocTypeHint(void* target); @@ -1214,6 +1218,7 @@ enum mcPackets Packet_GetHelperFtn = 233, Packet_GetContinuationType = 234, Packet_GetWasmTypeSymbol = 235, + Packet_GetWasmLowering = 236, }; void SetDebugDumpVariables(); diff --git a/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp index bf9ec80597d5a0..e863e5bff38506 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp @@ -1454,6 +1454,14 @@ void interceptor_ICJI::getFpStructLowering(CORINFO_CLASS_HANDLE structHnd, CORIN mc->recGetFpStructLowering(structHnd, pLowering); } +CorInfoWasmType interceptor_ICJI::getWasmLowering(CORINFO_CLASS_HANDLE structHnd) +{ + mc->cr->AddCall("getWasmLowering"); + CorInfoWasmType result = original_ICorJitInfo->getWasmLowering(structHnd); + mc->recGetWasmLowering(structHnd, result); + return result; +} + // Stuff on ICorDynamicInfo uint32_t interceptor_ICJI::getThreadTLSIndex(void** ppIndirection) { diff --git a/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp index c4f0ef3c9df7d4..2979dfd9510069 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo_generated.cpp @@ -1038,6 +1038,13 @@ void interceptor_ICJI::getFpStructLowering( original_ICorJitInfo->getFpStructLowering(structHnd, pLowering); } +CorInfoWasmType interceptor_ICJI::getWasmLowering( + CORINFO_CLASS_HANDLE structHnd) +{ + mcs->AddCall("getWasmLowering"); + return original_ICorJitInfo->getWasmLowering(structHnd); +} + uint32_t interceptor_ICJI::getThreadTLSIndex( void** ppIndirection) { diff --git a/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp index e9e868b34d3ea2..08e78c61e56ce8 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo_generated.cpp @@ -910,6 +910,12 @@ void interceptor_ICJI::getFpStructLowering( original_ICorJitInfo->getFpStructLowering(structHnd, pLowering); } +CorInfoWasmType interceptor_ICJI::getWasmLowering( + CORINFO_CLASS_HANDLE structHnd) +{ + return original_ICorJitInfo->getWasmLowering(structHnd); +} + uint32_t interceptor_ICJI::getThreadTLSIndex( void** ppIndirection) { diff --git a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp index 4acaa81cbc3f16..dd790c0272e886 100644 --- a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp @@ -1268,6 +1268,12 @@ void MyICJI::getFpStructLowering(CORINFO_CLASS_HANDLE structHnd, CORINFO_FPSTRUC jitInstance->mc->repGetFpStructLowering(structHnd, pLowering); } +CorInfoWasmType MyICJI::getWasmLowering(CORINFO_CLASS_HANDLE structHnd) +{ + jitInstance->mc->cr->AddCall("getWasmLowering"); + return jitInstance->mc->repGetWasmLowering(structHnd); +} + // Stuff on ICorDynamicInfo uint32_t MyICJI::getThreadTLSIndex(void** ppIndirection) { diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index bec8a1f3cbdce2..5824d737c2255d 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -2569,6 +2569,14 @@ void CEEInfo::getSwiftLowering(CORINFO_CLASS_HANDLE structHnd, CORINFO_SWIFT_LOW EE_TO_JIT_TRANSITION(); } +CorInfoWasmType CEEInfo::getWasmLowering(CORINFO_CLASS_HANDLE structHnd) +{ + LIMITED_METHOD_CONTRACT; + // Only needed for a Wasm Jit. + UNREACHABLE(); + return CORINFO_WASM_TYPE_VOID; +} + /*********************************************************************/ unsigned CEEInfo::getClassNumInstanceFields (CORINFO_CLASS_HANDLE clsHnd) {