Esempio n. 1
0
        public bool JoinBasicBlocks(List <ILNode> body, ILBasicBlock head, int pos)
        {
            ILLabel      nextLabel;
            ILBasicBlock nextBB;

            if (!head.Body.ElementAtOrDefault(head.Body.Count - 2).IsConditionalControlFlow() &&
                head.Body.Last().Match(ILCode.Br, out nextLabel) &&
                labelGlobalRefCount[nextLabel] == 1 &&
                labelToBasicBlock.TryGetValue(nextLabel, out nextBB) &&
                body.Contains(nextBB) &&
                nextBB.Body.First() == nextLabel &&
                !nextBB.Body.OfType <ILTryCatchBlock>().Any()
                )
            {
                var tail = head.Body.RemoveTail(ILCode.Br);
                tail[0].AddSelfAndChildrenRecursiveILRanges(nextBB.ILRanges);
                nextBB.Body[0].AddSelfAndChildrenRecursiveILRanges(nextBB.ILRanges);
                nextBB.Body.RemoveAt(0);                  // Remove label
                if (head.Body.Count > 0)
                {
                    head.Body[head.Body.Count - 1].EndILRanges.AddRange(nextBB.ILRanges);
                }
                else
                {
                    head.ILRanges.AddRange(nextBB.ILRanges);
                }
                head.EndILRanges.AddRange(nextBB.EndILRanges);
                head.Body.AddRange(nextBB.Body);

                body.RemoveOrThrow(nextBB);
                return(true);
            }
            return(false);
        }
Esempio n. 2
0
        public bool SimplifyShortCircuit(List <ILNode> body, ILBasicBlock head, int pos)
        {
            Debug.Assert(body.Contains(head));

            ILExpression condExpr;
            ILLabel      trueLabel;
            ILLabel      falseLabel;

            if (head.MatchLastAndBr(ILCode.Brtrue, out trueLabel, out condExpr, out falseLabel))
            {
                for (int pass = 0; pass < 2; pass++)
                {
                    // On the second pass, swap labels and negate expression of the first branch
                    // It is slightly ugly, but much better then copy-pasting this whole block
                    ILLabel nextLabel   = (pass == 0) ? trueLabel  : falseLabel;
                    ILLabel otherLablel = (pass == 0) ? falseLabel : trueLabel;
                    bool    negate      = (pass == 1);

                    ILBasicBlock nextBasicBlock = labelToBasicBlock[nextLabel];
                    ILExpression nextCondExpr;
                    ILLabel      nextTrueLablel;
                    ILLabel      nextFalseLabel;
                    if (body.Contains(nextBasicBlock) &&
                        nextBasicBlock != head &&
                        labelGlobalRefCount[(ILLabel)nextBasicBlock.Body.First()] == 1 &&
                        nextBasicBlock.MatchSingleAndBr(ILCode.Brtrue, out nextTrueLablel, out nextCondExpr, out nextFalseLabel) &&
                        (otherLablel == nextFalseLabel || otherLablel == nextTrueLablel))
                    {
                        // Create short cicuit branch
                        ILExpression logicExpr;
                        if (otherLablel == nextFalseLabel)
                        {
                            logicExpr = MakeLeftAssociativeShortCircuit(ILCode.LogicAnd, negate ? new ILExpression(ILCode.LogicNot, null, condExpr) : condExpr, nextCondExpr);
                        }
                        else
                        {
                            logicExpr = MakeLeftAssociativeShortCircuit(ILCode.LogicOr, negate ? condExpr : new ILExpression(ILCode.LogicNot, null, condExpr), nextCondExpr);
                        }
                        var tail = head.Body.RemoveTail(ILCode.Brtrue, ILCode.Br);
                        nextCondExpr.ILRanges.AddRange(tail[0].ILRanges);                                  // brtrue
                        nextCondExpr.ILRanges.AddRange(nextBasicBlock.ILRanges);
                        nextBasicBlock.Body[0].AddSelfAndChildrenRecursiveILRanges(nextCondExpr.ILRanges); // label
                        nextCondExpr.ILRanges.AddRange(nextBasicBlock.Body[1].ILRanges);                   // brtrue

                        head.Body.Add(new ILExpression(ILCode.Brtrue, nextTrueLablel, logicExpr));
                        ILExpression brFalseLbl;
                        head.Body.Add(brFalseLbl = new ILExpression(ILCode.Br, nextFalseLabel));
                        nextBasicBlock.Body[2].AddSelfAndChildrenRecursiveILRanges(brFalseLbl.ILRanges);          // br
                        brFalseLbl.ILRanges.AddRange(nextBasicBlock.EndILRanges);
                        tail[1].AddSelfAndChildrenRecursiveILRanges(brFalseLbl.ILRanges);                         // br

                        // Remove the inlined branch from scope
                        body.RemoveOrThrow(nextBasicBlock);

                        return(true);
                    }
                }
            }
            return(false);
        }
