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