public override CILInstructionMethod BuildNode(ParseTreeNode node)
        {
            CILInstructionMethod result = null;

            var instrMethodParseTreeNode = node.GetFirstChildWithGrammarName(GrammarNames.INSTR_METHOD);

            var callParseTreeNode = instrMethodParseTreeNode?.GetFirstChildWithGrammarName(GrammarNames.keyword_call);

            if (callParseTreeNode != null)
            {
                result = new CallInstruction();
            }

            var callvirtParseTreeNode = instrMethodParseTreeNode?.GetFirstChildWithGrammarName(GrammarNames.keyword_callvirt);

            if (callvirtParseTreeNode != null)
            {
                result = new CallVirtualInstruction();
            }

            var newobjParseTreeNode = instrMethodParseTreeNode?.GetFirstChildWithGrammarName(GrammarNames.keyword_newobj);

            if (newobjParseTreeNode != null)
            {
                result = new NewObjectInstruction();
            }

            if (result != null)
            {
                var typeParseTreeNode = node.GetFirstChildWithGrammarName(GrammarNames.type);
                result.MethodReturnType = TypeParseTreeNodeHelper.GetType(typeParseTreeNode);

                var typeSpecParseTreeNode = node.GetFirstChildWithGrammarName(GrammarNames.typeSpec);
                result.TypeSpecification = TypeSpecParseTreeNodeHelper.GetValue(typeSpecParseTreeNode);

                var methodNameParseTreeNode = node.GetFirstChildWithGrammarName(GrammarNames.methodName);
                result.MethodName = MethodNameParseTreeNodeHelper.GetMethodName(methodNameParseTreeNode);

                var sigArgs0ParseTreeNode = node.GetFirstChildWithGrammarName(GrammarNames.sigArgs0);
                result.MethodArgumentTypes = SigArgs0ParseTreeNodeHelper.GetTypes(sigArgs0ParseTreeNode);

                var callConvParseTreeNode = node.GetFirstChildWithGrammarName(GrammarNames.callConv);
                result.CallConvention = CallConvParseTreeNodeHelper.GetValue(callConvParseTreeNode);

                return(result);
            }

            throw new ArgumentException("Cannot recognize CIL instruction method.");
        }
예제 #2
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);
            }
        }
예제 #3
0
 public abstract void VisitCallVirtualInstruction(CallVirtualInstruction instruction);