Esempio n. 3
0
        public bool SimplifyNullCoalescing(List <ILNode> body, ILBasicBlock head, int pos)
        {
            // ...
            // v = ldloc(leftVar)
            // brtrue(endBBLabel, ldloc(leftVar))
            // br(rightBBLabel)
            //
            // rightBBLabel:
            // v = rightExpr
            // br(endBBLabel)
            // ...
            // =>
            // ...
            // v = NullCoalescing(ldloc(leftVar), rightExpr)
            // br(endBBLabel)

            ILVariable   v, v2;
            ILExpression leftExpr, leftExpr2;
            ILVariable   leftVar;
            ILLabel      endBBLabel, endBBLabel2;
            ILLabel      rightBBLabel;
            ILBasicBlock rightBB;
            ILExpression rightExpr;

            if (head.Body.Count >= 3 &&
                head.Body[head.Body.Count - 3].Match(ILCode.Stloc, out v, out leftExpr) &&
                leftExpr.Match(ILCode.Ldloc, out leftVar) &&
                head.MatchLastAndBr(ILCode.Brtrue, out endBBLabel, out leftExpr2, out rightBBLabel) &&
                leftExpr2.MatchLdloc(leftVar) &&
                labelToBasicBlock.TryGetValue(rightBBLabel, out rightBB) &&
                rightBB.MatchSingleAndBr(ILCode.Stloc, out v2, out rightExpr, out endBBLabel2) &&
                v == v2 &&
                endBBLabel == endBBLabel2 &&
                labelGlobalRefCount.GetOrDefault(rightBBLabel) == 1 &&
                body.Contains(rightBB)
                )
            {
                var          tail = head.Body.RemoveTail(ILCode.Stloc, ILCode.Brtrue, ILCode.Br);
                ILExpression nullCoal, stloc;
                head.Body.Add(stloc = new ILExpression(ILCode.Stloc, v, nullCoal = new ILExpression(ILCode.NullCoalescing, null, leftExpr, rightExpr)));
                head.Body.Add(new ILExpression(ILCode.Br, endBBLabel));
                tail[0].AddSelfAndChildrenRecursiveILRanges(stloc.ILRanges);
                tail[1].AddSelfAndChildrenRecursiveILRanges(nullCoal.ILRanges);
                tail[2].AddSelfAndChildrenRecursiveILRanges(rightExpr.ILRanges);            // br (to rightBB)
                rightExpr.ILRanges.AddRange(rightBB.AllILRanges);
                rightBB.Body[0].AddSelfAndChildrenRecursiveILRanges(rightExpr.ILRanges);    // label
                rightExpr.ILRanges.AddRange(rightBB.Body[1].ILRanges);                      // stloc: no recursive add
                rightBB.Body[2].AddSelfAndChildrenRecursiveILRanges(rightExpr.ILRanges);    // br

                body.RemoveOrThrow(labelToBasicBlock[rightBBLabel]);
                return(true);
            }
            return(false);
        }
Esempio n. 4
0
        public bool SimplifyNullCoalescing(List <ILNode> body, ILBasicBlock head, int pos)
        {
            // ...
            // v = ldloc(leftVar)
            // brtrue(endBBLabel, ldloc(leftVar))
            // br(rightBBLabel)
            //
            // rightBBLabel:
            // v = rightExpr
            // br(endBBLabel)
            // ...
            // =>
            // ...
            // v = NullCoalescing(ldloc(leftVar), rightExpr)
            // br(endBBLabel)

            ILVariable   v, v2;
            ILExpression leftExpr, leftExpr2;
            ILVariable   leftVar;
            ILLabel      endBBLabel, endBBLabel2;
            ILLabel      rightBBLabel;
            ILBasicBlock rightBB;
            ILExpression rightExpr;

            if (head.Body.Count >= 3 &&
                head.Body[head.Body.Count - 3].Match(ILCode.Stloc, out v, out leftExpr) &&
                leftExpr.Match(ILCode.Ldloc, out leftVar) &&
                head.MatchLastAndBr(ILCode.Brtrue, out endBBLabel, out leftExpr2, out rightBBLabel) &&
                leftExpr2.MatchLdloc(leftVar) &&
                labelToBasicBlock.TryGetValue(rightBBLabel, out rightBB) &&
                rightBB.MatchSingleAndBr(ILCode.Stloc, out v2, out rightExpr, out endBBLabel2) &&
                v == v2 &&
                endBBLabel == endBBLabel2 &&
                labelGlobalRefCount.GetOrDefault(rightBBLabel) == 1 &&
                body.Contains(rightBB)
                )
            {
                head.Body.RemoveTail(ILCode.Stloc, ILCode.Brtrue, ILCode.Br);
                head.Body.Add(new ILExpression(ILCode.Stloc, v, new ILExpression(ILCode.NullCoalescing, null, leftExpr, rightExpr)));
                head.Body.Add(new ILExpression(ILCode.Br, endBBLabel));

                body.RemoveOrThrow(labelToBasicBlock[rightBBLabel]);
                return(true);
            }
            return(false);
        }
Esempio n. 5
0
		public bool SimplifyNullCoalescing(List<AstNode> body, AstBasicBlock head, int pos)
		{
			// ...
			// v = ldloc(leftVar)
			// brtrue(endBBLabel, ldloc(leftVar))
			// br(rightBBLabel)
			//
			// rightBBLabel:
			// v = rightExpr
			// br(endBBLabel)
			// ...
			// =>
			// ...
			// v = NullCoalescing(ldloc(leftVar), rightExpr)
			// br(endBBLabel)
			
			AstVariable v, v2;
			AstExpression leftExpr, leftExpr2;
			AstVariable leftVar;
			AstLabel endBBLabel, endBBLabel2;
			AstLabel rightBBLabel;
			AstBasicBlock rightBB;
			AstExpression rightExpr;
			if (head.Body.Count >= 3 &&
			    head.Body[head.Body.Count - 3].Match(AstCode.Stloc, out v, out leftExpr) &&
			    leftExpr.Match(AstCode.Ldloc, out leftVar) &&
			    head.MatchLastAndBr(AstCode.Brtrue, out endBBLabel, out leftExpr2, out rightBBLabel) &&
			    leftExpr2.MatchLdloc(leftVar) &&
			    labelToBasicBlock.TryGetValue(rightBBLabel, out rightBB) &&
			    rightBB.MatchSingleAndBr(AstCode.Stloc, out v2, out rightExpr, out endBBLabel2) &&
			    v == v2 &&
			    endBBLabel == endBBLabel2 &&
			    labelGlobalRefCount.GetOrDefault(rightBBLabel) == 1 &&
			    body.Contains(rightBB)
			   )
			{
				head.Body.RemoveTail(AstCode.Stloc, AstCode.Brtrue, AstCode.Br);
				head.Body.Add(new AstExpression(leftExpr.SourceLocation, AstCode.Stloc, v, new AstExpression(leftExpr.SourceLocation, AstCode.NullCoalescing, null, leftExpr, rightExpr)));
				head.Body.Add(new AstExpression(leftExpr.SourceLocation, AstCode.Br, endBBLabel));
				
				body.RemoveOrThrow(labelToBasicBlock[rightBBLabel]);
				return true;
			}
			return false;
		}
