Example #1
0
        bool SimplifyLiftedOperators(List<ILNode> body, ILExpression expr, int pos)
        {
            if (!new PatternMatcher(typeSystem).SimplifyLiftedOperators(expr)) return false;

            var inlining = new ILInlining(method);
            while (--pos >= 0 && inlining.InlineIfPossible(body, ref pos)) ;

            return true;
        }
Example #2
0
 bool MatchFixedInitializer(List<ILNode> body, int i, out ILVariable pinnedVar, out ILExpression initValue, out int nextPos)
 {
     if (body[i].Match(ILCode.Stloc, out pinnedVar, out initValue) && pinnedVar.IsPinned && !IsNullOrZero(initValue)) {
         initValue = (ILExpression)body[i];
         nextPos = i + 1;
         HandleStringFixing(pinnedVar, body, ref nextPos, ref initValue);
         return true;
     }
     ILCondition ifStmt = body[i] as ILCondition;
     ILExpression arrayLoadingExpr;
     if (ifStmt != null && MatchFixedArrayInitializerCondition(ifStmt.Condition, out arrayLoadingExpr)) {
         ILVariable arrayVariable = (ILVariable)arrayLoadingExpr.Operand;
         ILExpression trueValue;
         if (ifStmt.TrueBlock != null && ifStmt.TrueBlock.Body.Count == 1
             && ifStmt.TrueBlock.Body[0].Match(ILCode.Stloc, out pinnedVar, out trueValue)
             && pinnedVar.IsPinned && IsNullOrZero(trueValue))
         {
             if (ifStmt.FalseBlock != null && ifStmt.FalseBlock.Body.Count == 1 && ifStmt.FalseBlock.Body[0] is ILFixedStatement) {
                 ILFixedStatement fixedStmt = (ILFixedStatement)ifStmt.FalseBlock.Body[0];
                 ILVariable stlocVar;
                 ILExpression falseValue;
                 if (fixedStmt.Initializers.Count == 1 && fixedStmt.BodyBlock.Body.Count == 0
                     && fixedStmt.Initializers[0].Match(ILCode.Stloc, out stlocVar, out falseValue) && stlocVar == pinnedVar)
                 {
                     ILVariable loadedVariable;
                     if (falseValue.Code == ILCode.Ldelema
                         && falseValue.Arguments[0].Match(ILCode.Ldloc, out loadedVariable) && loadedVariable == arrayVariable
                         && IsNullOrZero(falseValue.Arguments[1]))
                     {
                         // OK, we detected the pattern for fixing an array.
                         // Now check whether the loading expression was a store ot a temp. var
                         // that can be eliminated.
                         if (arrayLoadingExpr.Code == ILCode.Stloc) {
                             ILInlining inlining = new ILInlining(method);
                             if (inlining.numLdloc.GetOrDefault(arrayVariable) == 2 &&
                                 inlining.numStloc.GetOrDefault(arrayVariable) == 1 && inlining.numLdloca.GetOrDefault(arrayVariable) == 0)
                             {
                                 arrayLoadingExpr = arrayLoadingExpr.Arguments[0];
                             }
                         }
                         initValue = new ILExpression(ILCode.Stloc, pinnedVar, arrayLoadingExpr);
                         nextPos = i + 1;
                         return true;
                     }
                 }
             }
         }
     }
     initValue = null;
     nextPos = -1;
     return false;
 }
Example #3
0
 public static void RunStep2(DecompilerContext context, ILBlock method)
 {
     if (context.CurrentMethodIsAsync) {
         Step2(method.Body);
         ILAstOptimizer.RemoveRedundantCode(method);
         // Repeat the inlining/copy propagation optimization because the conversion of field access
         // to local variables can open up additional inlining possibilities.
         ILInlining inlining = new ILInlining(method);
         inlining.InlineAllVariables();
         inlining.CopyPropagation();
     }
 }
