Browse Source

Allow viewing 'typed IL'.

pull/728/head
Daniel Grunwald 11 years ago
parent
commit
c2ac889ebe
  1. 5
      ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs
  2. 2
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  3. 440
      ICSharpCode.Decompiler/IL/ILReader.cs
  4. 5
      ICSharpCode.Decompiler/IL/ILTypeExtensions.cs
  5. 28
      ICSharpCode.Decompiler/IL/ILVariable.cs
  6. 34
      ICSharpCode.Decompiler/IL/InstructionOutputExtensions.cs
  7. 21
      ICSharpCode.Decompiler/IL/Instructions/BinaryInstruction.cs
  8. 12
      ICSharpCode.Decompiler/IL/Instructions/Block.cs
  9. 15
      ICSharpCode.Decompiler/IL/Instructions/BranchInstruction.cs
  10. 25
      ICSharpCode.Decompiler/IL/Instructions/CallInstruction.cs
  11. 4
      ICSharpCode.Decompiler/IL/Instructions/ILInstruction.cs
  12. 96
      ICSharpCode.Decompiler/IL/Instructions/OpCode.cs
  13. 14
      ICSharpCode.Decompiler/IL/Instructions/Prefix.cs
  14. 42
      ICSharpCode.Decompiler/IL/Instructions/SimpleInstruction.cs
  15. 37
      ICSharpCode.Decompiler/IL/Instructions/UnaryInstruction.cs
  16. 25
      ICSharpCode.Decompiler/IL/Instructions/VarInstructions.cs
  17. 4
      ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj
  18. 1
      ICSharpCode.Decompiler/Tests/packages.config
  19. 2
      ICSharpCode.Decompiler/Util/Interval.cs
  20. 5
      ILSpy/App.xaml.cs
  21. 6
      ILSpy/ILSpy.csproj
  22. 71
      ILSpy/Languages/ILAstLanguage.cs
  23. 9
      ILSpy/Languages/ILLanguage.cs
  24. 3
      ILSpy/Languages/Languages.cs
  25. 2
      ILSpy/Properties/app.config.template
  26. 39
      ILSpy/TextView/DecompilerTextView.cs
  27. 1
      ILSpy/packages.config
  28. 77
      Mono.Cecil/Mono.Cecil.Cil/MethodBody.cs

5
ICSharpCode.Decompiler/Disassembler/DisassemblerHelpers.cs