Esempio n. 6
0
        public bool JoinBasicBlocks(List<ILNode> body, ILBasicBlock head, int pos)
        {
            ILLabel nextLabel;
            ILBasicBlock nextBB;
            if (!head.Body.ElementAtOrDefault(head.Body.Count - 2).IsConditionalControlFlow() &&
                head.Body.Last().Match(ILCode.Br, out nextLabel) &&
                labelGlobalRefCount[nextLabel] == 1 &&
                labelToBasicBlock.TryGetValue(nextLabel, out nextBB) &&
                body.Contains(nextBB) &&
                nextBB.Body.First() == nextLabel &&
                !nextBB.Body.OfType<ILTryCatchBlock>().Any()
               )
            {
                head.Body.RemoveTail(ILCode.Br);
                nextBB.Body.RemoveAt(0);  // Remove label
                head.Body.AddRange(nextBB.Body);

                body.RemoveOrThrow(nextBB);
                return true;
            }
            return false;
        }
Esempio n. 7
0
        public bool JoinBasicBlocks(List <AstNode> body, AstBasicBlock head, int pos)
        {
            AstLabel      nextLabel;
            AstBasicBlock nextBB;

            if (!head.Body.ElementAtOrDefault(head.Body.Count - 2).IsConditionalControlFlow() &&
                head.Body.Last().Match(AstCode.Br, out nextLabel) &&
                labelGlobalRefCount[nextLabel] == 1 &&
                labelToBasicBlock.TryGetValue(nextLabel, out nextBB) &&
                body.Contains(nextBB) &&
                nextBB.Body.First() == nextLabel &&
                !nextBB.Body.OfType <AstTryCatchBlock>().Any()
                )
            {
                head.Body.RemoveTail(AstCode.Br);
                nextBB.Body.RemoveAt(0);                  // Remove label
                head.Body.AddRange(nextBB.Body);

                body.RemoveOrThrow(nextBB);
                return(true);
            }
            return(false);
        }
Esempio n. 8
0
        public bool SimplifyTernaryOperator(List<ILNode> body, ILBasicBlock head, int pos)
        {
            Debug.Assert(body.Contains(head));

            ILExpression condExpr;
            ILLabel trueLabel;
            ILLabel falseLabel;
            ILVariable trueLocVar = null;
            ILExpression trueExpr;
            ILLabel trueFall;
            ILVariable falseLocVar = null;
            ILExpression falseExpr;
            ILLabel falseFall;
            object unused;

            if (head.MatchLastAndBr(ILCode.Brtrue, out trueLabel, out condExpr, out falseLabel) &&
                labelGlobalRefCount[trueLabel] == 1 &&
                labelGlobalRefCount[falseLabel] == 1 &&
                ((labelToBasicBlock[trueLabel].MatchSingleAndBr(ILCode.Stloc, out trueLocVar, out trueExpr, out trueFall) &&
                  labelToBasicBlock[falseLabel].MatchSingleAndBr(ILCode.Stloc, out falseLocVar, out falseExpr, out falseFall) &&
                  trueLocVar == falseLocVar && trueFall == falseFall) ||
                 (labelToBasicBlock[trueLabel].MatchSingle(ILCode.Ret, out unused, out trueExpr) &&
                  labelToBasicBlock[falseLabel].MatchSingle(ILCode.Ret, out unused, out falseExpr))) &&
                body.Contains(labelToBasicBlock[trueLabel]) &&
                body.Contains(labelToBasicBlock[falseLabel])
               )
            {
                bool isStloc = trueLocVar != null;
                ILCode opCode = isStloc ? ILCode.Stloc : ILCode.Ret;
                TypeSig retType = isStloc ? trueLocVar.Type : this.context.CurrentMethod.ReturnType;
                bool retTypeIsBoolean = retType.GetElementType() == ElementType.Boolean;
                int leftBoolVal;
                int rightBoolVal;
                ILExpression newExpr;
                // a ? true:false  is equivalent to  a
                // a ? false:true  is equivalent to  !a
                // a ? true : b    is equivalent to  a || b
                // a ? b : true    is equivalent to  !a || b
                // a ? b : false   is equivalent to  a && b
                // a ? false : b   is equivalent to  !a && b
                if (retTypeIsBoolean &&
                    trueExpr.Match(ILCode.Ldc_I4, out leftBoolVal) &&
                    falseExpr.Match(ILCode.Ldc_I4, out rightBoolVal) &&
                    ((leftBoolVal != 0 && rightBoolVal == 0) || (leftBoolVal == 0 && rightBoolVal != 0))
                   )
                {
                    // It can be expressed as trivilal expression
                    if (leftBoolVal != 0) {
                        newExpr = condExpr;
                    } else {
                        newExpr = new ILExpression(ILCode.LogicNot, null, condExpr) { InferredType = corLib.Boolean };
                    }
                } else if ((retTypeIsBoolean || falseExpr.InferredType.GetElementType() == ElementType.Boolean) && trueExpr.Match(ILCode.Ldc_I4, out leftBoolVal) && (leftBoolVal == 0 || leftBoolVal == 1)) {
                    // It can be expressed as logical expression
                    if (leftBoolVal != 0) {
                        newExpr = MakeLeftAssociativeShortCircuit(ILCode.LogicOr, condExpr, falseExpr);
                    } else {
                        newExpr = MakeLeftAssociativeShortCircuit(ILCode.LogicAnd, new ILExpression(ILCode.LogicNot, null, condExpr), falseExpr);
                    }
                } else if ((retTypeIsBoolean || trueExpr.InferredType.GetElementType() == ElementType.Boolean) && falseExpr.Match(ILCode.Ldc_I4, out rightBoolVal) && (rightBoolVal == 0 || rightBoolVal == 1)) {
                    // It can be expressed as logical expression
                    if (rightBoolVal != 0) {
                        newExpr = MakeLeftAssociativeShortCircuit(ILCode.LogicOr, new ILExpression(ILCode.LogicNot, null, condExpr), trueExpr);
                    } else {
                        newExpr = MakeLeftAssociativeShortCircuit(ILCode.LogicAnd, condExpr, trueExpr);
                    }
                } else {
                    // Ternary operator tends to create long complicated return statements
                    if (opCode == ILCode.Ret)
                        return false;

                    // Only simplify generated variables
                    if (opCode == ILCode.Stloc && !trueLocVar.GeneratedByDecompiler)
                        return false;

                    // Create ternary expression
                    newExpr = new ILExpression(ILCode.TernaryOp, null, condExpr, trueExpr, falseExpr);
                }

                var tail = head.Body.RemoveTail(ILCode.Brtrue, ILCode.Br);
                var listNodes = new List<ILNode>();
                var newExprNodes = newExpr.GetSelfAndChildrenRecursive<ILNode>(listNodes).ToArray();
                foreach (var node in labelToBasicBlock[trueLabel].GetSelfAndChildrenRecursive<ILNode>(listNodes).Except(newExprNodes))
                    newExpr.ILRanges.AddRange(node.AllILRanges);
                foreach (var node in labelToBasicBlock[falseLabel].GetSelfAndChildrenRecursive<ILNode>(listNodes).Except(newExprNodes))
                    newExpr.ILRanges.AddRange(node.AllILRanges);
                newExpr.ILRanges.AddRange(tail[0].ILRanges);
                tail[1].AddSelfAndChildrenRecursiveILRanges(newExpr.ILRanges);

                head.Body.Add(new ILExpression(opCode, trueLocVar, newExpr));
                if (isStloc)
                    head.Body.Add(new ILExpression(ILCode.Br, trueFall));

                // Remove the old basic blocks
                body.RemoveOrThrow(labelToBasicBlock[trueLabel]);
                body.RemoveOrThrow(labelToBasicBlock[falseLabel]);

                return true;
            }
            return false;
        }
