Beispiel #1
0
        public override void VisitCallInstruction(CallInstruction instruction)
        {
            var callExternal = _program.IsExternalType(instruction.TypeSpec);

            var    methodArgs = PopMethodArgs(instruction);
            IValue thisVal    = null;

            if (instruction.CallConv.IsInstance)
            {
                ControlState.EvaluationStack.PopValue(_program, instruction.TypeSpec.GetCilType(_program), out thisVal);
            }

            if (callExternal)
            {
                var result = CallExternalMethod(instruction, thisVal, methodArgs.ToArray(), null);

                if (!(instruction.ReturnType is CilTypeVoid))
                {
                    var resultVal = instruction.ReturnType.CreateValueFromRuntime(result, ManagedMemory, _program);
                    ControlState.EvaluationStack.PushValue(resultVal);
                }

                ControlState.MoveToNextInstruction();
            }
            else
            {
                var @class = _program.Classes.Single(c => c.Name.ToString() == instruction.TypeSpec.ClassName.ToString());
                var method = @class.Methods.Single(m => m.Name == instruction.MethodName && AreArgumentsAssignable(instruction.SigArgs, m.Arguments));

                var sigArgsWithThis = CompleteSigArgs(instruction, method);
                var argsWithThis    = CompleteArgs(instruction, methodArgs, thisVal);

                var newMethodState = new CilMethodState(method, sigArgsWithThis, argsWithThis, _program);

                ControlState.MoveToNextInstruction();
                ControlState.CallStack.Push(newMethodState);
            }
        }
Beispiel #2
0
        public override void VisitNewObjectInstruction(NewObjectInstruction instruction)
        {
            var callExternal = _program.IsExternalType(instruction.TypeSpec);

            var methodArgs = PopMethodArgs(instruction);

            if (callExternal)
            {
                object thisObject = null;
                if (instruction.CallConv.IsInstance)
                {
                    thisObject = GetRuntimeEmptyInstance(instruction, methodArgs, true);
                }

                var result    = CallExternalMethod(instruction, null, methodArgs.ToArray(), thisObject);
                var resultVal = instruction.TypeSpec.GetCilType(_program).CreateValueFromRuntime(result, ManagedMemory, _program);

                ControlState.EvaluationStack.PushValue(resultVal);
                ControlState.MoveToNextInstruction();
            }
            else
            {
                var @class = _program.Classes.Single(c => c.Name.ToString() == instruction.TypeSpec.ClassName.ToString());
                var method = @class.Methods.Single(m => m.Name == instruction.MethodName && AreArgumentsAssignable(instruction.SigArgs, m.Arguments));

                var emptyInstance = new CilClassInstance(@class, _program, ManagedMemory);
                var thisRef       = ManagedMemory.Store(emptyInstance);
                ControlState.EvaluationStack.PushValue(thisRef);

                var sigArgsWithThis = CompleteSigArgs(instruction, method);
                var argsWithThis    = CompleteArgs(instruction, methodArgs, thisRef);

                var newMethodState = new CilMethodState(method, sigArgsWithThis, argsWithThis, _program);

                ControlState.MoveToNextInstruction();
                ControlState.CallStack.Push(newMethodState);
            }
        }
Beispiel #3
0
        public override void VisitCallVirtualInstruction(CallVirtualInstruction instruction)
        {
            if (!instruction.CallConv.IsInstance)
            {
                throw new System.NotImplementedException();
            }

            var methodArgs = PopMethodArgs(instruction);

            ControlState.EvaluationStack.PopValue(_program, instruction.TypeSpec.GetCilType(_program), out var thisVal);

            var callExternal = true;

            CilClassInstance thisClassInstance = null;
            CilObject        thisObject        = null;

            if (thisVal is CilValueReference thisValRef)
            {
                var thisObj = ManagedMemory.Load(thisValRef);

                if (thisObj is CilClassInstance)
                {
                    thisClassInstance = thisObj as CilClassInstance;
                }
                else
                {
                    thisObject   = thisObj;
                    callExternal = true;
                }
            }
            else
            {
                throw new System.NotImplementedException();
            }

            CilMethod method = null;

            if (thisClassInstance != null)
            {
                var currentClass = thisClassInstance.Class;
                while (true)
                {
                    var possibleMethod = currentClass.Methods.SingleOrDefault(m => m.Name == instruction.MethodName && AreArgumentsAssignable(instruction.SigArgs, m.Arguments));
                    if (possibleMethod != null)
                    {
                        method       = possibleMethod;
                        callExternal = false;
                        break;
                    }

                    currentClass = currentClass.Extends;
                    if (currentClass == null)
                    {
                        callExternal = true;
                        break;
                    }
                }
            }

            if (callExternal)
            {
                var result = CallExternalMethod(instruction, thisVal, methodArgs.ToArray(), null);

                if (!(instruction.ReturnType is CilTypeVoid))
                {
                    var resultVal = instruction.ReturnType.CreateValueFromRuntime(result, ManagedMemory, _program);
                    ControlState.EvaluationStack.PushValue(resultVal);
                }

                ControlState.MoveToNextInstruction();
            }
            else
            {
                var sigArgsWithThis = CompleteSigArgs(instruction, method);
                var argsWithThis    = CompleteArgs(instruction, methodArgs, thisVal);

                var newMethodState = new CilMethodState(method, sigArgsWithThis, argsWithThis, _program);

                ControlState.MoveToNextInstruction();
                ControlState.CallStack.Push(newMethodState);
            }
        }