Author: jbevain
Date: 2008-02-06 19:03:01 -0500 (Wed, 06 Feb 2008)
New Revision: 95100

Added:
   trunk/cecil/flowanalysis/testcases/FlowAnalysis/Switch-cfg.txt
   trunk/cecil/flowanalysis/testcases/FlowAnalysis/Switch.il
Modified:
   trunk/cecil/flowanalysis/Cecil.FlowAnalysis.Tests/ControlFlowTestFixture.cs
   
trunk/cecil/flowanalysis/Cecil.FlowAnalysis/ControlFlow/ControlFlowGraphBuilder.cs
   trunk/cecil/flowanalysis/Cecil.FlowAnalysis/Utilities/Formatter.cs
   trunk/cecil/flowanalysis/ChangeLog
Log:
2008-02-07  Jb Evain  <[EMAIL PROTECTED]>

        * Cecil.FlowAnalysis/ControlFlow/ControlFlowGraphBuilder.cs
        * Cecil.FlowAnalysis/Utilities/Formatter.cs
        * Cecil.FlowAnalysis.Tests/ControlFlowTestFixture.cs
        * testcases/FlowAnalysis/Switch-cfg.txt
        * testcases/FlowAnalysis/Switch.il
                Add support for switch in control flow graphs.


Modified: 
trunk/cecil/flowanalysis/Cecil.FlowAnalysis/ControlFlow/ControlFlowGraphBuilder.cs
===================================================================
--- 
trunk/cecil/flowanalysis/Cecil.FlowAnalysis/ControlFlow/ControlFlowGraphBuilder.cs
  2008-02-06 23:39:19 UTC (rev 95099)
+++ 
trunk/cecil/flowanalysis/Cecil.FlowAnalysis/ControlFlow/ControlFlowGraphBuilder.cs
  2008-02-07 00:03:01 UTC (rev 95100)
@@ -80,9 +80,16 @@
                                if (!IsBlockDelimiter (instruction))
                                        continue;
 
-                               // the target of a branch starts a block
-                               Instruction target = GetBranchTarget 
(instruction);
-                               if (null != target) MarkBlockStart (target);
+                               if (HasMultipleBranches (instruction)) {
+                                       // each switch case first instruction 
starts a block
+                                       foreach (Instruction target in 
GetBranchTargets (instruction))
+                                               if (target != null)
+                                                       MarkBlockStart (target);
+                               } else {
+                                       // the target of a branch starts a block
+                                       Instruction target = GetBranchTarget 
(instruction);
+                                       if (null != target) MarkBlockStart 
(target);
+                               }
 
                                // the next instruction after a branch starts a 
block
                                if (null != instruction.Next) MarkBlockStart 
(instruction.Next);
@@ -275,6 +282,15 @@
                        switch (instruction.OpCode.FlowControl) {
                        case FlowControl.Branch:
                        case FlowControl.Cond_Branch: {
+                               if (HasMultipleBranches (instruction)) {
+                                       InstructionBlock [] blocks = 
GetBranchTargetsBlocks (instruction);
+                                       if (instruction.Next != null)
+                                               blocks = AddBlock (GetBlock 
(instruction.Next), blocks);
+
+                                       block.SetSuccessors (blocks);
+                                       break;
+                               }
+
                                InstructionBlock target = GetBranchTargetBlock 
(instruction);
                                if (instruction.OpCode.FlowControl == 
FlowControl.Cond_Branch && instruction.Next != null)
                                        block.SetSuccessors (new 
InstructionBlock [] { target, GetBlock (instruction.Next) });
@@ -298,12 +314,41 @@
                        }
                }
 
