Exemplo n.º 1
0
        private bool ReplaceChainedShortCircuitBooleanPattern(List <IStatement> statements, int i)
        {
            ConditionalStatement conditionalStatement = (ConditionalStatement)statements[i];

            if (!this.ReplaceShortCircuitPattern(statements, i + 1))
            {
                if (!this.ReplaceShortCircuitPatternCreatedByCCI2(statements, i + 1))
                {
                    return(false);
                }
            }
            //if (!this.ReplaceShortCircuitPattern(statements, i+1)) return false;
            PushStatement /*?*/ push = statements[i + 1] as PushStatement;

            if (push == null)
            {
                return(false);
            }
            Conditional /*?*/ chainedConditional = push.ValueToPush as Conditional;

            if (chainedConditional == null)
            {
                return(false);
            }

            return(this.ReplaceShortCircuitPattern(statements, i));
        }
Exemplo n.º 2
0
        public override IExpression Visit(IExpression expression)
        {
            Pop pop = expression as Pop;

            if (pop != null)
            {
                if (this.numberOfPopsToIgnore-- > 0)
                {
                    return(expression);
                }
                PushStatement push = (PushStatement)this.statements[this.i++];
                if (pop is PopAsUnsigned)
                {
                    return(new ConvertToUnsigned(push.ValueToPush));
                }
                else
                {
                    return(push.ValueToPush);
                }
            }
            return(base.Visit(expression));
        }
Exemplo n.º 3
0
        public override IStatement Visit(IStatement statement)
        {
            IGotoStatement gotoStatement = statement as IGotoStatement;

            if (gotoStatement != null)
            {
                this.visitedUnconditionalBranch = true;
                foreach (object ob in this.path)
                {
                    if (ob is IConditionalStatement)
                    {
                        this.visitedUnconditionalBranch = false;
                    }
                }
                StackOfLocals newStack = null;
                if (this.stackFor.TryGetValue(gotoStatement.TargetStatement, out newStack))
                {
                    return(this.TransferStack(gotoStatement, newStack));
                }
                this.stackFor.Add(gotoStatement.TargetStatement, this.operandStack.Clone(this.block));
                return(gotoStatement);
            }
            ILabeledStatement labeledStatement = statement as ILabeledStatement;

            if (labeledStatement != null)
            {
                StackOfLocals newStack = null;
                if (this.stackFor.TryGetValue(labeledStatement, out newStack))
                {
                    return(this.TransferStack(labeledStatement, newStack));
                }
                this.stackFor.Add(labeledStatement, this.operandStack.Clone(this.block));
                return(labeledStatement);
            }
            PushStatement /*?*/ push = statement as PushStatement;

            if (push != null)
            {
                push.ValueToPush = this.Visit(push.ValueToPush);
                this.tempCounter = this.body.localVariablesAndTemporaries.Count;
                var temp = new TempVariable()
                {
                    Name = this.body.host.NameTable.GetNameFor("__temp_" + this.tempCounter++)
                };
                temp.Type = push.ValueToPush.Type;
                this.operandStack.Push(temp);
                this.body.numberOfReferences.Add(temp, 0);
                var ctc = push.ValueToPush as ICompileTimeConstant;
                // "push null" doesn't tell us enough to know what type it really is
                if (ctc != null && ctc.Value == null) // REVIEW: need to make sure the type is a reference type?
                {
                    temp.isPolymorphic = true;
                }
                var be = push.ValueToPush as IBoundExpression;
                if (be != null)
                {
                    var sourceLocal = be.Definition as TempVariable;
                    if (sourceLocal != null && sourceLocal.isPolymorphic)
                    {
                        temp.isPolymorphic = true;
                    }
                }
                if (push.ValueToPush.Type is IManagedPointerTypeReference)
                {
                    temp.turnIntoPopValueExpression = true;
                    return(statement);
                }
                this.body.localVariablesAndTemporaries.Add(temp);
                if (this.block.LocalVariables == null)
                {
                    this.block.LocalVariables = new List <ILocalDefinition>();
                }
                this.block.LocalVariables.Add(temp);
                this.body.numberOfAssignments.Add(temp, 1);
                return(new ExpressionStatement()
                {
                    Expression = new Assignment()
                    {
                        Target = new TargetExpression()
                        {
                            Definition = temp
                        }, Source = push.ValueToPush
                    },
                    Locations = push.Locations
                });
            }
            if (statement is EndFilter || statement is EndFinally)
            {
                this.visitedUnconditionalBranch = true;
                return(statement);
            }
            if (statement is SwitchInstruction)
            {
                return(statement);
            }
            return(base.Visit(statement));
        }
Exemplo n.º 4
0
        private void ReplaceLocalArrayInitializerPattern(List <IStatement> statements, int i)
        {
            if (i > statements.Count - 4)
            {
                return;
            }
            PushStatement /*?*/ push = statements[i] as PushStatement;

            if (push == null)
            {
                return;
            }
            var pushDup = statements[i + 1] as PushStatement;

            if (pushDup == null || !(pushDup.ValueToPush is Dup))
            {
                return;
            }
            CreateArray /*?*/ createArray = push.ValueToPush as CreateArray;

            if (createArray == null)
            {
                return;
            }
            ExpressionStatement /*?*/ expressionStatement = statements[i + 2] as ExpressionStatement;

            if (expressionStatement == null)
            {
                return;
            }
            MethodCall /*?*/ methodCall = expressionStatement.Expression as MethodCall;

            if (methodCall == null || !methodCall.IsStaticCall || methodCall.IsJumpCall || methodCall.Arguments.Count != 2)
            {
                return;
            }
            var pop = methodCall.Arguments[0] as Pop;

            if (pop == null)
            {
                return;
            }
            TokenOf /*?*/ tokenOf = methodCall.Arguments[1] as TokenOf;

            if (tokenOf == null)
            {
                return;
            }
            IFieldDefinition /*?*/ initialValueField = tokenOf.Definition as IFieldDefinition;

            if (initialValueField == null || !initialValueField.IsMapped)
            {
                return;
            }
            if (methodCall.MethodToCall.Name.UniqueKey != this.InitializeArray.UniqueKey)
            {
                return;
            }
            List <ulong> sizes = new List <ulong>();

            foreach (IExpression expr in createArray.Sizes)
            {
                IMetadataConstant mdc = expr as IMetadataConstant;
                if (mdc == null)
                {
                    return;
                }
                sizes.Add(ConvertToUlong(mdc));
            }
            AddArrayInitializers(createArray, initialValueField, sizes.ToArray());
            expressionStatement = statements[i + 3] as ExpressionStatement;
            if (expressionStatement != null)
            {
                Assignment /*?*/ assignment = expressionStatement.Expression as Assignment;
                if (assignment != null)
                {
                    var pop2 = assignment.Source as Pop;
                    if (pop2 != null)
                    {
                        assignment.Source = createArray;
                        statements[i]     = expressionStatement;
                        statements.RemoveRange(i + 1, 3);
                        return;
                    }
                }
            }
            push.ValueToPush = createArray;
            statements.RemoveRange(i + 1, 2);
        }
Exemplo n.º 5
0
        private void ReplacePushPopPattern(List <IStatement> statements, int i)
        {
            if (i > statements.Count - 2)
            {
                return;
            }
            //First identify count consecutive push statements
            int count = 0;

            while (i + count < statements.Count - 1 && statements[i + count] is PushStatement)
            {
                count++;
            }
            while (i > 1 && statements[i - 1] is PushStatement)
            {
                i--; count++;
            }
            if (count == 0)
            {
                return;
            }
            for (int j = 0; j < count; j++)
            {
                if (((PushStatement)statements[j + i]).ValueToPush is Dup)
                {
                    return;
                }
            }
            //If any of the push statements (other than the first one) contains pop expressions, replace them with the corresponding push values and remove the pushes.
            int pushcount = 1; //the number of push statements that are eligble for removal at this point.

            for (int j = i + 1; j < i + count; j++)
            {
                PushStatement st  = (PushStatement)statements[j];
                PopCounter    pcc = new PopCounter();
                new CodeTraverser()
                {
                    PreorderVisitor = pcc
                }.Traverse(st.ValueToPush);
                int numberOfPushesToRemove = pushcount;
                if (pcc.count > 0)
                {
                    if (pcc.count < numberOfPushesToRemove)
                    {
                        numberOfPushesToRemove = pcc.count;
                    }
                    int         firstPushToRemove = j - numberOfPushesToRemove;
                    PopReplacer prr = new PopReplacer(this.sourceMethodBody.host, statements, firstPushToRemove, pcc.count - numberOfPushesToRemove);
                    st.ValueToPush = prr.Visit(st.ValueToPush);
                    statements.RemoveRange(firstPushToRemove, numberOfPushesToRemove);
                    j         = j - pcc.count;
                    count     = count - pcc.count;
                    pushcount = pushcount - pcc.count;
                }
                pushcount++;
            }
            //If the next statement is an expression statement that pops some of the just pushed values, replace those pops with the pushed values and remove the pushes.
            ExpressionStatement /*?*/ expressionStatement = statements[i + count] as ExpressionStatement;

            if (expressionStatement == null)
            {
                return;
            }
            PopCounter pc = new PopCounter();

            new CodeTraverser()
            {
                PreorderVisitor = pc
            }.Traverse(expressionStatement.Expression);
            if (pc.count == 0)
            {
                return;
            }
            if (pc.count < count)
            {
                i    += count - pc.count; //adjust i to point to the first push statement to remove because of subsequent pops.
                count = pc.count;
            }
            PopReplacer pr = new PopReplacer(this.sourceMethodBody.host, statements, i, pc.count - count);

            expressionStatement.Expression = pr.Visit(expressionStatement.Expression);
            expressionStatement.Locations.AddRange(statements[i].Locations);
            statements.RemoveRange(i, count);
        }
