diff --git a/src/coreclr/interpreter/compiler.cpp b/src/coreclr/interpreter/compiler.cpp index 45d931af5529aa..84b4155ddab4f2 100644 --- a/src/coreclr/interpreter/compiler.cpp +++ b/src/coreclr/interpreter/compiler.cpp @@ -2725,6 +2725,14 @@ void InterpCompiler::EmitCompareOp(int32_t opBase) EmitConv(m_pStackPointer - 1, StackTypeR8, INTOP_CONV_R8_R4); if (m_pStackPointer[-1].type == StackTypeR8 && m_pStackPointer[-2].type == StackTypeR4) EmitConv(m_pStackPointer - 2, StackTypeR8, INTOP_CONV_R8_R4); + +#ifdef TARGET_64BIT + // Support comparisons between I and I4 by inserting an implicit conversion to I8 + if (m_pStackPointer[-1].type == StackTypeI4 && m_pStackPointer[-2].type == StackTypeI8) + EmitConv(m_pStackPointer - 1, StackTypeI8, INTOP_CONV_I8_I4); + if (m_pStackPointer[-1].type == StackTypeI8 && m_pStackPointer[-2].type == StackTypeI4) + EmitConv(m_pStackPointer - 2, StackTypeI8, INTOP_CONV_I8_I4); +#endif AddIns(opBase + m_pStackPointer[-1].type - StackTypeI4); } m_pStackPointer -= 2; @@ -4591,7 +4599,20 @@ void InterpCompiler::EmitLdelem(int32_t opcode, InterpType interpType) void InterpCompiler::EmitStelem(InterpType interpType) { +#ifdef TARGET_64BIT + // nint and int32 can be used interchangeably. Add implicit conversions. + if (m_pStackPointer[-1].type == StackTypeI4 && g_stackTypeFromInterpType[interpType] == StackTypeI8) + EmitConv(m_pStackPointer - 1, StackTypeI8, INTOP_CONV_I8_I4); +#endif + + // Handle floating point conversions + if (m_pStackPointer[-1].type == StackTypeR4 && g_stackTypeFromInterpType[interpType] == StackTypeR8) + EmitConv(m_pStackPointer - 1, StackTypeR8, INTOP_CONV_R8_R4); + else if (m_pStackPointer[-1].type == StackTypeR8 && g_stackTypeFromInterpType[interpType] == StackTypeR4) + EmitConv(m_pStackPointer - 1, StackTypeR4, INTOP_CONV_R4_R8); + m_pStackPointer -= 3; + int32_t opcode = GetStelemForType(interpType); AddIns(opcode); m_pLastNewIns->SetSVars3(m_pStackPointer[0].var, m_pStackPointer[1].var, m_pStackPointer[2].var); @@ -5841,6 +5862,36 @@ void InterpCompiler::GenerateCode(CORINFO_METHOD_INFO* methodInfo) else { CheckStackExact(1); + +#ifdef TARGET_64BIT + // nint and int32 can be used interchangeably. Add implicit conversions. + if (m_pStackPointer[-1].type == StackTypeI4 && g_stackTypeFromInterpType[retType] == StackTypeI8) + EmitConv(m_pStackPointer - 1, StackTypeI8, INTOP_CONV_I8_I4); +#endif + if (m_pStackPointer[-1].type == StackTypeR4 && g_stackTypeFromInterpType[retType] == StackTypeR8) + EmitConv(m_pStackPointer - 1, StackTypeR8, INTOP_CONV_R8_R4); + else if (m_pStackPointer[-1].type == StackTypeR8 && g_stackTypeFromInterpType[retType] == StackTypeR4) + EmitConv(m_pStackPointer - 1, StackTypeR4, INTOP_CONV_R4_R8); + + if (m_pStackPointer[-1].type != g_stackTypeFromInterpType[retType]) + { + StackType retStackType = g_stackTypeFromInterpType[retType]; + StackType stackType = m_pStackPointer[-1].type; + + if (stackType == StackTypeI && (retStackType == StackTypeO || retStackType == StackTypeByRef)) + { + // Allow implicit conversion from nint to ref or byref + } + else if (retStackType == StackTypeI && (stackType == StackTypeO || stackType == StackTypeByRef)) + { + // Allow implicit conversion from ref or byref to nint + } + else + { + BADCODE("return type mismatch"); + } + } + AddIns(INTOP_RET); m_pStackPointer--; m_pLastNewIns->SetSVar(m_pStackPointer[0].var);