+               static InstructionBlock [] AddBlock (InstructionBlock block, 
InstructionBlock [] blocks)
+               {
+                       InstructionBlock [] result = new InstructionBlock 
[blocks.Length + 1];
+                       Array.Copy (blocks, result, blocks.Length);
+                       result [result.Length - 1] = block;
+
+                       return result;
+               }
+
+               static bool HasMultipleBranches (Instruction instruction)
+               {
+                       return instruction.OpCode.Code == Code.Switch;
+               }
+
+               InstructionBlock [] GetBranchTargetsBlocks (Instruction 
instruction)
+               {
+                       Instruction [] targets = GetBranchTargets (instruction);
+                       InstructionBlock [] blocks = new InstructionBlock 
[targets.Length];
+                       for (int i = 0; i < targets.Length; i++)
+                               blocks [i] = GetBlock (targets [i]);
+
+                       return blocks;
+               }
+
+               static Instruction [] GetBranchTargets (Instruction instruction)
+               {
+                       return (Instruction []) instruction.Operand;
+               }
+
                InstructionBlock GetBranchTargetBlock (Instruction instruction)
                {
                        return GetBlock (GetBranchTarget (instruction));
                }
 
-               Instruction GetBranchTarget (Instruction instruction)
+               static Instruction GetBranchTarget (Instruction instruction)
                {
                        return (Instruction) instruction.Operand;
                }

Modified: trunk/cecil/flowanalysis/Cecil.FlowAnalysis/Utilities/Formatter.cs
===================================================================
--- trunk/cecil/flowanalysis/Cecil.FlowAnalysis/Utilities/Formatter.cs  
2008-02-06 23:39:19 UTC (rev 95099)
+++ trunk/cecil/flowanalysis/Cecil.FlowAnalysis/Utilities/Formatter.cs  
2008-02-07 00:03:01 UTC (rev 95100)
@@ -85,6 +85,12 @@
                                return;
                        }
 
+                       Instruction [] targetInstructions = operand as 
Instruction [];
+                       if (null != targetInstructions) {
+                               WriteLabelList (writer, targetInstructions);
+                               return;
+                       }
+
                        VariableReference variableRef = operand as 
VariableReference;
                        if (null != variableRef) {
                                writer.Write (variableRef.Index.ToString ());
@@ -107,6 +113,18 @@
                        writer.Write (s);
                }
 