Esempio n. 9
0
        public bool SimplifyShortCircuit(List<ILNode> body, ILBasicBlock head, int pos)
        {
            Debug.Assert(body.Contains(head));

            ILExpression condExpr;
            ILLabel trueLabel;
            ILLabel falseLabel;
            if(head.MatchLastAndBr(ILCode.Brtrue, out trueLabel, out condExpr, out falseLabel)) {
                for (int pass = 0; pass < 2; pass++) {

                    // On the second pass, swap labels and negate expression of the first branch
                    // It is slightly ugly, but much better then copy-pasting this whole block
                    ILLabel nextLabel   = (pass == 0) ? trueLabel  : falseLabel;
                    ILLabel otherLablel = (pass == 0) ? falseLabel : trueLabel;
                    bool    negate      = (pass == 1);

                    ILBasicBlock nextBasicBlock = labelToBasicBlock[nextLabel];
                    ILExpression nextCondExpr;
                    ILLabel nextTrueLablel;
                    ILLabel nextFalseLabel;
                    if (body.Contains(nextBasicBlock) &&
                        nextBasicBlock != head &&
                        labelGlobalRefCount[(ILLabel)nextBasicBlock.Body.First()] == 1 &&
                        nextBasicBlock.MatchSingleAndBr(ILCode.Brtrue, out nextTrueLablel, out nextCondExpr, out nextFalseLabel) &&
                        (otherLablel == nextFalseLabel || otherLablel == nextTrueLablel))
                    {
                        // Create short cicuit branch
                        ILExpression logicExpr;
                        if (otherLablel == nextFalseLabel) {
                            logicExpr = MakeLeftAssociativeShortCircuit(ILCode.LogicAnd, negate ? new ILExpression(ILCode.LogicNot, null, condExpr) : condExpr, nextCondExpr);
                        } else {
                            logicExpr = MakeLeftAssociativeShortCircuit(ILCode.LogicOr, negate ? condExpr : new ILExpression(ILCode.LogicNot, null, condExpr), nextCondExpr);
                        }
                        var tail = head.Body.RemoveTail(ILCode.Brtrue, ILCode.Br);
                        nextCondExpr.ILRanges.AddRange(tail[0].ILRanges);	// brtrue
                        nextCondExpr.ILRanges.AddRange(nextBasicBlock.ILRanges);
                        nextBasicBlock.Body[0].AddSelfAndChildrenRecursiveILRanges(nextCondExpr.ILRanges);	// label
                        nextCondExpr.ILRanges.AddRange(nextBasicBlock.Body[1].ILRanges);	// brtrue

                        head.Body.Add(new ILExpression(ILCode.Brtrue, nextTrueLablel, logicExpr));
                        ILExpression brFalseLbl;
                        head.Body.Add(brFalseLbl = new ILExpression(ILCode.Br, nextFalseLabel));
                        nextBasicBlock.Body[2].AddSelfAndChildrenRecursiveILRanges(brFalseLbl.ILRanges);	// br
                        brFalseLbl.ILRanges.AddRange(nextBasicBlock.EndILRanges);
                        tail[1].AddSelfAndChildrenRecursiveILRanges(brFalseLbl.ILRanges); // br

                        // Remove the inlined branch from scope
                        body.RemoveOrThrow(nextBasicBlock);

                        return true;
                    }
                }
            }
            return false;
        }
