Example #1
0
        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);
        }
Example #2
0
        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);
        }
Example #3
0
        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);
        }