|
|
|
|
@ -76,6 +76,7 @@ namespace ICSharpCode.Decompiler.IL
@@ -76,6 +76,7 @@ namespace ICSharpCode.Decompiler.IL
|
|
|
|
|
BitArray isBranchTarget; |
|
|
|
|
BlockContainer mainContainer; |
|
|
|
|
List<ILInstruction> instructionBuilder; |
|
|
|
|
int currentInstructionStart; |
|
|
|
|
|
|
|
|
|
// Dictionary that stores stacks for each IL instruction
|
|
|
|
|
Dictionary<int, ImmutableStack<ILVariable>> stackByOffset; |
|
|
|
|
@ -251,7 +252,7 @@ namespace ICSharpCode.Decompiler.IL
@@ -251,7 +252,7 @@ namespace ICSharpCode.Decompiler.IL
|
|
|
|
|
/// </summary>
|
|
|
|
|
void Warn(string message) |
|
|
|
|
{ |
|
|
|
|
Warnings.Add(string.Format("IL_{0:x4}: {1}", reader.Offset, message)); |
|
|
|
|
Warnings.Add(string.Format("IL_{0:x4}: {1}", currentInstructionStart, message)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ImmutableStack<ILVariable> MergeStacks(ImmutableStack<ILVariable> a, ImmutableStack<ILVariable> b) |
|
|
|
|
@ -382,6 +383,7 @@ namespace ICSharpCode.Decompiler.IL
@@ -382,6 +383,7 @@ namespace ICSharpCode.Decompiler.IL
|
|
|
|
|
cancellationToken.ThrowIfCancellationRequested(); |
|
|
|
|
int start = reader.Offset; |
|
|
|
|
StoreStackForOffset(start, ref currentStack); |
|
|
|
|
currentInstructionStart = start; |
|
|
|
|
ILInstruction decodedInstruction; |
|
|
|
|
try { |
|
|
|
|
decodedInstruction = DecodeInstruction(); |
|
|
|
|
@ -1427,22 +1429,31 @@ namespace ICSharpCode.Decompiler.IL
@@ -1427,22 +1429,31 @@ namespace ICSharpCode.Decompiler.IL
|
|
|
|
|
{ |
|
|
|
|
var right = Pop(); |
|
|
|
|
var left = Pop(); |
|
|
|
|
// make the implicit I4->I conversion explicit:
|
|
|
|
|
if (left.ResultType == StackType.I4 && right.ResultType == StackType.I) { |
|
|
|
|
left = new Conv(left, PrimitiveType.I, false, Sign.None); |
|
|
|
|
} else if (left.ResultType == StackType.I && right.ResultType == StackType.I4) { |
|
|
|
|
right = new Conv(right, PrimitiveType.I, false, Sign.None); |
|
|
|
|
|
|
|
|
|
if (left.ResultType == StackType.O && right.ResultType.IsIntegerType()) { |
|
|
|
|
// C++/CLI sometimes compares object references with integers.
|
|
|
|
|
if (right.ResultType == StackType.I4) { |
|
|
|
|
// ensure we compare at least native integer size
|
|
|
|
|
right = new Conv(right, PrimitiveType.I, false, Sign.None); |
|
|
|
|
} |
|
|
|
|
left = new Conv(left, right.ResultType.ToPrimitiveType(), false, Sign.None); |
|
|
|
|
} else if (right.ResultType == StackType.O && left.ResultType.IsIntegerType()) { |
|
|
|
|
if (left.ResultType == StackType.I4) { |
|
|
|
|
left = new Conv(left, PrimitiveType.I, false, Sign.None); |
|
|
|
|
} |
|
|
|
|
right = new Conv(right, left.ResultType.ToPrimitiveType(), false, Sign.None); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// make implicit integer conversions explicit:
|
|
|
|
|
MakeExplicitConversion(sourceType: StackType.I4, targetType: StackType.I, conversionType: PrimitiveType.I); |
|
|
|
|
MakeExplicitConversion(sourceType: StackType.I4, targetType: StackType.I8, conversionType: PrimitiveType.I8); |
|
|
|
|
MakeExplicitConversion(sourceType: StackType.I, targetType: StackType.I8, conversionType: PrimitiveType.I8); |
|
|
|
|
|
|
|
|
|
// Based on Table 4: Binary Comparison or Branch Operation
|
|
|
|
|
if (left.ResultType.IsFloatType() && right.ResultType.IsFloatType()) { |
|
|
|
|
if (left.ResultType != right.ResultType) { |
|
|
|
|
// make the implicit F4->F8 conversion explicit:
|
|
|
|
|
if (left.ResultType == StackType.F4) { |
|
|
|
|
left = new Conv(left, PrimitiveType.R8, false, Sign.Signed); |
|
|
|
|
} else if (right.ResultType == StackType.F4) { |
|
|
|
|
right = new Conv(right, PrimitiveType.R8, false, Sign.Signed); |
|
|
|
|
} |
|
|
|
|
MakeExplicitConversion(StackType.F4, StackType.F8, PrimitiveType.R8); |
|
|
|
|
} |
|
|
|
|
if (un) { |
|
|
|
|
// for floats, 'un' means 'unordered'
|
|
|
|
|
@ -1466,6 +1477,15 @@ namespace ICSharpCode.Decompiler.IL
@@ -1466,6 +1477,15 @@ namespace ICSharpCode.Decompiler.IL
|
|
|
|
|
} |
|
|
|
|
return new Comp(kind, Sign.None, left, right); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void MakeExplicitConversion(StackType sourceType, StackType targetType, PrimitiveType conversionType) |
|
|
|
|
{ |
|
|
|
|
if (left.ResultType == sourceType && right.ResultType == targetType) { |
|
|
|
|
left = new Conv(left, conversionType, false, Sign.None); |
|
|
|
|
} else if (left.ResultType == targetType && right.ResultType == sourceType) { |
|
|
|
|
right = new Conv(right, conversionType, false, Sign.None); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool IsInvalidBranch(int target) => target < 0 || target >= reader.Length; |
|
|
|
|
|