Ejemplo n.º 1
0
        void ProcessBlock(Block block, ref bool blockContainerNeedsCleanup)
        {
            bool analysisSuccess = analysis.AnalyzeBlock(block);

            if (analysisSuccess && UseCSharpSwitch(out _))
            {
                // complex multi-block switch that can be combined into a single SwitchInstruction
                ILInstruction switchValue = new LdLoc(analysis.SwitchVariable);
                Debug.Assert(switchValue.ResultType.IsIntegerType() || switchValue.ResultType == StackType.Unknown);
                if (!(switchValue.ResultType == StackType.I4 || switchValue.ResultType == StackType.I8))
                {
                    // switchValue must have a result type of either I4 or I8
                    switchValue = new Conv(switchValue, PrimitiveType.I8, false, Sign.Signed);
                }
                var sw = new SwitchInstruction(switchValue);
                foreach (var section in analysis.Sections)
                {
                    sw.Sections.Add(new SwitchSection {
                        Labels = section.Key,
                        Body   = section.Value
                    });
                }
                if (block.Instructions.Last() is SwitchInstruction)
                {
                    // we'll replace the switch
                }
                else
                {
                    Debug.Assert(block.Instructions.SecondToLastOrDefault() is IfInstruction);
                    // Remove branch/leave after if; it's getting moved into a section.
                    block.Instructions.RemoveAt(block.Instructions.Count - 1);
                }
                sw.AddILRange(block.Instructions[block.Instructions.Count - 1]);
                block.Instructions[block.Instructions.Count - 1] = sw;

                // mark all inner blocks that were converted to the switch statement for deletion
                foreach (var innerBlock in analysis.InnerBlocks)
                {
                    Debug.Assert(innerBlock.Parent == block.Parent);
                    Debug.Assert(innerBlock != ((BlockContainer)block.Parent).EntryPoint);
                    innerBlock.Instructions.Clear();
                }

                controlFlowGraph           = null;       // control flow graph is no-longer valid
                blockContainerNeedsCleanup = true;
                SortSwitchSections(sw);
            }
            else
            {
                // 2nd pass of SimplifySwitchInstruction (after duplicating return blocks),
                // (1st pass was in ControlFlowSimplification)
                SimplifySwitchInstruction(block, context);
            }
        }