Implement castclass & isinst for WebAssembly (#5325)
* Implement castclass & isinst for wasm (#4510) Implement castclass and isinst opcodes in ILToWebAssemblyImporter by doing related function calls to methods in System.Runtime.TypeCast. Fix #4510 Add castclass & isinst test in HelloWasm. This includes three types of casting: * castclass/isinst to classes. * castclass/isinst to interfaces. * castclass/isinst to array types. For now, the second and third part of test is failing due to runtime implementation problems which should be further digged into.
This commit is contained in:
Родитель
569871f97d
Коммит
3470b34c12
|
@ -818,6 +818,25 @@ namespace Internal.IL
|
|||
|
||||
private void ImportCasting(ILOpcode opcode, int token)
|
||||
{
|
||||
TypeDesc type = ResolveTypeToken(token);
|
||||
|
||||
//TODO: call GetCastingHelperNameForType from JitHelper.cs (needs refactoring)
|
||||
string function;
|
||||
bool throwing = opcode == ILOpcode.castclass;
|
||||
if (type.IsArray)
|
||||
function = throwing ? "CheckCastArray" : "IsInstanceOfArray";
|
||||
else if (type.IsInterface)
|
||||
function = throwing ? "CheckCastInterface" : "IsInstanceOfInterface";
|
||||
else
|
||||
function = throwing ? "CheckCastClass" : "IsInstanceOfClass";
|
||||
|
||||
var arguments = new StackEntry[]
|
||||
{
|
||||
_stack.Pop(),
|
||||
new LoadExpressionEntry(StackValueKind.ValueType, "eeType", GetEETypePointerForTypeDesc(type, true), _compilation.TypeSystemContext.SystemModule.GetKnownType("System", "EETypePtr"))
|
||||
};
|
||||
|
||||
_stack.Push(CallRuntime(_compilation.TypeSystemContext, TypeCast, function, arguments, type));
|
||||
}
|
||||
|
||||
private void ImportLoadNull()
|
||||
|
@ -2344,6 +2363,7 @@ namespace Internal.IL
|
|||
private const string RuntimeExport = "RuntimeExports";
|
||||
private const string RuntimeImport = "RuntimeImports";
|
||||
private const string InternalCalls = "InternalCalls";
|
||||
private const string TypeCast = "TypeCast";
|
||||
private ExpressionEntry CallRuntime(TypeSystemContext context, string className, string methodName, StackEntry[] arguments, TypeDesc forcedReturnType = null)
|
||||
{
|
||||
MetadataType helperType = context.SystemModule.GetKnownType("System.Runtime", className);
|
||||
|
|
|
@ -181,6 +181,27 @@ internal static class Program
|
|||
|
||||
IntToStringTest();
|
||||
|
||||
CastingTestClass castingTest = new DerivedCastingTestClass1();
|
||||
if (((DerivedCastingTestClass1)castingTest).GetValue() == 1 && !(castingTest is DerivedCastingTestClass2))
|
||||
{
|
||||
PrintLine("Type casting with isinst & castclass to class test: Ok.");
|
||||
}
|
||||
|
||||
// Instead of checking the result of `GetValue`, we use null check by now until interface dispatch is implemented.
|
||||
if ((ICastingTest1)castingTest != null && !(castingTest is ICastingTest2))
|
||||
{
|
||||
PrintLine("Type casting with isinst & castclass to interface test: Ok.");
|
||||
}
|
||||
|
||||
object arrayCastingTest = new BoxStubTest[] { new BoxStubTest { Value = "Array" }, new BoxStubTest { Value = "Cast" }, new BoxStubTest { Value = "Test" } };
|
||||
PrintLine(((BoxStubTest[])arrayCastingTest)[0].Value);
|
||||
PrintLine(((BoxStubTest[])arrayCastingTest)[1].Value);
|
||||
PrintLine(((BoxStubTest[])arrayCastingTest)[2].Value);
|
||||
if (!(arrayCastingTest is CastingTestClass[]))
|
||||
{
|
||||
PrintLine("Type casting with isinst & castclass to array test: Ok.");
|
||||
}
|
||||
|
||||
PrintLine("Done");
|
||||
}
|
||||
|
||||
|
@ -367,3 +388,27 @@ public class TestDerivedClass : TestClass
|
|||
}
|
||||
}
|
||||
|
||||
public interface ICastingTest1
|
||||
{
|
||||
int GetValue();
|
||||
}
|
||||
|
||||
public interface ICastingTest2
|
||||
{
|
||||
int GetValue();
|
||||
}
|
||||
|
||||
public abstract class CastingTestClass
|
||||
{
|
||||
public abstract int GetValue();
|
||||
}
|
||||
|
||||
public class DerivedCastingTestClass1 : CastingTestClass, ICastingTest1
|
||||
{
|
||||
public override int GetValue() => 1;
|
||||
}
|
||||
|
||||
public class DerivedCastingTestClass2 : CastingTestClass, ICastingTest2
|
||||
{
|
||||
public override int GetValue() => 2;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче