Пример #1
0
        /// <summary>
        /// For an if statement with an unreachable end point and no else block,
        /// inverts to match IL order of the first statement of each branch
        /// </summary>
        private void ImproveILOrdering(Block block, IfInstruction ifInst, Block continueTarget)
        {
            if (!block.HasFlag(InstructionFlags.EndPointUnreachable) ||
                !ifInst.TrueInst.HasFlag(InstructionFlags.EndPointUnreachable) ||
                !ifInst.FalseInst.MatchNop())
            {
                return;
            }

            Debug.Assert(ifInst != block.Instructions.Last());

            var trueRangeStart  = ConditionDetection.GetStartILOffset(ifInst.TrueInst, out bool trueRangeIsEmpty);
            var falseRangeStart = ConditionDetection.GetStartILOffset(block.Instructions[block.Instructions.IndexOf(ifInst) + 1], out bool falseRangeIsEmpty);

            if (trueRangeIsEmpty || falseRangeIsEmpty || falseRangeStart >= trueRangeStart)
            {
                return;
            }

            if (block.Instructions.Last() is Leave leave && !leave.IsLeavingFunction && leave.TargetContainer.Kind == ContainerKind.Normal)
            {
                // non-keyword leave. Can't move out of the last position in the block (fall-through) without introducing goto, unless it can be replaced with a keyword (return/continue)
                if (!CanDuplicateExit(block.Instructions.Last(), continueTarget, out var keywordExit))
                {
                    return;
                }

                context.Step("Replace leave with keyword exit", ifInst.TrueInst);
                block.Instructions.Last().ReplaceWith(keywordExit.Clone());
            }

            ConditionDetection.InvertIf(block, ifInst, context);
        }
        /// <summary>
        /// For an if statement with an unreachable end point and no else block,
        /// inverts to match IL order of the first statement of each branch
        /// </summary>
        private void ImproveILOrdering(Block block, IfInstruction ifInst)
        {
            if (!block.HasFlag(InstructionFlags.EndPointUnreachable) ||
                !ifInst.TrueInst.HasFlag(InstructionFlags.EndPointUnreachable) ||
                !ifInst.FalseInst.MatchNop())
            {
                return;
            }

            Debug.Assert(ifInst != block.Instructions.Last());

            var trueRangeStart  = ConditionDetection.GetStartILOffset(ifInst.TrueInst, out bool trueRangeIsEmpty);
            var falseRangeStart = ConditionDetection.GetStartILOffset(block.Instructions[block.Instructions.IndexOf(ifInst) + 1], out bool falseRangeIsEmpty);

            if (!trueRangeIsEmpty && !falseRangeIsEmpty && falseRangeStart < trueRangeStart)
            {
                ConditionDetection.InvertIf(block, ifInst, context);
            }
        }