Exemplo n.º 6
0
        /// <summary>
        /// Finds the following pattern:
        /// i   :  c ? A : B; // either A or B must be an empty statement and the other is "goto L1;"
        /// i+1 :  push x;
        /// i+2 :  goto L2;
        /// i+3 :  Block1
        ///        0  : L1;
        ///        1  : push y;
        ///        2  : goto L2;
        ///        3  : Block2
        ///             0 : whatever (but presumably it is the label L2)
        ///
        /// Transforms it into:
        /// i   : push d ? X : Y;
        /// i+1 : goto L1;
        /// i+2 : Block 2
        ///
        /// Where if A is the empty statement,
        ///   d == c, X == x, Y == y
        /// If B is the empty statement and y is zero
        ///   d == !c, X == x, Y == y
        /// If B is the empty statement and y is not zero
        ///   d == c, X == y, Y == x
        /// And Block1 is deleted from the list.
        /// </summary>
        private bool ReplaceShortCircuitPatternCreatedByCCI2(List <IStatement> statements, int i)
        {
            if (i > statements.Count - 4)
            {
                return(false);
            }
            ConditionalStatement /*?*/ conditionalStatement = statements[i] as ConditionalStatement;

            if (conditionalStatement == null)
            {
                return(false);
            }
            PushStatement /*?*/ push1 = statements[i + 1] as PushStatement;

            if (push1 == null)
            {
                return(false);
            }
            GotoStatement /*?*/ Goto = statements[i + 2] as GotoStatement;

            if (Goto == null)
            {
                return(false);
            }
            BasicBlock /*?*/ block1 = statements[i + 3] as BasicBlock;

            if (block1 == null)
            {
                return(false);
            }
            if (block1.Statements.Count < 4)
            {
                return(false);
            }
            LabeledStatement /*?*/ label = block1.Statements[0] as LabeledStatement;

            if (label == null)
            {
                return(false);
            }
            List <IGotoStatement> branchesToThisLabel;

            if (this.predecessors.TryGetValue(label, out branchesToThisLabel))
            {
                if (1 < branchesToThisLabel.Count)
                {
                    return(false);
                }
            }
            // TODO? Should we make sure that one of the branches in the conditionalStatement is
            // to label?
            PushStatement /*?*/ push2 = block1.Statements[1] as PushStatement;

            if (push2 == null)
            {
                return(false);
            }
            GotoStatement /*?*/ Goto2 = block1.Statements[2] as GotoStatement;

            if (Goto2 == null)
            {
                return(false);
            }
            if (Goto.TargetStatement != Goto2.TargetStatement)
            {
                return(false);
            }
            BasicBlock /*?*/ block2 = block1.Statements[3] as BasicBlock;

            if (block2 == null)
            {
                return(false);
            }
            if (conditionalStatement.TrueBranch is EmptyStatement)
            {
                Conditional conditional = new Conditional();
                conditional.Condition     = conditionalStatement.Condition;
                conditional.ResultIfTrue  = push1.ValueToPush;
                conditional.ResultIfFalse = push2.ValueToPush;
                conditional.Type          = TypeHelper.MergedType(TypeHelper.StackType(conditional.ResultIfTrue.Type), TypeHelper.StackType(conditional.ResultIfFalse.Type));
                push1.ValueToPush         = conditional;
                push1.Locations           = conditionalStatement.Locations;
                statements[i]             = push1;
                statements[i + 1]         = statements[i + 2]; // move the goto up
                statements[i + 2]         = block2;
                statements.RemoveRange(i + 3, 1);
                return(true);
            }
            if (conditionalStatement.FalseBranch is EmptyStatement)
            {
                Conditional conditional = new Conditional();
                if (ExpressionHelper.IsIntegralZero(push2.ValueToPush))
                {
                    conditional.Condition     = InvertCondition(conditionalStatement.Condition);
                    conditional.ResultIfTrue  = push1.ValueToPush;
                    conditional.ResultIfFalse = push2.ValueToPush;
                }
                else
                {
                    conditional.Condition     = conditionalStatement.Condition;
                    conditional.ResultIfTrue  = push2.ValueToPush;
                    conditional.ResultIfFalse = push1.ValueToPush;
                }
                conditional.Locations = conditionalStatement.Locations;
                conditional.Type      = TypeHelper.MergedType(TypeHelper.StackType(conditional.ResultIfTrue.Type), TypeHelper.StackType(conditional.ResultIfFalse.Type));
                push1.ValueToPush     = conditional;
                push1.Locations       = conditionalStatement.Locations;
                statements[i]         = push1;
                statements[i + 1]     = statements[i + 2]; // move the goto up
                statements[i + 2]     = block2;
                statements.RemoveRange(i + 3, 1);
                return(true);
            }
            return(false);
        }