Esempio n. 10
0
        public bool SimplifyNullCoalescing(List<ILNode> body, ILBasicBlock head, int pos)
        {
            // ...
            // v = ldloc(leftVar)
            // brtrue(endBBLabel, ldloc(leftVar))
            // br(rightBBLabel)
            //
            // rightBBLabel:
            // v = rightExpr
            // br(endBBLabel)
            // ...
            // =>
            // ...
            // v = NullCoalescing(ldloc(leftVar), rightExpr)
            // br(endBBLabel)

            ILVariable v, v2;
            ILExpression leftExpr, leftExpr2;
            ILVariable leftVar;
            ILLabel endBBLabel, endBBLabel2;
            ILLabel rightBBLabel;
            ILBasicBlock rightBB;
            ILExpression rightExpr;
            if (head.Body.Count >= 3 &&
                head.Body[head.Body.Count - 3].Match(ILCode.Stloc, out v, out leftExpr) &&
                leftExpr.Match(ILCode.Ldloc, out leftVar) &&
                head.MatchLastAndBr(ILCode.Brtrue, out endBBLabel, out leftExpr2, out rightBBLabel) &&
                leftExpr2.MatchLdloc(leftVar) &&
                labelToBasicBlock.TryGetValue(rightBBLabel, out rightBB) &&
                rightBB.MatchSingleAndBr(ILCode.Stloc, out v2, out rightExpr, out endBBLabel2) &&
                v == v2 &&
                endBBLabel == endBBLabel2 &&
                labelGlobalRefCount.GetOrDefault(rightBBLabel) == 1 &&
                body.Contains(rightBB)
               )
            {
                var tail = head.Body.RemoveTail(ILCode.Stloc, ILCode.Brtrue, ILCode.Br);
                ILExpression nullCoal, stloc;
                head.Body.Add(stloc = new ILExpression(ILCode.Stloc, v, nullCoal = new ILExpression(ILCode.NullCoalescing, null, leftExpr, rightExpr)));
                head.Body.Add(new ILExpression(ILCode.Br, endBBLabel));
                tail[0].AddSelfAndChildrenRecursiveILRanges(stloc.ILRanges);
                tail[1].AddSelfAndChildrenRecursiveILRanges(nullCoal.ILRanges);
                tail[2].AddSelfAndChildrenRecursiveILRanges(rightExpr.ILRanges);	// br (to rightBB)
                rightExpr.ILRanges.AddRange(rightBB.AllILRanges);
                rightBB.Body[0].AddSelfAndChildrenRecursiveILRanges(rightExpr.ILRanges);	// label
                rightExpr.ILRanges.AddRange(rightBB.Body[1].ILRanges);      // stloc: no recursive add
                rightBB.Body[2].AddSelfAndChildrenRecursiveILRanges(rightExpr.ILRanges);	// br

                body.RemoveOrThrow(labelToBasicBlock[rightBBLabel]);
                return true;
            }
            return false;
        }
Esempio n. 11
0
        public bool SimplifyTernaryOperator(List <ILNode> body, ILBasicBlock head, int pos)
        {
            Debug.Assert(body.Contains(head));

            ILExpression condExpr;
            ILLabel      trueLabel;
            ILLabel      falseLabel;
            ILVariable   trueLocVar = null;
            ILExpression trueExpr;
            ILLabel      trueFall;
            ILVariable   falseLocVar = null;
            ILExpression falseExpr;
            ILLabel      falseFall;
            object       unused;

            if (head.MatchLastAndBr(ILCode.Brtrue, out trueLabel, out condExpr, out falseLabel) &&
                labelGlobalRefCount[trueLabel] == 1 &&
                labelGlobalRefCount[falseLabel] == 1 &&
                ((labelToBasicBlock[trueLabel].MatchSingleAndBr(ILCode.Stloc, out trueLocVar, out trueExpr, out trueFall) &&
                  labelToBasicBlock[falseLabel].MatchSingleAndBr(ILCode.Stloc, out falseLocVar, out falseExpr, out falseFall) &&
                  trueLocVar == falseLocVar && trueFall == falseFall) ||
                 (labelToBasicBlock[trueLabel].MatchSingle(ILCode.Ret, out unused, out trueExpr) &&
                  labelToBasicBlock[falseLabel].MatchSingle(ILCode.Ret, out unused, out falseExpr))) &&
                body.Contains(labelToBasicBlock[trueLabel]) &&
                body.Contains(labelToBasicBlock[falseLabel])
                )
            {
                bool          isStloc          = trueLocVar != null;
                ILCode        opCode           = isStloc ? ILCode.Stloc : ILCode.Ret;
                TypeReference retType          = isStloc ? trueLocVar.Type : this.context.CurrentMethod.ReturnType;
                bool          retTypeIsBoolean = TypeAnalysis.IsBoolean(retType);
                int           leftBoolVal;
                int           rightBoolVal;
                ILExpression  newExpr;
                // a ? true:false  is equivalent to  a
                // a ? false:true  is equivalent to  !a
                // a ? true : b    is equivalent to  a || b
                // a ? b : true    is equivalent to  !a || b
                // a ? b : false   is equivalent to  a && b
                // a ? false : b   is equivalent to  !a && b
                if (retTypeIsBoolean &&
                    trueExpr.Match(ILCode.Ldc_I4, out leftBoolVal) &&
                    falseExpr.Match(ILCode.Ldc_I4, out rightBoolVal) &&
                    ((leftBoolVal != 0 && rightBoolVal == 0) || (leftBoolVal == 0 && rightBoolVal != 0))
                    )
                {
                    // It can be expressed as trivilal expression
                    if (leftBoolVal != 0)
                    {
                        newExpr = condExpr;
                    }
                    else
                    {
                        newExpr = new ILExpression(ILCode.LogicNot, null, condExpr);
                    }
                }
                else if (retTypeIsBoolean && trueExpr.Match(ILCode.Ldc_I4, out leftBoolVal))
                {
                    // It can be expressed as logical expression
                    if (leftBoolVal != 0)
                    {
                        newExpr = MakeLeftAssociativeShortCircuit(ILCode.LogicOr, condExpr, falseExpr);
                    }
                    else
                    {
                        newExpr = MakeLeftAssociativeShortCircuit(ILCode.LogicAnd, new ILExpression(ILCode.LogicNot, null, condExpr), falseExpr);
                    }
                }
                else if (retTypeIsBoolean && falseExpr.Match(ILCode.Ldc_I4, out rightBoolVal))
                {
                    // It can be expressed as logical expression
                    if (rightBoolVal != 0)
                    {
                        newExpr = MakeLeftAssociativeShortCircuit(ILCode.LogicOr, new ILExpression(ILCode.LogicNot, null, condExpr), trueExpr);
                    }
                    else
                    {
                        newExpr = MakeLeftAssociativeShortCircuit(ILCode.LogicAnd, condExpr, trueExpr);
                    }
                }
                else
                {
                    // Ternary operator tends to create long complicated return statements
                    if (opCode == ILCode.Ret)
                    {
                        return(false);
                    }

                    // Only simplify generated variables
                    if (opCode == ILCode.Stloc && !trueLocVar.IsGenerated)
                    {
                        return(false);
                    }

                    // Create ternary expression
                    newExpr = new ILExpression(ILCode.TernaryOp, null, condExpr, trueExpr, falseExpr);
                }

                head.Body.RemoveTail(ILCode.Brtrue, ILCode.Br);
                head.Body.Add(new ILExpression(opCode, trueLocVar, newExpr));
                if (isStloc)
                {
                    head.Body.Add(new ILExpression(ILCode.Br, trueFall));
                }

                // Remove the old basic blocks
                body.RemoveOrThrow(labelToBasicBlock[trueLabel]);
                body.RemoveOrThrow(labelToBasicBlock[falseLabel]);

                return(true);
            }
            return(false);
        }
