/// <summary>
        /// Splits the block.
        /// </summary>
        /// <param name="ctx">The context.</param>
        /// <param name="addJump">if set to <c>true</c> [add jump].</param>
        /// <returns></returns>
        protected Context SplitContext(Context ctx, bool addJump)
        {
            Context current = ctx.Clone();

            int label = basicBlocks.Count + 0x10000000;

            BasicBlock nextBlock = CreateBlock(label);

            foreach (BasicBlock block in current.BasicBlock.NextBlocks)
            {
                nextBlock.NextBlocks.Add(block);
            }

            current.BasicBlock.NextBlocks.Clear();

            if (addJump)
            {
                current.BasicBlock.NextBlocks.Add(nextBlock);
                nextBlock.PreviousBlocks.Add(ctx.BasicBlock);
            }

            if (current.IsLastInstruction)
            {
                current.AppendInstruction(null);
                current.Ignore  = true;
                nextBlock.Index = current.Index;
                current.SliceBefore();
            }
            else
            {
                nextBlock.Index = current.Next.Index;
                current.SliceAfter();
            }

            if (addJump)
            {
                current.AppendInstruction(IR.Instruction.JmpInstruction, nextBlock);
            }

            return(CreateContext(nextBlock));
        }
        /// <summary>
        /// Finds all targets.
        /// </summary>
        /// <param name="index">The index.</param>
        private void SplitIntoBlocks(int index)
        {
            Dictionary<int, int> targets = new Dictionary<int, int>();

            targets.Add(index, -1);

            // Find out all targets labels
            for (Context ctx = new Context(InstructionSet, index); !ctx.EndOfInstruction; ctx.GotoNext())
            {
                switch (ctx.Instruction.FlowControl)
                {
                    case FlowControl.Next: continue;
                    case FlowControl.Call: continue;
                    case FlowControl.Break: goto case FlowControl.Branch;
                    case FlowControl.Return: continue;
                    case FlowControl.Throw: goto case FlowControl.Branch;
                    case FlowControl.Branch:
                        // Unconditional branch
                        Debug.Assert(ctx.Branch.Targets.Length == 1);
                        if (!targets.ContainsKey(ctx.Branch.Targets[0]))
                            targets.Add(ctx.Branch.Targets[0], -1);
                        continue;
                    case FlowControl.Switch: goto case FlowControl.ConditionalBranch;
                    case FlowControl.ConditionalBranch:
                        // Conditional branch with multiple targets
                        foreach (int target in ctx.Branch.Targets)
                            if (!targets.ContainsKey(target))
                                targets.Add(target, -1);
                        int next = ctx.Next.Label;
                        if (!targets.ContainsKey(next))
                            targets.Add(next, -1);
                        continue;
                    default:
                        Debug.Assert(false);
                        break;
                }
            }

            bool slice = false;

            for (Context ctx = new Context(InstructionSet, index); !ctx.EndOfInstruction; ctx.GotoNext())
            {
                FlowControl flow;

                if (targets.ContainsKey(ctx.Label))
                {
                    CreateBlock(ctx.Label, ctx.Index);

                    if (!ctx.IsFirstInstruction)
                    {
                        Context prev = ctx.Previous;
                        flow = prev.Instruction.FlowControl;
                        if (flow == FlowControl.Next || flow == FlowControl.Call || flow == FlowControl.ConditionalBranch || flow == FlowControl.Switch)
                        {
                            // This jump joins fall-through blocks, by giving them a proper end.
                            prev.AppendInstruction(CIL.Instruction.Get(CIL.OpCode.Br));
                            prev.SetBranch(ctx.Label);

                            prev.SliceAfter();
                        }
                    }

                    targets.Remove(ctx.Label);
                }

                if (slice)
                    ctx.SliceBefore();

                flow = ctx.Instruction.FlowControl;

                slice = (flow == FlowControl.Return || flow == FlowControl.Branch || flow == FlowControl.ConditionalBranch || flow == FlowControl.Break || flow == FlowControl.Throw);
            }

            Debug.Assert(targets.Count <= 1);

            if (FindBlock(0) == null)
                CreateBlock(0, index);
        }
Exemplo n.º 3
0
        /// <summary>
        /// Finds all targets.
        /// </summary>
        /// <param name="index">The index.</param>
        private void SplitIntoBlocks(int index)
        {
            Dictionary <int, int> targets = new Dictionary <int, int>();

            targets.Add(index, -1);

            // Find out all targets labels
            for (Context ctx = new Context(InstructionSet, index); !ctx.EndOfInstruction; ctx.GotoNext())
            {
                switch (ctx.Instruction.FlowControl)
                {
                case FlowControl.Next: continue;

                case FlowControl.Call: continue;

                case FlowControl.Break:
                    goto case FlowControl.Branch;

                case FlowControl.Return:
                    continue;

                case FlowControl.Throw:
                    goto case FlowControl.Branch;

                case FlowControl.Branch:
                    // Unconditional branch
                    Debug.Assert(ctx.Branch.Targets.Length == 1);
                    if (!targets.ContainsKey(ctx.Branch.Targets[0]))
                    {
                        targets.Add(ctx.Branch.Targets[0], -1);
                    }
                    continue;

                case FlowControl.Switch: goto case FlowControl.ConditionalBranch;

                case FlowControl.ConditionalBranch:
                    // Conditional branch with multiple targets
                    foreach (int target in ctx.Branch.Targets)
                    {
                        if (!targets.ContainsKey(target))
                        {
                            targets.Add(target, -1);
                        }
                    }
                    int next = ctx.Next.Label;
                    if (!targets.ContainsKey(next))
                    {
                        targets.Add(next, -1);
                    }
                    continue;

                default:
                    Debug.Assert(false);
                    break;
                }
            }

            bool slice = false;

            for (Context ctx = new Context(InstructionSet, index); !ctx.EndOfInstruction; ctx.GotoNext())
            {
                FlowControl flow;

                if (targets.ContainsKey(ctx.Label))
                {
                    CreateBlock(ctx.Label, ctx.Index);

                    if (!ctx.IsFirstInstruction)
                    {
                        Context prev = ctx.Previous;
                        flow = prev.Instruction.FlowControl;
                        if (flow == FlowControl.Next || flow == FlowControl.Call || flow == FlowControl.ConditionalBranch || flow == FlowControl.Switch)
                        {
                            prev.AppendInstruction(IR.Instruction.JmpInstruction);
                            prev.SetBranch(ctx.Label);
                            prev.SliceAfter();
                        }
                    }

                    targets.Remove(ctx.Label);
                }

                if (slice)
                {
                    ctx.SliceBefore();
                }

                flow = ctx.Instruction.FlowControl;

                slice = (flow == FlowControl.Return || flow == FlowControl.Branch || flow == FlowControl.ConditionalBranch || flow == FlowControl.Break || flow == FlowControl.Throw);
            }

            Debug.Assert(targets.Count <= 1);

            if (FindBlock(0) == null)
            {
                CreateBlock(0, index);
            }
        }