Exemplo n.º 7
0
        /// <summary>
        /// Finds the following pattern:
        /// i   :  if (c) A else B; // either A or B must be an empty statement and the other is "goto L1;"
        /// i+1 :  push x;
        /// i+2 :  goto L2;
        /// i+3 :  Block1
        ///        0  : L1;
        ///        1  : push y;
        ///        2  : Block2
        ///             0 : L2;
        ///             1 : (rest of statements in Block2)
        ///
        /// Transforms it into:
        /// i   : push (d ? X : Y);
        /// i+1 : (rest of statements in Block2, preceded by L2 if there are more branches to L2 than just the one that was at i+2)
        ///
        /// Where if A is the empty statement, then
        ///   d == c, X == x, Y == y
        /// If B is the empty statement, then if y is zero,
        ///   d == !c, X == x, Y == y
        /// If B is the empty statement, then if y is not zero,
        ///   d == c, X == y, Y == x
        /// </summary>
        private bool ReplaceShortCircuitPattern(List <IStatement> statements, int i)
        {
            if (i > statements.Count - 4)
            {
                return(false);
            }
            ConditionalStatement /*?*/ conditionalStatement = statements[i] as ConditionalStatement;

            if (conditionalStatement == null)
            {
                return(false);
            }
            if (statements[i + 1] is ConditionalStatement)
            {
                return(this.ReplaceChainedShortCircuitBooleanPattern(statements, i));
            }
            GotoStatement /*?*/ gotoL1 = null;

            if (conditionalStatement.TrueBranch is EmptyStatement)
            {
                gotoL1 = conditionalStatement.FalseBranch as GotoStatement;
            }
            else if (conditionalStatement.FalseBranch is EmptyStatement)
            {
                gotoL1 = conditionalStatement.TrueBranch as GotoStatement;
            }
            if (gotoL1 == null)
            {
                return(false);
            }

            PushStatement /*?*/ push = statements[i + 1] as PushStatement;

            if (push == null)
            {
                return(false);
            }
            GotoStatement /*?*/ gotoL2 = statements[i + 2] as GotoStatement;

            if (gotoL2 == null)
            {
                return(false);
            }

            BasicBlock /*?*/ block = statements[i + 3] as BasicBlock;

            if (block == null)
            {
                return(false);
            }
            if (block.Statements.Count < 3)
            {
                return(false);
            }
            LabeledStatement /*?*/ l1 = block.Statements[0] as LabeledStatement;

            if (l1 == null)
            {
                return(false);
            }
            if (l1 != gotoL1.TargetStatement)
            {
                return(false);
            }
            List <IGotoStatement> branchesToThisLabel;

            if (this.predecessors.TryGetValue(l1, out branchesToThisLabel))
            {
                if (branchesToThisLabel.Count > 1)
                {
                    return(false);
                }
            }
            PushStatement /*?*/ push2 = block.Statements[1] as PushStatement;

            if (push2 == null)
            {
                return(false);
            }

            BasicBlock /*?*/ block2 = block.Statements[2] as BasicBlock;

            if (block2 == null || block2.Statements.Count < 1 || block2.Statements[0] != gotoL2.TargetStatement)
            {
                return(false);
            }

            Conditional conditional = new Conditional();

            if (conditionalStatement.TrueBranch is EmptyStatement)
            {
                conditional.Condition     = conditionalStatement.Condition;
                conditional.ResultIfTrue  = push.ValueToPush;
                conditional.ResultIfFalse = push2.ValueToPush;
            }
            else if (conditionalStatement.FalseBranch is EmptyStatement)
            {
                if (ExpressionHelper.IsIntegralZero(push2.ValueToPush))
                {
                    conditional.Condition     = InvertCondition(conditionalStatement.Condition);
                    conditional.ResultIfTrue  = push.ValueToPush;
                    conditional.ResultIfFalse = push2.ValueToPush;
                }
                else
                {
                    conditional.Condition     = conditionalStatement.Condition;
                    conditional.ResultIfTrue  = push2.ValueToPush;
                    conditional.ResultIfFalse = push.ValueToPush;
                }
            }
            conditional.Type      = TypeHelper.MergedType(TypeHelper.StackType(conditional.ResultIfTrue.Type), TypeHelper.StackType(conditional.ResultIfFalse.Type));
            conditional.Locations = conditionalStatement.Locations;

            push.ValueToPush = conditional;
            push.Locations   = conditional.Locations;
            statements[i]    = push;
            statements.RemoveRange(i + 1, 3);
            var l2 = gotoL2.TargetStatement;

            this.predecessors.TryGetValue(l2, out branchesToThisLabel);
            branchesToThisLabel.Remove(gotoL2);
            if (branchesToThisLabel.Count == 0)
            {
                block2.Statements.RemoveAt(0);
            }
            statements.InsertRange(i + 1, block2.Statements);

            return(true);
        }