Esempio n. 12
0
		public bool SimplifyTernaryOperator(List<ILNode> body, ILBasicBlock head, int pos)
		{
			Debug.Assert(body.Contains(head));
			
			ILExpression condExpr;
			ILLabel trueLabel;
			ILLabel falseLabel;
			ILVariable trueLocVar = null;
			ILExpression trueExpr;
			ILLabel trueFall;
			ILVariable falseLocVar = null;
			ILExpression falseExpr;
			ILLabel falseFall;
			object unused;
			
			if (head.MatchLastAndBr(ILCode.Brtrue, out trueLabel, out condExpr, out falseLabel) &&
			    labelGlobalRefCount[trueLabel] == 1 &&
			    labelGlobalRefCount[falseLabel] == 1 &&
			    ((labelToBasicBlock[trueLabel].MatchSingleAndBr(ILCode.Stloc, out trueLocVar, out trueExpr, out trueFall) &&
			      labelToBasicBlock[falseLabel].MatchSingleAndBr(ILCode.Stloc, out falseLocVar, out falseExpr, out falseFall) &&
			      trueLocVar == falseLocVar && trueFall == falseFall) ||
			     (labelToBasicBlock[trueLabel].MatchSingle(ILCode.Ret, out unused, out trueExpr) &&
			      labelToBasicBlock[falseLabel].MatchSingle(ILCode.Ret, out unused, out falseExpr))) &&
			    body.Contains(labelToBasicBlock[trueLabel]) &&
			    body.Contains(labelToBasicBlock[falseLabel])
			   )
			{
				bool isStloc = trueLocVar != null;
				ILCode opCode = isStloc ? ILCode.Stloc : ILCode.Ret;
				TypeReference retType = isStloc ? trueLocVar.Type : this.context.CurrentMethod.ReturnType;
				bool retTypeIsBoolean = TypeAnalysis.IsBoolean(retType);
				int leftBoolVal;
				int rightBoolVal;
				ILExpression newExpr;
				// a ? true:false  is equivalent to  a
				// a ? false:true  is equivalent to  !a
				// a ? true : b    is equivalent to  a || b
				// a ? b : true    is equivalent to  !a || b
				// a ? b : false   is equivalent to  a && b
				// a ? false : b   is equivalent to  !a && b
				if (retTypeIsBoolean &&
				    trueExpr.Match(ILCode.Ldc_I4, out leftBoolVal) &&
				    falseExpr.Match(ILCode.Ldc_I4, out rightBoolVal) &&
				    ((leftBoolVal != 0 && rightBoolVal == 0) || (leftBoolVal == 0 && rightBoolVal != 0))
				   )
				{
					// It can be expressed as trivilal expression
					if (leftBoolVal != 0) {
						newExpr = condExpr;
					} else {
						newExpr = new ILExpression(ILCode.LogicNot, null, condExpr);
					}
				} else if (retTypeIsBoolean && trueExpr.Match(ILCode.Ldc_I4, out leftBoolVal)) {
					// It can be expressed as logical expression
					if (leftBoolVal != 0) {
						newExpr = MakeLeftAssociativeShortCircuit(ILCode.LogicOr, condExpr, falseExpr);
					} else {
						newExpr = MakeLeftAssociativeShortCircuit(ILCode.LogicAnd, new ILExpression(ILCode.LogicNot, null, condExpr), falseExpr);
					}
				} else if (retTypeIsBoolean && falseExpr.Match(ILCode.Ldc_I4, out rightBoolVal)) {
					// It can be expressed as logical expression
					if (rightBoolVal != 0) {
						newExpr = MakeLeftAssociativeShortCircuit(ILCode.LogicOr, new ILExpression(ILCode.LogicNot, null, condExpr), trueExpr);
					} else {
						newExpr = MakeLeftAssociativeShortCircuit(ILCode.LogicAnd, condExpr, trueExpr);
					}
				} else {
					// Ternary operator tends to create long complicated return statements					
					if (opCode == ILCode.Ret)
						return false;
					
					// Only simplify generated variables
					if (opCode == ILCode.Stloc && !trueLocVar.IsGenerated)
						return false;
					
					// Create ternary expression
					newExpr = new ILExpression(ILCode.TernaryOp, null, condExpr, trueExpr, falseExpr);
				}
				
				head.Body.RemoveTail(ILCode.Brtrue, ILCode.Br);
				head.Body.Add(new ILExpression(opCode, trueLocVar, newExpr));
				if (isStloc)
					head.Body.Add(new ILExpression(ILCode.Br, trueFall));
				
				// Remove the old basic blocks
				body.RemoveOrThrow(labelToBasicBlock[trueLabel]);
				body.RemoveOrThrow(labelToBasicBlock[falseLabel]);
				
				return true;
			}
			return false;
		}