@ -373,6 +373,11 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -373,6 +373,11 @@ namespace ICSharpCode.Decompiler.Disassembler
}
}
public static void WriteOperand(ITextOutput writer, long val)
{
writer.Write(ToInvariantCultureString(val));
}
public static void WriteOperand(ITextOutput writer, float val)
{
if (val == 0) {

2
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -78,7 +78,9 @@ @@ -78,7 +78,9 @@
<Compile Include="IL\ILReader.cs" />
<Compile Include="IL\ILTypeExtensions.cs" />
<Compile Include="IL\ILVariable.cs" />
<Compile Include="IL\InstructionOutputExtensions.cs" />
<Compile Include="IL\Instructions\BinaryInstruction.cs" />
<Compile Include="IL\Instructions\Block.cs" />
<Compile Include="IL\Instructions\BranchInstruction.cs" />
<Compile Include="IL\Instructions\CallInstruction.cs" />
<Compile Include="IL\Instructions\ILInstruction.cs" />

440
ICSharpCode.Decompiler/IL/ILReader.cs

@ -9,9 +9,9 @@ using Mono.Cecil; @@ -9,9 +9,9 @@ using Mono.Cecil;
namespace ICSharpCode.Decompiler.IL
{
class ILReader(MethodDefinition method, private Mono.Cecil.Cil.MethodBody body)
public class ILReader(private Mono.Cecil.Cil.MethodBody body)
{
public static ILOpCode ReadOpCode(ref BlobReader reader)
internal static ILOpCode ReadOpCode(ref BlobReader reader)
{
byte b = reader.ReadByte();
if (b == 0xfe)
@ -20,7 +20,7 @@ namespace ICSharpCode.Decompiler.IL @@ -20,7 +20,7 @@ namespace ICSharpCode.Decompiler.IL
return (ILOpCode)b;
}
public static MetadataToken ReadMetadataToken(ref BlobReader reader)
internal static MetadataToken ReadMetadataToken(ref BlobReader reader)
{
return new MetadataToken(reader.ReadUInt32());
}
@ -28,6 +28,8 @@ namespace ICSharpCode.Decompiler.IL @@ -28,6 +28,8 @@ namespace ICSharpCode.Decompiler.IL
ImmutableArray<ILInstruction>.Builder instructionBuilder = ImmutableArray.CreateBuilder<ILInstruction>();
BlobReader reader = body.GetILReader();
Stack<StackType> stack = new Stack<StackType>(body.MaxStackSize);
ILVariable[] parameterVariables;
ILVariable[] localVariables;
IMetadataTokenProvider ReadAndDecodeMetadataToken()
{
@ -35,11 +37,13 @@ namespace ICSharpCode.Decompiler.IL @@ -35,11 +37,13 @@ namespace ICSharpCode.Decompiler.IL
return body.LookupToken(token);
}
void ReadInstructions()
public ImmutableArray<ILInstruction> ReadInstructions()
{
//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);
@ -65,11 +69,12 @@ namespace ICSharpCode.Decompiler.IL @@ -65,11 +69,12 @@ namespace ICSharpCode.Decompiler.IL
}
}
}
}
return instructionBuilder.ToImmutable();
}
private bool IsUnconditionalBranch(OpCode opCode)
{
return opCode == OpCode.Branch;
return opCode == OpCode.Branch || opCode == OpCode.Ret || opCode == OpCode.Leave;
}
ILInstruction DecodeInstruction()
@ -78,8 +83,6 @@ namespace ICSharpCode.Decompiler.IL @@ -78,8 +83,6 @@ namespace ICSharpCode.Decompiler.IL
switch (ilOpCode) {
case ILOpCode.Constrained:
return DecodeConstrainedCall();
case ILOpCode.Nop:
return DecodeNoPrefix();
case ILOpCode.Readonly:
throw new NotImplementedException(); // needs ldelema
case ILOpCode.Tailcall:
@ -89,13 +92,13 @@ namespace ICSharpCode.Decompiler.IL @@ -89,13 +92,13 @@ namespace ICSharpCode.Decompiler.IL
case ILOpCode.Volatile:
return DecodeVolatile();
case ILOpCode.Add:
return DecodeBinaryNumericInstruction(OpCode.Add);
return BinaryNumeric(OpCode.Add);
case ILOpCode.Add_Ovf:
return DecodeBinaryNumericInstruction(OpCode.Add, OverflowMode.Ovf);
return BinaryNumeric(OpCode.Add, OverflowMode.Ovf);
case ILOpCode.Add_Ovf_Un:
return DecodeBinaryNumericInstruction(OpCode.Add, OverflowMode.Ovf_Un);
return BinaryNumeric(OpCode.Add, OverflowMode.Ovf_Un);
case ILOpCode.And:
return DecodeBinaryNumericInstruction(OpCode.BitAnd);
return BinaryNumeric(OpCode.BitAnd);
case ILOpCode.Arglist:
stack.Push(StackType.O);
return new SimpleInstruction(OpCode.Arglist);
@ -140,9 +143,9 @@ namespace ICSharpCode.Decompiler.IL @@ -140,9 +143,9 @@ namespace ICSharpCode.Decompiler.IL
case ILOpCode.Bne_Un_S:
return DecodeComparisonBranch(true, OpCode.Ceq, OpCode.Ceq, true);
case ILOpCode.Br:
return DecodeUnconditionalBranch(false);
return DecodeUnconditionalBranch(false, OpCode.Branch);
case ILOpCode.Br_S:
return DecodeUnconditionalBranch(true);
return DecodeUnconditionalBranch(true, OpCode.Branch);
case ILOpCode.Break:
return new SimpleInstruction(OpCode.Break);
case ILOpCode.Brfalse:
@ -155,92 +158,94 @@ namespace ICSharpCode.Decompiler.IL @@ -155,92 +158,94 @@ namespace ICSharpCode.Decompiler.IL
return DecodeConditionalBranch(true, false);
case ILOpCode.Call:
return DecodeCall(OpCode.Call);
case ILOpCode.Callvirt:
return DecodeCall(OpCode.CallVirt);
case ILOpCode.Calli:
throw new NotImplementedException();
case ILOpCode.Ceq:
return DecodeComparison(OpCode.Ceq, OpCode.Ceq);
return Comparison(OpCode.Ceq, OpCode.Ceq);
case ILOpCode.Cgt:
return DecodeComparison(OpCode.Cgt, OpCode.Cgt);
return Comparison(OpCode.Cgt, OpCode.Cgt);
case ILOpCode.Cgt_Un:
return DecodeComparison(OpCode.Cgt_Un, OpCode.Cgt_Un);
return Comparison(OpCode.Cgt_Un, OpCode.Cgt_Un);
case ILOpCode.Clt:
return DecodeComparison(OpCode.Clt, OpCode.Clt);
return Comparison(OpCode.Clt, OpCode.Clt);
case ILOpCode.Clt_Un:
return DecodeComparison(OpCode.Clt_Un, OpCode.Clt_Un);
return Comparison(OpCode.Clt_Un, OpCode.Clt_Un);
case ILOpCode.Ckfinite:
return new PeekInstruction(OpCode.Ckfinite);
case ILOpCode.Conv_I1:
return DecodeConv(PrimitiveType.I1, OverflowMode.None);
return Conv(PrimitiveType.I1, OverflowMode.None);
case ILOpCode.Conv_I2:
return DecodeConv(PrimitiveType.I2, OverflowMode.None);
return Conv(PrimitiveType.I2, OverflowMode.None);
case ILOpCode.Conv_I4:
return DecodeConv(PrimitiveType.I4, OverflowMode.None);
return Conv(PrimitiveType.I4, OverflowMode.None);
case ILOpCode.Conv_I8:
return DecodeConv(PrimitiveType.I8, OverflowMode.None);
return Conv(PrimitiveType.I8, OverflowMode.None);
case ILOpCode.Conv_R4:
return DecodeConv(PrimitiveType.R4, OverflowMode.None);
return Conv(PrimitiveType.R4, OverflowMode.None);
case ILOpCode.Conv_R8:
return DecodeConv(PrimitiveType.R8, OverflowMode.None);
return Conv(PrimitiveType.R8, OverflowMode.None);
case ILOpCode.Conv_U1:
return DecodeConv(PrimitiveType.U1, OverflowMode.None);
return Conv(PrimitiveType.U1, OverflowMode.None);
case ILOpCode.Conv_U2:
return DecodeConv(PrimitiveType.U2, OverflowMode.None);
return Conv(PrimitiveType.U2, OverflowMode.None);
case ILOpCode.Conv_U4:
return DecodeConv(PrimitiveType.U4, OverflowMode.None);
return Conv(PrimitiveType.U4, OverflowMode.None);
case ILOpCode.Conv_U8:
return DecodeConv(PrimitiveType.U8, OverflowMode.None);
return Conv(PrimitiveType.U8, OverflowMode.None);
case ILOpCode.Conv_I:
return DecodeConv(PrimitiveType.I, OverflowMode.None);
return Conv(PrimitiveType.I, OverflowMode.None);
case ILOpCode.Conv_U:
return DecodeConv(PrimitiveType.U, OverflowMode.None);
return Conv(PrimitiveType.U, OverflowMode.None);
case ILOpCode.Conv_R_Un:
return DecodeConv(PrimitiveType.R8, OverflowMode.Un);
return Conv(PrimitiveType.R8, OverflowMode.Un);
case ILOpCode.Conv_Ovf_I1:
return DecodeConv(PrimitiveType.I1, OverflowMode.Ovf);
return Conv(PrimitiveType.I1, OverflowMode.Ovf);
case ILOpCode.Conv_Ovf_I2:
return DecodeConv(PrimitiveType.I2, OverflowMode.Ovf);
return Conv(PrimitiveType.I2, OverflowMode.Ovf);
case ILOpCode.Conv_Ovf_I4:
return DecodeConv(PrimitiveType.I4, OverflowMode.Ovf);
return Conv(PrimitiveType.I4, OverflowMode.Ovf);
case ILOpCode.Conv_Ovf_I8:
return DecodeConv(PrimitiveType.I8, OverflowMode.Ovf);
return Conv(PrimitiveType.I8, OverflowMode.Ovf);
case ILOpCode.Conv_Ovf_U1:
return DecodeConv(PrimitiveType.U1, OverflowMode.Ovf);
return Conv(PrimitiveType.U1, OverflowMode.Ovf);
case ILOpCode.Conv_Ovf_U2:
return DecodeConv(PrimitiveType.U2, OverflowMode.Ovf);
return Conv(PrimitiveType.U2, OverflowMode.Ovf);
case ILOpCode.Conv_Ovf_U4:
return DecodeConv(PrimitiveType.U4, OverflowMode.Ovf);
return Conv(PrimitiveType.U4, OverflowMode.Ovf);
case ILOpCode.Conv_Ovf_U8:
return DecodeConv(PrimitiveType.U8, OverflowMode.Ovf);
return Conv(PrimitiveType.U8, OverflowMode.Ovf);
case ILOpCode.Conv_Ovf_I:
return DecodeConv(PrimitiveType.I, OverflowMode.Ovf);
return Conv(PrimitiveType.I, OverflowMode.Ovf);
case ILOpCode.Conv_Ovf_U:
return DecodeConv(PrimitiveType.U, OverflowMode.Ovf);
return Conv(PrimitiveType.U, OverflowMode.Ovf);
case ILOpCode.Conv_Ovf_I1_Un:
return DecodeConv(PrimitiveType.I1, OverflowMode.Ovf_Un);
return Conv(PrimitiveType.I1, OverflowMode.Ovf_Un);
case ILOpCode.Conv_Ovf_I2_Un:
return DecodeConv(PrimitiveType.I2, OverflowMode.Ovf_Un);
return Conv(PrimitiveType.I2, OverflowMode.Ovf_Un);
case ILOpCode.Conv_Ovf_I4_Un:
return DecodeConv(PrimitiveType.I4, OverflowMode.Ovf_Un);
return Conv(PrimitiveType.I4, OverflowMode.Ovf_Un);
case ILOpCode.Conv_Ovf_I8_Un:
return DecodeConv(PrimitiveType.I8, OverflowMode.Ovf_Un);
return Conv(PrimitiveType.I8, OverflowMode.Ovf_Un);
case ILOpCode.Conv_Ovf_U1_Un:
return DecodeConv(PrimitiveType.U1, OverflowMode.Ovf_Un);
return Conv(PrimitiveType.U1, OverflowMode.Ovf_Un);
case ILOpCode.Conv_Ovf_U2_Un:
return DecodeConv(PrimitiveType.U2, OverflowMode.Ovf_Un);
return Conv(PrimitiveType.U2, OverflowMode.Ovf_Un);
case ILOpCode.Conv_Ovf_U4_Un:
return DecodeConv(PrimitiveType.U4, OverflowMode.Ovf_Un);
return Conv(PrimitiveType.U4, OverflowMode.Ovf_Un);
case ILOpCode.Conv_Ovf_U8_Un:
return DecodeConv(PrimitiveType.U8, OverflowMode.Ovf_Un);
return Conv(PrimitiveType.U8, OverflowMode.Ovf_Un);
case ILOpCode.Conv_Ovf_I_Un:
return DecodeConv(PrimitiveType.I, OverflowMode.Ovf_Un);
return Conv(PrimitiveType.I, OverflowMode.Ovf_Un);
case ILOpCode.Conv_Ovf_U_Un:
return DecodeConv(PrimitiveType.U, OverflowMode.Ovf_Un);
return Conv(PrimitiveType.U, OverflowMode.Ovf_Un);
case ILOpCode.Cpblk:
throw new NotImplementedException();
case ILOpCode.Div:
return DecodeBinaryNumericInstruction(OpCode.Div, OverflowMode.None);
return BinaryNumeric(OpCode.Div, OverflowMode.None);
case ILOpCode.Div_Un:
return DecodeBinaryNumericInstruction(OpCode.Div, OverflowMode.Un);
return BinaryNumeric(OpCode.Div, OverflowMode.Un);
case ILOpCode.Dup:
return new PeekInstruction(OpCode.Peek);
case ILOpCode.Endfilter:
@ -251,11 +256,293 @@ namespace ICSharpCode.Decompiler.IL @@ -251,11 +256,293 @@ namespace ICSharpCode.Decompiler.IL
throw new NotImplementedException();
case ILOpCode.Jmp:
throw new NotImplementedException();
case ILOpCode.Ldarg:
return Ldarg(reader.ReadUInt16());
case ILOpCode.Ldarg_S:
return Ldarg(reader.ReadByte());
case ILOpCode.Ldarg_0:
case ILOpCode.Ldarg_1:
case ILOpCode.Ldarg_2:
case ILOpCode.Ldarg_3:
return Ldarg(ilOpCode - ILOpCode.Ldarg_0);
case ILOpCode.Ldarga:
return Ldarga(reader.ReadUInt16());
case ILOpCode.Ldarga_S:
return Ldarga(reader.ReadByte());
case ILOpCode.Ldc_I4:
return LdcI4(reader.ReadInt32());
case ILOpCode.Ldc_I8:
return LdcI8(reader.ReadInt64());
case ILOpCode.Ldc_R4:
return LdcF(reader.ReadSingle());
case ILOpCode.Ldc_R8:
return LdcF(reader.ReadDouble());
case ILOpCode.Ldc_I4_M1:
case ILOpCode.Ldc_I4_0:
case ILOpCode.Ldc_I4_1:
case ILOpCode.Ldc_I4_2:
case ILOpCode.Ldc_I4_3:
case ILOpCode.Ldc_I4_4:
case ILOpCode.Ldc_I4_5:
case ILOpCode.Ldc_I4_6:
case ILOpCode.Ldc_I4_7:
case ILOpCode.Ldc_I4_8:
return LdcI4(ilOpCode - ILOpCode.Ldc_I4_0);
case ILOpCode.Ldc_I4_S:
return LdcI4(reader.ReadSByte());
case ILOpCode.Ldnull:
stack.Push(StackType.O);
return new SimpleInstruction(OpCode.LdNull);
case ILOpCode.Ldstr:
return DecodeLdstr();
case ILOpCode.Ldftn:
throw new NotImplementedException();
case ILOpCode.Ldind_I1:
case ILOpCode.Ldind_I2:
case ILOpCode.Ldind_I4:
case ILOpCode.Ldind_I8:
case ILOpCode.Ldind_U1:
case ILOpCode.Ldind_U2:
case ILOpCode.Ldind_U4:
case ILOpCode.Ldind_R4:
case ILOpCode.Ldind_R8:
case ILOpCode.Ldind_I:
case ILOpCode.Ldind_Ref:
throw new NotImplementedException();
case ILOpCode.Ldloc:
return Ldloc(reader.ReadUInt16());
case ILOpCode.Ldloc_S:
return Ldloc(reader.ReadByte());
case ILOpCode.Ldloc_0:
case ILOpCode.Ldloc_1:
case ILOpCode.Ldloc_2:
case ILOpCode.Ldloc_3:
return Ldloc(ilOpCode - ILOpCode.Ldloc_0);
case ILOpCode.Ldloca:
return Ldloca(reader.ReadUInt16());
case ILOpCode.Ldloca_S:
return Ldloca(reader.ReadByte());
case ILOpCode.Leave:
return DecodeUnconditionalBranch(false, OpCode.Leave);
case ILOpCode.Leave_S:
return DecodeUnconditionalBranch(true, OpCode.Leave);
case ILOpCode.Localloc:
throw new NotImplementedException();
case ILOpCode.Mul:
return BinaryNumeric(OpCode.Mul, OverflowMode.None);
case ILOpCode.Mul_Ovf:
return BinaryNumeric(OpCode.Mul, OverflowMode.Ovf);
case ILOpCode.Mul_Ovf_Un:
return BinaryNumeric(OpCode.Mul, OverflowMode.Ovf_Un);
case ILOpCode.Neg:
return UnaryNumeric(OpCode.Neg);
case ILOpCode.Nop:
return new SimpleInstruction(OpCode.Nop);
case ILOpCode.Not:
return UnaryNumeric(OpCode.BitNot);
case ILOpCode.Or:
return BinaryNumeric(OpCode.BitOr);
case ILOpCode.Pop:
stack.PopOrDefault();
return new UnaryInstruction(OpCode.Void);
case ILOpCode.Rem:
return BinaryNumeric(OpCode.Rem, OverflowMode.None);
case ILOpCode.Rem_Un:
return BinaryNumeric(OpCode.Rem, OverflowMode.Un);
case ILOpCode.Ret:
return Ret();
case ILOpCode.Shl:
return Shift(OpCode.Shl);
case ILOpCode.Shr:
return Shift(OpCode.Shr);
case ILOpCode.Shr_Un:
return Shift(OpCode.Shl, OverflowMode.Un);
case ILOpCode.Starg:
return Starg(reader.ReadUInt16());
case ILOpCode.Starg_S:
return Starg(reader.ReadByte());
case ILOpCode.Stind_I1:
case ILOpCode.Stind_I2:
case ILOpCode.Stind_I4:
case ILOpCode.Stind_I8:
case ILOpCode.Stind_R4:
case ILOpCode.Stind_R8:
case ILOpCode.Stind_I:
case ILOpCode.Stind_Ref:
throw new NotImplementedException();
case ILOpCode.Stloc:
return Stloc(reader.ReadUInt16());
case ILOpCode.Stloc_S:
return Stloc(reader.ReadByte());
case ILOpCode.Stloc_0:
case ILOpCode.Stloc_1:
case ILOpCode.Stloc_2:
case ILOpCode.Stloc_3:
return Stloc(ilOpCode - ILOpCode.Stloc_0);
case ILOpCode.Box:
throw new NotImplementedException();
case ILOpCode.Castclass:
throw new NotImplementedException();
case ILOpCode.Cpobj:
throw new NotImplementedException();
case ILOpCode.Initobj:
throw new NotImplementedException();
case ILOpCode.Isinst:
throw new NotImplementedException();
case ILOpCode.Ldelem:
case ILOpCode.Ldelem_I1:
case ILOpCode.Ldelem_I2:
case ILOpCode.Ldelem_I4:
case ILOpCode.Ldelem_I8:
case ILOpCode.Ldelem_U1:
case ILOpCode.Ldelem_U2:
case ILOpCode.Ldelem_U4:
case ILOpCode.Ldelem_R4:
case ILOpCode.Ldelem_R8:
case ILOpCode.Ldelem_I:
case ILOpCode.Ldelem_Ref:
throw new NotImplementedException();
case ILOpCode.Ldelema:
throw new NotImplementedException();
case ILOpCode.Ldfld:
throw new NotImplementedException();
case ILOpCode.Ldflda:
throw new NotImplementedException();
case ILOpCode.Stfld:
throw new NotImplementedException();
case ILOpCode.Ldlen:
throw new NotImplementedException();
case ILOpCode.Ldobj:
throw new NotImplementedException();
case ILOpCode.Ldsfld:
throw new NotImplementedException();
case ILOpCode.Ldsflda:
throw new NotImplementedException();
case ILOpCode.Stsfld:
throw new NotImplementedException();
case ILOpCode.Ldtoken:
throw new NotImplementedException();
case ILOpCode.Ldvirtftn:
throw new NotImplementedException();
case ILOpCode.Mkrefany:
throw new NotImplementedException();
case ILOpCode.Newarr:
throw new NotImplementedException();
case ILOpCode.Refanytype:
throw new NotImplementedException();
case ILOpCode.Refanyval:
throw new NotImplementedException();
case ILOpCode.Rethrow:
throw new NotImplementedException();
case ILOpCode.Sizeof:
throw new NotImplementedException();
case ILOpCode.Stelem:
case ILOpCode.Stelem_I1:
case ILOpCode.Stelem_I2:
case ILOpCode.Stelem_I4:
case ILOpCode.Stelem_I8:
case ILOpCode.Stelem_R4:
case ILOpCode.Stelem_R8:
case ILOpCode.Stelem_I:
case ILOpCode.Stelem_Ref:
throw new NotImplementedException();
case ILOpCode.Stobj:
throw new NotImplementedException();
case ILOpCode.Throw:
throw new NotImplementedException();
case ILOpCode.Unbox:
case ILOpCode.Unbox_Any:
throw new NotImplementedException();
default:
return InvalidInstruction();
throw new NotImplementedException(ilOpCode.ToString());
}
}
private ILInstruction Shift(OpCode opCode, OverflowMode overflowMode = OverflowMode.None)
{
var shiftAmountType = stack.PopOrDefault();
var valueType = stack.PopOrDefault();
stack.Push(valueType);
return new BinaryNumericInstruction(opCode, valueType, overflowMode);
}
private ILInstruction Ret()
{
if (body.Method.ReturnType.GetStackType() == StackType.Void)
return new SimpleInstruction(OpCode.Ret);
else
return new UnaryInstruction(OpCode.Ret);
}
private ILInstruction UnaryNumeric(OpCode opCode)
{
var opType = stack.PopOrDefault();
stack.Push(opType);
return new UnaryNumericInstruction(opCode, opType);
}
private ILInstruction DecodeLdstr()
{
stack.Push(StackType.O);
var metadataToken = ReadMetadataToken(ref reader);
return new ConstantStringInstruction(body.LookupStringToken(metadataToken));
}
private ILInstruction LdcI4(int val)
{
stack.Push(StackType.I4);
return new ConstantI4Instruction(val);
}
private ILInstruction LdcI8(long val)
{
stack.Push(StackType.I8);
return new ConstantI8Instruction(val);
}
private ILInstruction LdcF(double val)
{
stack.Push(StackType.F);
return new ConstantFloatInstruction(val);
}
private ILInstruction Ldarg(ushort v)
{
stack.Push(parameterVariables[v].Type.GetStackType());
return new LoadVarInstruction(parameterVariables[v]);
}
private ILInstruction Ldarga(ushort v)
{
stack.Push(StackType.Ref);
return new LoadVarInstruction(parameterVariables[v], OpCode.LoadVarAddress);
}
private ILInstruction Starg(ushort v)
{
stack.PopOrDefault();
return new StoreVarInstruction(parameterVariables[v]);
}
private ILInstruction Ldloc(ushort v)
{
stack.Push(localVariables[v].Type.GetStackType());
return new LoadVarInstruction(localVariables[v]);
}
private ILInstruction Ldloca(ushort v)
{
stack.Push(StackType.Ref);
return new LoadVarInstruction(localVariables[v], OpCode.LoadVarAddress);
}
private ILInstruction Stloc(ushort v)
{
stack.PopOrDefault();
return new StoreVarInstruction(localVariables[v]);
}
private ILInstruction DecodeConstrainedCall()
{
var typeRef = ReadAndDecodeMetadataToken() as TypeReference;
@ -290,31 +577,26 @@ namespace ICSharpCode.Decompiler.IL @@ -290,31 +577,26 @@ namespace ICSharpCode.Decompiler.IL
return inst;
}
/// <summary>no prefix -- possibly skip a fault check</summary>
private ILInstruction DecodeNoPrefix()
{
var flags = (NoPrefixFlags)reader.ReadByte();
var inst = DecodeInstruction();
if ((var snp = inst as ISupportsNoPrefix) != null)
snp.NoPrefix = flags;
return inst;
}
private ILInstruction DecodeConv(PrimitiveType targetType, OverflowMode mode)
private ILInstruction Conv(PrimitiveType targetType, OverflowMode mode)
{
StackType from = stack.PopOrDefault();
return new ConvInstruction(from, targetType, mode);
}
ILInstruction DecodeCall(OpCode call)
ILInstruction DecodeCall(OpCode opCode)
{
var token = ReadMetadataToken(ref reader);
var methodRef = body.LookupToken(token);
// TODO: we need the decoded + (in case of generic calls) type substituted
throw new NotImplementedException();
var method = (MethodReference)ReadAndDecodeMetadataToken();
int numPopCalls = Math.Min(stack.Count, method.GetPopAmount());
for (int i = 0; i < numPopCalls; i++) {
stack.Pop();
}
var returnType = method.ReturnType.GetStackType();
if (returnType != StackType.Void)
stack.Push(returnType);
return new CallInstruction(opCode, method);
}
ILInstruction DecodeComparison(OpCode opCode_I, OpCode opCode_F)
ILInstruction Comparison(OpCode opCode_I, OpCode opCode_F)
{
StackType right = stack.PopOrDefault();
StackType left = stack.PopOrDefault();
@ -331,7 +613,7 @@ namespace ICSharpCode.Decompiler.IL @@ -331,7 +613,7 @@ namespace ICSharpCode.Decompiler.IL
ILInstruction DecodeComparisonBranch(bool shortForm, OpCode comparisonOpCodeForInts, OpCode comparisonOpCodeForFloats, bool negate)
{
int start = reader.Position - 1;
var condition = DecodeComparison(comparisonOpCodeForInts, comparisonOpCodeForFloats);
var condition = Comparison(comparisonOpCodeForInts, comparisonOpCodeForFloats);
int target = start + (shortForm ? reader.ReadSByte() : reader.ReadInt32());
condition.ILRange = new Interval(start, reader.Position);
if (negate) {
@ -351,14 +633,14 @@ namespace ICSharpCode.Decompiler.IL @@ -351,14 +633,14 @@ namespace ICSharpCode.Decompiler.IL
return new ConditionalBranchInstruction(condition, target);
}
ILInstruction DecodeUnconditionalBranch(bool shortForm)
ILInstruction DecodeUnconditionalBranch(bool shortForm, OpCode opCode)
{
int start = reader.Position - 1;
int target = start + (shortForm ? reader.ReadSByte() : reader.ReadInt32());
return new BranchInstruction(OpCode.Branch, target);
return new BranchInstruction(opCode, target);
}
ILInstruction DecodeBinaryNumericInstruction(OpCode opCode, OverflowMode overflowMode = OverflowMode.None)
ILInstruction BinaryNumeric(OpCode opCode, OverflowMode overflowMode = OverflowMode.None)
{
StackType right = stack.PopOrDefault();
StackType left = stack.PopOrDefault();
@ -386,11 +668,5 @@ namespace ICSharpCode.Decompiler.IL @@ -386,11 +668,5 @@ namespace ICSharpCode.Decompiler.IL
stack.Push(StackType.Unknown);
return new BinaryNumericInstruction(opCode, StackType.Unknown, overflowMode);
}
ILInstruction InvalidInstruction()
{
Debug.Fail("This should only happen in obfuscated code");
return new SimpleInstruction(OpCode.Invalid);
}
}
}

