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); } }
void ProcessBlock(Block block, ref bool blockContainerNeedsCleanup) { bool analysisSuccess = analysis.AnalyzeBlock(block); KeyValuePair <LongSet, ILInstruction> defaultSection; if (analysisSuccess && UseCSharpSwitch(analysis, out defaultSection)) { // complex multi-block switch that can be combined into a single SwitchInstruction var sw = new SwitchInstruction(new LdLoc(analysis.SwitchVariable)); 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); } 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(); } blockContainerNeedsCleanup = true; SortSwitchSections(sw); } else { // 2nd pass of SimplifySwitchInstruction (after duplicating return blocks), // (1st pass was in ControlFlowSimplification) SimplifySwitchInstruction(block); } }
void ProcessBlock(Block block, ref bool blockContainerNeedsCleanup) { bool analysisSuccess = analysis.AnalyzeBlock(block); KeyValuePair <LongSet, ILInstruction> defaultSection; if (analysisSuccess && UseCSharpSwitch(analysis, out defaultSection)) { // complex multi-block switch that can be combined into a single SwitchInstruction var sw = new SwitchInstruction(new LdLoc(analysis.SwitchVariable)); foreach (var section in analysis.Sections) { if (!section.Key.SetEquals(defaultSection.Key)) { sw.Sections.Add(new SwitchSection { Labels = section.Key, Body = section.Value }); } } block.Instructions[block.Instructions.Count - 2] = sw; block.Instructions[block.Instructions.Count - 1] = defaultSection.Value; // 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(); } blockContainerNeedsCleanup = true; } else { // 2nd pass of SimplifySwitchInstruction (after duplicating return blocks), // (1st pass was in ControlFlowSimplification) SimplifySwitchInstruction(block); } }