Inazuma.PetitClr.Core.PetitClrInterpreter.ExecuteMethodCore C# (CSharp) Метод

ExecuteMethodCore() приватный Метод

private ExecuteMethodCore ( ObjectInstance &retVal, bool &doJmpCall, MemberReference &jmpCallToken ) : void
retVal Inazuma.PetitClr.Core.Structure.ObjectInstance
doJmpCall bool
jmpCallToken Inazuma.Mono.Cecil.MemberReference
Результат void
        private void ExecuteMethodCore(out ObjectInstance retVal, out bool doJmpCall, out MemberReference jmpCallToken)
        {
            jmpCallToken = null;
            doJmpCall = false;
            retVal = null;

            for (; _instructions.Length > _instructionPtr; _instructionPtr++)
            {
                var inst = _instructions[_instructionPtr];

                if (inst.OpCode == OpCodes.Nop)
                {
                    continue;
                }
                else if (inst.OpCode == OpCodes.Break)
                {
                    continue;
                }

                else if (inst.OpCode == OpCodes.Ldarg_0)
                {
                    LdArg(0);
                    continue;
                }
                else if (inst.OpCode == OpCodes.Ldarg_1)
                {
                    LdArg(1);
                    continue;
                }
                else if (inst.OpCode == OpCodes.Ldarg_2)
                {
                    LdArg(2);
                    continue;
                }
                else if (inst.OpCode == OpCodes.Ldarg_3)
                {
                    LdArg(3);
                    continue;
                }

                else if (inst.OpCode == OpCodes.Ldloc_0)
                {
                    LdLoc(0);
                    continue;
                }
                else if (inst.OpCode == OpCodes.Ldloc_1)
                {
                    LdLoc(1);
                    continue;
                }
                else if (inst.OpCode == OpCodes.Ldloc_2)
                {
                    LdLoc(2);
                    continue;
                }
                else if (inst.OpCode == OpCodes.Ldloc_3)
                {
                    LdLoc(3);
                    continue;
                }

                else if (inst.OpCode == OpCodes.Stloc_0)
                {
                    StLoc(0);
                    continue;
                }
                else if (inst.OpCode == OpCodes.Stloc_1)
                {
                    StLoc(1);
                    continue;
                }
                else if (inst.OpCode == OpCodes.Stloc_2)
                {
                    StLoc(2);
                    continue;
                }
                else if (inst.OpCode == OpCodes.Stloc_3)
                {
                    StLoc(3);
                    continue;
                }

                else if (inst.OpCode == OpCodes.Ldarg_S)
                {
                    // TODO: get index directly
                    var index = (inst.Operand is ParameterReference) ? ((ParameterReference)inst.Operand).Index : ((VariableReference)inst.Operand).Index;
                    LdArg(index);
                    continue;
                }
                else if (inst.OpCode == OpCodes.Ldarga_S)
                {
                    // TODO: get index directly
                    var index = (inst.Operand is ParameterReference) ? ((ParameterReference)inst.Operand).Index : ((VariableReference)inst.Operand).Index;
                    LdArgA(index);
                    continue;
                }
                else if (inst.OpCode == OpCodes.Starg_S)
                {
                    // TODO: get index directly
                    var index = (inst.Operand is ParameterReference) ? ((ParameterReference)inst.Operand).Index : ((VariableReference)inst.Operand).Index;
                    StArg(index);
                    continue;
                }
                else if (inst.OpCode == OpCodes.Ldloc_S)
                {
                    // TODO: get index directly
                    var index = (inst.Operand is ParameterReference) ? ((ParameterReference)inst.Operand).Index : ((VariableReference)inst.Operand).Index;
                    LdLoc(index);
                    continue;
                }
                else if (inst.OpCode == OpCodes.Ldloca_S)
                {
                    // TODO: get index directly
                    var index = (inst.Operand is ParameterReference) ? ((ParameterReference)inst.Operand).Index : ((VariableReference)inst.Operand).Index;
                    LdLocA(index);
                    continue;
                }
                else if (inst.OpCode == OpCodes.Stloc_S)
                {
                    // TODO: get index directly
                    var index = (inst.Operand is ParameterReference) ? ((ParameterReference)inst.Operand).Index : ((VariableReference)inst.Operand).Index;
                    StLoc(index);
                    continue;
                }

                else if (inst.OpCode == OpCodes.Ldnull)
                {
                    Ldnull();
                    continue;
                }

                else if (inst.OpCode == OpCodes.Ldc_I4_M1)
                {
                    LdIcon(-1);
                    continue;
                }
                else if (inst.OpCode == OpCodes.Ldc_I4_0)
                {
                    LdIcon(0);
                    continue;
                }
                else if (inst.OpCode == OpCodes.Ldc_I4_1)
                {
                    LdIcon(1);
                    continue;
                }
                else if (inst.OpCode == OpCodes.Ldc_I4_2)
                {
                    LdIcon(2);
                    continue;
                }
                else if (inst.OpCode == OpCodes.Ldc_I4_3)
                {
                    LdIcon(3);
                    continue;
                }
                else if (inst.OpCode == OpCodes.Ldc_I4_4)
                {
                    LdIcon(4);
                    continue;
                }
                else if (inst.OpCode == OpCodes.Ldc_I4_5)
                {
                    LdIcon(5);
                    continue;
                }
                else if (inst.OpCode == OpCodes.Ldc_I4_6)
                {
                    LdIcon(6);
                    continue;
                }
                else if (inst.OpCode == OpCodes.Ldc_I4_7)
                {
                    LdIcon(7);
                    continue;
                }
                else if (inst.OpCode == OpCodes.Ldc_I4_8)
                {
                    LdIcon(8);
                    continue;
                }
                else if (inst.OpCode == OpCodes.Ldc_I4_S)
                {
                    LdIcon(inst.Operand);
                    continue;
                }
                else if (inst.OpCode == OpCodes.Ldc_I4)
                {
                    LdIcon(inst.Operand);
                    continue;
                }

                else if (inst.OpCode == OpCodes.Ldstr)
                {
                    LdStr();
                    continue;
                }

                else if (inst.OpCode == OpCodes.Ldfld)
                {
                    LdFld();
                    continue;
                }
                else if (inst.OpCode == OpCodes.Ldflda)
                {
                    LdFldA();
                    continue;
                }
                else if (inst.OpCode == OpCodes.Stfld)
                {
                    StFld();
                    continue;
                }
                else if (inst.OpCode == OpCodes.Ldsfld)
                {
                    LdSFld();
                    continue;
                }
                else if (inst.OpCode == OpCodes.Ldsflda)
                {
                    LdSFldA();
                    continue;
                }
                else if (inst.OpCode == OpCodes.Stsfld)
                {
                    StSFld();
                    continue;
                }
                else if (inst.OpCode == OpCodes.Stobj)
                {
                    StObj();
                    continue;
                }

                // ...
                else if (inst.OpCode == OpCodes.Add)
                {
                    Add(checkOverflow: false, unsigned: false);
                    continue;
                }
                else if (inst.OpCode == OpCodes.Add_Ovf)
                {
                    Add(checkOverflow: true, unsigned: false);
                    continue;
                }
                else if (inst.OpCode == OpCodes.Add_Ovf_Un)
                {
                    Add(checkOverflow: true, unsigned: true);
                    continue;
                }
                else if (inst.OpCode == OpCodes.Sub)
                {
                    Sub(checkOverflow: false, unsigned: false);
                    continue;
                }
                else if (inst.OpCode == OpCodes.Sub_Ovf)
                {
                    Sub(checkOverflow: true, unsigned: false);
                    continue;
                }
                else if (inst.OpCode == OpCodes.Sub_Ovf_Un)
                {
                    Sub(checkOverflow: true, unsigned: true);
                    continue;
                }
                else if (inst.OpCode == OpCodes.Mul)
                {
                    Mul(checkOverflow: false, unsigned: false);
                    continue;
                }
                else if (inst.OpCode == OpCodes.Mul_Ovf)
                {
                    Mul(checkOverflow: true, unsigned: false);
                    continue;
                }
                else if (inst.OpCode == OpCodes.Mul_Ovf_Un)
                {
                    Mul(checkOverflow: true, unsigned: true);
                    continue;
                }
                else if (inst.OpCode == OpCodes.Div)
                {
                    Div(checkOverflow: true, unsigned: false);
                    continue;
                }
                else if (inst.OpCode == OpCodes.Div_Un)
                {
                    Div(checkOverflow: true, unsigned: true);
                    continue;
                }
                else if (inst.OpCode == OpCodes.Rem)
                {
                    Rem(checkOverflow: true, unsigned: false);
                    continue;
                }
                else if (inst.OpCode == OpCodes.Rem_Un)
                {
                    Rem(checkOverflow: true, unsigned: true);
                    continue;
                }

                else if (inst.OpCode == OpCodes.Newobj)
                {
                    NewObj();
                    continue;
                }

                else if (inst.OpCode == OpCodes.Box)
                {
                    // TODO: not implemented yet
                    continue;
                }

                else if (inst.OpCode == OpCodes.Call)
                {
                    Call(virtualCall: false);
                    continue;
                }
                else if (inst.OpCode == OpCodes.Callvirt)
                {
                    Call(virtualCall: true);
                    continue;
                }

                else if (inst.OpCode == OpCodes.Ret)
                {
                    // TODO: use reference or type
                    if (_methInfo2.ReturnType.Namespace == "System" && _methInfo2.ReturnType.Name == "Void")
                    {
                        Debug.Assert(_opStack.Count == 0);
                    }
                    else
                    {
                        Debug.Assert(_opStack.Count != 0);
                        retVal = _opStack.Pop();
                    }

                    return; // goto ExitEvalLoop;
                }

                else if (inst.OpCode == OpCodes.Br_S)
                {
                    // TODO: below code is too slow
                    _instructionPtr = _instructions.Select((x, i) => new { Index = i, IsMatched = x == inst.Operand }).First(x => x.IsMatched).Index - 1; // increments ops ptr after "continue;". ptr must be subtracted here.
                    continue;
                }
                else if (inst.OpCode == OpCodes.Leave_S)
                {
                    _opStack.Clear();
                    throw ThrowHelper.NotImplementedYet;
                }
                else if (inst.OpCode == OpCodes.Brfalse_S)
                {
                    // TODO: below code is too slow
                    var value = _opStack.Pop();
                    if ((value.IsReference && value.IsNull) || value.I == 0)
                    {
                        _instructionPtr = _instructions.Select((x, i) => new { Index = i, IsMatched = x == inst.Operand }).First(x => x.IsMatched).Index - 1; // increments ops ptr after "continue;". ptr must be subtracted here.
                    }
                    continue;
                }
                else if (inst.OpCode == OpCodes.Brtrue_S)
                {
                    // TODO: below code is too slow
                    var value = _opStack.Pop();
                    if ((value.IsReference && !value.IsNull) || value.I != 0)
                    {
                        _instructionPtr = _instructions.Select((x, i) => new { Index = i, IsMatched = x == inst.Operand }).First(x => x.IsMatched).Index - 1; // increments ops ptr after "continue;". ptr must be subtracted here.
                    }
                    continue;
                }

                // case CEE_PREFIX1:
                else if (inst.OpCode == OpCodes.Arglist)
                {
                    throw ThrowHelper.NotImplementedYet;
                }
                else if (inst.OpCode == OpCodes.Ceq)
                {
                    var value2 = _opStack.Pop();
                    var value1 = _opStack.Pop();

                    if (value1.Type == CorInfoType.Class)
                    {
                        _opStack.Push(ObjectInstance.FromClrObject((value1 == value2) ? 1 : 0));
                    }
                    else if (value1.Type == CorInfoType.String)
                    {
                        _opStack.Push(ObjectInstance.FromClrObject((value1.ObjectRef == value2.ObjectRef) ? 1 : 0));
                    }
                    else
                    {
                        _opStack.Push(ObjectInstance.FromClrObject((value1.I == value2.I) ? 1 : 0));
                    }
                    continue;
                }
                else if (inst.OpCode == OpCodes.Cgt)
                {
                    var value2 = _opStack.Pop().I;
                    var value1 = _opStack.Pop().I;
                    _opStack.Push(ObjectInstance.FromClrObject((value1 > value2) ? 1 : 0));
                    continue;
                }
                else if (inst.OpCode == OpCodes.Cgt_Un)
                {
                    var value2 = _opStack.Pop();
                    var value1 = _opStack.Pop();

                    if (value1.Type == CorInfoType.Class)
                    {
                        _opStack.Push(ObjectInstance.FromClrObject((value1 != value2) ? 1 : 0));
                    }
                    else if (value1.Type == CorInfoType.String)
                    {
                        _opStack.Push(ObjectInstance.FromClrObject((value1.ObjectRef != value2.ObjectRef) ? 1 : 0));
                    }
                    else
                    {
                        _opStack.Push(ObjectInstance.FromClrObject(((ulong)value1.I > (ulong)value2.I) ? 1 : 0));
                    }

                    continue;
                }
                else if (inst.OpCode == OpCodes.Clt)
                {
                    var value2 = _opStack.Pop().I;
                    var value1 = _opStack.Pop().I;
                    _opStack.Push(ObjectInstance.FromClrObject((value1 < value2) ? 1 : 0));
                    continue;
                }
                else if (inst.OpCode == OpCodes.Clt_Un)
                {
                    var value2 = (ulong)_opStack.Pop().I;
                    var value1 = (ulong)_opStack.Pop().I;
                    _opStack.Push(ObjectInstance.FromClrObject((value1 < value2) ? 1 : 0));
                    continue;
                }

                else if (inst.OpCode == OpCodes.Throw)
                {
                    Throw();
                    continue;
                }

                throw new InazumaExecutionException("Unknown OpCode: " + inst.OpCode.ToString());
            }
        }