Esempio n. 13
0
        public bool SimplifyTernaryOperator(List <ILNode> body, ILBasicBlock head, int pos)
        {
            Debug.Assert(body.Contains(head));

            ILExpression condExpr;
            ILLabel      trueLabel;
            ILLabel      falseLabel;
            ILVariable   trueLocVar = null;
            ILExpression trueExpr;
            ILLabel      trueFall;
            ILVariable   falseLocVar = null;
            ILExpression falseExpr;
            ILLabel      falseFall;
            object       unused;

            if (head.MatchLastAndBr(ILCode.Brtrue, out trueLabel, out condExpr, out falseLabel) &&
                labelGlobalRefCount[trueLabel] == 1 &&
                labelGlobalRefCount[falseLabel] == 1 &&
                ((labelToBasicBlock[trueLabel].MatchSingleAndBr(ILCode.Stloc, out trueLocVar, out trueExpr, out trueFall) &&
                  labelToBasicBlock[falseLabel].MatchSingleAndBr(ILCode.Stloc, out falseLocVar, out falseExpr, out falseFall) &&
                  trueLocVar == falseLocVar && trueFall == falseFall) ||
                 (labelToBasicBlock[trueLabel].MatchSingle(ILCode.Ret, out unused, out trueExpr) &&
                  labelToBasicBlock[falseLabel].MatchSingle(ILCode.Ret, out unused, out falseExpr))) &&
                body.Contains(labelToBasicBlock[trueLabel]) &&
                body.Contains(labelToBasicBlock[falseLabel])
                )
            {
                bool         isStloc          = trueLocVar != null;
                ILCode       opCode           = isStloc ? ILCode.Stloc : ILCode.Ret;
                TypeSig      retType          = isStloc ? trueLocVar.Type : this.context.CurrentMethod.ReturnType;
                bool         retTypeIsBoolean = retType.GetElementType() == ElementType.Boolean;
                int          leftBoolVal;
                int          rightBoolVal;
                ILExpression newExpr;
                // a ? true:false  is equivalent to  a
                // a ? false:true  is equivalent to  !a
                // a ? true : b    is equivalent to  a || b
                // a ? b : true    is equivalent to  !a || b
                // a ? b : false   is equivalent to  a && b
                // a ? false : b   is equivalent to  !a && b
                if (retTypeIsBoolean &&
                    trueExpr.Match(ILCode.Ldc_I4, out leftBoolVal) &&
                    falseExpr.Match(ILCode.Ldc_I4, out rightBoolVal) &&
                    ((leftBoolVal != 0 && rightBoolVal == 0) || (leftBoolVal == 0 && rightBoolVal != 0))
                    )
                {
                    // It can be expressed as trivilal expression
                    if (leftBoolVal != 0)
                    {
                        newExpr = condExpr;
                    }
                    else
                    {
                        newExpr = new ILExpression(ILCode.LogicNot, null, condExpr)
                        {
                            InferredType = corLib.Boolean
                        };
                    }
                }
                else if ((retTypeIsBoolean || falseExpr.InferredType.GetElementType() == ElementType.Boolean) && trueExpr.Match(ILCode.Ldc_I4, out leftBoolVal) && (leftBoolVal == 0 || leftBoolVal == 1))
                {
                    // It can be expressed as logical expression
                    if (leftBoolVal != 0)
                    {
                        newExpr = MakeLeftAssociativeShortCircuit(ILCode.LogicOr, condExpr, falseExpr);
                    }
                    else
                    {
                        newExpr = MakeLeftAssociativeShortCircuit(ILCode.LogicAnd, new ILExpression(ILCode.LogicNot, null, condExpr), falseExpr);
                    }
                }
                else if ((retTypeIsBoolean || trueExpr.InferredType.GetElementType() == ElementType.Boolean) && falseExpr.Match(ILCode.Ldc_I4, out rightBoolVal) && (rightBoolVal == 0 || rightBoolVal == 1))
                {
                    // It can be expressed as logical expression
                    if (rightBoolVal != 0)
                    {
                        newExpr = MakeLeftAssociativeShortCircuit(ILCode.LogicOr, new ILExpression(ILCode.LogicNot, null, condExpr), trueExpr);
                    }
                    else
                    {
                        newExpr = MakeLeftAssociativeShortCircuit(ILCode.LogicAnd, condExpr, trueExpr);
                    }
                }
                else
                {
                    // Ternary operator tends to create long complicated return statements
                    if (opCode == ILCode.Ret)
                    {
                        return(false);
                    }

                    // Only simplify generated variables
                    if (opCode == ILCode.Stloc && !trueLocVar.GeneratedByDecompiler)
                    {
                        return(false);
                    }

                    // Create ternary expression
                    newExpr = new ILExpression(ILCode.TernaryOp, null, condExpr, trueExpr, falseExpr);
                }

                var tail         = head.Body.RemoveTail(ILCode.Brtrue, ILCode.Br);
                var listNodes    = new List <ILNode>();
                var newExprNodes = newExpr.GetSelfAndChildrenRecursive <ILNode>(listNodes).ToArray();
                foreach (var node in labelToBasicBlock[trueLabel].GetSelfAndChildrenRecursive <ILNode>(listNodes).Except(newExprNodes))
                {
                    newExpr.ILRanges.AddRange(node.AllILRanges);
                }
                foreach (var node in labelToBasicBlock[falseLabel].GetSelfAndChildrenRecursive <ILNode>(listNodes).Except(newExprNodes))
                {
                    newExpr.ILRanges.AddRange(node.AllILRanges);
                }
                newExpr.ILRanges.AddRange(tail[0].ILRanges);
                tail[1].AddSelfAndChildrenRecursiveILRanges(newExpr.ILRanges);

                head.Body.Add(new ILExpression(opCode, trueLocVar, newExpr));
                if (isStloc)
                {
                    head.Body.Add(new ILExpression(ILCode.Br, trueFall));
                }

                // Remove the old basic blocks
                body.RemoveOrThrow(labelToBasicBlock[trueLabel]);
                body.RemoveOrThrow(labelToBasicBlock[falseLabel]);

                return(true);
            }
            return(false);
        }