5
ICSharpCode.Decompiler/IL/ILTypeExtensions.cs

@ -20,6 +20,11 @@ namespace ICSharpCode.Decompiler.IL @@ -20,6 +20,11 @@ namespace ICSharpCode.Decompiler.IL
return ImmutableArray.Create(result);
}*/
public static int GetPopAmount(this MethodReference methodRef)
{
return methodRef.Parameters.Count + (methodRef.HasThis ? 1 : 0);
}
public static StackType GetStackType(this TypeReference typeRef)
{
return typeRef.SkipModifiers().MetadataType.GetStackType();

28
ICSharpCode.Decompiler/IL/ILVariable.cs

@ -1,4 +1,6 @@ @@ -1,4 +1,6 @@
using System;
using Mono.Cecil;
using Mono.Cecil.Cil;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@ -12,8 +14,28 @@ namespace ICSharpCode.Decompiler.IL @@ -12,8 +14,28 @@ namespace ICSharpCode.Decompiler.IL
Parameter,
}
class ILVariable(public readonly VariableKind Kind, public readonly int Index)
class ILVariable(public readonly VariableKind Kind, public readonly TypeReference Type, public readonly int Index)
{
public ILVariable(VariableDefinition v)
: this(VariableKind.Local, v.VariableType, v.Index)
{
}
public ILVariable(ParameterDefinition p)
: this(VariableKind.Parameter, p.ParameterType, p.Index)
{
}
public override string ToString()
{
switch (Kind) {
case VariableKind.Local:
return "V_" + Index.ToString();
case VariableKind.Parameter:
return "P_" + Index.ToString();
default:
return Kind.ToString();
}
}
}
}