Example #4
0
        bool MakeAssignmentExpression(List<ILNode> body, ILExpression expr, int pos)
        {
            // exprVar = ...
            // stloc(v, exprVar)
            // ->
            // exprVar = stloc(v, ...))
            ILVariable exprVar;
            ILExpression initializer;
            if (!(expr.Match(ILCode.Stloc, out exprVar, out initializer) && exprVar.IsGenerated))
                return false;
            ILExpression nextExpr = body.ElementAtOrDefault(pos + 1) as ILExpression;
            ILVariable v;
            ILExpression stLocArg;
            if (nextExpr.Match(ILCode.Stloc, out v, out stLocArg) && stLocArg.MatchLdloc(exprVar)) {
                ILExpression store2 = body.ElementAtOrDefault(pos + 2) as ILExpression;
                if (StoreCanBeConvertedToAssignment(store2, exprVar)) {
                    // expr_44 = ...
                    // stloc(v1, expr_44)
                    // anystore(v2, expr_44)
                    // ->
                    // stloc(v1, anystore(v2, ...))
                    ILInlining inlining = new ILInlining(method);
                    if (inlining.numLdloc.GetOrDefault(exprVar) == 2 && inlining.numStloc.GetOrDefault(exprVar) == 1) {
                        body.RemoveAt(pos + 2); // remove store2
                        body.RemoveAt(pos); // remove expr = ...
                        nextExpr.Arguments[0] = store2;
                        store2.Arguments[store2.Arguments.Count - 1] = initializer;

                        inlining.InlineIfPossible(body, ref pos);

                        return true;
                    }
                }

                body.RemoveAt(pos + 1); // remove stloc
                nextExpr.Arguments[0] = initializer;
                ((ILExpression)body[pos]).Arguments[0] = nextExpr;
                return true;
            } else if ((nextExpr.Code == ILCode.Stsfld || nextExpr.Code == ILCode.CallSetter || nextExpr.Code == ILCode.CallvirtSetter) && nextExpr.Arguments.Count == 1) {
                // exprVar = ...
                // stsfld(fld, exprVar)
                // ->
                // exprVar = stsfld(fld, ...))
                if (nextExpr.Arguments[0].MatchLdloc(exprVar)) {
                    body.RemoveAt(pos + 1); // remove stsfld
                    nextExpr.Arguments[0] = initializer;
                    ((ILExpression)body[pos]).Arguments[0] = nextExpr;
                    return true;
                }
            }
            return false;
        }
Example #5
0
        void CachedDelegateInitializationWithLocal(ILBlock block, ref int i)
        {
            // if (logicnot(ldloc(v))) {
            //     stloc(v, newobj(Action::.ctor, ldloc(displayClass), ldftn(method)))
            // } else {
            // }
            // ...(..., ldloc(v), ...)

            ILCondition c = block.Body[i] as ILCondition;
            if (c == null || c.Condition == null && c.TrueBlock == null || c.FalseBlock == null)
                return;
            if (!(c.TrueBlock.Body.Count == 1 && c.FalseBlock.Body.Count == 0))
                return;
            if (!c.Condition.Match(ILCode.LogicNot))
                return;
            ILExpression condition = c.Condition.Arguments.Single() as ILExpression;
            if (condition == null || condition.Code != ILCode.Ldloc)
                return;
            ILVariable v = (ILVariable)condition.Operand;
            ILExpression stloc = c.TrueBlock.Body[0] as ILExpression;
            if (!(stloc != null && stloc.Code == ILCode.Stloc && (ILVariable)stloc.Operand == v))
                return;
            ILExpression newObj = stloc.Arguments[0];
            if (!(newObj.Code == ILCode.Newobj && newObj.Arguments.Count == 2))
                return;
            if (newObj.Arguments[0].Code != ILCode.Ldloc)
                return;
            if (newObj.Arguments[1].Code != ILCode.Ldftn)
                return;
            MethodDefinition anonymousMethod = ((MethodReference)newObj.Arguments[1].Operand).ResolveWithinSameModule(); // method is defined in current assembly
            if (!Ast.Transforms.DelegateConstruction.IsAnonymousMethod(context, anonymousMethod))
                return;

            ILNode followingNode = block.Body.ElementAtOrDefault(i + 1);
            if (followingNode != null && followingNode.GetSelfAndChildrenRecursive<ILExpression>().Count(
                e => e.Code == ILCode.Ldloc && (ILVariable)e.Operand == v) == 1)
            {
                ILInlining inlining = new ILInlining(method);
                if (!(inlining.numLdloc.GetOrDefault(v) == 2 && inlining.numStloc.GetOrDefault(v) == 2 && inlining.numLdloca.GetOrDefault(v) == 0))
                    return;

                // Find the store instruction that initializes the local to null:
                foreach (ILBlock storeBlock in method.GetSelfAndChildrenRecursive<ILBlock>()) {
                    for (int j = 0; j < storeBlock.Body.Count; j++) {
                        ILVariable storedVar;
                        ILExpression storedExpr;
                        if (storeBlock.Body[j].Match(ILCode.Stloc, out storedVar, out storedExpr) && storedVar == v && storedExpr.Match(ILCode.Ldnull)) {
                            // Remove the instruction
                            storeBlock.Body.RemoveAt(j);
                            if (storeBlock == block && j < i)
                                i--;
                            break;
                        }
                    }
                }

                block.Body[i] = stloc; // remove the 'if (v==null)'
                inlining = new ILInlining(method);
                inlining.InlineIfPossible(block.Body, ref i);
            }
        }
