Browse Source

'Typed IL' view shows stack

pull/728/head
Daniel Grunwald 11 years ago
parent
commit
167e140c75
  1. 15
      ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs
  2. 15
      ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
  3. 4
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  4. 12
      ICSharpCode.Decompiler/IL/BlockBuilder.cs
  5. 149
      ICSharpCode.Decompiler/IL/ILReader.cs
  6. 11
      ICSharpCode.Decompiler/IL/ILVariable.cs
  7. 6
      ICSharpCode.Decompiler/IL/Instructions/BinaryInstruction.cs
  8. 22
      ICSharpCode.Decompiler/IL/Instructions/BoxInstructions.cs
  9. 9
      ICSharpCode.Decompiler/IL/Instructions/BranchInstruction.cs
  10. 11
      ICSharpCode.Decompiler/IL/Instructions/CallInstruction.cs
  11. 2
      ICSharpCode.Decompiler/IL/Instructions/FieldAccess.cs
  12. 45
      ICSharpCode.Decompiler/IL/Instructions/MemoryInstruction.cs
  13. 10
      ICSharpCode.Decompiler/IL/Instructions/OpCode.cs
  14. 24
      ICSharpCode.Decompiler/IL/Instructions/Prefix.cs
  15. 6
      ICSharpCode.Decompiler/IL/Instructions/SimpleInstruction.cs
  16. 17
      ICSharpCode.Decompiler/IL/Instructions/UnaryInstruction.cs
  17. 8
      ICSharpCode.Decompiler/IL/Instructions/VarInstructions.cs
  18. 1
      ILSpy.sln
  19. 16
      ILSpy/Languages/ILAstLanguage.cs
  20. 2
      Mono.Cecil/Mono.Cecil.Cil/MethodBody.cs

15
ICSharpCode.Decompiler/Disassembler/MethodBodyDisassembler.cs

@ -100,12 +100,17 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -100,12 +100,17 @@ namespace ICSharpCode.Decompiler.Disassembler
output.WriteLine();
}
if (method.Body.HasExceptionHandlers) {
WriteExceptionHandlers(body);
}
}
internal void WriteExceptionHandlers(MethodBody body)
{
if (body.HasExceptionHandlers) {
output.WriteLine();
foreach (var eh in body.ExceptionHandlers) {
eh.WriteTo(output);
output.WriteLine();
foreach (var eh in method.Body.ExceptionHandlers) {
eh.WriteTo(output);
output.WriteLine();
}
}
}
}

15
ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs

@ -99,16 +99,22 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -99,16 +99,22 @@ namespace ICSharpCode.Decompiler.Disassembler
};
public void DisassembleMethod(MethodDefinition method)
{
DisassembleMethodHeader(method);
DisassembleMethodBlock(method);
}
public void DisassembleMethodHeader(MethodDefinition method)
{
// set current member
currentMember = method;
// write method header
output.WriteDefinition(".method ", method);
DisassembleMethodInternal(method);
DisassembleMethodHeaderInternal(method);
}
void DisassembleMethodInternal(MethodDefinition method)
void DisassembleMethodHeaderInternal(MethodDefinition method)
{
// .method public hidebysig specialname
// instance default class [mscorlib]System.IO.TextWriter get_BaseWriter () cil managed
@ -201,6 +207,10 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -201,6 +207,10 @@ namespace ICSharpCode.Decompiler.Disassembler
WriteFlags(method.ImplAttributes & ~(MethodImplAttributes.CodeTypeMask | MethodImplAttributes.ManagedMask), methodImpl);
output.Unindent();
}
void DisassembleMethodBlock(MethodDefinition method)
{
OpenBlock(defaultCollapsed: isInType);
WriteAttributes(method.CustomAttributes);
if (method.HasOverrides) {
@ -216,7 +226,6 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -216,7 +226,6 @@ namespace ICSharpCode.Decompiler.Disassembler
WriteSecurityDeclarations(method);
if (method.HasBody) {
// create IL code mappings - used in debugger
methodBodyDisassembler.Disassemble(method.Body);
}

4
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -70,6 +70,7 @@ @@ -70,6 +70,7 @@
<Compile Include="Disassembler\ILStructure.cs" />
<Compile Include="Disassembler\MethodBodyDisassembler.cs" />
<Compile Include="Disassembler\ReflectionDisassembler.cs" />
<Compile Include="IL\BlockBuilder.cs" />
<Compile Include="IL\ILOpCodes.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
@ -81,12 +82,13 @@ @@ -81,12 +82,13 @@
<Compile Include="IL\InstructionOutputExtensions.cs" />
<Compile Include="IL\Instructions\BinaryInstruction.cs" />
<Compile Include="IL\Instructions\Block.cs" />
<Compile Include="IL\Instructions\BoxInstructions.cs" />
<Compile Include="IL\Instructions\BranchInstruction.cs" />
<Compile Include="IL\Instructions\CallInstruction.cs" />
<Compile Include="IL\Instructions\FieldAccess.cs" />
<Compile Include="IL\Instructions\ILInstruction.cs" />
<Compile Include="IL\Instructions\OpCode.cs" />
<Compile Include="IL\Instructions\Prefix.cs" />
<Compile Include="IL\Instructions\MemoryInstruction.cs" />
<Compile Include="IL\Instructions\SimpleInstruction.cs" />
<Compile Include="IL\Instructions\UnaryInstruction.cs" />
<Compile Include="IL\Instructions\VarInstructions.cs" />

12
ICSharpCode.Decompiler/IL/BlockBuilder.cs

@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ICSharpCode.Decompiler.IL
{
class BlockBuilder
{
}
}

149
ICSharpCode.Decompiler/IL/ILReader.cs

@ -6,10 +6,12 @@ using System.Threading.Tasks; @@ -6,10 +6,12 @@ using System.Threading.Tasks;
using System.Collections.Immutable;
using System.Diagnostics;
using Mono.Cecil;
using System.Collections;
using System.Threading;
namespace ICSharpCode.Decompiler.IL
{
public class ILReader(private Mono.Cecil.Cil.MethodBody body)
public class ILReader(private readonly Mono.Cecil.Cil.MethodBody body, private readonly CancellationToken cancellationToken)
{
internal static ILOpCode ReadOpCode(ref BlobReader reader)
{
@ -25,11 +27,13 @@ namespace ICSharpCode.Decompiler.IL @@ -25,11 +27,13 @@ namespace ICSharpCode.Decompiler.IL
return new MetadataToken(reader.ReadUInt32());
}
ImmutableArray<ILInstruction>.Builder instructionBuilder = ImmutableArray.CreateBuilder<ILInstruction>();
readonly TypeSystem typeSystem = body.Method.Module.TypeSystem;
BlobReader reader = body.GetILReader();
Stack<StackType> stack = new Stack<StackType>(body.MaxStackSize);
ILVariable[] parameterVariables;
ILVariable[] localVariables;
ILVariable[] parameterVariables = InitParameterVariables(body);
ILVariable[] localVariables = body.Variables.Select(v => new ILVariable(v)).ToArray();
BitArray isBranchTarget;
List<ILInstruction> instructionBuilder;
IMetadataTokenProvider ReadAndDecodeMetadataToken()
{
@ -37,30 +41,41 @@ namespace ICSharpCode.Decompiler.IL @@ -37,30 +41,41 @@ namespace ICSharpCode.Decompiler.IL
return body.LookupToken(token);
}
public ImmutableArray<ILInstruction> ReadInstructions()
static ILVariable[] InitParameterVariables(Mono.Cecil.Cil.MethodBody body)
{
//var body = method.GetBody();
//var methodSignature = new MethodSignature(method.Signature);
//var localVariableTypes = GetStackTypes(body.GetLocalVariableTypes(method.ContainingModule.metadata));
localVariables = body.Variables.Select(v => new ILVariable(v)).ToArray();
parameterVariables = body.Method.Parameters.Select(p => new ILVariable(p)).ToArray();
//var parameterTypes = GetStackTypes(methodSignature.ParameterTypes);
//var stack = new Stack<StackType>(body.MaxStack);
var parameterVariables = new ILVariable[body.Method.GetPopAmount()];
int paramIndex = 0;
if (body.Method.HasThis)
parameterVariables[paramIndex++] = new ILVariable(body.ThisParameter);
foreach (var p in body.Method.Parameters)
parameterVariables[paramIndex++] = new ILVariable(p);
Debug.Assert(paramIndex == parameterVariables.Length);
return parameterVariables;
}
void ReadInstructions(Dictionary<int, ImmutableArray<StackType>> outputStacks)
{
instructionBuilder = new List<ILInstruction>();
isBranchTarget = new BitArray(body.CodeSize);
stack.Clear();
// Dictionary that stores stacks for forward jumps
var branchStackDict = new Dictionary<int, ImmutableArray<StackType>>();
while (reader.Position < reader.Length) {
cancellationToken.ThrowIfCancellationRequested();
int start = reader.Position;
if (outputStacks != null)
outputStacks.Add(start, stack.ToImmutableArray());
ILInstruction decodedInstruction = DecodeInstruction();
decodedInstruction.ILRange = new Interval(start, reader.Position);
instructionBuilder.Add(decodedInstruction);
if ((var branch = decodedInstruction as Branch) != null) {
isBranchTarget[branch.TargetILOffset] = true;
if (branch.TargetILOffset >= reader.Position) {
branchStackDict[branch.TargetILOffset] = stack.ToImmutableArray();
}
}
if (IsUnconditionalBranch(decodedInstruction.OpCode)) {
if (!decodedInstruction.IsEndReachable) {
stack.Clear();
if (branchStackDict.TryGetValue(reader.Position, out var stackFromBranch)) {
for (int i = stackFromBranch.Length - 1; i >= 0; i--) {
@ -69,12 +84,34 @@ namespace ICSharpCode.Decompiler.IL @@ -69,12 +84,34 @@ namespace ICSharpCode.Decompiler.IL
}
}
}
return instructionBuilder.ToImmutable();
}
private bool IsUnconditionalBranch(OpCode opCode)
public void WriteTypedIL(ITextOutput output)
{
return opCode == OpCode.Branch || opCode == OpCode.Ret || opCode == OpCode.Leave;
var outputStacks = new Dictionary<int, ImmutableArray<StackType>>();
ReadInstructions(outputStacks);
foreach (var inst in instructionBuilder) {
output.Write(" [");
bool isFirstElement = true;
foreach (var element in outputStacks[inst.ILRange.Start]) {
if (isFirstElement)
isFirstElement = false;
else
output.Write(", ");
output.Write(element);
}
output.Write(']');
output.WriteLine();
if (isBranchTarget[inst.ILRange.Start])
output.Write('*');
else
output.Write(' ');
output.WriteDefinition("IL_" + inst.ILRange.Start.ToString("x4"), inst.ILRange.Start);
output.Write(": ");
inst.WriteTo(output);
output.WriteLine();
}
new Disassembler.MethodBodyDisassembler(output, false, cancellationToken).WriteExceptionHandlers(body);
}
ILInstruction DecodeInstruction()
@ -287,7 +324,7 @@ namespace ICSharpCode.Decompiler.IL @@ -287,7 +324,7 @@ namespace ICSharpCode.Decompiler.IL
case ILOpCode.Ldc_I4_6:
case ILOpCode.Ldc_I4_7:
case ILOpCode.Ldc_I4_8:
return LdcI4(ilOpCode - ILOpCode.Ldc_I4_0);
return LdcI4((int)ilOpCode - (int)ILOpCode.Ldc_I4_0);
case ILOpCode.Ldc_I4_S:
return LdcI4(reader.ReadSByte());
case ILOpCode.Ldnull:
@ -298,17 +335,27 @@ namespace ICSharpCode.Decompiler.IL @@ -298,17 +335,27 @@ namespace ICSharpCode.Decompiler.IL
case ILOpCode.Ldftn:
throw new NotImplementedException();
case ILOpCode.Ldind_I1:
return LdInd(typeSystem.SByte);
case ILOpCode.Ldind_I2:
return LdInd(typeSystem.Int16);
case ILOpCode.Ldind_I4:
return LdInd(typeSystem.Int32);
case ILOpCode.Ldind_I8:
return LdInd(typeSystem.Int64);
case ILOpCode.Ldind_U1:
return LdInd(typeSystem.Byte);
case ILOpCode.Ldind_U2:
return LdInd(typeSystem.UInt16);
case ILOpCode.Ldind_U4:
return LdInd(typeSystem.UInt32);
case ILOpCode.Ldind_R4:
return LdInd(typeSystem.Single);
case ILOpCode.Ldind_R8:
return LdInd(typeSystem.Double);
case ILOpCode.Ldind_I:
return LdInd(typeSystem.IntPtr);
case ILOpCode.Ldind_Ref:
throw new NotImplementedException();
return LdInd(typeSystem.Object);
case ILOpCode.Ldloc:
return Ldloc(reader.ReadUInt16());
case ILOpCode.Ldloc_S:
@ -336,6 +383,8 @@ namespace ICSharpCode.Decompiler.IL @@ -336,6 +383,8 @@ namespace ICSharpCode.Decompiler.IL
return BinaryNumeric(OpCode.Mul, OverflowMode.Ovf_Un);
case ILOpCode.Neg:
return UnaryNumeric(OpCode.Neg);
case ILOpCode.Newobj:
return DecodeCall(OpCode.NewObj);
case ILOpCode.Nop:
return new Nop();
case ILOpCode.Not:
@ -350,7 +399,7 @@ namespace ICSharpCode.Decompiler.IL @@ -350,7 +399,7 @@ namespace ICSharpCode.Decompiler.IL
case ILOpCode.Rem_Un:
return BinaryNumeric(OpCode.Rem, OverflowMode.Un);
case ILOpCode.Ret:
return Ret();
return Return();
case ILOpCode.Shl:
return Shift(OpCode.Shl);
case ILOpCode.Shr:
@ -379,7 +428,16 @@ namespace ICSharpCode.Decompiler.IL @@ -379,7 +428,16 @@ namespace ICSharpCode.Decompiler.IL
case ILOpCode.Stloc_2:
case ILOpCode.Stloc_3:
return Stloc(ilOpCode - ILOpCode.Stloc_0);
case ILOpCode.Sub:
return BinaryNumeric(OpCode.Sub);
case ILOpCode.Sub_Ovf:
return BinaryNumeric(OpCode.Sub, OverflowMode.Ovf);
case ILOpCode.Sub_Ovf_Un:
return BinaryNumeric(OpCode.Sub, OverflowMode.Ovf_Un);
case ILOpCode.Switch:
throw new NotImplementedException();
case ILOpCode.Xor:
return BinaryNumeric(OpCode.BitXor);
case ILOpCode.Box:
throw new NotImplementedException();
case ILOpCode.Castclass:
@ -389,7 +447,9 @@ namespace ICSharpCode.Decompiler.IL @@ -389,7 +447,9 @@ namespace ICSharpCode.Decompiler.IL
case ILOpCode.Initobj:
throw new NotImplementedException();
case ILOpCode.Isinst:
throw new NotImplementedException();
stack.PopOrDefault();
stack.Push(StackType.O);
return new IsInst((TypeReference)ReadAndDecodeMetadataToken());
case ILOpCode.Ldelem:
case ILOpCode.Ldelem_I1:
case ILOpCode.Ldelem_I2:
@ -465,15 +525,32 @@ namespace ICSharpCode.Decompiler.IL @@ -465,15 +525,32 @@ namespace ICSharpCode.Decompiler.IL
case ILOpCode.Stobj:
throw new NotImplementedException();
case ILOpCode.Throw:
throw new NotImplementedException();
stack.PopOrDefault();
return new ThrowInstruction();
case ILOpCode.Unbox:
case ILOpCode.Unbox_Any:
throw new NotImplementedException();
case ILOpCode.Unbox_Any:
return DecodeUnboxAny();
default:
throw new NotImplementedException(ilOpCode.ToString());
}
}
private ILInstruction DecodeUnboxAny()
{
TypeReference typeRef = (TypeReference)ReadAndDecodeMetadataToken();
stack.PopOrDefault();
stack.Push(typeRef.GetStackType());
return new UnboxAny(typeRef);
}
private ILInstruction LdInd(TypeReference typeRef)
{
stack.PopOrDefault(); // pointer
stack.Push(typeRef.GetStackType());
return new LoadIndirect(typeRef);
}
private ILInstruction Shift(OpCode opCode, OverflowMode overflowMode = OverflowMode.None)
{
var shiftAmountType = stack.PopOrDefault();
@ -482,12 +559,12 @@ namespace ICSharpCode.Decompiler.IL @@ -482,12 +559,12 @@ namespace ICSharpCode.Decompiler.IL
return new BinaryNumericInstruction(opCode, valueType, overflowMode);
}
private ILInstruction Ret()
private ILInstruction Return()
{
if (body.Method.ReturnType.GetStackType() == StackType.Void)
return new RetVoid();
return new ReturnVoidInstruction();
else
return new Ret();
return new ReturnInstruction();
}
private ILInstruction UnaryNumeric(OpCode opCode)
@ -595,17 +672,18 @@ namespace ICSharpCode.Decompiler.IL @@ -595,17 +672,18 @@ namespace ICSharpCode.Decompiler.IL
private ILInstruction Conv(PrimitiveType targetType, OverflowMode mode)
{
StackType from = stack.PopOrDefault();
stack.Push(targetType.GetStackType());
return new ConvInstruction(from, targetType, mode);
}
ILInstruction DecodeCall(OpCode opCode)
{
var method = (MethodReference)ReadAndDecodeMetadataToken();
int numPopCalls = Math.Min(stack.Count, method.GetPopAmount());
for (int i = 0; i < numPopCalls; i++) {
var inst = new CallInstruction(opCode, method);
for (int i = 0; i < inst.Operands.Length; i++) {
stack.Pop();
}
var returnType = method.ReturnType.GetStackType();
var returnType = (opCode == OpCode.NewObj ? method.DeclaringType : method.ReturnType).GetStackType();
if (returnType != StackType.Void)
stack.Push(returnType);
return new CallInstruction(opCode, method);
@ -629,29 +707,32 @@ namespace ICSharpCode.Decompiler.IL @@ -629,29 +707,32 @@ namespace ICSharpCode.Decompiler.IL
{
int start = reader.Position - 1;
var condition = Comparison(comparisonOpCodeForInts, comparisonOpCodeForFloats);
int target = start + (shortForm ? reader.ReadSByte() : reader.ReadInt32());
int target = shortForm ? reader.ReadSByte() : reader.ReadInt32();
target += reader.Position;
condition.ILRange = new Interval(start, reader.Position);
if (negate) {
condition = new LogicNotInstruction { Operand = condition };
}
stack.PopOrDefault();
return new ConditionalBranch(condition, target);
}
ILInstruction DecodeConditionalBranch(bool shortForm, bool negate)
{
int start = reader.Position - 1;
int target = start + (shortForm ? reader.ReadSByte() : reader.ReadInt32());
int target = shortForm ? reader.ReadSByte() : reader.ReadInt32();
target += reader.Position;
ILInstruction condition = ILInstruction.Pop;
if (negate) {
condition = new LogicNotInstruction { Operand = condition };
}
stack.PopOrDefault();
return new ConditionalBranch(condition, target);
}
ILInstruction DecodeUnconditionalBranch(bool shortForm, OpCode opCode)
{
int start = reader.Position - 1;
int target = start + (shortForm ? reader.ReadSByte() : reader.ReadInt32());
int target = shortForm ? reader.ReadSByte() : reader.ReadInt32();
target += reader.Position;
return new Branch(opCode, target);
}

11
ICSharpCode.Decompiler/IL/ILVariable.cs

@ -16,14 +16,18 @@ namespace ICSharpCode.Decompiler.IL @@ -16,14 +16,18 @@ namespace ICSharpCode.Decompiler.IL
class ILVariable(public readonly VariableKind Kind, public readonly TypeReference Type, public readonly int Index)
{
readonly object CecilObject;
public ILVariable(VariableDefinition v)
: this(VariableKind.Local, v.VariableType, v.Index)
{
this.CecilObject = v;
}
public ILVariable(ParameterDefinition p)
: this(VariableKind.Parameter, p.ParameterType, p.Index)
{
this.CecilObject = p;
}
public override string ToString()
@ -32,10 +36,17 @@ namespace ICSharpCode.Decompiler.IL @@ -32,10 +36,17 @@ namespace ICSharpCode.Decompiler.IL
case VariableKind.Local:
return "V_" + Index.ToString();
case VariableKind.Parameter:
if (Index == -1)
return "this";
return "P_" + Index.ToString();
default:
return Kind.ToString();
}
}
internal void WriteTo(ITextOutput output)
{
output.WriteReference(this.ToString(), CecilObject ?? this, isLocal: true);
}
}
}

6
ICSharpCode.Decompiler/IL/Instructions/BinaryInstruction.cs

@ -32,6 +32,7 @@ namespace ICSharpCode.Decompiler.IL @@ -32,6 +32,7 @@ namespace ICSharpCode.Decompiler.IL
output.WriteSuffix(OverflowMode);
output.Write(' ');
output.Write(OpType);
output.Write('(');
Left.WriteTo(output);
output.Write(", ");
Right.WriteTo(output);
@ -46,7 +47,10 @@ namespace ICSharpCode.Decompiler.IL @@ -46,7 +47,10 @@ namespace ICSharpCode.Decompiler.IL
public override void WriteTo(ITextOutput output)
{
output.Write("{0}.{1}(", OpCode, OpType);
output.Write(OpCode);
output.Write('.');
output.Write(OpType);
output.Write('(');
Left.WriteTo(output);
output.Write(", ");
Right.WriteTo(output);

22
ICSharpCode.Decompiler/IL/Instructions/BoxInstructions.cs

@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
using Mono.Cecil;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ICSharpCode.Decompiler.IL
{
class UnboxAny(public readonly TypeReference TypeReference) : UnaryInstruction(OpCode.UnboxAny)
{
public override void WriteTo(ITextOutput output)
{
output.Write(OpCode);
output.Write(' ');
Disassembler.DisassemblerHelpers.WriteOperand(output, TypeReference);
output.Write('(');
Operand.WriteTo(output);
output.Write(')');
}
}
}

9
ICSharpCode.Decompiler/IL/Instructions/BranchInstruction.cs

@ -56,12 +56,17 @@ namespace ICSharpCode.Decompiler.IL @@ -56,12 +56,17 @@ namespace ICSharpCode.Decompiler.IL
}
}
class RetVoid() : SimpleInstruction(OpCode.Ret)
class ReturnVoidInstruction() : SimpleInstruction(OpCode.Ret)
{
public override bool IsEndReachable { get { return false; } }
}
class Ret() : UnaryInstruction(OpCode.Ret)
class ReturnInstruction() : UnaryInstruction(OpCode.Ret)
{
public override bool IsEndReachable { get { return false; } }
}
class ThrowInstruction() : UnaryInstruction(OpCode.Throw)
{
public override bool IsEndReachable { get { return false; } }
}

11
ICSharpCode.Decompiler/IL/Instructions/CallInstruction.cs

@ -11,11 +11,14 @@ namespace ICSharpCode.Decompiler.IL @@ -11,11 +11,14 @@ namespace ICSharpCode.Decompiler.IL
class CallInstruction(OpCode opCode, MethodReference methodReference) : ILInstruction(opCode)
{
public readonly MethodReference Method = methodReference;
public readonly ILInstruction[] Operands = InitOperands(methodReference);
public readonly ILInstruction[] Operands = InitOperands(opCode, methodReference);
static ILInstruction[] InitOperands(MethodReference mr)
static ILInstruction[] InitOperands(OpCode opCode, MethodReference mr)
{
ILInstruction[] operands = new ILInstruction[mr.GetPopAmount()];
int popCount = mr.Parameters.Count;
if (opCode != OpCode.NewObj && mr.HasThis)
popCount++;
ILInstruction[] operands = new ILInstruction[popCount];
for (int i = 0; i < operands.Length; i++) {
operands[i] = Pop;
}
@ -28,7 +31,7 @@ namespace ICSharpCode.Decompiler.IL @@ -28,7 +31,7 @@ namespace ICSharpCode.Decompiler.IL
{
get
{
return Method.ReturnType.GetStackType() == StackType.Void;
return OpCode != OpCode.NewObj && Method.ReturnType.GetStackType() == StackType.Void;
}
}

2
ICSharpCode.Decompiler/IL/Instructions/FieldAccess.cs

@ -63,7 +63,7 @@ namespace ICSharpCode.Decompiler.IL @@ -63,7 +63,7 @@ namespace ICSharpCode.Decompiler.IL
}
}
class StoreInstanceField(FieldReference field, OpCode opCode = OpCode.Ldfld) : BinaryInstruction(opCode), ISupportsVolatilePrefix
class StoreInstanceField(FieldReference field, OpCode opCode = OpCode.Stfld) : BinaryInstruction(opCode), ISupportsVolatilePrefix
{
public readonly FieldReference Field = field;

45
ICSharpCode.Decompiler/IL/Instructions/MemoryInstruction.cs

@ -0,0 +1,45 @@ @@ -0,0 +1,45 @@
using Mono.Cecil;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ICSharpCode.Decompiler.IL
{
interface ISupportsMemoryPrefix : ISupportsVolatilePrefix
{
/// <summary>
/// Returns the alignment specified by the 'unaligned' prefix; or 0 if there was no 'unaligned' prefix.
/// </summary>
byte UnalignedPrefix { get; set; }
}
interface ISupportsVolatilePrefix
{
/// <summary>
/// Gets/Sets whether the memory access is volatile.
/// </summary>
bool IsVolatile { get; set; }
}
class LoadIndirect(public readonly TypeReference TypeReference) : UnaryInstruction(OpCode.LdInd), ISupportsMemoryPrefix
{
public byte UnalignedPrefix { get; set; }
public bool IsVolatile { get; set; }
public override void WriteTo(ITextOutput output)
{
if (IsVolatile)
output.Write("volatile.");
if (UnalignedPrefix != 0)
output.Write("unaligned " + UnalignedPrefix + ".");
output.Write(OpCode);
output.Write(' ');
Disassembler.DisassemblerHelpers.WriteOperand(output, TypeReference);
output.Write('(');
Operand.WriteTo(output);
output.Write(')');
}
}
}

10
ICSharpCode.Decompiler/IL/Instructions/OpCode.cs

@ -182,7 +182,7 @@ namespace ICSharpCode.Decompiler.IL @@ -182,7 +182,7 @@ namespace ICSharpCode.Decompiler.IL
LdNull,
/// <summary>
/// Returns from the current method or lambda.
/// <see cref="IL.RetVoid"/> or <see cref="IL.Ret"/>, depending on whether
/// <see cref="IL.ReturnVoidInstruction"/> or <see cref="IL.ReturnInstruction"/>, depending on whether
/// the method has return type void.
/// </summary>
Ret,
@ -218,5 +218,13 @@ namespace ICSharpCode.Decompiler.IL @@ -218,5 +218,13 @@ namespace ICSharpCode.Decompiler.IL
/// Store to static field. <see cref="StoreStaticField"/>
/// </summary>
Stsfld,
/// <summary>
/// Test if object is instance of class or interface. <see cref="IL.IsInst"/>
/// </summary>
IsInst,
LdInd,
UnboxAny,
NewObj,
Throw,
}
}

24
ICSharpCode.Decompiler/IL/Instructions/Prefix.cs

@ -1,24 +0,0 @@ @@ -1,24 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ICSharpCode.Decompiler.IL
{
interface ISupportsMemoryPrefix : ISupportsVolatilePrefix
{
/// <summary>
/// Returns the alignment specified by the 'unaligned' prefix; or 0 if there was no 'unaligned' prefix.
/// </summary>
byte UnalignedPrefix { get; set; }
}
interface ISupportsVolatilePrefix
{
/// <summary>
/// Gets/Sets whether the memory access is volatile.
/// </summary>
bool IsVolatile { get; set; }
}
}

6
ICSharpCode.Decompiler/IL/Instructions/SimpleInstruction.cs

@ -51,6 +51,7 @@ namespace ICSharpCode.Decompiler.IL @@ -51,6 +51,7 @@ namespace ICSharpCode.Decompiler.IL
{
public override void WriteTo(ITextOutput output)
{
output.Write("ldstr ");
Disassembler.DisassemblerHelpers.WriteOperand(output, Value);
}
}
@ -59,6 +60,7 @@ namespace ICSharpCode.Decompiler.IL @@ -59,6 +60,7 @@ namespace ICSharpCode.Decompiler.IL
{
public override void WriteTo(ITextOutput output)
{
output.Write("ldc.i4 ");
Disassembler.DisassemblerHelpers.WriteOperand(output, Value);
}
}
@ -67,14 +69,16 @@ namespace ICSharpCode.Decompiler.IL @@ -67,14 +69,16 @@ namespace ICSharpCode.Decompiler.IL
{
public override void WriteTo(ITextOutput output)
{
output.Write("ldc.i8 ");
Disassembler.DisassemblerHelpers.WriteOperand(output, Value);
}
}
class ConstantFloat(public readonly double Value) : SimpleInstruction(OpCode.LdcI8)
class ConstantFloat(public readonly double Value) : SimpleInstruction(OpCode.LdcF)
{
public override void WriteTo(ITextOutput output)
{
output.Write("ldc.f ");
Disassembler.DisassemblerHelpers.WriteOperand(output, Value);
}
}

17
ICSharpCode.Decompiler/IL/Instructions/UnaryInstruction.cs

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
using System;
using Mono.Cecil;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@ -50,6 +51,19 @@ namespace ICSharpCode.Decompiler.IL @@ -50,6 +51,19 @@ namespace ICSharpCode.Decompiler.IL
}
}
class IsInst(public readonly TypeReference Type) : UnaryInstruction(OpCode.IsInst)
{
public override void WriteTo(ITextOutput output)
{
output.Write(OpCode);
output.Write(' ');
Disassembler.DisassemblerHelpers.WriteOperand(output, Type);
output.Write('(');
Operand.WriteTo(output);
output.Write(')');
}
}
class ConvInstruction(
public readonly StackType FromType, public readonly PrimitiveType ToType, public readonly OverflowMode ConvMode
) : UnaryInstruction(OpCode.Conv)
@ -68,3 +82,4 @@ namespace ICSharpCode.Decompiler.IL @@ -68,3 +82,4 @@ namespace ICSharpCode.Decompiler.IL
}
}
}