34
ICSharpCode.Decompiler/IL/InstructionOutputExtensions.cs

@ -0,0 +1,34 @@ @@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ICSharpCode.Decompiler.IL
{
static class InstructionOutputExtensions
{
public static void Write(this ITextOutput output, OpCode opCode)
{
output.Write(opCode.ToString().ToLowerInvariant());
}
public static void Write(this ITextOutput output, StackType stackType)
{
output.Write(stackType.ToString().ToLowerInvariant());
}
public static void Write(this ITextOutput output, PrimitiveType primitiveType)
{
output.Write(primitiveType.ToString().ToLowerInvariant());
}
public static void WriteSuffix(this ITextOutput output, OverflowMode mode)
{
if ((mode & OverflowMode.Ovf) != 0)
output.Write(".ovf");
if ((mode & OverflowMode.Un) != 0)
output.Write(".un");
}
}
}

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

@ -19,12 +19,33 @@ namespace ICSharpCode.Decompiler.IL @@ -19,12 +19,33 @@ namespace ICSharpCode.Decompiler.IL
{
public readonly StackType OpType = opType;
public readonly OverflowMode OverflowMode = overflowMode;
public override void WriteTo(ITextOutput output)
{
output.Write(OpCode);
output.WriteSuffix(OverflowMode);
output.Write(' ');
output.Write(OpType);
Left.WriteTo(output);
output.Write(", ");
Right.WriteTo(output);
output.Write(')');
}
}
class BinaryComparisonInstruction(OpCode opCode, StackType opType)
: BinaryInstruction(opCode)
{
public readonly StackType OpType = opType;
public override void WriteTo(ITextOutput output)
{
output.Write("{0}.{1}(", OpCode, OpType);
Left.WriteTo(output);
output.Write(", ");
Right.WriteTo(output);
output.Write(')');
}
}
public enum OverflowMode : byte