Example #6
0
        void CachedDelegateInitializationWithField(ILBlock block, ref int i)
        {
            // if (logicnot(ldsfld(field))) {
            //     stsfld(field, newobj(Action::.ctor, ldnull(), ldftn(method)))
            // } else {
            // }
            // ...(..., ldsfld(field), ...)

            ILCondition c = block.Body[i] as ILCondition;
            if (c == null || c.Condition == null && c.TrueBlock == null || c.FalseBlock == null)
                return;
            if (!(c.TrueBlock.Body.Count == 1 && c.FalseBlock.Body.Count == 0))
                return;
            if (!c.Condition.Match(ILCode.LogicNot))
                return;
            ILExpression condition = c.Condition.Arguments.Single() as ILExpression;
            if (condition == null || condition.Code != ILCode.Ldsfld)
                return;
            FieldDefinition field = ((FieldReference)condition.Operand).ResolveWithinSameModule(); // field is defined in current assembly
            if (field == null || !field.IsCompilerGeneratedOrIsInCompilerGeneratedClass())
                return;
            ILExpression stsfld = c.TrueBlock.Body[0] as ILExpression;
            if (!(stsfld != null && stsfld.Code == ILCode.Stsfld && ((FieldReference)stsfld.Operand).ResolveWithinSameModule() == field))
                return;
            ILExpression newObj = stsfld.Arguments[0];
            if (!(newObj.Code == ILCode.Newobj && newObj.Arguments.Count == 2))
                return;
            if (newObj.Arguments[0].Code != ILCode.Ldnull)
                return;
            if (newObj.Arguments[1].Code != ILCode.Ldftn)
                return;
            MethodDefinition anonymousMethod = ((MethodReference)newObj.Arguments[1].Operand).ResolveWithinSameModule(); // method is defined in current assembly
            if (!Ast.Transforms.DelegateConstruction.IsAnonymousMethod(context, anonymousMethod))
                return;

            ILNode followingNode = block.Body.ElementAtOrDefault(i + 1);
            if (followingNode != null && followingNode.GetSelfAndChildrenRecursive<ILExpression>().Count(
                e => e.Code == ILCode.Ldsfld && ((FieldReference)e.Operand).ResolveWithinSameModule() == field) == 1)
            {
                foreach (ILExpression parent in followingNode.GetSelfAndChildrenRecursive<ILExpression>()) {
                    for (int j = 0; j < parent.Arguments.Count; j++) {
                        if (parent.Arguments[j].Code == ILCode.Ldsfld && ((FieldReference)parent.Arguments[j].Operand).ResolveWithinSameModule() == field) {
                            parent.Arguments[j] = newObj;
                            block.Body.RemoveAt(i);
                            i -= new ILInlining(method).InlineInto(block.Body, i, aggressive: false);
                            return;
                        }
                    }
                }
            }
        }
Example #7
0
 public bool InlineAllVariables()
 {
     bool modified = false;
     ILInlining i = new ILInlining(method);
     foreach (ILBlock block in method.GetSelfAndChildrenRecursive<ILBlock>())
         modified |= i.InlineAllInBlock(block);
     return modified;
 }
Example #8
0
        public static void Run(DecompilerContext context, ILBlock method)
        {
            if (!context.Settings.YieldReturn)
                return; // abort if enumerator decompilation is disabled
            var yrd = new YieldReturnDecompiler();
            yrd.context = context;
            if (!yrd.MatchEnumeratorCreationPattern(method))
                return;
            yrd.enumeratorType = yrd.enumeratorCtor.DeclaringType;
            #if DEBUG
            if (Debugger.IsAttached) {
                yrd.Run();
            } else {
                #endif
                try {
                    yrd.Run();
                } catch (SymbolicAnalysisFailedException) {
                    return;
                }
                #if DEBUG
            }
            #endif
            method.Body.Clear();
            method.EntryGoto = null;
            method.Body.AddRange(yrd.newBody);

            // Repeat the inlining/copy propagation optimization because the conversion of field access
            // to local variables can open up additional inlining possibilities.
            ILInlining inlining = new ILInlining(method);
            inlining.InlineAllVariables();
            inlining.CopyPropagation();
        }