Exemple #1
0
        public CilExpression Translate(RecompilerContext context, ILInstructionExpression expression)
        {
            switch (expression.OpCode.Code)
            {
            case ILCode.PUSHR_OBJECT:
            case ILCode.PUSHR_BYTE:
            case ILCode.PUSHR_WORD:
            case ILCode.PUSHR_DWORD:
            case ILCode.PUSHR_QWORD:
                return(CompileRegisterPush(context, expression));

            case ILCode.PUSHI_DWORD:
                return(new CilInstructionExpression(CilOpCodes.Ldc_I4,
                                                    unchecked ((int)(uint)expression.Operand))
                {
                    ExpressionType = context.TargetImage.TypeSystem.Int32
                });

            case ILCode.PUSHI_QWORD:
                return(new CilInstructionExpression(CilOpCodes.Ldc_I8,
                                                    unchecked ((long)(ulong)expression.Operand))
                {
                    ExpressionType = context.TargetImage.TypeSystem.Int64
                });

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
Exemple #2
0
        private bool TryOptimiseToXor(MatchResult matchResult, ILInstructionExpression expression)
        {
            var lefts  = matchResult.Captures["left"];
            var rights = matchResult.Captures["right"];

            if (((ILVariableExpression)lefts[0]).Variable == ((ILVariableExpression)lefts[1]).Variable &&
                ((ILVariableExpression)rights[0]).Variable == ((ILVariableExpression)rights[1]).Variable)
            {
                // Unregister remaining variable references.
                ((ILVariableExpression)lefts[1]).Variable  = null;
                ((ILVariableExpression)rights[1]).Variable = null;

                // Replace with XOR pseudo opcode.
                var newExpression = new ILInstructionExpression(
                    expression.OriginalOffset,
                    ILOpCodes.__XOR_DWORD,
                    null,
                    VMType.Dword);
                newExpression.Arguments.Add((ILExpression)lefts[0].Parent.Remove());
                newExpression.Arguments.Add((ILExpression)rights[0].Parent.Remove());
                newExpression.FlagsVariable = expression.FlagsVariable;
                expression.FlagsVariable    = null;
                expression.ReplaceWith(newExpression);

                return(true);
            }

            return(false);
        }
Exemple #3
0
        public override bool VisitInstructionExpression(ILInstructionExpression expression)
        {
            // Depth-first to minimize the amount of iterations.
            bool changed = base.VisitInstructionExpression(expression);

            MatchResult matchResult;

            if ((matchResult = NotPattern.Match(expression)).Success)
            {
                changed = TryOptimiseToNot(matchResult, expression);
            }
            else if ((matchResult = NegIntegerPattern.Match(expression)).Success ||
                     (matchResult = NegRealPattern.Match(expression)).Success)
            {
                changed = TryOptimiseToNeg(matchResult, expression);
            }
            else if ((matchResult = AndPattern.Match(expression)).Success)
            {
                changed = TryOptimiseToAnd(matchResult, expression);
            }
            else if ((matchResult = OrPattern.Match(expression)).Success)
            {
                changed = TryOptimiseToOr(matchResult, expression);
            }
            else if ((matchResult = XorPattern.Match(expression)).Success)
            {
                changed = TryOptimiseToXor(matchResult, expression);
            }
            else if ((matchResult = SubPattern.Match(expression)).Success)
            {
                changed = TryOptimiseToSub(matchResult, expression);
            }

            return(changed);
        }
Exemple #4
0
        public override CilExpression Translate(RecompilerContext context, ILInstructionExpression expression)
        {
            var result = base.Translate(context, expression);

            result.ExpressionType = null;
            return(result);
        }
Exemple #5
0
        public CilExpression Translate(RecompilerContext context, ILInstructionExpression expression)
        {
            CilOpCode code;

            switch (expression.OpCode.Code)
            {
            case ILCode.SIND_PTR:
                code = CilOpCodes.Stind_I;
                break;

            case ILCode.SIND_BYTE:
                code = CilOpCodes.Stind_I1;
                break;

            case ILCode.SIND_WORD:
                code = CilOpCodes.Stind_I2;
                break;

            case ILCode.SIND_DWORD:
                code = CilOpCodes.Stind_I4;
                break;

            case ILCode.SIND_QWORD:
                code = CilOpCodes.Stind_I8;
                break;

            case ILCode.SIND_OBJECT:
                code = CilOpCodes.Stind_Ref;
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(expression));
            }

            var value       = (CilExpression)expression.Arguments[0].AcceptVisitor(context.Recompiler);
            var destination = (CilExpression)expression.Arguments[1].AcceptVisitor(context.Recompiler);

            switch (destination.ExpressionType)
            {
            case PointerTypeSignature pointerType:
                value.ExpectedType = pointerType.BaseType;
                break;

            case ByReferenceTypeSignature byRefType:
                value.ExpectedType = byRefType.BaseType;
                break;
            }


            return(new CilInstructionExpression(code, null, destination, value)
            {
                ExpressionType = null
            });
        }
        public void VisitInstructionExpression(ILInstructionExpression expression)
        {
            foreach (var argument in expression.Arguments)
            {
                argument.AcceptVisitor(this);
            }

            if (_offsets.TryGetValue(expression.OriginalOffset, out var variable))
            {
                expression.FlagsVariable = variable;
                variable.ImplicitAssignments.Add(expression);
            }
        }
        public virtual CilExpression Translate(RecompilerContext context, ILInstructionExpression expression)
        {
            if (!SupportedOpCodes.Contains(expression.OpCode.Code))
            {
                throw new NotSupportedException();
            }

            var result = new CilInstructionExpression();

            // Copy instructions
            foreach (var instruction in NewInstructions)
            {
                result.Instructions.Add(new CilInstruction(0, instruction.OpCode, instruction.Operand));
            }

            // Create arguments
            for (var i = 0; i < expression.Arguments.Count; i++)
            {
                // Convert argument.
                var argument    = expression.Arguments[i];
                var cilArgument = (CilExpression)argument.AcceptVisitor(context.Recompiler);

                // Check type.
                cilArgument.ExpectedType = expression.OpCode.StackBehaviourPop
                                           .GetArgumentType(i)
                                           .ToMetadataType(context.TargetImage);

                // Convert if necessary, and add to argument list.
                result.Arguments.Add(cilArgument);
            }

            // Determine expression type from opcode.
            if (expression.OpCode.StackBehaviourPush != ILStackBehaviour.None)
            {
                result.ExpressionType = expression.OpCode.StackBehaviourPush
                                        .GetResultType()
                                        .ToMetadataType(context.TargetImage);
            }

            result.ShouldEmitFlagsUpdate = expression.IsFlagDataSource;
            if (expression.IsFlagDataSource)
            {
                result.AffectedFlags       = expression.OpCode.AffectedFlags;
                result.InvertedFlagsUpdate = InvertedFlagsUpdate;
            }

            return(result);
        }
Exemple #8
0
        private static bool TryOptimiseToNot(MatchResult matchResult, ILInstructionExpression expression)
        {
            var(left, right) = GetOperands(matchResult);
            if (left.Variable == right.Variable)
            {
                // Unregister one of the variable uses.
                right.Variable = null;

                // Replace with NOT pseudo opcode.
                var newExpression = new ILInstructionExpression(
                    expression.OriginalOffset,
                    expression.OpCode.Code switch
                {
                    ILCode.NOR_DWORD => ILOpCodes.__NOT_DWORD,
                    ILCode.NOR_QWORD => ILOpCodes.__NOT_QWORD,
                    _ => throw new ArgumentOutOfRangeException(nameof(expression))
                },
Exemple #9
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);
        }
Exemple #10
0
        private bool TryOptimiseToSub(MatchResult matchResult, ILInstructionExpression expression)
        {
            var(left, right) = GetOperands(matchResult);

            // Replace with SUB pseudo opcode.
            var newExpression = new ILInstructionExpression(
                expression.OriginalOffset,
                ILOpCodes.__SUB_DWORD,
                null,
                VMType.Dword);

            newExpression.Arguments.Add((ILExpression)left.Parent.Remove());
            newExpression.Arguments.Add((ILExpression)right.Parent.Remove());
            newExpression.FlagsVariable = expression.FlagsVariable;
            expression.FlagsVariable    = null;
            expression.ReplaceWith(newExpression);

            return(true);
        }
Exemple #11
0
        public override bool VisitInstructionExpression(ILInstructionExpression expression)
        {
            // Any push expression that pushes the same type as its argument is superfluous.

            bool changed = base.VisitInstructionExpression(expression);

            var match = PushPattern.Match(expression);

            if (match.Success)
            {
                var expr = (ILExpression)match.Captures["expr"][0];
                if (expression.ExpressionType == expr.ExpressionType)
                {
                    expression.ReplaceWith(expr.Remove());
                    changed = true;
                }
            }

            return(changed);
        }
Exemple #12
0
        private static bool TryOptimiseToNot(ILInstructionExpression expression, MatchResult matchResult)
        {
            var(left, right) = GetOperands(matchResult);
            if (left.Variable == right.Variable)
            {
                // Unregister one of the variable uses.
                right.Variable = null;

                // Replace with NOT pseudo opcode.
                var newExpression = new ILInstructionExpression(
                    expression.OriginalOffset,
                    ILOpCodes.__NOT_DWORD,
                    null,
                    VMType.Dword);
                newExpression.Arguments.Add((ILExpression)left.Parent.Remove());
                newExpression.FlagsVariable = expression.FlagsVariable;
                expression.FlagsVariable    = null;
                expression.ReplaceWith(newExpression);

                return(true);
            }

            return(false);
        }
Exemple #13
0
 public virtual bool VisitInstructionExpression(ILInstructionExpression expression)
 {
     return(TryOptimiseArguments(expression));
 }
Exemple #14
0
        private static CilExpression CompileRegisterPush(RecompilerContext context, ILInstructionExpression expression)
        {
            var cilExpression = (CilExpression)expression.Arguments[0].AcceptVisitor(context.Recompiler);

            var resultType = expression.OpCode.StackBehaviourPush.GetResultType();

            if (cilExpression is CilUnboxToVmExpression)
            {
                // HACK: Unbox expressions unbox the value from the stack, but also convert it to their unsigned
                //       variant and box it again into an object. We need to unpack it again, however, we do not
                //       know the actual type of the value inside the box, as this is determined at runtime.
                //
                //       For now, we just make use of the Convert class provided by .NET, which works but would rather
                //       see a true "native" CIL conversion instead.

                MethodBase convertMethod;
                switch (resultType)
                {
                case VMType.Byte:
                    convertMethod = typeof(Convert).GetMethod("ToByte", new[] { typeof(object) });
                    break;

                case VMType.Word:
                    convertMethod = typeof(Convert).GetMethod("ToUInt16", new[] { typeof(object) });
                    break;

                case VMType.Dword:
                    convertMethod = typeof(Convert).GetMethod("ToUInt32", new[] { typeof(object) });
                    break;

                case VMType.Qword:
                    convertMethod = typeof(Convert).GetMethod("ToUInt64", new[] { typeof(object) });
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                cilExpression.ExpectedType = context.TargetImage.TypeSystem.Object;
                cilExpression = new CilInstructionExpression(
                    CilOpCodes.Call,
                    context.ReferenceImporter.ImportMethod(convertMethod),
                    cilExpression);
            }

            if (resultType == VMType.Object)
            {
                if (cilExpression.ExpressionType.IsValueType)
                {
                    if (cilExpression is CilInstructionExpression instructionExpression &&
                        instructionExpression.Instructions.Count == 1 &&
                        instructionExpression.Instructions[0].IsLdcI4 &&
                        instructionExpression.Instructions[0].GetLdcValue() == 0)
                    {
                        cilExpression = new CilInstructionExpression(CilOpCodes.Ldnull);
                    }
                    else
                    {
                        // If expression returns a value type, we have to box it to an object.
                        cilExpression = new CilInstructionExpression(CilOpCodes.Box,
                                                                     context.ReferenceImporter.ImportType(cilExpression.ExpressionType.ToTypeDefOrRef()),
                                                                     cilExpression);
                    }
                }
                else
                {
                    // Use the reference type of the expression instead of System.Object.
                    cilExpression.ExpressionType = cilExpression.ExpressionType;
                }
            }
 public CilExpression Translate(RecompilerContext context, ILInstructionExpression expression)
 {
     return(new CilInstructionExpression(CilOpCodes.Nop));
 }
Exemple #16
0
 public string VisitInstructionExpression(ILInstructionExpression expression) => $"{expression.OpCode} {expression.Operand}";
        public CilExpression Translate(RecompilerContext context, ILInstructionExpression expression)
        {
            var arguments = expression.Arguments
                            .Select(a => (CilExpression)a.AcceptVisitor(context.Recompiler))
                            .ToArray();

            CilOpCode opCode;

            switch (expression.OpCode.Code)
            {
            case ILCode.__EQUALS_OBJECT:
                opCode = CilOpCodes.Ceq;
                break;

            case ILCode.__EQUALS_R32:
            case ILCode.__EQUALS_R64:
            case ILCode.__EQUALS_DWORD:
            case ILCode.__EQUALS_QWORD:
                opCode = CilOpCodes.Ceq;
                break;

            case ILCode.__GT_R32:
            case ILCode.__GT_R64:
                opCode = CilOpCodes.Cgt;
                break;

            case ILCode.__GT_DWORD:
            case ILCode.__GT_QWORD:
                opCode = CilOpCodes.Cgt_Un;
                break;

            case ILCode.__LT_R32:
            case ILCode.__LT_R64:
                opCode = CilOpCodes.Clt;
                break;

            case ILCode.__LT_DWORD:
            case ILCode.__LT_QWORD:
                opCode = CilOpCodes.Clt_Un;
                break;

            default:
                throw new ArgumentOutOfRangeException(nameof(expression));
            }

            var argumentType = expression.OpCode.StackBehaviourPop.GetArgumentType(0)
                               .ToMetadataType(context.TargetModule)
                               .ToTypeSignature();

            var result = new CilInstructionExpression(opCode)
            {
                ExpressionType = context.TargetModule.CorLibTypeFactory.Boolean
            };

            foreach (var argument in arguments)
            {
                argument.ExpectedType = argumentType;
                result.Arguments.Add(argument);
            }

            return(result);
        }