12
ICSharpCode.Decompiler/IL/Instructions/Block.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.Instructions
{
class Block
{
}
}

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

@ -12,6 +12,13 @@ namespace ICSharpCode.Decompiler.IL @@ -12,6 +12,13 @@ namespace ICSharpCode.Decompiler.IL
class BranchInstruction(OpCode opCode, public int TargetILOffset) : ILInstruction(opCode)
{
public override bool IsPeeking { get { return false; } }
public override void WriteTo(ITextOutput output)
{
output.Write(OpCode.ToString());
output.Write(' ');
output.WriteReference(CecilExtensions.OffsetToString(TargetILOffset), TargetILOffset, isLocal: true);
}
}
/// <summary>
@ -21,5 +28,13 @@ namespace ICSharpCode.Decompiler.IL @@ -21,5 +28,13 @@ namespace ICSharpCode.Decompiler.IL
class ConditionalBranchInstruction(public ILInstruction Condition, int targetILOffset) : BranchInstruction(OpCode.ConditionalBranch, targetILOffset)
{
public override bool IsPeeking { get { return Condition.IsPeeking; } }
public override void WriteTo(ITextOutput output)
{
base.WriteTo(output);
output.Write('(');
Condition.WriteTo(output);
output.Write(')');
}
}
}

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

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
using Mono.Cecil;
using ICSharpCode.Decompiler.Disassembler;
using Mono.Cecil;
using System;
using System.Collections.Generic;
using System.Linq;
@ -14,7 +15,7 @@ namespace ICSharpCode.Decompiler.IL @@ -14,7 +15,7 @@ namespace ICSharpCode.Decompiler.IL
static ILInstruction[] InitOperands(MethodReference mr)
{
ILInstruction[] operands = new ILInstruction[mr.Parameters.Count];
ILInstruction[] operands = new ILInstruction[mr.GetPopAmount()];
for (int i = 0; i < operands.Length; i++) {
operands[i] = Pop;
}
@ -33,5 +34,25 @@ namespace ICSharpCode.Decompiler.IL @@ -33,5 +34,25 @@ namespace ICSharpCode.Decompiler.IL
/// Returns null if no 'constrained.' prefix exists for this call.
/// </summary>
public TypeReference ConstrainedTo;
public override void WriteTo(ITextOutput output)
{
if (ConstrainedTo != null) {
output.Write("constrained.");
ConstrainedTo.WriteTo(output, ILNameSyntax.ShortTypeName);
}
if (IsTail)
output.Write("tail.");
output.Write(OpCode);
output.Write(' ');
Method.WriteTo(output);
output.Write('(');
for (int i = 0; i < Operands.Length; i++) {
if (i > 0)
output.Write(", ");
Operands[i].WriteTo(output);
}
output.Write(')');
}
}
}

4
ICSharpCode.Decompiler/IL/Instructions/ILInstruction.cs

@ -9,7 +9,7 @@ namespace ICSharpCode.Decompiler.IL @@ -9,7 +9,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>
/// Represents a decoded IL instruction
/// </summary>
abstract class ILInstruction(public readonly OpCode OpCode)
public abstract class ILInstruction(public readonly OpCode OpCode)
{
public static readonly ILInstruction Nop = new SimpleInstruction(OpCode.Nop);
public static readonly ILInstruction Pop = new SimpleInstruction(OpCode.Pop);
@ -25,5 +25,7 @@ namespace ICSharpCode.Decompiler.IL @@ -25,5 +25,7 @@ namespace ICSharpCode.Decompiler.IL
/// left after the pop operations.
/// </summary>
public abstract bool IsPeeking { get; }
public abstract void WriteTo(ITextOutput output);
}
}

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