Exemplo n.º 8
0
        private ILocalDefinition ExtractExceptionContainer(DecompiledBlock nestedBlock, ITypeReference exceptionType)
        {
            Contract.Requires(nestedBlock != null);
            Contract.Requires(exceptionType != null);
            Contract.Ensures(Contract.Result <ILocalDefinition>() != null);

            Contract.Assume(nestedBlock.Statements.Count > 0);
            int i = 0;

            while (nestedBlock.Statements[i] is LocalDeclarationStatement)
            {
                i++; Contract.Assume(i < nestedBlock.Statements.Count);
            }
            ;
            var firstStatement = nestedBlock.Statements[i++];
            var firstBlock     = firstStatement as DecompiledBlock;

            while (firstBlock != null)
            {
                Contract.Assume(firstBlock.Statements.Count > 0);
                i = 0;
                while (firstBlock.Statements[i] is LocalDeclarationStatement)
                {
                    i++; Contract.Assume(i < firstBlock.Statements.Count);
                }
                ;
                firstStatement = firstBlock.Statements[i++];
                nestedBlock    = firstBlock;
                firstBlock     = firstStatement as DecompiledBlock;
            }
            //Ignoring any local declarations inserted for lexical scopes, any decompiled block that does not start with a nested block, starts with a label.
            Contract.Assume(firstStatement is LabeledStatement);
            if (nestedBlock.Statements.Count > i)
            {
                var exprStatement = nestedBlock.Statements[i] as ExpressionStatement;
                if (exprStatement != null)
                {
                    nestedBlock.Statements.RemoveRange(i - 1, 2);
                    if (exprStatement.Expression is PopValue)
                    {
                        return(Dummy.LocalVariable);
                    }
                    var assignment = exprStatement.Expression as Assignment;
                    if (assignment != null && assignment.Source is PopValue)
                    {
                        var local = assignment.Target.Definition as ILocalDefinition;
                        if (local != null)
                        {
                            return(local);   //if not, this is not a recognized code pattern.
                        }
                    }
                }
                // can't find the local, so just introduce one and leave its value on the stack
                var ld = new LocalDefinition()
                {
                    Type = exceptionType,
                };
                var pushStatement = new PushStatement()
                {
                    ValueToPush = new BoundExpression()
                    {
                        Definition = ld,
                        Type       = exceptionType,
                    },
                };
                nestedBlock.Statements.Insert(0, pushStatement);
                return(ld);
            }
            else
            {
                //Valid IL should always have at least one instruction to consume the exception value as well as a branch out of the handler block.
                Contract.Assume(false);
                return(Dummy.LocalVariable);
            }
        }