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."); }
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); } }
public abstract void VisitCallVirtualInstruction(CallVirtualInstruction instruction);