@ -6,7 +6,7 @@ using System.Threading.Tasks; @@ -6,7 +6,7 @@ using System.Threading.Tasks;
namespace ICSharpCode.Decompiler.IL
{
enum OpCode
public enum OpCode
{
/// <summary>
/// A instruction that could not be decoded correctly.
@ -31,7 +31,7 @@ namespace ICSharpCode.Decompiler.IL @@ -31,7 +31,7 @@ namespace ICSharpCode.Decompiler.IL
/// Ignore the arguments and produce void. Used to prevent the end result of an instruction
/// from being pushed to the evaluation stack.
/// </summary>
Drop,
Void,
/// <summary>
/// Unary operator that expects an input of type I4.
/// Return 1 (of type I4) if the input value is 0. Otherwise, return 0 (of type I4).
@ -43,10 +43,42 @@ namespace ICSharpCode.Decompiler.IL @@ -43,10 +43,42 @@ namespace ICSharpCode.Decompiler.IL
/// </summary>
Add,
/// <summary>
/// Subtracts two numbers. <see cref="BinaryNumericInstruction"/>
/// </summary>
Sub,
/// <summary>
/// Multiplies two numbers. <see cref="BinaryNumericInstruction"/>
/// </summary>
Mul,
/// <summary>
/// Division. <see cref="BinaryNumericInstruction"/>
/// </summary>
Div,
/// <summary>
/// Division remainder. <see cref="BinaryNumericInstruction"/>
/// </summary>
Rem,
/// <summary>
/// Unary negation. <see cref="UnaryInstruction"/>
/// </summary>
Neg,
/// <summary>
/// Bitwise AND. <see cref="BinaryNumericInstruction"/>
/// </summary>
BitAnd,
/// <summary>
/// Bitwise OR. <see cref="BinaryNumericInstruction"/>
/// </summary>
BitOr,
/// <summary>
/// Bitwise XOR. <see cref="BinaryNumericInstruction"/>
/// </summary>
BitXor,
/// <summary>
/// Bitwise NOT. <see cref="UnaryNumericInstruction"/>
/// </summary>
BitNot,
/// <summary>
/// Retrieves the RuntimeArgumentHandle
/// </summary>
Arglist,
@ -60,6 +92,7 @@ namespace ICSharpCode.Decompiler.IL @@ -60,6 +92,7 @@ namespace ICSharpCode.Decompiler.IL
/// <see cref="BranchInstruction"/>
/// </summary>
Branch,
Leave,
/// <summary>
/// Breakpoint instruction.
/// </summary>
@ -102,9 +135,66 @@ namespace ICSharpCode.Decompiler.IL @@ -102,9 +135,66 @@ namespace ICSharpCode.Decompiler.IL
/// Call a method.
/// </summary>
Call,
/// <summary>
/// Call a method using virtual dispatch.
/// </summary>
CallVirt,
/// <summary>
/// Checks that the float on top of the stack is not NaN or infinite.
/// </summary>
Ckfinite,
/// <summary>
/// Numeric cast. <see cref="ConvInstruction"/>
/// </summary>
Conv,
Div,
/// <summary>
/// Loads the value of a variable. (ldarg/ldloc)
/// <see cref="LoadVarInstruction"/>
/// </summary>
LoadVar,
/// <summary>
/// Loads the address of a variable as managed ref. (ldarga/ldloca)
/// <see cref="LoadVarInstruction"/>
/// </summary>
LoadVarAddress,
/// <summary>
/// Stores a value into a variable. (starg/stloc)
/// <see cref="StoreVarInstruction"/>
/// </summary>
StoreVar,
/// <summary>
/// Loads a constant string. <see cref="ConstantStringInstruction"/>
/// </summary>
LdStr,
/// <summary>
/// Loads a constant 32-bit integer. <see cref="ConstantI4Instruction"/>
/// </summary>
LdcI4,
/// <summary>
/// Loads a constant 64-bit integer. <see cref="ConstantI8Instruction"/>
/// </summary>
LdcI8,
/// <summary>
/// Loads a constant floating point number. <see cref="ConstantFloatInstruction"/>
/// </summary>
LdcF,
/// <summary>
/// Loads a null reference.
/// </summary>
LdNull,
/// <summary>
/// Returns from the current method or lambda.
/// <see cref="UnaryInstruction"/> or <see cref="SimpleInstruction"/>, depending on whether
/// the method has return type void.
/// </summary>
Ret,
/// <summary>
/// Shift left. <see cref="BinaryNumericInstruction"/>
/// </summary>
Shl,
/// <summary>
/// Shift right. <see cref="BinaryNumericInstruction"/>
/// </summary>
Shr,
}
}

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

@ -18,18 +18,4 @@ namespace ICSharpCode.Decompiler.IL @@ -18,18 +18,4 @@ namespace ICSharpCode.Decompiler.IL
/// </summary>
bool IsVolatile { get; set; }
}
[Flags]
enum NoPrefixFlags : byte
{
None = 0,
TypeCheck = 0x01,
RangeCheck = 0x02,
NullCheck = 0x04,
}
interface ISupportsNoPrefix
{
NoPrefixFlags NoPrefix { get; set; }
}
}

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

@ -12,10 +12,52 @@ namespace ICSharpCode.Decompiler.IL @@ -12,10 +12,52 @@ namespace ICSharpCode.Decompiler.IL
class SimpleInstruction(OpCode opCode) : ILInstruction(opCode)
{
public override bool IsPeeking { get { return false; } }
public override void WriteTo(ITextOutput output)
{
output.Write(OpCode);
}
}
class PeekInstruction(OpCode opCode = OpCode.Peek) : ILInstruction(opCode)
{
public override bool IsPeeking { get { return true; } }
public override void WriteTo(ITextOutput output)
{
output.Write(OpCode);
}
}
class ConstantStringInstruction(public readonly string Value) : SimpleInstruction(OpCode.LdStr)
{
public override void WriteTo(ITextOutput output)
{
Disassembler.DisassemblerHelpers.WriteOperand(output, Value);
}
}
class ConstantI4Instruction(public readonly int Value) : SimpleInstruction(OpCode.LdcI4)
{
public override void WriteTo(ITextOutput output)
{
Disassembler.DisassemblerHelpers.WriteOperand(output, Value);
}
}
class ConstantI8Instruction(public readonly long Value) : SimpleInstruction(OpCode.LdcI8)
{
public override void WriteTo(ITextOutput output)
{
Disassembler.DisassemblerHelpers.WriteOperand(output, Value);
}
}
class ConstantFloatInstruction(public readonly double Value) : SimpleInstruction(OpCode.LdcI8)
{
public override void WriteTo(ITextOutput output)
{
Disassembler.DisassemblerHelpers.WriteOperand(output, Value);
}
}
}

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

@ -6,20 +6,55 @@ using System.Threading.Tasks; @@ -6,20 +6,55 @@ using System.Threading.Tasks;
namespace ICSharpCode.Decompiler.IL
{
abstract class UnaryInstruction(OpCode opCode) : ILInstruction(opCode)
class UnaryInstruction(OpCode opCode) : ILInstruction(opCode)
{
public ILInstruction Operand = Pop;
public override bool IsPeeking { get { return Operand.IsPeeking; } }
public override void WriteTo(ITextOutput output)
{
output.Write(OpCode);
output.Write('(');
Operand.WriteTo(output);
output.Write(')');
}
}
class LogicNotInstruction() : UnaryInstruction(OpCode.LogicNot)
{
}
class UnaryNumericInstruction(OpCode opCode, StackType opType) : UnaryInstruction(opCode)
{
public readonly StackType OpType = opType;
public override void WriteTo(ITextOutput output)
{
output.Write(OpCode);
output.Write(' ');
output.Write(OpType);
output.Write('(');
Operand.WriteTo(output);
output.Write(')');
}
}
class ConvInstruction(
public readonly StackType FromType, public readonly PrimitiveType ToType, public readonly OverflowMode ConvMode
) : UnaryInstruction(OpCode.Conv)
{
public override void WriteTo(ITextOutput output)
{
output.Write(OpCode);
output.WriteSuffix(ConvMode);
output.Write(' ');
output.Write(FromType);
output.Write("->");
output.Write(ToType);
output.Write('(');
Operand.WriteTo(output);
output.Write(')');
}
}
}

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

