@@ -2233,7 +2233,7 @@ void InterpCompiler::CreateBasicBlocks(CORINFO_METHOD_INFO* methodInfo)
22332233 default :
22342234 assert (0 );
22352235 }
2236- if (opcode == CEE_THROW || opcode == CEE_ENDFINALLY || opcode == CEE_RETHROW)
2236+ if (opcode == CEE_THROW || opcode == CEE_ENDFINALLY || opcode == CEE_RETHROW || opcode == CEE_JMP )
22372237 GetBB ((int32_t )(ip - codeStart));
22382238 }
22392239}
@@ -3898,6 +3898,7 @@ void InterpCompiler::EmitCall(CORINFO_RESOLVED_TOKEN* pConstrainedToken, bool re
38983898
38993899 bool isVirtual = (*m_ip == CEE_CALLVIRT);
39003900 bool isDelegateInvoke = false ;
3901+ bool isJmp = (*m_ip == CEE_JMP);
39013902
39023903 CORINFO_RESOLVED_TOKEN resolvedCallToken;
39033904 CORINFO_CALL_INFO callInfo;
@@ -3941,6 +3942,16 @@ void InterpCompiler::EmitCall(CORINFO_RESOLVED_TOKEN* pConstrainedToken, bool re
39413942 BADCODE (" Vararg methods are not supported in interpreted code" );
39423943 }
39433944
3945+ if (isJmp)
3946+ {
3947+ if (callInfo.sig .numArgs != m_methodInfo->args .numArgs ||
3948+ callInfo.sig .retType != m_methodInfo->args .retType ||
3949+ callInfo.sig .callConv != m_methodInfo->args .callConv )
3950+ {
3951+ BADCODE (" Incompatible target for CEE_JMP" );
3952+ }
3953+ }
3954+
39443955 // Inject call to callsite callout helper
39453956 EmitCallsiteCallout (callInfo.accessAllowed , &callInfo.callsiteCalloutHelper );
39463957
@@ -4029,6 +4040,16 @@ void InterpCompiler::EmitCall(CORINFO_RESOLVED_TOKEN* pConstrainedToken, bool re
40294040 CORINFO_ARG_LIST_HANDLE args;
40304041 args = callInfo.sig .args ;
40314042
4043+ if (isJmp)
4044+ {
4045+ assert (tailcall);
4046+ // CEE_JMP is simulated as a tail call, so we need to load the current method's args
4047+ for (int i = 0 ; i < numArgsFromStack; i++)
4048+ {
4049+ EmitLoadVar (i);
4050+ }
4051+ }
4052+
40324053 for (int iActualArg = 0 , iLogicalArg = 0 ; iActualArg < numArgs; iActualArg++)
40334054 {
40344055 if (iActualArg == extraParamArgLocation)
@@ -6970,6 +6991,18 @@ void InterpCompiler::GenerateCode(CORINFO_METHOD_INFO* methodInfo)
69706991 EmitUnaryArithmeticOp (INTOP_NOT_I4);
69716992 m_ip++;
69726993 break ;
6994+ case CEE_JMP:
6995+ {
6996+ CHECK_STACK (0 );
6997+ if (m_pCBB->clauseType != BBClauseNone)
6998+ {
6999+ // CEE_JMP inside a funclet is not allowed
7000+ BADCODE (" CEE_JMP inside funclet" );
7001+ }
7002+ EmitCall (pConstrainedToken, readonly, true /* tailcall */ , false /* newObj*/ , false /* isCalli*/ );
7003+ linkBBlocks = false ;
7004+ break ;
7005+ }
69737006 case CEE_CALLVIRT:
69747007 case CEE_CALL:
69757008 EmitCall (pConstrainedToken, readonly, tailcall, false /* newObj*/ , false /* isCalli*/ );
0 commit comments