+               static void WriteLabelList (TextWriter writer, Instruction [] 
instructions)
+               {
+                       writer.Write ("(");
+
+                       for (int i = 0; i < instructions.Length; i++) {
+                               if (i != 0) writer.Write (", ");
+                               writer.Write (FormatLabel (instructions 
[i].Offset));
+                       }
+
+                       writer.Write (")");
+               }
+
                public static string ToInvariantCultureString (object value)
                {
                        IConvertible convertible = value as IConvertible;

Modified: 
trunk/cecil/flowanalysis/Cecil.FlowAnalysis.Tests/ControlFlowTestFixture.cs
===================================================================
--- trunk/cecil/flowanalysis/Cecil.FlowAnalysis.Tests/ControlFlowTestFixture.cs 
2008-02-06 23:39:19 UTC (rev 95099)
+++ trunk/cecil/flowanalysis/Cecil.FlowAnalysis.Tests/ControlFlowTestFixture.cs 
2008-02-07 00:03:01 UTC (rev 95100)
@@ -31,6 +31,12 @@
        public class ControlFlowTestFixture : AbstractControlFlowTestFixture {
 
                [Test]
+               public void Switch ()
+               {
+                       RunTestCase ("Switch");
+               }
+
+               [Test]
                public void StaticField ()
                {
                        RunTestCase ("StaticField");

Modified: trunk/cecil/flowanalysis/ChangeLog
===================================================================
--- trunk/cecil/flowanalysis/ChangeLog  2008-02-06 23:39:19 UTC (rev 95099)
+++ trunk/cecil/flowanalysis/ChangeLog  2008-02-07 00:03:01 UTC (rev 95100)
@@ -1,3 +1,12 @@
+2008-02-07  Jb Evain  <[EMAIL PROTECTED]>
+
+       * Cecil.FlowAnalysis/ControlFlow/ControlFlowGraphBuilder.cs
+       * Cecil.FlowAnalysis/Utilities/Formatter.cs
+       * Cecil.FlowAnalysis.Tests/ControlFlowTestFixture.cs
+       * testcases/FlowAnalysis/Switch-cfg.txt
+       * testcases/FlowAnalysis/Switch.il
+               Add support for switch in control flow graphs.
+
 2008-01-16  Jb Evain  <[EMAIL PROTECTED]>
 
        * Support for not.

Added: trunk/cecil/flowanalysis/testcases/FlowAnalysis/Switch-cfg.txt
===================================================================
--- trunk/cecil/flowanalysis/testcases/FlowAnalysis/Switch-cfg.txt      
2008-02-06 23:39:19 UTC (rev 95099)
+++ trunk/cecil/flowanalysis/testcases/FlowAnalysis/Switch-cfg.txt      
2008-02-07 00:03:01 UTC (rev 95100)
@@ -0,0 +1,59 @@
+block 1:
+       body:
+               IL_0000: nop
+               IL_0001: ldarg.0
+               IL_0002: stloc.1
+               IL_0003: ldloc.1
+               IL_0004: ldc.i4.1
+               IL_0005: sub
+               IL_0006: switch (IL_001d, IL_0021, IL_0025, IL_0029)
+       successors:
+               block 3
+               block 4
+               block 5
+               block 6
+               block 2
+block 2:
+       body:
+               IL_001b: br.s IL_002d
+       successors:
+               block 7
+block 3:
+       body:
+               IL_001d: ldc.i4.1
+               IL_001e: stloc.0
+               IL_001f: br.s IL_0031
+       successors:
+               block 8
+block 4:
+       body:
+               IL_0021: ldc.i4.2
+               IL_0022: stloc.0
+               IL_0023: br.s IL_0031
+       successors:
+               block 8
+block 5:
+       body:
+               IL_0025: ldc.i4.3
+               IL_0026: stloc.0
+               IL_0027: br.s IL_0031
+       successors:
+               block 8
+block 6:
+       body:
+               IL_0029: ldc.i4.4
+               IL_002a: stloc.0
+               IL_002b: br.s IL_0031
+       successors:
+               block 8
+block 7:
+       body:
+               IL_002d: ldc.i4.m1
+               IL_002e: stloc.0
+               IL_002f: br.s IL_0031
+       successors:
+               block 8
+block 8:
+       body:
+               IL_0031: ldloc.0
+               IL_0032: ret


Property changes on: 
trunk/cecil/flowanalysis/testcases/FlowAnalysis/Switch-cfg.txt
___________________________________________________________________
Name: svn:eol-style
   + native

Added: trunk/cecil/flowanalysis/testcases/FlowAnalysis/Switch.il
===================================================================
--- trunk/cecil/flowanalysis/testcases/FlowAnalysis/Switch.il   2008-02-06 
23:39:19 UTC (rev 95099)
+++ trunk/cecil/flowanalysis/testcases/FlowAnalysis/Switch.il   2008-02-07 
00:03:01 UTC (rev 95100)
@@ -0,0 +1,35 @@
+.assembly TestCase {}
+
+.class public auto ansi beforefieldinit TestCase
+       extends [mscorlib]System.Object
+{
+       .method public hidebysig static int32 Main(int32 'value') cil managed
+       {
+               .locals init (int32 local0, int32 local1)
+               IL_0000:  nop
+               IL_0001:  ldarg.0
+               IL_0002:  stloc.1
+               IL_0003:  ldloc.1
+               IL_0004:  ldc.i4.1
+               IL_0005:  sub
+               IL_0006:  switch (IL_001d, IL_0021, IL_0025, IL_0029)
+               IL_001b:  br.s       IL_002d
+               IL_001d:  ldc.i4.1
+               IL_001e:  stloc.0
+               IL_001f:  br.s       IL_0031
+               IL_0021:  ldc.i4.2
+               IL_0022:  stloc.0
+               IL_0023:  br.s       IL_0031
+               IL_0025:  ldc.i4.3
+               IL_0026:  stloc.0
+               IL_0027:  br.s       IL_0031
+               IL_0029:  ldc.i4.4
+               IL_002a:  stloc.0
+               IL_002b:  br.s       IL_0031
+               IL_002d:  ldc.i4.m1
+               IL_002e:  stloc.0
+               IL_002f:  br.s       IL_0031
+               IL_0031:  ldloc.0
+               IL_0032:  ret
+       }
+}


Property changes on: trunk/cecil/flowanalysis/testcases/FlowAnalysis/Switch.il
___________________________________________________________________
Name: svn:eol-style
   + native

_______________________________________________
Mono-patches maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches

Reply via email to