@ -4,10 +4,31 @@ using System.Linq; @@ -4,10 +4,31 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ICSharpCode.Decompiler.IL.Instructions
namespace ICSharpCode.Decompiler.IL
{
class LoadVarInstruction(public readonly ILVariable Variable) : ILInstruction(OpCode.LoadVar)
class LoadVarInstruction(public readonly ILVariable Variable, OpCode opCode = OpCode.LoadVar) : ILInstruction(opCode)
{
public override bool IsPeeking { get { return false; } }
public override void WriteTo(ITextOutput output)
{
if (OpCode != OpCode.LoadVar) {
output.Write(OpCode);
output.Write(' ');
}
output.WriteReference(Variable.ToString(), Variable, isLocal: true);
}
}
class StoreVarInstruction(public readonly ILVariable Variable) : UnaryInstruction(OpCode.StoreVar)
{
public override bool IsPeeking { get { return false; } }
public override void WriteTo(ITextOutput output)
{
output.WriteReference(Variable.ToString(), Variable, isLocal: true);
output.Write(" = ");
Operand.WriteTo(output);
}
}
}

4
ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj

@ -53,6 +53,10 @@ @@ -53,6 +53,10 @@
<HintPath>..\..\packages\NUnit.2.6.3\lib\nunit.framework.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Collections.Immutable, Version=1.1.22.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\..\packages\Microsoft.Bcl.Immutable.1.1.22-beta\lib\portable-net45+win8+wpa81\System.Collections.Immutable.dll</HintPath>
</Reference>
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>

1
ICSharpCode.Decompiler/Tests/packages.config

@ -1,5 +1,6 @@ @@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="DiffLib" version="1.0.0.55" />
<package id="Microsoft.Bcl.Immutable" version="1.1.22-beta" targetFramework="net45" />
<package id="NUnit" version="2.6.3" targetFramework="net45" />
</packages>

2
ICSharpCode.Decompiler/Util/Interval.cs

@ -11,7 +11,7 @@ namespace ICSharpCode.Decompiler @@ -11,7 +11,7 @@ namespace ICSharpCode.Decompiler
/// Represents a half-open interval.
/// The start position is inclusive; but the end position is exclusive.
/// </summary>
struct Interval
public struct Interval
{
public static readonly Interval Empty = new Interval(0, 0);

5
ILSpy/App.xaml.cs

@ -87,14 +87,13 @@ namespace ICSharpCode.ILSpy @@ -87,14 +87,13 @@ namespace ICSharpCode.ILSpy
compositionContainer = new CompositionContainer(catalog);
Languages.Initialize(compositionContainer);
if (!System.Diagnostics.Debugger.IsAttached) {
AppDomain.CurrentDomain.UnhandledException += ShowErrorBox;
Dispatcher.CurrentDispatcher.UnhandledException += Dispatcher_UnhandledException;
}
TaskScheduler.UnobservedTaskException += DotNet40_UnobservedTaskException;
Languages.Initialize(compositionContainer);
EventManager.RegisterClassHandler(typeof(Window),
Hyperlink.RequestNavigateEvent,
new RequestNavigateEventHandler(Window_RequestNavigate));

6
ILSpy/ILSpy.csproj

@ -23,6 +23,7 @@ @@ -23,6 +23,7 @@
<AssemblyOriginatorKeyFile>..\NRefactory\ICSharpCode.NRefactory.snk</AssemblyOriginatorKeyFile>
<DelaySign>False</DelaySign>
<AssemblyOriginatorKeyMode>File</AssemblyOriginatorKeyMode>
<LangVersion>experimental</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Platform)' == 'x86' ">
<PlatformTarget>x86</PlatformTarget>
@ -57,6 +58,7 @@ @@ -57,6 +58,7 @@
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|AnyCPU'">
<Prefer32Bit>false</Prefer32Bit>
<UseVSHostingProcess>false</UseVSHostingProcess>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<Prefer32Bit>false</Prefer32Bit>
@ -78,6 +80,10 @@ @@ -78,6 +80,10 @@
<RequiredTargetFramework>3.0</RequiredTargetFramework>
</Reference>
<Reference Include="System" />
<Reference Include="System.Collections.Immutable, Version=1.1.22.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Microsoft.Bcl.Immutable.1.1.22-beta\lib\portable-net45+win8+wpa81\System.Collections.Immutable.dll</HintPath>
</Reference>
<Reference Include="System.ComponentModel.Composition">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>

71
ILSpy/Languages/ILAstLanguage.cs

@ -15,34 +15,29 @@ @@ -15,34 +15,29 @@
// 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;
using System.Linq;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.Decompiler.ILAst;
using ICSharpCode.Decompiler.IL;
using Mono.Cecil;
namespace ICSharpCode.ILSpy
{
#if DEBUG
#if DEBUG
/// <summary>
/// Represents the ILAst "language" used for debugging purposes.
/// </summary>
sealed class ILAstLanguage : Language
abstract class ILAstLanguage(string name) : Language
{
string name;
bool inlineVariables = true;
ILAstOptimizationStep? abortBeforeStep;
public override string Name {
get {
return name;
}
}
//ILAstOptimizationStep? abortBeforeStep;
public override string Name { get; } = name;
/*
public override void DecompileMethod(MethodDefinition method, ITextOutput output, DecompilationOptions options)
{
if (!method.HasBody) {
@ -82,32 +77,50 @@ namespace ICSharpCode.ILSpy @@ -82,32 +77,50 @@ namespace ICSharpCode.ILSpy
node.WriteTo(output);
output.WriteLine();
}
}
}*/
internal static IEnumerable<ILAstLanguage> GetDebugLanguages()
{
yield return new ILAstLanguage { name = "ILAst (unoptimized)", inlineVariables = false };
string nextName = "ILAst (variable splitting)";
foreach (ILAstOptimizationStep step in Enum.GetValues(typeof(ILAstOptimizationStep))) {
yield return new ILAstLanguage { name = nextName, abortBeforeStep = step };
nextName = "ILAst (after " + step + ")";
}
yield return new TypedIL();
//yield return new ILAstLanguage { name = "ILAst (unoptimized)", inlineVariables = false };
//string nextName = "ILAst (variable splitting)";
//foreach (ILAstOptimizationStep step in Enum.GetValues(typeof(ILAstOptimizationStep))) {
// yield return new ILAstLanguage { name = nextName, abortBeforeStep = step };
// nextName = "ILAst (after " + step + ")";
//}
}
public override string FileExtension {
get {
public override string FileExtension
{
get
{
return ".il";
}
}
public override string TypeToString(TypeReference t, bool includeNamespace, ICustomAttributeProvider attributeProvider = null)
{
PlainTextOutput output = new PlainTextOutput();
t.WriteTo(output, includeNamespace ? ILNameSyntax.TypeName : ILNameSyntax.ShortTypeName);
return output.ToString();
}
}
#endif
class TypedIL() : ILAstLanguage("Typed IL")
{
public override void DecompileMethod(MethodDefinition method, ITextOutput output, DecompilationOptions options)
{
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();
}
}
}
}
#endif
}
*/

9
ILSpy/Languages/ILLanguage.cs