8
ICSharpCode.Decompiler/IL/Instructions/VarInstructions.cs

@ -10,7 +10,7 @@ namespace ICSharpCode.Decompiler.IL @@ -10,7 +10,7 @@ namespace ICSharpCode.Decompiler.IL
{
public override void WriteTo(ITextOutput output)
{
output.WriteReference(Variable.ToString(), Variable, isLocal: true);
Variable.WriteTo(output);
}
}
@ -18,8 +18,8 @@ namespace ICSharpCode.Decompiler.IL @@ -18,8 +18,8 @@ namespace ICSharpCode.Decompiler.IL
{
public override void WriteTo(ITextOutput output)
{
output.Write("ref ");
output.WriteReference(Variable.ToString(), Variable, isLocal: true);
output.Write("ldloca ");
Variable.WriteTo(output);
}
}
@ -27,7 +27,7 @@ namespace ICSharpCode.Decompiler.IL @@ -27,7 +27,7 @@ namespace ICSharpCode.Decompiler.IL
{
public override void WriteTo(ITextOutput output)
{
output.WriteReference(Variable.ToString(), Variable, isLocal: true);
Variable.WriteTo(output);
output.Write(" = ");
Operand.WriteTo(output);
}

1
ILSpy.sln

@ -6,6 +6,7 @@ MinimumVisualStudioVersion = 10.0.40219.1 @@ -6,6 +6,7 @@ MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "doc", "doc", "{F45DB999-7E72-4000-B5AD-3A7B485A0896}"
ProjectSection(SolutionItems) = preProject
doc\Command Line.txt = doc\Command Line.txt
ILAst.txt = ILAst.txt
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ILSpy", "ILSpy\ILSpy.csproj", "{1E85EFF9-E370-4683-83E4-8A3D063FF791}"

16
ILSpy/Languages/ILAstLanguage.cs

@ -105,6 +105,13 @@ namespace ICSharpCode.ILSpy @@ -105,6 +105,13 @@ namespace ICSharpCode.ILSpy
return output.ToString();
}
public override void DecompileMethod(MethodDefinition method, ITextOutput output, DecompilationOptions options)
{
base.DecompileMethod(method, output, options);
new ReflectionDisassembler(output, false, options.CancellationToken).DisassembleMethodHeader(method);
output.WriteLine();
}
class TypedIL() : ILAstLanguage("Typed IL")
{
public override void DecompileMethod(MethodDefinition method, ITextOutput output, DecompilationOptions options)
@ -112,13 +119,8 @@ namespace ICSharpCode.ILSpy @@ -112,13 +119,8 @@ namespace ICSharpCode.ILSpy
base.DecompileMethod(method, output, options);
if (!method.HasBody)
return;
ILReader reader = new ILReader(method.Body);
foreach (var inst in reader.ReadInstructions()) {
output.WriteDefinition("IL_" + inst.ILRange.Start.ToString("x2"), inst.ILRange.Start);
output.Write(": ");
inst.WriteTo(output);
output.WriteLine();
}
ILReader reader = new ILReader(method.Body, options.CancellationToken);
reader.WriteTypedIL(output);
}
}
}

2
Mono.Cecil/Mono.Cecil.Cil/MethodBody.cs

@ -130,7 +130,7 @@ namespace Mono.Cecil.Cil { @@ -130,7 +130,7 @@ namespace Mono.Cecil.Cil {
{
var declaring_type = method.DeclaringType;
var type = declaring_type.IsValueType || declaring_type.IsPrimitive
? new PointerType(declaring_type)
? new ByReferenceType(declaring_type)
: declaring_type as TypeReference;
return new ParameterDefinition(type, method);

Loading…
Cancel
Save