public CilExpression Translate(RecompilerContext context, ILInstructionExpression expression) { var callMetadata = (CallAnnotation)expression.Annotation; // Convert entrypoint address to physical method def. var method = context.ExportResolver.ResolveMethod(callMetadata.Function.EntrypointAddress); var methodSig = ((MethodSignature)method.Signature); // Create call instruction. CilExpression result = new CilInstructionExpression(CilOpCodes.Call, method, context.RecompileCallArguments(method, expression.Arguments.Skip(1).ToArray(), VMECallOpCode.CALL)) { ExpressionType = methodSig.ReturnType }; // Make sure the resulting object is converted to an unsigned integer if necessary. return(result); }
public CilExpression Translate(RecompilerContext context, ILVCallExpression expression) { var ecall = (ECallAnnotation)expression.Annotation; var methodSig = (MethodSignature)ecall.Method.Signature; // Select calling instruction, return type and call prefix. CilInstruction prefix = null; TypeSignature resultType; CilOpCode opcode; switch (ecall.OpCode) { case VMECallOpCode.CALL: opcode = CilOpCodes.Call; resultType = methodSig.ReturnType; break; case VMECallOpCode.CALLVIRT: opcode = CilOpCodes.Callvirt; resultType = methodSig.ReturnType; break; case VMECallOpCode.NEWOBJ: opcode = CilOpCodes.Newobj; resultType = ecall.Method.DeclaringType.ToTypeSignature(); break; case VMECallOpCode.CALLVIRT_CONSTRAINED: prefix = CilInstruction.Create(CilOpCodes.Constrained, ecall.ConstrainedType); opcode = CilOpCodes.Callvirt; resultType = methodSig.ReturnType; break; default: throw new ArgumentOutOfRangeException(); } // Enter generic context of method. context.EnterMember(ecall.Method); // Collect arguments. var arguments = expression.Arguments .Skip(ecall.IsConstrained ? 3 : 2) .ToArray(); // Build call expression. var result = new CilInstructionExpression(opcode, ecall.Method, context.RecompileCallArguments(ecall.Method, arguments, ecall.OpCode == VMECallOpCode.NEWOBJ)) { ExpressionType = resultType.InstantiateGenericTypes(context.GenericContext) }; // Add prefix when necessary. if (prefix != null) { result.Arguments[0].ExpectedType = ecall.ConstrainedType; result.Instructions.Insert(0, prefix); } // Leave generic context. context.ExitMember(); return(result); }
public CilExpression Translate(RecompilerContext context, ILVCallExpression expression) { var ecall = (ECallAnnotation)expression.Annotation; var methodSig = ecall.Method.Signature; // Select calling instruction, return type and call prefix. CilInstruction prefix = null; TypeSignature resultType; CilOpCode opcode; object operand = ecall.Method; switch (ecall.OpCode) { case VMECallOpCode.CALL: opcode = CilOpCodes.Call; resultType = methodSig.ReturnType; break; case VMECallOpCode.CALLVIRT: opcode = CilOpCodes.Callvirt; resultType = methodSig.ReturnType; break; case VMECallOpCode.NEWOBJ: opcode = CilOpCodes.Newobj; resultType = ecall.Method.DeclaringType.ToTypeSignature(); // KoiVM translates "newarr ElementType" instructions to "newobj ElementType[]::.ctor(int32)". // Revert this operation if necessary: if (resultType is SzArrayTypeSignature arrayType) { opcode = CilOpCodes.Newarr; operand = context.ReferenceImporter.ImportType(arrayType.BaseType.ToTypeDefOrRef()); } break; case VMECallOpCode.CALLVIRT_CONSTRAINED: prefix = new CilInstruction(CilOpCodes.Constrained, ecall.ConstrainedType); opcode = CilOpCodes.Callvirt; resultType = methodSig.ReturnType; break; default: throw new ArgumentOutOfRangeException(); } // Enter generic context of method. context.EnterMember(ecall.Method); // Collect arguments. var arguments = expression.Arguments .Skip(ecall.IsConstrained ? 3 : 2) .ToArray(); // Build call expression. var result = new CilInstructionExpression(opcode, operand, context.RecompileCallArguments(ecall.Method, arguments, ecall.OpCode, ecall.ConstrainedType)) { ExpressionType = resultType.InstantiateGenericTypes(context.GenericContext) }; // Add prefix when necessary. if (prefix != null) { result.Instructions.Insert(0, prefix); } // Leave generic context. context.ExitMember(); return(result); }