@ -21,6 +21,7 @@ using System.Collections.Generic; @@ -21,6 +21,7 @@ using System.Collections.Generic;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Disassembler;
using Mono.Cecil;
using System.ComponentModel.Composition;
namespace ICSharpCode.ILSpy
{
@ -31,14 +32,10 @@ namespace ICSharpCode.ILSpy @@ -31,14 +32,10 @@ namespace ICSharpCode.ILSpy
/// Currently comes in two versions:
/// flat IL (detectControlStructure=false) and structured IL (detectControlStructure=true).
/// </remarks>
[Export(typeof(Language))]
public class ILLanguage : Language
{
private readonly bool detectControlStructure;
public ILLanguage(bool detectControlStructure)
{
this.detectControlStructure = detectControlStructure;
}
private readonly bool detectControlStructure = true;
public override string Name {
get { return "IL"; }

3
ILSpy/Languages/Languages.cs

@ -40,9 +40,8 @@ namespace ICSharpCode.ILSpy @@ -40,9 +40,8 @@ namespace ICSharpCode.ILSpy
{
List<Language> languages = new List<Language>();
languages.AddRange(composition.GetExportedValues<Language>());
languages.Add(new ILLanguage(true));
#if DEBUG
//languages.AddRange(ILAstLanguage.GetDebugLanguages());
languages.AddRange(ILAstLanguage.GetDebugLanguages());
//languages.AddRange(CSharpLanguage.GetDebugLanguages());
#endif
allLanguages = languages.AsReadOnly();

2
ILSpy/Properties/app.config.template

@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="ICSharpCode.AvalonEdit" publicKeyToken="9cc39be672370310" culture="neutral"/>
<bindingRedirect oldVersion="4.1.0.0-99.9.9.9" newVersion="4.2.0.8752"/>
<bindingRedirect oldVersion="4.1.0.0-99.9.9.9" newVersion="4.4.2.9744"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="ICSharpCode.NRefactory" publicKeyToken="d4bfe873e7598c49" culture="neutral"/>

39
ILSpy/TextView/DecompilerTextView.cs

@ -460,35 +460,16 @@ namespace ICSharpCode.ILSpy.TextView @@ -460,35 +460,16 @@ namespace ICSharpCode.ILSpy.TextView
Thread thread = new Thread(new ThreadStart(
delegate {
#if DEBUG
if (System.Diagnostics.Debugger.IsAttached) {
try {
AvalonEditTextOutput textOutput = new AvalonEditTextOutput();
textOutput.LengthLimit = outputLengthLimit;
DecompileNodes(context, textOutput);
textOutput.PrepareDocument();
tcs.SetResult(textOutput);
} catch (OutputLengthExceededException ex) {
tcs.SetException(ex);
} catch (AggregateException ex) {
tcs.SetException(ex.InnerExceptions);
} catch (OperationCanceledException) {
tcs.SetCanceled();
}
} else
#endif
{
try {
AvalonEditTextOutput textOutput = new AvalonEditTextOutput();
textOutput.LengthLimit = outputLengthLimit;
DecompileNodes(context, textOutput);
textOutput.PrepareDocument();
tcs.SetResult(textOutput);
} catch (OperationCanceledException) {
tcs.SetCanceled();
} catch (Exception ex) {
tcs.SetException(ex);
}
try {
AvalonEditTextOutput textOutput = new AvalonEditTextOutput();
textOutput.LengthLimit = outputLengthLimit;
DecompileNodes(context, textOutput);
textOutput.PrepareDocument();
tcs.SetResult(textOutput);
} catch (OperationCanceledException) {
tcs.SetCanceled();
} catch (Exception ex) {
tcs.SetException(ex);
}
}));
thread.Start();

1
ILSpy/packages.config

@ -1,4 +1,5 @@ @@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="AvalonEdit" version="4.4.2.9744" targetFramework="net45" />
<package id="Microsoft.Bcl.Immutable" version="1.1.22-beta" targetFramework="net45" />
</packages>

77
Mono.Cecil/Mono.Cecil.Cil/MethodBody.cs

@ -33,7 +33,8 @@ using Mono.Collections.Generic; @@ -33,7 +33,8 @@ using Mono.Collections.Generic;
namespace Mono.Cecil.Cil {
public sealed class MethodBody : IVariableDefinitionProvider {
public sealed class MethodBody : IVariableDefinitionProvider
{
readonly internal MethodDefinition method;
@ -49,90 +50,103 @@ namespace Mono.Cecil.Cil { @@ -49,90 +50,103 @@ namespace Mono.Cecil.Cil {
internal Collection<VariableDefinition> variables;
Scope scope;
public MethodDefinition Method {
public MethodDefinition Method
{
get { return method; }
}
public int MaxStackSize {
public int MaxStackSize
{
get { return max_stack_size; }
set { max_stack_size = value; }
}
public int CodeSize {
public int CodeSize
{
get { return code_size; }
}
public bool InitLocals {
public bool InitLocals
{
get { return init_locals; }
set { init_locals = value; }
}
public MetadataToken LocalVarToken {
public MetadataToken LocalVarToken
{
get { return local_var_token; }
set { local_var_token = value; }
}
public Collection<Instruction> Instructions {
get { return instructions ?? (instructions = new InstructionCollection ()); }
public Collection<Instruction> Instructions
{
get { return instructions ?? (instructions = new InstructionCollection()); }
}
public bool HasExceptionHandlers {
get { return !exceptions.IsNullOrEmpty (); }
public bool HasExceptionHandlers
{
get { return !exceptions.IsNullOrEmpty(); }
}
public Collection<ExceptionHandler> ExceptionHandlers {
get { return exceptions ?? (exceptions = new Collection<ExceptionHandler> ()); }
public Collection<ExceptionHandler> ExceptionHandlers
{
get { return exceptions ?? (exceptions = new Collection<ExceptionHandler>()); }
}
public bool HasVariables {
get { return !variables.IsNullOrEmpty (); }
public bool HasVariables
{
get { return !variables.IsNullOrEmpty(); }
}
public Collection<VariableDefinition> Variables {
get { return variables ?? (variables = new VariableDefinitionCollection ()); }
public Collection<VariableDefinition> Variables
{
get { return variables ?? (variables = new VariableDefinitionCollection()); }
}
public Scope Scope {
public Scope Scope
{
get { return scope; }
set { scope = value; }
}
public ParameterDefinition ThisParameter {
get {
public ParameterDefinition ThisParameter
{
get
{
if (method == null || method.DeclaringType == null)
throw new NotSupportedException ();
throw new NotSupportedException();
if (!method.HasThis)
return null;
if (this_parameter == null)
Interlocked.CompareExchange (ref this_parameter, ThisParameterFor (method), null);
Interlocked.CompareExchange(ref this_parameter, ThisParameterFor(method), null);
return this_parameter;
}
}
static ParameterDefinition ThisParameterFor (MethodDefinition method)
static ParameterDefinition ThisParameterFor(MethodDefinition method)
{
var declaring_type = method.DeclaringType;
var type = declaring_type.IsValueType || declaring_type.IsPrimitive
? new PointerType (declaring_type)
? new PointerType(declaring_type)
: declaring_type as TypeReference;
return new ParameterDefinition (type, method);
return new ParameterDefinition(type, method);
}
public MethodBody (MethodDefinition method)
public MethodBody(MethodDefinition method)
{
this.method = method;
}
public ILProcessor GetILProcessor ()
public ILProcessor GetILProcessor()
{
return new ILProcessor (this);
return new ILProcessor(this);
}
public BlobReader GetILReader ()
public BlobReader GetILReader()
{
return code_reader;
}
@ -144,7 +158,12 @@ namespace Mono.Cecil.Cil { @@ -144,7 +158,12 @@ namespace Mono.Cecil.Cil {
return reader.LookupToken(t);
});
}
}
public string LookupStringToken(MetadataToken token)
{
return method.Module.Image.UserStringHeap.Read(token.RID);
}
}
public interface IVariableDefinitionProvider {
bool HasVariables { get; }

Loading…
Cancel
Save