Browse Source

Include operands in ILAst output

pull/728/head
Daniel Grunwald 11 years ago
parent
commit
3a3220ccc2
  1. 23
      ICSharpCode.Decompiler/IL/ILReader.cs
  2. 202
      ICSharpCode.Decompiler/IL/Instructions.cs
  3. 60
      ICSharpCode.Decompiler/IL/Instructions.tt
  4. 10
      ICSharpCode.Decompiler/IL/Instructions/BinaryComparisonInstruction.cs
  5. 43
      ICSharpCode.Decompiler/IL/Instructions/ILInstruction.cs

23
ICSharpCode.Decompiler/IL/ILReader.cs

@ -24,6 +24,7 @@ using System.Threading.Tasks; @@ -24,6 +24,7 @@ using System.Threading.Tasks;
using System.Collections.Immutable;
using System.Diagnostics;
using Mono.Cecil;
using Cil = Mono.Cecil.Cil;
using System.Collections;
using System.Threading;
@ -45,7 +46,7 @@ namespace ICSharpCode.Decompiler.IL @@ -45,7 +46,7 @@ namespace ICSharpCode.Decompiler.IL
return new MetadataToken(reader.ReadUInt32());
}
readonly Mono.Cecil.Cil.MethodBody body;
readonly Cil.MethodBody body;
readonly CancellationToken cancellationToken;
readonly TypeSystem typeSystem;
@ -56,7 +57,7 @@ namespace ICSharpCode.Decompiler.IL @@ -56,7 +57,7 @@ namespace ICSharpCode.Decompiler.IL
BitArray isBranchTarget;
List<ILInstruction> instructionBuilder;
public ILReader(Mono.Cecil.Cil.MethodBody body, CancellationToken cancellationToken)
public ILReader(Cil.MethodBody body, CancellationToken cancellationToken)
{
if (body == null)
throw new ArgumentNullException("body");
@ -101,7 +102,23 @@ namespace ICSharpCode.Decompiler.IL @@ -101,7 +102,23 @@ namespace ICSharpCode.Decompiler.IL
isBranchTarget = new BitArray(body.CodeSize);
stack.Clear();
branchStackDict.Clear();
// Fill isBranchTarget and branchStackDict based on exception handlers
foreach (var eh in body.ExceptionHandlers) {
isBranchTarget[eh.TryStart.Offset] = true;
if (eh.FilterStart != null) {
isBranchTarget[eh.FilterStart.Offset] = true;
branchStackDict[eh.FilterStart.Offset] = ImmutableArray.Create(StackType.O);
}
if (eh.HandlerStart != null) {
isBranchTarget[eh.HandlerStart.Offset] = true;
if (eh.HandlerType == Cil.ExceptionHandlerType.Catch || eh.HandlerType == Cil.ExceptionHandlerType.Filter)
branchStackDict[eh.HandlerStart.Offset] = ImmutableArray.Create(StackType.O);
else
branchStackDict[eh.HandlerStart.Offset] = ImmutableArray<StackType>.Empty;
}
}
while (reader.Position < reader.Length) {
cancellationToken.ThrowIfCancellationRequested();
int start = reader.Position;

202
ICSharpCode.Decompiler/IL/Instructions.cs

@ -167,12 +167,12 @@ namespace ICSharpCode.Decompiler.IL @@ -167,12 +167,12 @@ namespace ICSharpCode.Decompiler.IL
{
this.resultType = resultType;
}
StackType resultType;
public override StackType ResultType { get { return resultType; } }
protected override InstructionFlags ComputeFlags()
{
return InstructionFlags.MayPeek;
}
StackType resultType;
public override StackType ResultType { get { return resultType; } }
public override T AcceptVisitor<T>(ILVisitor<T> visitor)
{
return visitor.VisitPeek(this);
@ -270,11 +270,11 @@ namespace ICSharpCode.Decompiler.IL @@ -270,11 +270,11 @@ namespace ICSharpCode.Decompiler.IL
public Div(ILInstruction left, ILInstruction right, OverflowMode overflowMode) : base(OpCode.Div, left, right, overflowMode)
{
}
protected override InstructionFlags ComputeFlags()
{
return base.ComputeFlags() | InstructionFlags.MayThrow;
}
public override T AcceptVisitor<T>(ILVisitor<T> visitor)
{
return visitor.VisitDiv(this);
@ -287,11 +287,11 @@ namespace ICSharpCode.Decompiler.IL @@ -287,11 +287,11 @@ namespace ICSharpCode.Decompiler.IL
public Rem(ILInstruction left, ILInstruction right, OverflowMode overflowMode) : base(OpCode.Rem, left, right, overflowMode)
{
}
protected override InstructionFlags ComputeFlags()
{
return base.ComputeFlags() | InstructionFlags.MayThrow;
}
public override T AcceptVisitor<T>(ILVisitor<T> visitor)
{
return visitor.VisitRem(this);
@ -366,11 +366,11 @@ namespace ICSharpCode.Decompiler.IL @@ -366,11 +366,11 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Unconditional branch. <c>goto target;</c></summary>
public sealed partial class Branch : SimpleInstruction
{
public override StackType ResultType { get { return StackType.Void; } }
protected override InstructionFlags ComputeFlags()
{
return InstructionFlags.EndPointUnreachable | InstructionFlags.MayBranch;
}
public override StackType ResultType { get { return StackType.Void; } }
public override T AcceptVisitor<T>(ILVisitor<T> visitor)
{
return visitor.VisitBranch(this);
@ -393,11 +393,11 @@ namespace ICSharpCode.Decompiler.IL @@ -393,11 +393,11 @@ namespace ICSharpCode.Decompiler.IL
public DebugBreak() : base(OpCode.DebugBreak)
{
}
public override StackType ResultType { get { return StackType.Void; } }
protected override InstructionFlags ComputeFlags()
{
return InstructionFlags.SideEffect;
}
public override StackType ResultType { get { return StackType.Void; } }
public override T AcceptVisitor<T>(ILVisitor<T> visitor)
{
return visitor.VisitDebugBreak(this);
@ -501,11 +501,11 @@ namespace ICSharpCode.Decompiler.IL @@ -501,11 +501,11 @@ namespace ICSharpCode.Decompiler.IL
public Ckfinite() : base(OpCode.Ckfinite)
{
}
public override StackType ResultType { get { return StackType.Void; } }
protected override InstructionFlags ComputeFlags()
{
return InstructionFlags.MayPeek | InstructionFlags.MayThrow;
}
public override StackType ResultType { get { return StackType.Void; } }
public override T AcceptVisitor<T>(ILVisitor<T> visitor)
{
return visitor.VisitCkfinite(this);
@ -533,6 +533,12 @@ namespace ICSharpCode.Decompiler.IL @@ -533,6 +533,12 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Returns the variable operand.</summary>
public ILVariable Variable { get { return variable; } }
public override StackType ResultType { get { return variable.Type.GetStackType(); } }
public override void WriteTo(ITextOutput output)
{
output.Write(OpCode);
output.Write(' ');
variable.WriteTo(output);
}
public override T AcceptVisitor<T>(ILVisitor<T> visitor)
{
return visitor.VisitLdLoc(this);
@ -550,6 +556,12 @@ namespace ICSharpCode.Decompiler.IL @@ -550,6 +556,12 @@ namespace ICSharpCode.Decompiler.IL
readonly ILVariable variable;
/// <summary>Returns the variable operand.</summary>
public ILVariable Variable { get { return variable; } }
public override void WriteTo(ITextOutput output)
{
output.Write(OpCode);
output.Write(' ');
variable.WriteTo(output);
}
public override T AcceptVisitor<T>(ILVisitor<T> visitor)
{
return visitor.VisitLdLoca(this);
@ -567,6 +579,15 @@ namespace ICSharpCode.Decompiler.IL @@ -567,6 +579,15 @@ namespace ICSharpCode.Decompiler.IL
readonly ILVariable variable;
/// <summary>Returns the variable operand.</summary>
public ILVariable Variable { get { return variable; } }
public override void WriteTo(ITextOutput output)
{
output.Write(OpCode);
output.Write(' ');
variable.WriteTo(output);
output.Write('(');
Argument.WriteTo(output);
output.Write(')');
}
public override T AcceptVisitor<T>(ILVisitor<T> visitor)
{
return visitor.VisitStLoc(this);
@ -581,13 +602,13 @@ namespace ICSharpCode.Decompiler.IL @@ -581,13 +602,13 @@ namespace ICSharpCode.Decompiler.IL
this.Value = value;
}
public readonly string Value;
public override StackType ResultType { get { return StackType.O; } }
public override void WriteTo(ITextOutput output)
{
output.Write(OpCode);
output.Write(' ');
Disassembler.DisassemblerHelpers.WriteOperand(output, Value);
}
public override StackType ResultType { get { return StackType.O; } }
public override T AcceptVisitor<T>(ILVisitor<T> visitor)
{
return visitor.VisitLdStr(this);
@ -602,13 +623,13 @@ namespace ICSharpCode.Decompiler.IL @@ -602,13 +623,13 @@ namespace ICSharpCode.Decompiler.IL
this.Value = value;
}
public readonly int Value;
public override StackType ResultType { get { return StackType.I4; } }
public override void WriteTo(ITextOutput output)
{
output.Write(OpCode);
output.Write(' ');
Disassembler.DisassemblerHelpers.WriteOperand(output, Value);
}
public override StackType ResultType { get { return StackType.I4; } }
public override T AcceptVisitor<T>(ILVisitor<T> visitor)
{
return visitor.VisitLdcI4(this);
@ -623,13 +644,13 @@ namespace ICSharpCode.Decompiler.IL @@ -623,13 +644,13 @@ namespace ICSharpCode.Decompiler.IL
this.Value = value;
}
public readonly long Value;
public override StackType ResultType { get { return StackType.I8; } }
public override void WriteTo(ITextOutput output)
{
output.Write(OpCode);
output.Write(' ');
Disassembler.DisassemblerHelpers.WriteOperand(output, Value);
}
public override StackType ResultType { get { return StackType.I8; } }
public override T AcceptVisitor<T>(ILVisitor<T> visitor)
{
return visitor.VisitLdcI8(this);
@ -644,13 +665,13 @@ namespace ICSharpCode.Decompiler.IL @@ -644,13 +665,13 @@ namespace ICSharpCode.Decompiler.IL
this.Value = value;
}
public readonly double Value;
public override StackType ResultType { get { return StackType.F; } }
public override void WriteTo(ITextOutput output)
{
output.Write(OpCode);
output.Write(' ');
Disassembler.DisassemblerHelpers.WriteOperand(output, Value);
}
public override StackType ResultType { get { return StackType.F; } }
public override T AcceptVisitor<T>(ILVisitor<T> visitor)
{
return visitor.VisitLdcF(this);
@ -673,11 +694,11 @@ namespace ICSharpCode.Decompiler.IL @@ -673,11 +694,11 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Returns from the current method or lambda.</summary>
public sealed partial class Return : ILInstruction
{
public override StackType ResultType { get { return StackType.Void; } }
protected override InstructionFlags ComputeFlags()
{
return InstructionFlags.MayBranch | InstructionFlags.EndPointUnreachable;
}
public override StackType ResultType { get { return StackType.Void; } }
public override T AcceptVisitor<T>(ILVisitor<T> visitor)
{
return visitor.VisitReturn(this);
@ -717,10 +738,6 @@ namespace ICSharpCode.Decompiler.IL @@ -717,10 +738,6 @@ namespace ICSharpCode.Decompiler.IL
{
this.field = field;
}
protected override InstructionFlags ComputeFlags()
{
return base.ComputeFlags() | InstructionFlags.SideEffect | InstructionFlags.MayThrow;
}
/// <summary>Gets/Sets whether the memory access is volatile.</summary>
public bool IsVolatile { get; set; }
/// <summary>Returns the alignment specified by the 'unaligned' prefix; or 0 if there was no 'unaligned' prefix.</summary>
@ -729,6 +746,23 @@ namespace ICSharpCode.Decompiler.IL @@ -729,6 +746,23 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Returns the field operand.</summary>
public FieldReference Field { get { return field; } }
public override StackType ResultType { get { return field.FieldType.GetStackType(); } }
protected override InstructionFlags ComputeFlags()
{
return base.ComputeFlags() | InstructionFlags.SideEffect | InstructionFlags.MayThrow;
}
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, field);
output.Write('(');
Argument.WriteTo(output);
output.Write(')');
}
public override T AcceptVisitor<T>(ILVisitor<T> visitor)
{
return visitor.VisitLdFld(this);
@ -742,14 +776,23 @@ namespace ICSharpCode.Decompiler.IL @@ -742,14 +776,23 @@ namespace ICSharpCode.Decompiler.IL
{
this.field = field;
}
protected override InstructionFlags ComputeFlags()
{
return base.ComputeFlags() | InstructionFlags.MayThrow;
}
readonly FieldReference field;
/// <summary>Returns the field operand.</summary>
public FieldReference Field { get { return field; } }
public override StackType ResultType { get { return StackType.Ref; } }
protected override InstructionFlags ComputeFlags()
{
return base.ComputeFlags() | InstructionFlags.MayThrow;
}
public override void WriteTo(ITextOutput output)
{
output.Write(OpCode);
output.Write(' ');
Disassembler.DisassemblerHelpers.WriteOperand(output, field);
output.Write('(');
Argument.WriteTo(output);
output.Write(')');
}
public override T AcceptVisitor<T>(ILVisitor<T> visitor)
{
return visitor.VisitLdFlda(this);
@ -763,10 +806,6 @@ namespace ICSharpCode.Decompiler.IL @@ -763,10 +806,6 @@ namespace ICSharpCode.Decompiler.IL
{
this.field = field;
}
protected override InstructionFlags ComputeFlags()
{
return base.ComputeFlags() | InstructionFlags.SideEffect | InstructionFlags.MayThrow;
}
/// <summary>Gets/Sets whether the memory access is volatile.</summary>
public bool IsVolatile { get; set; }
/// <summary>Returns the alignment specified by the 'unaligned' prefix; or 0 if there was no 'unaligned' prefix.</summary>
@ -775,6 +814,25 @@ namespace ICSharpCode.Decompiler.IL @@ -775,6 +814,25 @@ namespace ICSharpCode.Decompiler.IL
readonly FieldReference field;
/// <summary>Returns the field operand.</summary>
public FieldReference Field { get { return field; } }
protected override InstructionFlags ComputeFlags()
{
return base.ComputeFlags() | InstructionFlags.SideEffect | InstructionFlags.MayThrow;
}
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, field);
output.Write('(');
Left.WriteTo(output);
output.Write(", ");
Right.WriteTo(output);
output.Write(')');
}
public override T AcceptVisitor<T>(ILVisitor<T> visitor)
{
return visitor.VisitStFld(this);
@ -788,10 +846,6 @@ namespace ICSharpCode.Decompiler.IL @@ -788,10 +846,6 @@ namespace ICSharpCode.Decompiler.IL
{
this.field = field;
}
protected override InstructionFlags ComputeFlags()
{
return InstructionFlags.SideEffect;
}
/// <summary>Gets/Sets whether the memory access is volatile.</summary>
public bool IsVolatile { get; set; }
/// <summary>Returns the alignment specified by the 'unaligned' prefix; or 0 if there was no 'unaligned' prefix.</summary>
@ -800,6 +854,20 @@ namespace ICSharpCode.Decompiler.IL @@ -800,6 +854,20 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Returns the field operand.</summary>
public FieldReference Field { get { return field; } }
public override StackType ResultType { get { return field.FieldType.GetStackType(); } }
protected override InstructionFlags ComputeFlags()
{
return InstructionFlags.SideEffect;
}
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, field);
}
public override T AcceptVisitor<T>(ILVisitor<T> visitor)
{
return visitor.VisitLdsFld(this);
@ -817,6 +885,12 @@ namespace ICSharpCode.Decompiler.IL @@ -817,6 +885,12 @@ namespace ICSharpCode.Decompiler.IL
readonly FieldReference field;
/// <summary>Returns the field operand.</summary>
public FieldReference Field { get { return field; } }
public override void WriteTo(ITextOutput output)
{
output.Write(OpCode);
output.Write(' ');
Disassembler.DisassemblerHelpers.WriteOperand(output, field);
}
public override T AcceptVisitor<T>(ILVisitor<T> visitor)
{
return visitor.VisitLdsFlda(this);
@ -830,10 +904,6 @@ namespace ICSharpCode.Decompiler.IL @@ -830,10 +904,6 @@ namespace ICSharpCode.Decompiler.IL
{
this.field = field;
}
protected override InstructionFlags ComputeFlags()
{
return base.ComputeFlags() | InstructionFlags.SideEffect;
}
/// <summary>Gets/Sets whether the memory access is volatile.</summary>
public bool IsVolatile { get; set; }
/// <summary>Returns the alignment specified by the 'unaligned' prefix; or 0 if there was no 'unaligned' prefix.</summary>
@ -842,6 +912,23 @@ namespace ICSharpCode.Decompiler.IL @@ -842,6 +912,23 @@ namespace ICSharpCode.Decompiler.IL
readonly FieldReference field;
/// <summary>Returns the field operand.</summary>
public FieldReference Field { get { return field; } }
protected override InstructionFlags ComputeFlags()
{
return base.ComputeFlags() | InstructionFlags.SideEffect;
}
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, field);
output.Write('(');
Argument.WriteTo(output);
output.Write(')');
}
public override T AcceptVisitor<T>(ILVisitor<T> visitor)
{
return visitor.VisitStsFld(this);
@ -859,6 +946,15 @@ namespace ICSharpCode.Decompiler.IL @@ -859,6 +946,15 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Returns the type operand.</summary>
public TypeReference Type { get { return type; } }
public override StackType ResultType { get { return type.GetStackType(); } }
public override void WriteTo(ITextOutput output)
{
output.Write(OpCode);
output.Write(' ');
Disassembler.DisassemblerHelpers.WriteOperand(output, type);
output.Write('(');
Argument.WriteTo(output);
output.Write(')');
}
public override T AcceptVisitor<T>(ILVisitor<T> visitor)
{
return visitor.VisitIsInst(this);
@ -872,10 +968,6 @@ namespace ICSharpCode.Decompiler.IL @@ -872,10 +968,6 @@ namespace ICSharpCode.Decompiler.IL
{
this.type = type;
}
protected override InstructionFlags ComputeFlags()
{
return base.ComputeFlags() | InstructionFlags.SideEffect | InstructionFlags.MayThrow;
}
readonly TypeReference type;
/// <summary>Returns the type operand.</summary>
public TypeReference Type { get { return type; } }
@ -884,6 +976,23 @@ namespace ICSharpCode.Decompiler.IL @@ -884,6 +976,23 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Returns the alignment specified by the 'unaligned' prefix; or 0 if there was no 'unaligned' prefix.</summary>
public byte UnalignedPrefix { get; set; }
public override StackType ResultType { get { return type.GetStackType(); } }
protected override InstructionFlags ComputeFlags()
{
return base.ComputeFlags() | InstructionFlags.SideEffect | InstructionFlags.MayThrow;
}
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, type);
output.Write('(');
Argument.WriteTo(output);
output.Write(')');
}
public override T AcceptVisitor<T>(ILVisitor<T> visitor)
{
return visitor.VisitLdObj(this);
@ -897,14 +1006,23 @@ namespace ICSharpCode.Decompiler.IL @@ -897,14 +1006,23 @@ namespace ICSharpCode.Decompiler.IL
{
this.type = type;
}
protected override InstructionFlags ComputeFlags()
{
return base.ComputeFlags() | InstructionFlags.SideEffect | InstructionFlags.MayThrow;
}
readonly TypeReference type;
/// <summary>Returns the type operand.</summary>
public TypeReference Type { get { return type; } }
public override StackType ResultType { get { return type.GetStackType(); } }
protected override InstructionFlags ComputeFlags()
{
return base.ComputeFlags() | InstructionFlags.SideEffect | InstructionFlags.MayThrow;
}
public override void WriteTo(ITextOutput output)
{
output.Write(OpCode);
output.Write(' ');
Disassembler.DisassemblerHelpers.WriteOperand(output, type);
output.Write('(');
Argument.WriteTo(output);
output.Write(')');
}
public override T AcceptVisitor<T>(ILVisitor<T> visitor)
{
return visitor.VisitUnboxAny(this);
@ -930,11 +1048,11 @@ namespace ICSharpCode.Decompiler.IL @@ -930,11 +1048,11 @@ namespace ICSharpCode.Decompiler.IL
public Throw(ILInstruction argument) : base(OpCode.Throw, argument)
{
}
public override StackType ResultType { get { return StackType.Void; } }
protected override InstructionFlags ComputeFlags()
{
return base.ComputeFlags() | InstructionFlags.MayThrow | InstructionFlags.EndPointUnreachable;
}
public override StackType ResultType { get { return StackType.Void; } }
public override T AcceptVisitor<T>(ILVisitor<T> visitor)
{
return visitor.VisitThrow(this);
@ -947,11 +1065,11 @@ namespace ICSharpCode.Decompiler.IL @@ -947,11 +1065,11 @@ namespace ICSharpCode.Decompiler.IL
public LdLen(ILInstruction argument) : base(OpCode.LdLen, argument)
{
}
public override StackType ResultType { get { return StackType.I; } }
protected override InstructionFlags ComputeFlags()
{
return base.ComputeFlags() | InstructionFlags.MayThrow;
}
public override StackType ResultType { get { return StackType.I; } }
public override T AcceptVisitor<T>(ILVisitor<T> visitor)
{
return visitor.VisitLdLen(this);

60
ICSharpCode.Decompiler/IL/Instructions.tt

@ -147,13 +147,17 @@ namespace ICSharpCode.Decompiler.IL @@ -147,13 +147,17 @@ namespace ICSharpCode.Decompiler.IL
public <#=opCode.Name#>(<#=string.Join(", ", opCode.ConstructorParameters)#>) : base(<#=string.Join(", ", opCode.BaseConstructorArguments)#>)
{<#=Body(opCode.ConstructorBody)#>}
<# } #>
<#=string.Join(Environment.NewLine, opCode.Members.Select(m => "\t\t" + m.Replace("\n", "\n\t\t")))#>
<# if (opCode.GenerateComputeFlags && opCode.Flags.Any(f => f != "base.ComputeFlags()")) { #>
protected override InstructionFlags ComputeFlags()
{
return <#=string.Join(" | ", opCode.Flags)#>;
}
<# } #>
<#=string.Join(Environment.NewLine, opCode.Members.Select(m => "\t\t" + m.Replace("\n", "\n\t\t")))#>
<# if (opCode.GenerateWriteTo) { #>
public override void WriteTo(ITextOutput output)
{<#=Body(opCode.WriteToBody)#>}
<# } #>
public override T AcceptVisitor<T>(ILVisitor<T> visitor)
{
return visitor.Visit<#=opCode.Name#>(this);
@ -219,7 +223,7 @@ namespace ICSharpCode.Decompiler.IL @@ -219,7 +223,7 @@ namespace ICSharpCode.Decompiler.IL
}
<#+
static string Body(List<string> statements)
static string Body(IEnumerable<string> statements)
{
StringBuilder b = new StringBuilder();
foreach (var st in statements) {
@ -269,6 +273,22 @@ namespace ICSharpCode.Decompiler.IL @@ -269,6 +273,22 @@ namespace ICSharpCode.Decompiler.IL
public List<string> Flags = new List<string>();
public bool GenerateComputeFlags = true;
public bool GenerateWriteTo = false;
public List<string> WriteOpCodePrefix = new List<string>();
public List<string> WriteOpCodeSuffix = new List<string>();
public List<string> WriteOperand = new List<string>();
public List<string> WriteArguments = new List<string>();
public IEnumerable<string> WriteToBody {
get {
foreach (string line in WriteOpCodePrefix)
yield return line;
yield return "output.Write(OpCode);";
foreach (string line in WriteOpCodeSuffix.Concat(WriteOperand).Concat(WriteArguments))
yield return line;
}
}
}
static Action<OpCode> CustomClassName(string name)
@ -323,9 +343,6 @@ namespace ICSharpCode.Decompiler.IL @@ -323,9 +343,6 @@ namespace ICSharpCode.Decompiler.IL
// MayBranch trait: the instruction may cause control flow to branch (e.g. branch, conditionalbranch, return)
static Action<OpCode> MayBranch = HasFlag("InstructionFlags.MayBranch");
// HasBranchTarget trait: the instruction has an explicit branch target offset
static Action<OpCode> HasBranchTarget = opCode => {};
// UnconditionalBranch trait: the instruction does not produce a result normally; it always branches or throws an exception. Implies VoidResult.
static Action<OpCode> UnconditionalBranch = VoidResult + HasFlag("InstructionFlags.EndPointUnreachable");
@ -348,6 +365,9 @@ namespace ICSharpCode.Decompiler.IL @@ -348,6 +365,9 @@ namespace ICSharpCode.Decompiler.IL
opCode.Flags.Add("base.ComputeFlags()");
opCode.ConstructorParameters.Add("ILInstruction argument");
opCode.BaseConstructorArguments.Add("argument");
opCode.WriteArguments.Add("output.Write('(');");
opCode.WriteArguments.Add("Argument.WriteTo(output);");
opCode.WriteArguments.Add("output.Write(')');");
};
// Binary trait: the instruction has two arguments named 'Left' and 'Right'
@ -358,6 +378,11 @@ namespace ICSharpCode.Decompiler.IL @@ -358,6 +378,11 @@ namespace ICSharpCode.Decompiler.IL
opCode.ConstructorParameters.Add("ILInstruction right");
opCode.BaseConstructorArguments.Add("left");
opCode.BaseConstructorArguments.Add("right");
opCode.WriteArguments.Add("output.Write('(');");
opCode.WriteArguments.Add("Left.WriteTo(output);");
opCode.WriteArguments.Add("output.Write(\", \");");
opCode.WriteArguments.Add("Right.WriteTo(output);");
opCode.WriteArguments.Add("output.Write(')');");
};
// BinaryNumeric trait: the instruction is derived from BinaryNumericInstruction. Implies Binary; and implies MayThrow if the overflow mode is checked.
@ -366,12 +391,15 @@ namespace ICSharpCode.Decompiler.IL @@ -366,12 +391,15 @@ namespace ICSharpCode.Decompiler.IL
opCode.BaseClass = "BinaryNumericInstruction";
opCode.ConstructorParameters.Add("OverflowMode overflowMode");
opCode.BaseConstructorArguments.Add("overflowMode");
opCode.WriteOpCodeSuffix.Add("output.WriteSuffix(overflowMode);");
};
// BinaryNumeric trait: the instruction is derived from BinaryComparisonInstruction. Implies Binary and I4Result.
static Action<OpCode> BinaryComparison = opCode => {
Binary(opCode);
opCode.BaseClass = "BinaryComparisonInstruction";
opCode.WriteOpCodeSuffix.Add("output.Write('.');");
opCode.WriteOpCodeSuffix.Add("output.Write(OpType);");
};
// SideEffect trait: the instruction has a non-local side effect
@ -392,6 +420,9 @@ namespace ICSharpCode.Decompiler.IL @@ -392,6 +420,9 @@ namespace ICSharpCode.Decompiler.IL
opCode.ConstructorBody.Add("this.variable = variable;");
opCode.Members.Add("/// <summary>Returns the variable operand.</summary>" + Environment.NewLine
+ "public ILVariable Variable { get { return variable; } }");
opCode.GenerateWriteTo = true;
opCode.WriteOperand.Add("output.Write(' ');");
opCode.WriteOperand.Add("variable.WriteTo(output);");
};
static Action<OpCode> HasFieldOperand = opCode => {
@ -400,6 +431,9 @@ namespace ICSharpCode.Decompiler.IL @@ -400,6 +431,9 @@ namespace ICSharpCode.Decompiler.IL
opCode.ConstructorBody.Add("this.field = field;");
opCode.Members.Add("/// <summary>Returns the field operand.</summary>" + Environment.NewLine
+ "public FieldReference Field { get { return field; } }");
opCode.GenerateWriteTo = true;
opCode.WriteOperand.Add("output.Write(' ');");
opCode.WriteOperand.Add("Disassembler.DisassemblerHelpers.WriteOperand(output, field);");
};
static Action<OpCode> HasTypeOperand = opCode => {
@ -408,6 +442,9 @@ namespace ICSharpCode.Decompiler.IL @@ -408,6 +442,9 @@ namespace ICSharpCode.Decompiler.IL
opCode.ConstructorBody.Add("this.type = type;");
opCode.Members.Add("/// <summary>Returns the type operand.</summary>" + Environment.NewLine
+ "public TypeReference Type { get { return type; } }");
opCode.GenerateWriteTo = true;
opCode.WriteOperand.Add("output.Write(' ');");
opCode.WriteOperand.Add("Disassembler.DisassemblerHelpers.WriteOperand(output, type);");
};
// LoadConstant trait: the instruction loads a compile-time constant. Implies NoArguments.
@ -418,12 +455,9 @@ namespace ICSharpCode.Decompiler.IL @@ -418,12 +455,9 @@ namespace ICSharpCode.Decompiler.IL
opCode.ConstructorParameters.Add(operandType + " value");
opCode.Members.Add("public readonly " + operandType + " Value;");
opCode.ConstructorBody.Add("this.Value = value;");
opCode.Members.Add("public override void WriteTo(ITextOutput output)" + Environment.NewLine
+ "{" + Environment.NewLine
+ "\toutput.Write(OpCode);" + Environment.NewLine
+ "\toutput.Write(' ');" + Environment.NewLine
+ "\tDisassembler.DisassemblerHelpers.WriteOperand(output, Value);" + Environment.NewLine
+ "}");
opCode.GenerateWriteTo = true;
opCode.WriteOperand.Add("output.Write(' ');");
opCode.WriteOperand.Add("Disassembler.DisassemblerHelpers.WriteOperand(output, Value);");
};
}
@ -431,11 +465,15 @@ namespace ICSharpCode.Decompiler.IL @@ -431,11 +465,15 @@ namespace ICSharpCode.Decompiler.IL
opCode.Interfaces.Add("ISupportsVolatilePrefix");
opCode.Members.Add("/// <summary>Gets/Sets whether the memory access is volatile.</summary>" + Environment.NewLine
+ "public bool IsVolatile { get; set; }");
opCode.GenerateWriteTo = true;
opCode.WriteOpCodePrefix.Add("if (IsVolatile)" + Environment.NewLine + "\toutput.Write(\"volatile.\");");
};
static Action<OpCode> SupportsUnalignedPrefix = opCode => {
opCode.Interfaces.Add("ISupportsUnalignedPrefix");
opCode.Members.Add("/// <summary>Returns the alignment specified by the 'unaligned' prefix; or 0 if there was no 'unaligned' prefix.</summary>" + Environment.NewLine
+ "public byte UnalignedPrefix { get; set; }");
opCode.GenerateWriteTo = true;
opCode.WriteOpCodePrefix.Add("if (UnalignedPrefix > 0)" + Environment.NewLine + "\toutput.Write(\"unaligned(\" + UnalignedPrefix + \").\");");
};
#>

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

@ -30,9 +30,17 @@ namespace ICSharpCode.Decompiler.IL @@ -30,9 +30,17 @@ namespace ICSharpCode.Decompiler.IL
protected BinaryComparisonInstruction(OpCode opCode, ILInstruction left, ILInstruction right) : base(opCode, left, right)
{
// TODO this.OpType = opType;
this.OpType = ComputeOpType(left.ResultType, right.ResultType);
}
static StackType ComputeOpType(StackType left, StackType right)
{
if (left == StackType.I || right == StackType.I)
return StackType.I;
Debug.Assert(left == right);
return left;
}
public sealed override StackType ResultType {
get {
return StackType.I4;

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

@ -98,6 +98,9 @@ namespace ICSharpCode.Decompiler.IL @@ -98,6 +98,9 @@ namespace ICSharpCode.Decompiler.IL
/// </summary>
public Interval ILRange;
/// <summary>
/// Writes the ILAst to the text output.
/// </summary>
public abstract void WriteTo(ITextOutput output);
public override string ToString()
@ -107,6 +110,9 @@ namespace ICSharpCode.Decompiler.IL @@ -107,6 +110,9 @@ namespace ICSharpCode.Decompiler.IL
return output.ToString();
}
/// <summary>
/// Calls the Visit*-method on the visitor corresponding to the concrete type of this instruction.
/// </summary>
public abstract T AcceptVisitor<T>(ILVisitor<T> visitor);
/// <summary>
@ -131,42 +137,5 @@ namespace ICSharpCode.Decompiler.IL @@ -131,42 +137,5 @@ namespace ICSharpCode.Decompiler.IL
/// <param name="instructionStack">The instruction stack.</param>
/// <param name="finished">Receives 'true' if all open 'pop' or 'peek' placeholders were inlined into; false otherwise.</param>
internal abstract ILInstruction Inline(InstructionFlags flagsBefore, Stack<ILInstruction> instructionStack, out bool finished);
/*
/// <summary>
/// Gets whether this instruction peeks at the top value of the stack.
/// If this instruction also pops elements from the stack, this property refers to the top value
/// left after the pop operations.
/// </summary>
public abstract bool IsPeeking { get; }
/// <summary>
/// Gets whether the instruction produces no result.
/// Instructions without result may not be used as arguments to other instructions;
/// and do not result in a stack push when used as a top-level instruction within a block.
/// </summary>
public virtual bool NoResult
{
get { return false; }
}
/// <summary>
/// Gets whether the end point of this instruction is reachable from the start point.
/// Returns false if the instruction performs an unconditional branch, or always throws an exception.
/// </summary>
public virtual bool IsEndReachable
{
get { return true; }
}
public abstract InstructionFlags Flags { get; }
public virtual void WriteTo(ITextOutput output)
{
output.Write(OpCode);
}
public abstract void TransformChildren(Func<ILInstruction, ILInstruction> transformFunc);
*/
}
}

Loading…
Cancel
Save