Esempio n. 14
0
        public bool JoinBasicBlocks(List<ILNode> body, ILBasicBlock head, int pos)
        {
            ILLabel nextLabel;
            ILBasicBlock nextBB;
            if (!head.Body.ElementAtOrDefault(head.Body.Count - 2).IsConditionalControlFlow() &&
                head.Body.Last().Match(ILCode.Br, out nextLabel) &&
                labelGlobalRefCount[nextLabel] == 1 &&
                labelToBasicBlock.TryGetValue(nextLabel, out nextBB) &&
                body.Contains(nextBB) &&
                nextBB.Body.First() == nextLabel &&
                !nextBB.Body.OfType<ILTryCatchBlock>().Any()
               )
            {
                var tail = head.Body.RemoveTail(ILCode.Br);
                if (context.CalculateILRanges) {
                    tail[0].AddSelfAndChildrenRecursiveILRanges(nextBB.ILRanges);
                    nextBB.Body[0].AddSelfAndChildrenRecursiveILRanges(nextBB.ILRanges);
                }
                nextBB.Body.RemoveAt(0);  // Remove label
                if (context.CalculateILRanges) {
                    if (head.Body.Count > 0)
                        head.Body[head.Body.Count - 1].EndILRanges.AddRange(nextBB.ILRanges);
                    else
                        head.ILRanges.AddRange(nextBB.ILRanges);
                    head.EndILRanges.AddRange(nextBB.EndILRanges);
                }
                head.Body.AddRange(nextBB.Body);

                body.RemoveOrThrow(nextBB);
                return true;
            }
            return false;
        }
Esempio n. 15
0
        // This is before the expression is processed, so ILValue's and constants havn't been assigned



        public bool SimplifyTernaryOperator(List <ILNode> body, ILBasicBlock head, int pos)
        {
            Debug.Assert(body.Contains(head));
            //    Debug.Assert((head.Body[0] as ILLabel).Name != "Block_54");
            //     Debug.Assert((head.Body[0] as ILLabel).Name != "L1257");

            ILExpression condExpr;
            ILLabel      trueLabel;
            ILLabel      falseLabel;

            ILExpression trueExpr;
            ILLabel      trueFall;

            ILExpression falseExpr;
            ILLabel      falseFall;

            ILExpression finalFall;
            ILLabel      finalFalseFall;
            ILLabel      finalTrueFall;

            if ((head.MatchLastAndBr(GMCode.Bt, out trueLabel, out condExpr, out falseLabel) ||
                 head.MatchLastAndBr(GMCode.Bf, out falseLabel, out condExpr, out trueLabel)) &&
                labelGlobalRefCount[trueLabel] == 1 &&
                labelGlobalRefCount[falseLabel] == 1 &&
                labelToBasicBlock[trueLabel].MatchSingleAndBr(GMCode.Push, out trueExpr, out trueFall) &&
                labelToBasicBlock[falseLabel].MatchSingleAndBr(GMCode.Push, out falseExpr, out falseFall) &&
                trueFall == falseFall &&
                body.Contains(labelToBasicBlock[trueLabel]) &&
                labelToBasicBlock[trueFall].MatchLastAndBr(GMCode.Bf, out finalFalseFall, out finalFall, out finalTrueFall) &&
                finalFall.Code == GMCode.Pop
                ) // (finalFall == null || finalFall.Code == GMCode.Pop)
            {
                Debug.Assert(finalFall.Arguments.Count != 2);
                ILValue falseLocVar = falseExpr.Code == GMCode.Constant ? falseExpr.Operand as ILValue : null;
                ILValue trueLocVar  = trueExpr.Code == GMCode.Constant ? trueExpr.Operand as ILValue : null;
                Debug.Assert(falseLocVar != null || trueLocVar != null);
                ILExpression newExpr = null;
                // a ? true : b    is equivalent to  a || b
                // a ? b : true    is equivalent to  !a || b
                // a ? b : false   is equivalent to  a && b
                // a ? false : b   is equivalent to  !a && b
                if (trueLocVar != null && trueLocVar.Type == GM_Type.Short && (trueLocVar == 0 || trueLocVar == 1))
                {
                    // It can be expressed as logical expression
                    if (trueLocVar != 0)
                    {
                        newExpr = MakeLeftAssociativeShortCircuit(GMCode.LogicOr, condExpr, falseExpr);
                    }
                    else
                    {
                        newExpr = MakeLeftAssociativeShortCircuit(GMCode.LogicAnd, new ILExpression(GMCode.Not, null, condExpr), falseExpr);
                    }
                }
                else if (falseLocVar != null && falseLocVar.Type == GM_Type.Short && (falseLocVar == 0 || falseLocVar == 1))
                {
                    // It can be expressed as logical expression
                    if (falseLocVar != 0)
                    {
                        newExpr = MakeLeftAssociativeShortCircuit(GMCode.LogicOr, new ILExpression(GMCode.Not, null, condExpr), trueExpr);
                    }
                    else
                    {
                        newExpr = MakeLeftAssociativeShortCircuit(GMCode.LogicAnd, condExpr, trueExpr);
                    }
                }
                Debug.Assert(newExpr != null);
                // head.Body.RemoveTail(ILCode.Brtrue, ILCode.Br);
                head.Body.RemoveRange(head.Body.Count - 2, 2);
                head.Body.Add(new ILExpression(GMCode.Bf, finalFalseFall, newExpr));
                head.Body.Add(new ILExpression(GMCode.B, finalTrueFall));

                // Remove the inlined branch from scope
                // body.RemoveOrThrow(nextBasicBlock);
                // Remove the old basic blocks
                body.RemoveOrThrow(labelToBasicBlock[trueLabel]);
                body.RemoveOrThrow(labelToBasicBlock[falseLabel]);
                body.RemoveOrThrow(labelToBasicBlock[trueFall]);
                return(true);
            }
            return(false);
        }