diff --git a/ICSharpCode.Decompiler/FlowAnalysis/DefiniteAssignmentVisitor.cs b/ICSharpCode.Decompiler/FlowAnalysis/DefiniteAssignmentVisitor.cs
index b71286c32..26dcfdf93 100644
--- a/ICSharpCode.Decompiler/FlowAnalysis/DefiniteAssignmentVisitor.cs
+++ b/ICSharpCode.Decompiler/FlowAnalysis/DefiniteAssignmentVisitor.cs
@@ -48,7 +48,7 @@ namespace ICSharpCode.Decompiler.FlowAnalysis
public State(int variableCount)
{
this.bits = new BitSet(variableCount);
- this.bits.SetAll();
+ this.bits.Set(0, variableCount);
}
private State(BitSet bits)
diff --git a/ICSharpCode.Decompiler/Tests/TestRunner.cs b/ICSharpCode.Decompiler/Tests/TestRunner.cs
index 036c92723..2ac194e57 100644
--- a/ICSharpCode.Decompiler/Tests/TestRunner.cs
+++ b/ICSharpCode.Decompiler/Tests/TestRunner.cs
@@ -117,23 +117,27 @@ namespace ICSharpCode.Decompiler.Tests
if (result1 != result2 || output1 != output2 || error1 != error2) {
Console.WriteLine("Test {0} failed.", testFileName);
Console.WriteLine("Decompiled code in {0}:line 1", decompiledCodeFile);
- string outputFileName = Path.Combine(Path.GetTempPath(), Path.GetFileNameWithoutExtension(testFileName));
- File.WriteAllText(outputFileName + ".original.out", output1);
- File.WriteAllText(outputFileName + ".decompiled.out", output2);
- int diffLine = 0;
- foreach (var pair in output1.Split('\n').Zip(output2.Split('\n'), Tuple.Create)) {
- diffLine++;
- if (pair.Item1 != pair.Item2) {
- break;
+ if (error1 == "" && error2 != "") {
+ Console.WriteLine(error2);
+ } else {
+ string outputFileName = Path.Combine(Path.GetTempPath(), Path.GetFileNameWithoutExtension(testFileName));
+ File.WriteAllText(outputFileName + ".original.out", output1);
+ File.WriteAllText(outputFileName + ".decompiled.out", output2);
+ int diffLine = 0;
+ foreach (var pair in output1.Split('\n').Zip(output2.Split('\n'), Tuple.Create)) {
+ diffLine++;
+ if (pair.Item1 != pair.Item2) {
+ break;
+ }
}
+ Console.WriteLine("Output: {0}.original.out:line {1}", outputFileName, diffLine);
+ Console.WriteLine("Output: {0}.decompiled.out:line {1}", outputFileName, diffLine);
}
- Console.WriteLine("Output: {0}.original.out:line {1}", outputFileName, diffLine);
- Console.WriteLine("Output: {0}.decompiled.out:line {1}", outputFileName, diffLine);
}
- Assert.AreEqual(result1, result2);
- Assert.AreEqual(output1, output2);
+ Assert.AreEqual(result1, result2, "Exit codes differ; did the decompiled code crash?");
Assert.AreEqual(error1, error2);
+ Assert.AreEqual(output1, output2);
} finally {
if (outputFile != null)
outputFile.TempFiles.Delete();
diff --git a/ICSharpCode.Decompiler/Util/BitSet.cs b/ICSharpCode.Decompiler/Util/BitSet.cs
index 7f315b1f6..804b75084 100644
--- a/ICSharpCode.Decompiler/Util/BitSet.cs
+++ b/ICSharpCode.Decompiler/Util/BitSet.cs
@@ -30,70 +30,93 @@ namespace ICSharpCode.Decompiler
///
public class BitSet
{
- readonly BitArray bits;
+ const int BitsPerWord = 64;
+ const int Log2BitsPerWord = 6;
+ const ulong Mask = 0xffffffffffffffffUL;
+
+ readonly ulong[] words;
+
+ static int WordIndex(int bitIndex)
+ {
+ Debug.Assert(bitIndex >= 0);
+ return bitIndex >> Log2BitsPerWord;
+ }
///
/// Creates a new bitset, where initially all bits are zero.
///
public BitSet(int capacity)
{
- this.bits = new BitArray(capacity);
+ this.words = new ulong[Math.Max(1, WordIndex(capacity + BitsPerWord - 1))];
}
- private BitSet(BitArray bits)
+ private BitSet(ulong[] bits)
{
- this.bits = bits;
+ this.words = bits;
}
public BitSet Clone()
{
- return new BitSet((BitArray)bits.Clone());
+ return new BitSet((ulong[])words.Clone());
}
public bool this[int index] {
get {
- return bits[index];
+ return (words[WordIndex(index)] & (1UL << index)) != 0;
}
set {
- bits[index] = value;
+ if (value)
+ Set(index);
+ else
+ Clear(index);
}
}
+ ///
+ /// Gets whether at least one bit is set.
+ ///
public bool Any()
{
- for (int i = 0; i < bits.Length; i++) {
- if (bits[i])
+ for (int i = 0; i < words.Length; i++) {
+ if (words[i] != 0)
return true;
}
return false;
}
+ ///
+ /// Gets whether both bitsets have the same content.
+ ///
+ public bool SetEquals(BitSet other)
+ {
+ Debug.Assert(words.Length == other.words.Length);
+ for (int i = 0; i < words.Length; i++) {
+ if (words[i] != other.words[i])
+ return false;
+ }
+ return true;
+ }
+
///
/// Gets whether this set is a subset of other, or equal.
///
public bool IsSubsetOf(BitSet other)
{
- for (int i = 0; i < bits.Length; i++) {
- if (bits[i] && !other[i])
+ for (int i = 0; i < words.Length; i++) {
+ if ((words[i] & ~other.words[i]) != 0)
return false;
}
return true;
}
+ ///
+ /// Gets whether this set is a superset of other, or equal.
+ ///
public bool IsSupersetOf(BitSet other)
{
return other.IsSubsetOf(this);
}
- public bool SetEquals(BitSet other)
- {
- for (int i = 0; i < bits.Length; i++) {
- if (bits[i] != other[i])
- return false;
- }
- return true;
- }
-
public bool IsProperSubsetOf(BitSet other)
{
return IsSubsetOf(other) && !SetEquals(other);
@@ -104,10 +127,13 @@ namespace ICSharpCode.Decompiler
return IsSubsetOf(other) && !SetEquals(other);
}
+ ///
+ /// Gets whether at least one bit is set in both bitsets.
+ ///
public bool Overlaps(BitSet other)
{
- for (int i = 0; i < bits.Length; i++) {
- if (bits[i] && other[i])
+ for (int i = 0; i < words.Length; i++) {
+ if ((words[i] & other.words[i]) != 0)
return true;
}
return false;
@@ -115,62 +141,99 @@ namespace ICSharpCode.Decompiler
public void UnionWith(BitSet other)
{
- bits.Or(other.bits);
+ Debug.Assert(words.Length == other.words.Length);
+ for (int i = 0; i < words.Length; i++) {
+ words[i] |= other.words[i];
+ }
}
public void IntersectWith(BitSet other)
{
- bits.And(other.bits);
+ for (int i = 0; i < words.Length; i++) {
+ words[i] &= other.words[i];
+ }
}
- public void ClearAll()
+ public void Set(int index)
+ {
+ words[WordIndex(index)] |= (1UL << index);
+ }
+
+ ///
+ /// Sets all bits i; where startIndex <= i < endIndex.
+ ///
+ public void Set(int startIndex, int endIndex)
{
- bits.SetAll(false);
+ Debug.Assert(startIndex <= endIndex);
+ if (startIndex >= endIndex) {
+ return;
+ }
+ int startWordIndex = WordIndex(startIndex);
+ int endWordIndex = WordIndex(endIndex - 1);
+ ulong startMask = Mask << startIndex;
+ ulong endMask = Mask >> -endIndex; // same as (Mask >> (64 - (endIndex % 64)))
+ if (startWordIndex == endWordIndex) {
+ words[startWordIndex] |= (startMask & endMask);
+ } else {
+ words[startWordIndex] |= startMask;
+ for (int i = startWordIndex + 1; i < endWordIndex; i++) {
+ words[i] = 0;
+ }
+ words[endWordIndex] |= endMask;
+ }
}
+ // Note: intentionally no SetAll(), because it would also set the
+ // extra bits (due to the capacity being rounded up to a full word).
+
public void Clear(int index)
{
- bits[index] = false;
+ words[WordIndex(index)] &= ~(1UL << index);
}
+ ///
+ /// Clear all bits i; where startIndex <= i < endIndex.
+ ///
public void Clear(int startIndex, int endIndex)
{
- for (int i = startIndex; i < endIndex; i++) {
- bits[i] = false;
+ Debug.Assert(startIndex <= endIndex);
+ if (startIndex >= endIndex) {
+ return;
+ }
+ int startWordIndex = WordIndex(startIndex);
+ int endWordIndex = WordIndex(endIndex - 1);
+ ulong startMask = Mask << startIndex;
+ ulong endMask = Mask >> -endIndex; // same as (Mask >> (64 - (endIndex % 64)))
+ if (startWordIndex == endWordIndex) {
+ words[startWordIndex] &= ~(startMask & endMask);
+ } else {
+ words[startWordIndex] &= ~startMask;
+ for (int i = startWordIndex + 1; i < endWordIndex; i++) {
+ words[i] = 0;
+ }
+ words[endWordIndex] &= ~endMask;
}
}
- public void SetAll()
- {
- bits.SetAll(true);
- }
-
- public void Set(int index)
- {
- bits[index] = true;
- }
-
- public void Set(int startIndex, int endIndex)
+ public void ClearAll()
{
- for (int i = startIndex; i < endIndex; i++) {
- bits[i] = true;
+ for (int i = 0; i < words.Length; i++) {
+ words[i] = 0;
}
}
public void ReplaceWith(BitSet incoming)
{
- Debug.Assert(bits.Length == incoming.bits.Length);
- for (int i = 0; i < bits.Length; i++) {
- bits[i] = incoming.bits[i];
- }
+ Debug.Assert(words.Length == incoming.words.Length);
+ Array.Copy(incoming.words, 0, words, 0, words.Length);
}
public override string ToString()
{
StringBuilder b = new StringBuilder();
b.Append('{');
- for (int i = 0; i < bits.Length; i++) {
- if (bits[i]) {
+ for (int i = 0; i < words.Length; i++) {
+ if (this[i]) {
if (b.Length > 1)
b.Append(", ");
if (b.Length > 500) {