Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 34 additions & 1 deletion src/coreclr/interpreter/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2233,7 +2233,7 @@ void InterpCompiler::CreateBasicBlocks(CORINFO_METHOD_INFO* methodInfo)
default:
assert(0);
}
if (opcode == CEE_THROW || opcode == CEE_ENDFINALLY || opcode == CEE_RETHROW)
if (opcode == CEE_THROW || opcode == CEE_ENDFINALLY || opcode == CEE_RETHROW || opcode == CEE_JMP)
GetBB((int32_t)(ip - codeStart));
}
}
Expand Down Expand Up @@ -3900,6 +3900,7 @@ void InterpCompiler::EmitCall(CORINFO_RESOLVED_TOKEN* pConstrainedToken, bool re

bool isVirtual = (*m_ip == CEE_CALLVIRT);
bool isDelegateInvoke = false;
bool isJmp = (*m_ip == CEE_JMP);

CORINFO_RESOLVED_TOKEN resolvedCallToken;
CORINFO_CALL_INFO callInfo;
Expand Down Expand Up @@ -3943,6 +3944,16 @@ void InterpCompiler::EmitCall(CORINFO_RESOLVED_TOKEN* pConstrainedToken, bool re
BADCODE("Vararg methods are not supported in interpreted code");
}

if (isJmp)
{
if (callInfo.sig.numArgs != m_methodInfo->args.numArgs ||
callInfo.sig.retType != m_methodInfo->args.retType ||
callInfo.sig.callConv != m_methodInfo->args.callConv)
{
BADCODE("Incompatible target for CEE_JMP");
}
}

// Inject call to callsite callout helper
EmitCallsiteCallout(callInfo.accessAllowed, &callInfo.callsiteCalloutHelper);

Expand Down Expand Up @@ -4031,6 +4042,16 @@ void InterpCompiler::EmitCall(CORINFO_RESOLVED_TOKEN* pConstrainedToken, bool re
CORINFO_ARG_LIST_HANDLE args;
args = callInfo.sig.args;

if (isJmp)
{
assert(tailcall);
// CEE_JMP is simulated as a tail call, so we need to load the current method's args
for (int i = 0; i < numArgsFromStack; i++)
{
EmitLoadVar(i);
}
}

for (int iActualArg = 0, iLogicalArg = 0; iActualArg < numArgs; iActualArg++)
{
if (iActualArg == extraParamArgLocation)
Expand Down Expand Up @@ -6929,6 +6950,18 @@ void InterpCompiler::GenerateCode(CORINFO_METHOD_INFO* methodInfo)
EmitUnaryArithmeticOp(INTOP_NOT_I4);
m_ip++;
break;
case CEE_JMP:
{
CHECK_STACK(0);
if (m_pCBB->clauseType != BBClauseNone)
{
// CEE_JMP inside a funclet is not allowed
BADCODE("CEE_JMP inside funclet");
}
EmitCall(pConstrainedToken, readonly, true /* tailcall */, false /*newObj*/, false /*isCalli*/);
linkBBlocks = false;
break;
}
case CEE_CALLVIRT:
case CEE_CALL:
EmitCall(pConstrainedToken, readonly, tailcall, false /*newObj*/, false /*isCalli*/);
Expand Down
1 change: 1 addition & 0 deletions src/tests/JIT/Directed/Directed_1.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
<ItemGroup>
<MergedWrapperProjectReference Include="coverage/**/*.??proj" />
<MergedWrapperProjectReference Include="nullabletypes/**/*.??proj" />
<ProjectReference Include="jmp/**/*.??proj" />
</ItemGroup>

<Import Project="$(TestSourceDir)MergedTestRunner.targets" />
Expand Down
1 change: 1 addition & 0 deletions src/tests/JIT/Directed/Directed_3.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<!-- Directed_1 -->
<MergedWrapperProjectReference Remove="coverage/**/*.??proj" />
<MergedWrapperProjectReference Remove="nullabletypes/**/*.??proj" />
<MergedWrapperProjectReference Remove="jmp/**/*.??proj" />

<!-- Directed_2 -->
<MergedWrapperProjectReference Remove="cmov/**/*.??proj" />
Expand Down
112 changes: 112 additions & 0 deletions src/tests/JIT/Directed/jmp/genericjmp.il
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
.assembly JmpGenericTest {}
.assembly extern System.Console
{
.publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A )
.ver 0:0:0:0
}
.assembly extern System.Runtime
{
.publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A )
.ver 0:0:0:0
}
.assembly extern xunit.core {}
.assembly extern xunit.assert {}

.assembly genericjmp { }

.class public auto ansi beforefieldinit JmpGenericToGeneric extends [System.Runtime]System.Object
{
.method public static void Target<T>() cil managed
{
.maxstack 8
ldstr "Target<T> called"
call void [System.Console]System.Console::WriteLine(string)
ret
}

.method public static void Source<T>() cil managed
{
jmp void JmpGenericToGeneric::Target<!!0>()
}

.method public static void TestEntryPoint() cil managed
{
.custom instance void [xunit.core]Xunit.FactAttribute::.ctor() = (
01 00 00 00
)
call void JmpGenericToGeneric::Source<int32>()
ret
}
}

.class public auto ansi beforefieldinit JmpGenericToRegular extends [System.Runtime]System.Object
{
.method public static void Target() cil managed
{
.maxstack 8
ldstr "Regular Target called"
call void [System.Console]System.Console::WriteLine(string)
ret
}

.method public static void Source<T>() cil managed
{
jmp void JmpGenericToRegular::Target()
}

.method public static void TestEntryPoint() cil managed
{
.custom instance void [xunit.core]Xunit.FactAttribute::.ctor() = (
01 00 00 00
)
.try
{
call void JmpGenericToRegular::Source<int32>()
ldstr "JMP from generic to regular method is not allowed"
call void [xunit.assert]Xunit.Assert::Fail(string)
leave END
}
catch [System.Runtime]System.InvalidProgramException
{
leave END
}
END:
ret
}
}

.class public auto ansi beforefieldinit JmpRegularToGeneric extends [System.Runtime]System.Object
{
.method public static void Target<T>() cil managed
{
.maxstack 8
ldstr "Generic Target<T> called"
call void [System.Console]System.Console::WriteLine(string)
ret
}

.method public static void Source() cil managed
{
jmp void JmpRegularToGeneric::Target<int32>()
}

.method public static void TestEntryPoint() cil managed
{
.custom instance void [xunit.core]Xunit.FactAttribute::.ctor() = (
01 00 00 00
)
.try
{
call void JmpRegularToGeneric::Source()
ldstr "JMP from regular to generic method is not allowed"
call void [xunit.assert]Xunit.Assert::Fail(string)
leave END
}
catch [System.Runtime]System.InvalidProgramException
{
leave END
}
END:
ret
}
}
9 changes: 9 additions & 0 deletions src/tests/JIT/Directed/jmp/genericjmp.ilproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk.IL">
<PropertyGroup>
<DebugType>Full</DebugType>
<CLRTestPriority>1</CLRTestPriority>
</PropertyGroup>
<ItemGroup>
<Compile Include="genericjmp.il" />
</ItemGroup>
</Project>
Loading