Permalink
Browse files

do not use DominanceFrontiers to detect condition bodies; closes #300

  • Loading branch information...
1 parent ef45f4e commit 1e79bf35882ada02fa384470bf092d4a9f3a46b5 @siegfriedpammer siegfriedpammer committed Apr 12, 2012
View
2 ICSharpCode.Decompiler/CecilExtensions.cs
@@ -133,6 +133,8 @@ public static bool IsValueTypeOrVoid(this TypeReference type)
/// </summary>
public static int GetEndOffset(this Instruction inst)
{
+ if (inst == null)
+ throw new ArgumentNullException("inst");
return inst.Offset + inst.GetSize();
}
View
7 ICSharpCode.Decompiler/FlowAnalysis/ControlFlowNode.cs
@@ -253,8 +253,11 @@ public override string ToString()
StringWriter writer = new StringWriter();
switch (NodeType) {
case ControlFlowNodeType.Normal:
- int endOffset = End.GetEndOffset();
- writer.Write("Block #{0}: IL_{1:x4} to IL_{2:x4}", BlockIndex, Start.Offset, endOffset);
+ writer.Write("Block #{0}", BlockIndex);
+ if (Start != null)
+ writer.Write(": IL_{0:x4}", Start.Offset);
+ if (End != null)
+ writer.Write(" to IL_{0:x4}", End.GetEndOffset());
break;
case ControlFlowNodeType.CatchHandler:
case ControlFlowNodeType.FinallyOrFaultHandler:
View
12 ICSharpCode.Decompiler/ILAst/LoopsAndConditions.cs
@@ -101,7 +101,7 @@ ControlFlowGraph BuildGraph(List<ILNode> nodes, ILLabel entryLabel)
// Find all branches
foreach(ILLabel target in node.GetSelfAndChildrenRecursive<ILExpression>(e => e.IsBranch()).SelectMany(e => e.GetBranchTargets())) {
ControlFlowNode destination;
- // Labels which are out of out scope will not be int the collection
+ // Labels which are out of out scope will not be in the collection
// Insert self edge only if we are sure we are a loop
if (labelToCfNode.TryGetValue(target, out destination) && (destination != source || target == node.Body.FirstOrDefault())) {
ControlFlowEdge edge = new ControlFlowEdge(source, destination, JumpType.Normal);
@@ -364,18 +364,12 @@ List<ILNode> FindConditions(HashSet<ControlFlowNode> scope, ControlFlowNode entr
labelToCfNode.TryGetValue(falseLabel, out falseTarget);
// Pull in the conditional code
- HashSet<ControlFlowNode> frontiers = new HashSet<ControlFlowNode>();
- if (trueTarget != null)
- frontiers.UnionWith(trueTarget.DominanceFrontier.Except(new [] { trueTarget }));
- if (falseTarget != null)
- frontiers.UnionWith(falseTarget.DominanceFrontier.Except(new [] { falseTarget }));
-
- if (trueTarget != null && !frontiers.Contains(trueTarget)) {
+ if (trueTarget != null && trueTarget.Incoming.Count == 1) {
HashSet<ControlFlowNode> content = FindDominatedNodes(scope, trueTarget);
scope.ExceptWith(content);
ilCond.TrueBlock.Body.AddRange(FindConditions(content, trueTarget));
}
- if (falseTarget != null && !frontiers.Contains(falseTarget)) {
+ if (falseTarget != null && falseTarget.Incoming.Count == 1) {
HashSet<ControlFlowNode> content = FindDominatedNodes(scope, falseTarget);
scope.ExceptWith(content);
ilCond.FalseBlock.Body.AddRange(FindConditions(content, falseTarget));
View
81 ICSharpCode.Decompiler/Tests/ControlFlow.cs
@@ -0,0 +1,81 @@
+// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy of this
+// software and associated documentation files (the "Software"), to deal in the Software
+// without restriction, including without limitation the rights to use, copy, modify, merge,
+// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
+// to whom the Software is furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in all copies or
+// substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
+// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
+// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+// DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+
+public static class ControlFlow
+{
+ public static void EmptyIf(string input, List<string> value, Dictionary<int, string> _headers)
+ {
+ if (value.Contains("test"))
+ {
+ }
+ _headers.Add(2, "result");
+ }
+
+ public static void NormalIf(string input, List<string> value, Dictionary<int, string> _headers)
+ {
+ if (value.Contains("test"))
+ {
+ _headers.Add(1, "result");
+ }
+ else
+ {
+ _headers.Add(1, "else");
+ }
+ _headers.Add(2, "end");
+ }
+
+ public static void NormalIf2(string input, List<string> value, Dictionary<int, string> _headers)
+ {
+ if (value.Contains("test"))
+ {
+ _headers.Add(1, "result");
+ }
+ _headers.Add(2, "end");
+ }
+
+ public static void NormalIf3(string input, List<string> value, Dictionary<int, string> _headers)
+ {
+ if (value.Contains("test"))
+ {
+ _headers.Add(1, "result");
+ }
+ else
+ {
+ _headers.Add(1, "else");
+ }
+ }
+
+ public static void Test(string input, List<string> value, Dictionary<int, string> _headers)
+ {
+ foreach (string current in value)
+ {
+ _headers.Add(0, current);
+ }
+ if (value.Contains("test"))
+ {
+ _headers.Add(1, "result");
+ }
+ else
+ {
+ _headers.Add(1, "else");
+ }
+ }
+}
View
2 ICSharpCode.Decompiler/Tests/Helpers/RemoveCompilerAttribute.cs
@@ -15,7 +15,7 @@ public override object VisitAttribute(NRefactory.CSharp.Attribute attribute, obj
var section = (AttributeSection)attribute.Parent;
SimpleType type = attribute.Type as SimpleType;
if (section.AttributeTarget == "assembly" &&
- (type.Identifier == "CompilationRelaxations" || type.Identifier == "RuntimeCompatibility" || type.Identifier == "SecurityPermission" || type.Identifier == "AssemblyVersion"))
+ (type.Identifier == "CompilationRelaxations" || type.Identifier == "RuntimeCompatibility" || type.Identifier == "SecurityPermission" || type.Identifier == "AssemblyVersion" || type.Identifier == "Debuggable"))
{
attribute.Remove();
if (section.Attributes.Count == 0)
View
1 ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj
@@ -64,6 +64,7 @@
<ItemGroup>
<Compile Include="CallOverloadedMethod.cs" />
<Compile Include="CheckedUnchecked.cs" />
+ <Compile Include="ControlFlow.cs" />
<Compile Include="ExpressionTrees.cs" />
<Compile Include="LiftedOperators.cs" />
<Compile Include="CustomShortCircuitOperators.cs" />
View
20 ICSharpCode.Decompiler/Tests/TestRunner.cs
@@ -77,6 +77,12 @@ public void CustomShortCircuitOperators()
}
[Test]
+ public void ControlFlowWithDebug()
+ {
+ TestFile(@"..\..\Tests\ControlFlow.cs", false, true);
+ }
+
+ [Test]
public void IncrementDecrement()
{
TestFile(@"..\..\Tests\IncrementDecrement.cs");
@@ -160,16 +166,16 @@ public void TypeAnalysis()
TestFile(@"..\..\Tests\TypeAnalysisTests.cs");
}
- static void TestFile(string fileName)
+ static void TestFile(string fileName, bool useDebug = false)
@pentp
pentp Apr 13, 2012

I think this changes the overload resolution result for TestFile("", false) - before this change it called the second overload (that does the real work of TestFile) now it calls the first overload. Since optimize and useDebug are probably mutually exclusive anyway then there is no need to add the optional useDebug parameter for the first overload.

{
- TestFile(fileName, false);
- TestFile(fileName, true);
+ TestFile(fileName, false, useDebug);
+ TestFile(fileName, true, useDebug);
}
- static void TestFile(string fileName, bool optimize)
+ static void TestFile(string fileName, bool optimize, bool useDebug = false)
{
string code = File.ReadAllText(fileName);
- AssemblyDefinition assembly = Compile(code, optimize);
+ AssemblyDefinition assembly = Compile(code, optimize, useDebug);
AstBuilder decompiler = new AstBuilder(new DecompilerContext(assembly.MainModule));
decompiler.AddAssembly(assembly);
new Helpers.RemoveCompilerAttribute().Run(decompiler.CompilationUnit);
@@ -178,11 +184,11 @@ static void TestFile(string fileName, bool optimize)
CodeAssert.AreEqual(code, output.ToString());
}
- static AssemblyDefinition Compile(string code, bool optimize)
+ static AssemblyDefinition Compile(string code, bool optimize, bool useDebug)
{
CSharpCodeProvider provider = new CSharpCodeProvider(new Dictionary<string, string> { { "CompilerVersion", "v4.0" } });
CompilerParameters options = new CompilerParameters();
- options.CompilerOptions = "/unsafe /o" + (optimize ? "+" : "-");
+ options.CompilerOptions = "/unsafe /o" + (optimize ? "+" : "-") + (useDebug ? " /debug": "");
options.ReferencedAssemblies.Add("System.Core.dll");
CompilerResults results = provider.CompileAssemblyFromSource(options, code);
try {

0 comments on commit 1e79bf3

Please sign in to comment.