Browse Source

Bracket ILAst WriteTo in one place via WriteToCore

The debug-step node bracket (MarkNodeStart/try/finally/MarkNodeEnd) was copied
into every hand-written WriteTo override and re-emitted by the T4 generator, so
a newly added instruction could silently omit it and lose step highlighting with
no compile error or test failure. Seal WriteTo on ILInstruction to apply the
bracket once and delegate to a new abstract WriteToCore; move every override
(hand-written and generated) to WriteToCore without the wrapper. Rendered output
is unchanged -- the marks are no-ops unless the output tracks nodes.

Assisted-by: Claude:claude-opus-4-8:Claude Code
pull/3847/head
Siegfried Pammer 6 days ago committed by Siegfried Pammer
parent
commit
468e3da92c
  1. 887
      ICSharpCode.Decompiler/IL/Instructions.cs
  2. 8
      ICSharpCode.Decompiler/IL/Instructions.tt
  3. 54
      ICSharpCode.Decompiler/IL/Instructions/BinaryNumericInstruction.cs
  4. 60
      ICSharpCode.Decompiler/IL/Instructions/Block.cs
  5. 80
      ICSharpCode.Decompiler/IL/Instructions/BlockContainer.cs
  6. 18
      ICSharpCode.Decompiler/IL/Instructions/Branch.cs
  7. 42
      ICSharpCode.Decompiler/IL/Instructions/CallIndirect.cs
  8. 42
      ICSharpCode.Decompiler/IL/Instructions/CallInstruction.cs
  9. 72
      ICSharpCode.Decompiler/IL/Instructions/Comp.cs
  10. 110
      ICSharpCode.Decompiler/IL/Instructions/CompoundAssignmentInstruction.cs
  11. 78
      ICSharpCode.Decompiler/IL/Instructions/Conv.cs
  12. 58
      ICSharpCode.Decompiler/IL/Instructions/DeconstructInstruction.cs
  13. 24
      ICSharpCode.Decompiler/IL/Instructions/DeconstructResultInstruction.cs
  14. 288
      ICSharpCode.Decompiler/IL/Instructions/DynamicInstructions.cs
  15. 28
      ICSharpCode.Decompiler/IL/Instructions/ExpressionTreeCast.cs
  16. 140
      ICSharpCode.Decompiler/IL/Instructions/ILFunction.cs
  17. 24
      ICSharpCode.Decompiler/IL/Instructions/ILInstruction.cs
  18. 58
      ICSharpCode.Decompiler/IL/Instructions/IfInstruction.cs
  19. 24
      ICSharpCode.Decompiler/IL/Instructions/LdLen.cs
  20. 26
      ICSharpCode.Decompiler/IL/Instructions/Leave.cs
  21. 28
      ICSharpCode.Decompiler/IL/Instructions/LockInstruction.cs
  22. 92
      ICSharpCode.Decompiler/IL/Instructions/MatchInstruction.cs
  23. 98
      ICSharpCode.Decompiler/IL/Instructions/MemoryInstructions.cs
  24. 24
      ICSharpCode.Decompiler/IL/Instructions/NullCoalescingInstruction.cs
  25. 24
      ICSharpCode.Decompiler/IL/Instructions/NullableInstructions.cs
  26. 82
      ICSharpCode.Decompiler/IL/Instructions/SimpleInstruction.cs
  27. 42
      ICSharpCode.Decompiler/IL/Instructions/StringToInt.cs
  28. 84
      ICSharpCode.Decompiler/IL/Instructions/SwitchInstruction.cs
  29. 94
      ICSharpCode.Decompiler/IL/Instructions/TryInstruction.cs
  30. 24
      ICSharpCode.Decompiler/IL/Instructions/UnaryInstruction.cs
  31. 42
      ICSharpCode.Decompiler/IL/Instructions/UsingInstruction.cs

887
ICSharpCode.Decompiler/IL/Instructions.cs

File diff suppressed because it is too large Load Diff

8
ICSharpCode.Decompiler/IL/Instructions.tt

@ -429,12 +429,8 @@ namespace <#=opCode.Namespace#> @@ -429,12 +429,8 @@ namespace <#=opCode.Namespace#>
void OriginalWriteTo(ITextOutput output, ILAstWritingOptions options)
{<#=Body(opCode.WriteToBody)#>}
<# } else { #>
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try {<#=Body(opCode.WriteToBody)#>}
finally { output.MarkNodeEnd(this); }
}
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{<#=Body(opCode.WriteToBody)#>}
<# } #>
<# } #>
<# if (opCode.GenerateAcceptVisitor) { #>

54
ICSharpCode.Decompiler/IL/Instructions/BinaryNumericInstruction.cs

@ -184,42 +184,34 @@ namespace ICSharpCode.Decompiler.IL @@ -184,42 +184,34 @@ namespace ICSharpCode.Decompiler.IL
}
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
WriteILRange(output, options);
output.Write(OpCode);
output.Write("." + GetOperatorName(Operator));
if (CheckForOverflow)
{
WriteILRange(output, options);
output.Write(OpCode);
output.Write("." + GetOperatorName(Operator));
if (CheckForOverflow)
{
output.Write(".ovf");
}
if (Sign == Sign.Unsigned)
{
output.Write(".unsigned");
}
else if (Sign == Sign.Signed)
{
output.Write(".signed");
}
output.Write('.');
output.Write(resultType.ToString().ToLowerInvariant());
if (IsLifted)
{
output.Write(".lifted");
}
output.Write('(');
Left.WriteTo(output, options);
output.Write(", ");
Right.WriteTo(output, options);
output.Write(')');
output.Write(".ovf");
}
if (Sign == Sign.Unsigned)
{
output.Write(".unsigned");
}
else if (Sign == Sign.Signed)
{
output.Write(".signed");
}
finally
output.Write('.');
output.Write(resultType.ToString().ToLowerInvariant());
if (IsLifted)
{
output.MarkNodeEnd(this);
output.Write(".lifted");
}
output.Write('(');
Left.WriteTo(output, options);
output.Write(", ");
Right.WriteTo(output, options);
output.Write(')');
}
}
}

60
ICSharpCode.Decompiler/IL/Instructions/Block.cs

@ -258,47 +258,39 @@ namespace ICSharpCode.Decompiler.IL @@ -258,47 +258,39 @@ namespace ICSharpCode.Decompiler.IL
get { return Disassembler.DisassemblerHelpers.OffsetToString(this.StartILOffset); }
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
WriteILRange(output, options);
output.Write("Block ");
output.WriteLocalReference(Label, this, isDefinition: true);
if (Kind != BlockKind.ControlFlow)
output.Write($" ({Kind})");
if (Parent is BlockContainer)
output.Write(" (incoming: {0})", IncomingEdgeCount);
output.Write(' ');
output.MarkFoldStart("{...}");
output.WriteLine("{");
output.Indent();
int index = 0;
foreach (var inst in Instructions)
{
WriteILRange(output, options);
output.Write("Block ");
output.WriteLocalReference(Label, this, isDefinition: true);
if (Kind != BlockKind.ControlFlow)
output.Write($" ({Kind})");
if (Parent is BlockContainer)
output.Write(" (incoming: {0})", IncomingEdgeCount);
output.Write(' ');
output.MarkFoldStart("{...}");
output.WriteLine("{");
output.Indent();
int index = 0;
foreach (var inst in Instructions)
{
if (options.ShowChildIndexInBlock)
{
output.Write("[" + index + "] ");
index++;
}
inst.WriteTo(output, options);
output.WriteLine();
}
if (finalInstruction.OpCode != OpCode.Nop)
if (options.ShowChildIndexInBlock)
{
output.Write("final: ");
finalInstruction.WriteTo(output, options);
output.WriteLine();
output.Write("[" + index + "] ");
index++;
}
output.Unindent();
output.Write("}");
output.MarkFoldEnd();
inst.WriteTo(output, options);
output.WriteLine();
}
finally
if (finalInstruction.OpCode != OpCode.Nop)
{
output.MarkNodeEnd(this);
output.Write("final: ");
finalInstruction.WriteTo(output, options);
output.WriteLine();
}
output.Unindent();
output.Write("}");
output.MarkFoldEnd();
}
protected override int GetChildCount()

80
ICSharpCode.Decompiler/IL/Instructions/BlockContainer.cs

@ -125,57 +125,49 @@ namespace ICSharpCode.Decompiler.IL @@ -125,57 +125,49 @@ namespace ICSharpCode.Decompiler.IL
entryPoint.IncomingEdgeCount--;
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
WriteILRange(output, options);
output.WriteLocalReference("BlockContainer", this, isDefinition: true);
output.Write(' ');
switch (Kind)
{
case ContainerKind.Loop:
output.Write("(while-true) ");
break;
case ContainerKind.Switch:
output.Write("(switch) ");
break;
case ContainerKind.While:
output.Write("(while) ");
break;
case ContainerKind.DoWhile:
output.Write("(do-while) ");
break;
case ContainerKind.For:
output.Write("(for) ");
break;
}
output.MarkFoldStart("{...}");
output.WriteLine("{");
output.Indent();
foreach (var inst in Blocks)
{
WriteILRange(output, options);
output.WriteLocalReference("BlockContainer", this, isDefinition: true);
output.Write(' ');
switch (Kind)
if (inst.Parent == this)
{
case ContainerKind.Loop:
output.Write("(while-true) ");
break;
case ContainerKind.Switch:
output.Write("(switch) ");
break;
case ContainerKind.While:
output.Write("(while) ");
break;
case ContainerKind.DoWhile:
output.Write("(do-while) ");
break;
case ContainerKind.For:
output.Write("(for) ");
break;
inst.WriteTo(output, options);
}
output.MarkFoldStart("{...}");
output.WriteLine("{");
output.Indent();
foreach (var inst in Blocks)
else
{
if (inst.Parent == this)
{
inst.WriteTo(output, options);
}
else
{
output.Write("stale reference to ");
output.WriteLocalReference(inst.Label, inst);
}
output.WriteLine();
output.WriteLine();
output.Write("stale reference to ");
output.WriteLocalReference(inst.Label, inst);
}
output.Unindent();
output.Write("}");
output.MarkFoldEnd();
}
finally
{
output.MarkNodeEnd(this);
output.WriteLine();
output.WriteLine();
}
output.Unindent();
output.Write("}");
output.MarkFoldEnd();
}
protected override int GetChildCount()

18
ICSharpCode.Decompiler/IL/Instructions/Branch.cs

@ -118,20 +118,12 @@ namespace ICSharpCode.Decompiler.IL @@ -118,20 +118,12 @@ namespace ICSharpCode.Decompiler.IL
}
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
{
WriteILRange(output, options);
output.Write(OpCode);
output.Write(' ');
output.WriteLocalReference(TargetLabel, (object?)targetBlock ?? TargetILOffset);
}
finally
{
output.MarkNodeEnd(this);
}
WriteILRange(output, options);
output.Write(OpCode);
output.Write(' ');
output.WriteLocalReference(TargetLabel, (object?)targetBlock ?? TargetILOffset);
}
}

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

@ -74,36 +74,28 @@ namespace ICSharpCode.Decompiler.IL @@ -74,36 +74,28 @@ namespace ICSharpCode.Decompiler.IL
Debug.Assert(Arguments.Count == FunctionPointerType.ParameterTypes.Length + (IsInstance ? 1 : 0));
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
WriteILRange(output, options);
output.Write("call.indirect ");
FunctionPointerType.ReturnType.WriteTo(output);
output.Write('(');
functionPointer.WriteTo(output, options);
int firstArgument = IsInstance ? 1 : 0;
if (firstArgument == 1)
{
WriteILRange(output, options);
output.Write("call.indirect ");
FunctionPointerType.ReturnType.WriteTo(output);
output.Write('(');
functionPointer.WriteTo(output, options);
int firstArgument = IsInstance ? 1 : 0;
if (firstArgument == 1)
{
output.Write(", ");
Arguments[0].WriteTo(output, options);
}
foreach (var (inst, type) in Arguments.Zip(FunctionPointerType.ParameterTypes, (a, b) => (a, b)))
{
output.Write(", ");
inst.WriteTo(output, options);
output.Write(" : ");
type.WriteTo(output);
}
if (Arguments.Count > 0)
output.Write(')');
output.Write(", ");
Arguments[0].WriteTo(output, options);
}
finally
foreach (var (inst, type) in Arguments.Zip(FunctionPointerType.ParameterTypes, (a, b) => (a, b)))
{
output.MarkNodeEnd(this);
output.Write(", ");
inst.WriteTo(output, options);
output.Write(" : ");
type.WriteTo(output);
}
if (Arguments.Count > 0)
output.Write(')');
}
protected override int GetChildCount()

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

@ -138,36 +138,28 @@ namespace ICSharpCode.Decompiler.IL @@ -138,36 +138,28 @@ namespace ICSharpCode.Decompiler.IL
}
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
WriteILRange(output, options);
if (ConstrainedTo != null)
{
WriteILRange(output, options);
if (ConstrainedTo != null)
{
output.Write("constrained[");
ConstrainedTo.WriteTo(output);
output.Write("].");
}
if (IsTail)
output.Write("tail.");
output.Write(OpCode);
output.Write(' ');
Method.WriteTo(output);
output.Write('(');
for (int i = 0; i < Arguments.Count; i++)
{
if (i > 0)
output.Write(", ");
Arguments[i].WriteTo(output, options);
}
output.Write(')');
output.Write("constrained[");
ConstrainedTo.WriteTo(output);
output.Write("].");
}
finally
if (IsTail)
output.Write("tail.");
output.Write(OpCode);
output.Write(' ');
Method.WriteTo(output);
output.Write('(');
for (int i = 0; i < Arguments.Count; i++)
{
output.MarkNodeEnd(this);
if (i > 0)
output.Write(", ");
Arguments[i].WriteTo(output, options);
}
output.Write(')');
}
protected internal sealed override bool PerformMatch(ILInstruction? other, ref Patterns.Match match)

72
ICSharpCode.Decompiler/IL/Instructions/Comp.cs

@ -179,52 +179,44 @@ namespace ICSharpCode.Decompiler.IL @@ -179,52 +179,44 @@ namespace ICSharpCode.Decompiler.IL
}
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
WriteILRange(output, options);
if (options.UseLogicOperationSugar && MatchLogicNot(out var arg))
{
WriteILRange(output, options);
if (options.UseLogicOperationSugar && MatchLogicNot(out var arg))
{
output.Write("logic.not(");
arg.WriteTo(output, options);
output.Write(')');
return;
}
output.Write(OpCode);
output.Write('.');
output.Write(InputType.ToString().ToLower());
switch (Sign)
{
case Sign.Signed:
output.Write(".signed");
break;
case Sign.Unsigned:
output.Write(".unsigned");
break;
}
switch (LiftingKind)
{
case ComparisonLiftingKind.CSharp:
output.Write(".lifted[C#]");
break;
case ComparisonLiftingKind.ThreeValuedLogic:
output.Write(".lifted[3VL]");
break;
}
output.Write('(');
Left.WriteTo(output, options);
output.Write(' ');
output.Write(Kind.GetToken());
output.Write(' ');
Right.WriteTo(output, options);
output.Write("logic.not(");
arg.WriteTo(output, options);
output.Write(')');
return;
}
finally
output.Write(OpCode);
output.Write('.');
output.Write(InputType.ToString().ToLower());
switch (Sign)
{
output.MarkNodeEnd(this);
case Sign.Signed:
output.Write(".signed");
break;
case Sign.Unsigned:
output.Write(".unsigned");
break;
}
switch (LiftingKind)
{
case ComparisonLiftingKind.CSharp:
output.Write(".lifted[C#]");
break;
case ComparisonLiftingKind.ThreeValuedLogic:
output.Write(".lifted[3VL]");
break;
}
output.Write('(');
Left.WriteTo(output, options);
output.Write(' ');
output.Write(Kind.GetToken());
output.Write(' ');
Right.WriteTo(output, options);
output.Write(')');
}
public static Comp LogicNot(ILInstruction arg)

110
ICSharpCode.Decompiler/IL/Instructions/CompoundAssignmentInstruction.cs

@ -272,43 +272,35 @@ namespace ICSharpCode.Decompiler.IL @@ -272,43 +272,35 @@ namespace ICSharpCode.Decompiler.IL
}
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
WriteILRange(output, options);
output.Write(OpCode);
output.Write("." + BinaryNumericInstruction.GetOperatorName(Operator));
if (CheckForOverflow)
{
WriteILRange(output, options);
output.Write(OpCode);
output.Write("." + BinaryNumericInstruction.GetOperatorName(Operator));
if (CheckForOverflow)
{
output.Write(".ovf");
}
if (Sign == Sign.Unsigned)
{
output.Write(".unsigned");
}
else if (Sign == Sign.Signed)
{
output.Write(".signed");
}
output.Write('.');
output.Write(UnderlyingResultType.ToString().ToLowerInvariant());
if (IsLifted)
{
output.Write(".lifted");
}
base.WriteSuffix(output);
output.Write('(');
Target.WriteTo(output, options);
output.Write(", ");
Value.WriteTo(output, options);
output.Write(')');
output.Write(".ovf");
}
if (Sign == Sign.Unsigned)
{
output.Write(".unsigned");
}
finally
else if (Sign == Sign.Signed)
{
output.MarkNodeEnd(this);
output.Write(".signed");
}
output.Write('.');
output.Write(UnderlyingResultType.ToString().ToLowerInvariant());
if (IsLifted)
{
output.Write(".lifted");
}
base.WriteSuffix(output);
output.Write('(');
Target.WriteTo(output, options);
output.Write(", ");
Value.WriteTo(output, options);
output.Write(')');
}
}
@ -344,26 +336,18 @@ namespace ICSharpCode.Decompiler.IL @@ -344,26 +336,18 @@ namespace ICSharpCode.Decompiler.IL
public override StackType ResultType => Method.ReturnType.GetStackType();
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
{
WriteILRange(output, options);
output.Write(OpCode);
base.WriteSuffix(output);
output.Write(' ');
Method.WriteTo(output);
output.Write('(');
this.Target.WriteTo(output, options);
output.Write(", ");
this.Value.WriteTo(output, options);
output.Write(')');
}
finally
{
output.MarkNodeEnd(this);
}
WriteILRange(output, options);
output.Write(OpCode);
base.WriteSuffix(output);
output.Write(' ');
Method.WriteTo(output);
output.Write('(');
this.Target.WriteTo(output, options);
output.Write(", ");
this.Value.WriteTo(output, options);
output.Write(')');
}
}
@ -388,23 +372,15 @@ namespace ICSharpCode.Decompiler.IL @@ -388,23 +372,15 @@ namespace ICSharpCode.Decompiler.IL
this.ValueArgumentInfo = valueArgumentInfo;
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
{
WriteILRange(output, options);
output.Write(OpCode);
output.Write("." + Operation.ToString().ToLower());
DynamicInstruction.WriteBinderFlags(BinderFlags, output, options);
base.WriteSuffix(output);
output.Write(' ');
DynamicInstruction.WriteArgumentList(output, options, (Target, TargetArgumentInfo), (Value, ValueArgumentInfo));
}
finally
{
output.MarkNodeEnd(this);
}
WriteILRange(output, options);
output.Write(OpCode);
output.Write("." + Operation.ToString().ToLower());
DynamicInstruction.WriteBinderFlags(BinderFlags, output, options);
base.WriteSuffix(output);
output.Write(' ');
DynamicInstruction.WriteArgumentList(output, options, (Target, TargetArgumentInfo), (Value, ValueArgumentInfo));
}
internal static bool IsExpressionTypeSupported(ExpressionType type)

78
ICSharpCode.Decompiler/IL/Instructions/Conv.cs

@ -314,54 +314,46 @@ namespace ICSharpCode.Decompiler.IL @@ -314,54 +314,46 @@ namespace ICSharpCode.Decompiler.IL
get => TargetType.GetStackType();
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
WriteILRange(output, options);
output.Write(OpCode);
if (CheckForOverflow)
{
output.Write(".ovf");
}
if (InputSign == Sign.Unsigned)
{
output.Write(".unsigned");
}
else if (InputSign == Sign.Signed)
{
output.Write(".signed");
}
if (IsLifted)
{
WriteILRange(output, options);
output.Write(OpCode);
if (CheckForOverflow)
{
output.Write(".ovf");
}
if (InputSign == Sign.Unsigned)
{
output.Write(".unsigned");
}
else if (InputSign == Sign.Signed)
{
output.Write(".signed");
}
if (IsLifted)
{
output.Write(".lifted");
}
output.Write(' ');
output.Write(InputType);
output.Write("->");
output.Write(TargetType);
output.Write(' ');
switch (Kind)
{
case ConversionKind.SignExtend:
output.Write("<sign extend>");
break;
case ConversionKind.ZeroExtend:
output.Write("<zero extend>");
break;
case ConversionKind.Invalid:
output.Write("<invalid>");
break;
}
output.Write('(');
Argument.WriteTo(output, options);
output.Write(')');
output.Write(".lifted");
}
finally
output.Write(' ');
output.Write(InputType);
output.Write("->");
output.Write(TargetType);
output.Write(' ');
switch (Kind)
{
output.MarkNodeEnd(this);
case ConversionKind.SignExtend:
output.Write("<sign extend>");
break;
case ConversionKind.ZeroExtend:
output.Write("<zero extend>");
break;
case ConversionKind.Invalid:
output.Write("<invalid>");
break;
}
output.Write('(');
Argument.WriteTo(output, options);
output.Write(')');
}
protected override InstructionFlags ComputeFlags()

58
ICSharpCode.Decompiler/IL/Instructions/DeconstructInstruction.cs

@ -159,43 +159,35 @@ namespace ICSharpCode.Decompiler.IL @@ -159,43 +159,35 @@ namespace ICSharpCode.Decompiler.IL
assignments.ChildIndex = Init.Count + 2;
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
WriteILRange(output, options);
output.Write("deconstruct ");
output.MarkFoldStart("{...}");
output.WriteLine("{");
output.Indent();
output.WriteLine("init:");
output.Indent();
foreach (var inst in this.Init)
{
WriteILRange(output, options);
output.Write("deconstruct ");
output.MarkFoldStart("{...}");
output.WriteLine("{");
output.Indent();
output.WriteLine("init:");
output.Indent();
foreach (var inst in this.Init)
{
inst.WriteTo(output, options);
output.WriteLine();
}
output.Unindent();
output.WriteLine("pattern:");
output.Indent();
pattern.WriteTo(output, options);
output.Unindent();
output.WriteLine();
output.Write("conversions: ");
conversions.WriteTo(output, options);
inst.WriteTo(output, options);
output.WriteLine();
output.Write("assignments: ");
assignments.WriteTo(output, options);
output.Unindent();
output.WriteLine();
output.Write('}');
output.MarkFoldEnd();
}
finally
{
output.MarkNodeEnd(this);
}
output.Unindent();
output.WriteLine("pattern:");
output.Indent();
pattern.WriteTo(output, options);
output.Unindent();
output.WriteLine();
output.Write("conversions: ");
conversions.WriteTo(output, options);
output.WriteLine();
output.Write("assignments: ");
assignments.WriteTo(output, options);
output.Unindent();
output.WriteLine();
output.Write('}');
output.MarkFoldEnd();
}
internal static bool IsConversionStLoc(ILInstruction inst, out ILVariable variable, out ILVariable inputVariable)

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

@ -37,23 +37,15 @@ namespace ICSharpCode.Decompiler.IL @@ -37,23 +37,15 @@ namespace ICSharpCode.Decompiler.IL
ResultType = resultType;
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
{
WriteILRange(output, options);
output.Write(OpCode);
output.Write(' ');
output.Write(Index.ToString());
output.Write('(');
this.Argument.WriteTo(output, options);
output.Write(')');
}
finally
{
output.MarkNodeEnd(this);
}
WriteILRange(output, options);
output.Write(OpCode);
output.Write(' ');
output.Write(Index.ToString());
output.Write('(');
this.Argument.WriteTo(output, options);
output.Write(')');
}
MatchInstruction? FindMatch()

288
ICSharpCode.Decompiler/IL/Instructions/DynamicInstructions.cs

@ -130,24 +130,16 @@ namespace ICSharpCode.Decompiler.IL @@ -130,24 +130,16 @@ namespace ICSharpCode.Decompiler.IL
partial class DynamicConvertInstruction
{
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
{
WriteILRange(output, options);
output.Write(OpCode);
WriteBinderFlags(output, options);
output.Write(' ');
type.WriteTo(output);
output.Write('(');
argument.WriteTo(output, options);
output.Write(')');
}
finally
{
output.MarkNodeEnd(this);
}
WriteILRange(output, options);
output.Write(OpCode);
WriteBinderFlags(output, options);
output.Write(' ');
type.WriteTo(output);
output.Write('(');
argument.WriteTo(output, options);
output.Write(')');
}
public DynamicConvertInstruction(CSharpBinderFlags binderFlags, IType type, IType? context, ILInstruction argument)
@ -190,35 +182,27 @@ namespace ICSharpCode.Decompiler.IL @@ -190,35 +182,27 @@ namespace ICSharpCode.Decompiler.IL
Arguments.AddRange(arguments);
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
WriteILRange(output, options);
output.Write(OpCode);
WriteBinderFlags(output, options);
output.Write(' ');
output.Write(Name);
if (TypeArguments.Count > 0)
{
WriteILRange(output, options);
output.Write(OpCode);
WriteBinderFlags(output, options);
output.Write(' ');
output.Write(Name);
if (TypeArguments.Count > 0)
output.Write('<');
int i = 0;
foreach (var typeArg in TypeArguments)
{
output.Write('<');
int i = 0;
foreach (var typeArg in TypeArguments)
{
if (i > 0)
output.Write(", ");
typeArg.WriteTo(output);
i++;
}
output.Write('>');
if (i > 0)
output.Write(", ");
typeArg.WriteTo(output);
i++;
}
WriteArgumentList(output, options, Arguments.Zip(ArgumentInfo));
}
finally
{
output.MarkNodeEnd(this);
output.Write('>');
}
WriteArgumentList(output, options, Arguments.Zip(ArgumentInfo));
}
public override StackType ResultType => StackType.O;
@ -244,22 +228,14 @@ namespace ICSharpCode.Decompiler.IL @@ -244,22 +228,14 @@ namespace ICSharpCode.Decompiler.IL
Target = target;
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
{
WriteILRange(output, options);
output.Write(OpCode);
WriteBinderFlags(output, options);
output.Write(' ');
output.Write(Name);
WriteArgumentList(output, options, (Target, TargetArgumentInfo));
}
finally
{
output.MarkNodeEnd(this);
}
WriteILRange(output, options);
output.Write(OpCode);
WriteBinderFlags(output, options);
output.Write(' ');
output.Write(Name);
WriteArgumentList(output, options, (Target, TargetArgumentInfo));
}
public override StackType ResultType => StackType.O;
@ -288,22 +264,14 @@ namespace ICSharpCode.Decompiler.IL @@ -288,22 +264,14 @@ namespace ICSharpCode.Decompiler.IL
Value = value;
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
{
WriteILRange(output, options);
output.Write(OpCode);
WriteBinderFlags(output, options);
output.Write(' ');
output.Write(Name);
WriteArgumentList(output, options, (Target, TargetArgumentInfo), (Value, ValueArgumentInfo));
}
finally
{
output.MarkNodeEnd(this);
}
WriteILRange(output, options);
output.Write(OpCode);
WriteBinderFlags(output, options);
output.Write(' ');
output.Write(Name);
WriteArgumentList(output, options, (Target, TargetArgumentInfo), (Value, ValueArgumentInfo));
}
public override StackType ResultType => StackType.O;
@ -334,22 +302,14 @@ namespace ICSharpCode.Decompiler.IL @@ -334,22 +302,14 @@ namespace ICSharpCode.Decompiler.IL
Arguments.AddRange(arguments);
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
{
WriteILRange(output, options);
output.Write(OpCode);
WriteBinderFlags(output, options);
output.Write(' ');
output.Write("get_Item");
WriteArgumentList(output, options, Arguments.Zip(ArgumentInfo));
}
finally
{
output.MarkNodeEnd(this);
}
WriteILRange(output, options);
output.Write(OpCode);
WriteBinderFlags(output, options);
output.Write(' ');
output.Write("get_Item");
WriteArgumentList(output, options, Arguments.Zip(ArgumentInfo));
}
public override StackType ResultType => StackType.O;
@ -374,22 +334,14 @@ namespace ICSharpCode.Decompiler.IL @@ -374,22 +334,14 @@ namespace ICSharpCode.Decompiler.IL
Arguments.AddRange(arguments);
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
{
WriteILRange(output, options);
output.Write(OpCode);
WriteBinderFlags(output, options);
output.Write(' ');
output.Write("set_Item");
WriteArgumentList(output, options, Arguments.Zip(ArgumentInfo));
}
finally
{
output.MarkNodeEnd(this);
}
WriteILRange(output, options);
output.Write(OpCode);
WriteBinderFlags(output, options);
output.Write(' ');
output.Write("set_Item");
WriteArgumentList(output, options, Arguments.Zip(ArgumentInfo));
}
public override StackType ResultType => StackType.O;
@ -417,23 +369,15 @@ namespace ICSharpCode.Decompiler.IL @@ -417,23 +369,15 @@ namespace ICSharpCode.Decompiler.IL
this.resultType = type;
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
{
WriteILRange(output, options);
output.Write(OpCode);
WriteBinderFlags(output, options);
output.Write(' ');
resultType?.WriteTo(output);
output.Write(".ctor");
WriteArgumentList(output, options, Arguments.Zip(ArgumentInfo));
}
finally
{
output.MarkNodeEnd(this);
}
WriteILRange(output, options);
output.Write(OpCode);
WriteBinderFlags(output, options);
output.Write(' ');
resultType?.WriteTo(output);
output.Write(".ctor");
WriteArgumentList(output, options, Arguments.Zip(ArgumentInfo));
}
public override StackType ResultType => resultType?.GetStackType() ?? StackType.Unknown;
@ -462,22 +406,14 @@ namespace ICSharpCode.Decompiler.IL @@ -462,22 +406,14 @@ namespace ICSharpCode.Decompiler.IL
Right = right;
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
{
WriteILRange(output, options);
output.Write(OpCode);
WriteBinderFlags(output, options);
output.Write(' ');
output.Write(Operation.ToString());
WriteArgumentList(output, options, (Left, LeftArgumentInfo), (Right, RightArgumentInfo));
}
finally
{
output.MarkNodeEnd(this);
}
WriteILRange(output, options);
output.Write(OpCode);
WriteBinderFlags(output, options);
output.Write(' ');
output.Write(Operation.ToString());
WriteArgumentList(output, options, (Left, LeftArgumentInfo), (Right, RightArgumentInfo));
}
public override StackType ResultType => StackType.O;
@ -512,22 +448,14 @@ namespace ICSharpCode.Decompiler.IL @@ -512,22 +448,14 @@ namespace ICSharpCode.Decompiler.IL
Right = right;
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
{
WriteILRange(output, options);
output.Write(OpCode);
WriteBinderFlags(output, options);
output.Write(' ');
output.Write(Operation.ToString());
WriteArgumentList(output, options, (Left, LeftArgumentInfo), (Right, RightArgumentInfo));
}
finally
{
output.MarkNodeEnd(this);
}
WriteILRange(output, options);
output.Write(OpCode);
WriteBinderFlags(output, options);
output.Write(' ');
output.Write(Operation.ToString());
WriteArgumentList(output, options, (Left, LeftArgumentInfo), (Right, RightArgumentInfo));
}
public override StackType ResultType => StackType.O;
@ -567,22 +495,14 @@ namespace ICSharpCode.Decompiler.IL @@ -567,22 +495,14 @@ namespace ICSharpCode.Decompiler.IL
Operand = operand;
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
{
WriteILRange(output, options);
output.Write(OpCode);
WriteBinderFlags(output, options);
output.Write(' ');
output.Write(Operation.ToString());
WriteArgumentList(output, options, (Operand, OperandArgumentInfo));
}
finally
{
output.MarkNodeEnd(this);
}
WriteILRange(output, options);
output.Write(OpCode);
WriteBinderFlags(output, options);
output.Write(' ');
output.Write(Operation.ToString());
WriteArgumentList(output, options, (Operand, OperandArgumentInfo));
}
public override StackType ResultType {
@ -622,21 +542,13 @@ namespace ICSharpCode.Decompiler.IL @@ -622,21 +542,13 @@ namespace ICSharpCode.Decompiler.IL
Arguments.AddRange(arguments);
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
{
WriteILRange(output, options);
output.Write(OpCode);
WriteBinderFlags(output, options);
output.Write(' ');
WriteArgumentList(output, options, Arguments.Zip(ArgumentInfo));
}
finally
{
output.MarkNodeEnd(this);
}
WriteILRange(output, options);
output.Write(OpCode);
WriteBinderFlags(output, options);
output.Write(' ');
WriteArgumentList(output, options, Arguments.Zip(ArgumentInfo));
}
public override StackType ResultType => StackType.O;
@ -660,23 +572,15 @@ namespace ICSharpCode.Decompiler.IL @@ -660,23 +572,15 @@ namespace ICSharpCode.Decompiler.IL
Argument = argument;
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
{
WriteILRange(output, options);
output.Write(OpCode);
WriteBinderFlags(output, options);
output.Write(' ');
output.Write('(');
Argument.WriteTo(output, options);
output.Write(')');
}
finally
{
output.MarkNodeEnd(this);
}
WriteILRange(output, options);
output.Write(OpCode);
WriteBinderFlags(output, options);
output.Write(' ');
output.Write('(');
Argument.WriteTo(output, options);
output.Write(')');
}
public override StackType ResultType => StackType.I4;

28
ICSharpCode.Decompiler/IL/Instructions/ExpressionTreeCast.cs

@ -14,25 +14,17 @@ namespace ICSharpCode.Decompiler.IL @@ -14,25 +14,17 @@ namespace ICSharpCode.Decompiler.IL
this.IsChecked = isChecked;
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
{
WriteILRange(output, options);
output.Write(OpCode);
if (IsChecked)
output.Write(".checked");
output.Write(' ');
type.WriteTo(output);
output.Write('(');
Argument.WriteTo(output, options);
output.Write(')');
}
finally
{
output.MarkNodeEnd(this);
}
WriteILRange(output, options);
output.Write(OpCode);
if (IsChecked)
output.Write(".checked");
output.Write(' ');
type.WriteTo(output);
output.Write('(');
Argument.WriteTo(output, options);
output.Write(')');
}
}
}

140
ICSharpCode.Decompiler/IL/Instructions/ILFunction.cs

@ -270,93 +270,85 @@ namespace ICSharpCode.Decompiler.IL @@ -270,93 +270,85 @@ namespace ICSharpCode.Decompiler.IL
throw new NotSupportedException("ILFunction.CloneVariables is currently not supported!");
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
WriteILRange(output, options);
output.Write(OpCode);
if (Method != null)
{
WriteILRange(output, options);
output.Write(OpCode);
if (Method != null)
{
output.Write(' ');
Method.WriteTo(output);
}
switch (kind)
{
case ILFunctionKind.ExpressionTree:
output.Write(".ET");
break;
case ILFunctionKind.LocalFunction:
output.Write(".local");
break;
}
if (DelegateType != null)
{
output.Write("[");
DelegateType.WriteTo(output);
output.Write("]");
}
output.WriteLine(" {");
output.Indent();
output.Write(' ');
Method.WriteTo(output);
}
switch (kind)
{
case ILFunctionKind.ExpressionTree:
output.Write(".ET");
break;
case ILFunctionKind.LocalFunction:
output.Write(".local");
break;
}
if (DelegateType != null)
{
output.Write("[");
DelegateType.WriteTo(output);
output.Write("]");
}
output.WriteLine(" {");
output.Indent();
if (IsAsync)
{
output.WriteLine(".async");
}
if (IsIterator)
{
output.WriteLine(".iterator");
}
if (DeclarationScope != null)
{
output.Write("declared as " + Name + " in ");
output.WriteLocalReference(DeclarationScope.EntryPoint.Label, DeclarationScope);
output.WriteLine();
}
if (IsAsync)
{
output.WriteLine(".async");
}
if (IsIterator)
{
output.WriteLine(".iterator");
}
if (DeclarationScope != null)
{
output.Write("declared as " + Name + " in ");
output.WriteLocalReference(DeclarationScope.EntryPoint.Label, DeclarationScope);
output.WriteLine();
}
output.MarkFoldStart(Variables.Count + " variable(s)", true);
foreach (var variable in Variables)
{
variable.WriteDefinitionTo(output);
output.WriteLine();
}
output.MarkFoldEnd();
output.MarkFoldStart(Variables.Count + " variable(s)", true);
foreach (var variable in Variables)
{
variable.WriteDefinitionTo(output);
output.WriteLine();
}
output.MarkFoldEnd();
output.WriteLine();
foreach (string warning in Warnings)
{
output.WriteLine("//" + warning);
}
foreach (string warning in Warnings)
{
output.WriteLine("//" + warning);
}
body.WriteTo(output, options);
body.WriteTo(output, options);
output.WriteLine();
foreach (var localFunction in LocalFunctions)
{
output.WriteLine();
localFunction.WriteTo(output, options);
}
foreach (var localFunction in LocalFunctions)
if (options.ShowILRanges)
{
var unusedILRanges = FindUnusedILRanges();
if (!unusedILRanges.IsEmpty)
{
output.Write("// Unused IL Ranges: ");
output.Write(string.Join(", ", unusedILRanges.Intervals.Select(
range => $"[{range.Start:x4}..{range.InclusiveEnd:x4}]")));
output.WriteLine();
localFunction.WriteTo(output, options);
}
if (options.ShowILRanges)
{
var unusedILRanges = FindUnusedILRanges();
if (!unusedILRanges.IsEmpty)
{
output.Write("// Unused IL Ranges: ");
output.Write(string.Join(", ", unusedILRanges.Intervals.Select(
range => $"[{range.Start:x4}..{range.InclusiveEnd:x4}]")));
output.WriteLine();
}
}
output.Unindent();
output.WriteLine("}");
}
finally
{
output.MarkNodeEnd(this);
}
output.Unindent();
output.WriteLine("}");
}
LongSet FindUnusedILRanges()

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

@ -383,9 +383,29 @@ namespace ICSharpCode.Decompiler.IL @@ -383,9 +383,29 @@ namespace ICSharpCode.Decompiler.IL
}
/// <summary>
/// Writes the ILAst to the text output.
/// Writes the ILAst to the text output. Brackets the instruction's rendered span so it can be
/// mapped back to its character range for debug-step highlighting; the bracket lives here, in
/// one place, so a new instruction cannot forget it. Override <see cref="WriteToCore"/> to
/// render an instruction, not this method. Both marks are no-ops unless the output tracks nodes.
/// </summary>
public abstract void WriteTo(ITextOutput output, ILAstWritingOptions options);
public void WriteTo(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
{
WriteToCore(output, options);
}
finally
{
output.MarkNodeEnd(this);
}
}
/// <summary>
/// Renders this instruction to the text output. This is the override point; callers use
/// <see cref="WriteTo"/>, which wraps this in the node-tracking bracket.
/// </summary>
protected abstract void WriteToCore(ITextOutput output, ILAstWritingOptions options);
public override string ToString()
{

58
ICSharpCode.Decompiler/IL/Instructions/IfInstruction.cs

@ -82,47 +82,39 @@ namespace ICSharpCode.Decompiler.IL @@ -82,47 +82,39 @@ namespace ICSharpCode.Decompiler.IL
return InstructionFlags.ControlFlow | condition.Flags | SemanticHelper.CombineBranches(trueInst.Flags, falseInst.Flags);
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
WriteILRange(output, options);
if (options.UseLogicOperationSugar)
{
WriteILRange(output, options);
if (options.UseLogicOperationSugar)
if (MatchLogicAnd(out var lhs, out var rhs))
{
if (MatchLogicAnd(out var lhs, out var rhs))
{
output.Write("logic.and(");
lhs.WriteTo(output, options);
output.Write(", ");
rhs.WriteTo(output, options);
output.Write(')');
return;
}
if (MatchLogicOr(out lhs, out rhs))
{
output.Write("logic.or(");
lhs.WriteTo(output, options);
output.Write(", ");
rhs.WriteTo(output, options);
output.Write(')');
return;
}
output.Write("logic.and(");
lhs.WriteTo(output, options);
output.Write(", ");
rhs.WriteTo(output, options);
output.Write(')');
return;
}
output.Write(OpCode);
output.Write(" (");
condition.WriteTo(output, options);
output.Write(") ");
trueInst.WriteTo(output, options);
if (falseInst.OpCode != OpCode.Nop)
if (MatchLogicOr(out lhs, out rhs))
{
output.Write(" else ");
falseInst.WriteTo(output, options);
output.Write("logic.or(");
lhs.WriteTo(output, options);
output.Write(", ");
rhs.WriteTo(output, options);
output.Write(')');
return;
}
}
finally
output.Write(OpCode);
output.Write(" (");
condition.WriteTo(output, options);
output.Write(") ");
trueInst.WriteTo(output, options);
if (falseInst.OpCode != OpCode.Nop)
{
output.MarkNodeEnd(this);
output.Write(" else ");
falseInst.WriteTo(output, options);
}
}

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

@ -39,23 +39,15 @@ namespace ICSharpCode.Decompiler.IL @@ -39,23 +39,15 @@ namespace ICSharpCode.Decompiler.IL
get { return resultType; }
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
{
WriteILRange(output, options);
output.Write(OpCode);
output.Write('.');
output.Write(resultType);
output.Write('(');
this.array.WriteTo(output, options);
output.Write(')');
}
finally
{
output.MarkNodeEnd(this);
}
WriteILRange(output, options);
output.Write(OpCode);
output.Write('.');
output.Write(resultType);
output.Write('(');
this.array.WriteTo(output, options);
output.Write(')');
}
}
}

26
ICSharpCode.Decompiler/IL/Instructions/Leave.cs

@ -114,25 +114,17 @@ namespace ICSharpCode.Decompiler.IL @@ -114,25 +114,17 @@ namespace ICSharpCode.Decompiler.IL
Debug.Assert(phase <= ILPhase.InILReader || phase == ILPhase.InAsyncAwait || value.ResultType == targetContainer!.ResultType);
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
{
WriteILRange(output, options);
output.Write(OpCode);
if (targetContainer != null)
{
output.Write(' ');
output.WriteLocalReference(TargetLabel, targetContainer);
output.Write(" (");
value.WriteTo(output, options);
output.Write(')');
}
}
finally
WriteILRange(output, options);
output.Write(OpCode);
if (targetContainer != null)
{
output.MarkNodeEnd(this);
output.Write(' ');
output.WriteLocalReference(TargetLabel, targetContainer);
output.Write(" (");
value.WriteTo(output, options);
output.Write(')');
}
}
}

28
ICSharpCode.Decompiler/IL/Instructions/LockInstruction.cs

@ -27,25 +27,17 @@ namespace ICSharpCode.Decompiler.IL @@ -27,25 +27,17 @@ namespace ICSharpCode.Decompiler.IL
{
partial class LockInstruction
{
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
{
WriteILRange(output, options);
output.Write("lock (");
OnExpression.WriteTo(output, options);
output.WriteLine(") {");
output.Indent();
Body.WriteTo(output, options);
output.Unindent();
output.WriteLine();
output.Write("}");
}
finally
{
output.MarkNodeEnd(this);
}
WriteILRange(output, options);
output.Write("lock (");
OnExpression.WriteTo(output, options);
output.WriteLine(") {");
output.Indent();
Body.WriteTo(output, options);
output.Unindent();
output.WriteLine();
output.Write("}");
}
}
}

92
ICSharpCode.Decompiler/IL/Instructions/MatchInstruction.cs

@ -274,60 +274,52 @@ namespace ICSharpCode.Decompiler.IL @@ -274,60 +274,52 @@ namespace ICSharpCode.Decompiler.IL
return true;
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
WriteILRange(output, options);
output.Write(OpCode);
if (CheckNotNull)
{
WriteILRange(output, options);
output.Write(OpCode);
if (CheckNotNull)
{
output.Write(".notnull");
}
if (CheckType)
{
output.Write(".type[");
variable.Type.WriteTo(output);
output.Write(']');
}
if (IsDeconstructCall)
{
output.Write(".deconstruct[");
if (method == null)
output.Write("<null>");
else
method.WriteTo(output);
output.Write(']');
}
if (IsDeconstructTuple)
{
output.Write(".tuple");
}
output.Write(' ');
output.Write('(');
Variable.WriteTo(output);
output.Write(" = ");
TestedOperand.WriteTo(output, options);
output.Write(')');
if (SubPatterns.Count > 0)
{
output.MarkFoldStart("{...}");
output.WriteLine("{");
output.Indent();
foreach (var pattern in SubPatterns)
{
pattern.WriteTo(output, options);
output.WriteLine();
}
output.Unindent();
output.Write('}');
output.MarkFoldEnd();
}
output.Write(".notnull");
}
if (CheckType)
{
output.Write(".type[");
variable.Type.WriteTo(output);
output.Write(']');
}
finally
if (IsDeconstructCall)
{
output.MarkNodeEnd(this);
output.Write(".deconstruct[");
if (method == null)
output.Write("<null>");
else
method.WriteTo(output);
output.Write(']');
}
if (IsDeconstructTuple)
{
output.Write(".tuple");
}
output.Write(' ');
output.Write('(');
Variable.WriteTo(output);
output.Write(" = ");
TestedOperand.WriteTo(output, options);
output.Write(')');
if (SubPatterns.Count > 0)
{
output.MarkFoldStart("{...}");
output.WriteLine("{");
output.Indent();
foreach (var pattern in SubPatterns)
{
pattern.WriteTo(output, options);
output.WriteLine();
}
output.Unindent();
output.Write('}');
output.MarkFoldEnd();
}
}
}

98
ICSharpCode.Decompiler/IL/Instructions/MemoryInstructions.cs

@ -37,78 +37,62 @@ namespace ICSharpCode.Decompiler.IL @@ -37,78 +37,62 @@ namespace ICSharpCode.Decompiler.IL
partial class LdObj
{
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
if (options.UseFieldSugar)
{
if (options.UseFieldSugar)
if (this.MatchLdFld(out var target, out var field))
{
if (this.MatchLdFld(out var target, out var field))
{
WriteILRange(output, options);
output.Write("ldfld ");
field.WriteTo(output);
output.Write('(');
target.WriteTo(output, options);
output.Write(')');
return;
}
else if (this.MatchLdsFld(out field))
{
WriteILRange(output, options);
output.Write("ldsfld ");
field.WriteTo(output);
return;
}
WriteILRange(output, options);
output.Write("ldfld ");
field.WriteTo(output);
output.Write('(');
target.WriteTo(output, options);
output.Write(')');
return;
}
else if (this.MatchLdsFld(out field))
{
WriteILRange(output, options);
output.Write("ldsfld ");
field.WriteTo(output);
return;
}
OriginalWriteTo(output, options);
}
finally
{
output.MarkNodeEnd(this);
}
OriginalWriteTo(output, options);
}
}
partial class StObj
{
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
if (options.UseFieldSugar)
{
if (options.UseFieldSugar)
if (this.MatchStFld(out var target, out var field, out var value))
{
if (this.MatchStFld(out var target, out var field, out var value))
{
WriteILRange(output, options);
output.Write("stfld ");
field.WriteTo(output);
output.Write('(');
target.WriteTo(output, options);
output.Write(", ");
value.WriteTo(output, options);
output.Write(')');
return;
}
else if (this.MatchStsFld(out field, out value))
{
WriteILRange(output, options);
output.Write("stsfld ");
field.WriteTo(output);
output.Write('(');
value.WriteTo(output, options);
output.Write(')');
return;
}
WriteILRange(output, options);
output.Write("stfld ");
field.WriteTo(output);
output.Write('(');
target.WriteTo(output, options);
output.Write(", ");
value.WriteTo(output, options);
output.Write(')');
return;
}
else if (this.MatchStsFld(out field, out value))
{
WriteILRange(output, options);
output.Write("stsfld ");
field.WriteTo(output);
output.Write('(');
value.WriteTo(output, options);
output.Write(')');
return;
}
OriginalWriteTo(output, options);
}
finally
{
output.MarkNodeEnd(this);
}
OriginalWriteTo(output, options);
}
}
}

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

@ -90,23 +90,15 @@ namespace ICSharpCode.Decompiler.IL @@ -90,23 +90,15 @@ namespace ICSharpCode.Decompiler.IL
| SemanticHelper.CombineBranches(InstructionFlags.None, fallbackInst.Flags);
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
{
WriteILRange(output, options);
output.Write(OpCode);
output.Write("(");
valueInst.WriteTo(output, options);
output.Write(", ");
fallbackInst.WriteTo(output, options);
output.Write(")");
}
finally
{
output.MarkNodeEnd(this);
}
WriteILRange(output, options);
output.Write(OpCode);
output.Write("(");
valueInst.WriteTo(output, options);
output.Write(", ");
fallbackInst.WriteTo(output, options);
output.Write(")");
}
}
}

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

@ -90,25 +90,17 @@ namespace ICSharpCode.Decompiler.IL @@ -90,25 +90,17 @@ namespace ICSharpCode.Decompiler.IL
Debug.Assert(Ancestors.Any(a => a is NullableRewrap));
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
output.Write("nullable.unwrap.");
if (RefInput)
{
output.Write("nullable.unwrap.");
if (RefInput)
{
output.Write("refinput.");
}
output.Write(ResultType);
output.Write('(');
Argument.WriteTo(output, options);
output.Write(')');
}
finally
{
output.MarkNodeEnd(this);
output.Write("refinput.");
}
output.Write(ResultType);
output.Write('(');
Argument.WriteTo(output, options);
output.Write(')');
}
public override StackType ResultType { get; }

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

@ -24,19 +24,11 @@ namespace ICSharpCode.Decompiler.IL @@ -24,19 +24,11 @@ namespace ICSharpCode.Decompiler.IL
/// </summary>
public abstract partial class SimpleInstruction : ILInstruction
{
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
{
WriteILRange(output, options);
output.Write(OpCode);
// the non-custom WriteTo would add useless parentheses
}
finally
{
output.MarkNodeEnd(this);
}
WriteILRange(output, options);
output.Write(OpCode);
// the non-custom WriteTo would add useless parentheses
}
}
@ -52,25 +44,17 @@ namespace ICSharpCode.Decompiler.IL @@ -52,25 +44,17 @@ namespace ICSharpCode.Decompiler.IL
public NopKind Kind;
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
WriteILRange(output, options);
output.Write(OpCode);
if (Kind != NopKind.Normal)
{
WriteILRange(output, options);
output.Write(OpCode);
if (Kind != NopKind.Normal)
{
output.Write("." + Kind.ToString().ToLowerInvariant());
}
if (!string.IsNullOrEmpty(Comment))
{
output.Write(" // " + Comment);
}
output.Write("." + Kind.ToString().ToLowerInvariant());
}
finally
if (!string.IsNullOrEmpty(Comment))
{
output.MarkNodeEnd(this);
output.Write(" // " + Comment);
}
}
}
@ -89,23 +73,15 @@ namespace ICSharpCode.Decompiler.IL @@ -89,23 +73,15 @@ namespace ICSharpCode.Decompiler.IL
get { return ExpectedResultType; }
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
WriteILRange(output, options);
output.Write(OpCode);
if (!string.IsNullOrEmpty(Message))
{
WriteILRange(output, options);
output.Write(OpCode);
if (!string.IsNullOrEmpty(Message))
{
output.Write("(\"");
output.Write(Message);
output.Write("\")");
}
}
finally
{
output.MarkNodeEnd(this);
output.Write("(\"");
output.Write(Message);
output.Write("\")");
}
}
}
@ -125,23 +101,15 @@ namespace ICSharpCode.Decompiler.IL @@ -125,23 +101,15 @@ namespace ICSharpCode.Decompiler.IL
get { return ExpectedResultType; }
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
{
WriteILRange(output, options);
output.Write(OpCode);
if (!string.IsNullOrEmpty(Message))
{
output.Write("(\"");
output.Write(Message);
output.Write("\")");
}
}
finally
WriteILRange(output, options);
output.Write(OpCode);
if (!string.IsNullOrEmpty(Message))
{
output.MarkNodeEnd(this);
output.Write("(\"");
output.Write(Message);
output.Write("\")");
}
}
}

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

@ -52,34 +52,26 @@ namespace ICSharpCode.Decompiler.IL @@ -52,34 +52,26 @@ namespace ICSharpCode.Decompiler.IL
return dict;
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
WriteILRange(output, options);
output.Write("string.to.int ");
ExpectedType.WriteTo(output);
output.Write('(');
Argument.WriteTo(output, options);
output.Write(", { ");
int i = 0;
foreach (var entry in Map)
{
WriteILRange(output, options);
output.Write("string.to.int ");
ExpectedType.WriteTo(output);
output.Write('(');
Argument.WriteTo(output, options);
output.Write(", { ");
int i = 0;
foreach (var entry in Map)
{
if (i > 0)
output.Write(", ");
if (entry.Key is null)
output.Write($"[null] = {entry.Value}");
else
output.Write($"[\"{entry.Key}\"] = {entry.Value}");
i++;
}
output.Write(" })");
}
finally
{
output.MarkNodeEnd(this);
if (i > 0)
output.Write(", ");
if (entry.Key is null)
output.Write($"[null] = {entry.Value}");
else
output.Write($"[\"{entry.Key}\"] = {entry.Value}");
i++;
}
output.Write(" })");
}
}
}

84
ICSharpCode.Decompiler/IL/Instructions/SwitchInstruction.cs

@ -83,36 +83,28 @@ namespace ICSharpCode.Decompiler.IL @@ -83,36 +83,28 @@ namespace ICSharpCode.Decompiler.IL
}
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
WriteILRange(output, options);
output.Write("switch");
if (IsLifted)
output.Write(".lifted");
output.Write(' ');
Type?.WriteTo(output);
output.Write('(');
value.WriteTo(output, options);
output.Write(") ");
output.MarkFoldStart("{...}");
output.WriteLine("{");
output.Indent();
foreach (var section in this.Sections)
{
WriteILRange(output, options);
output.Write("switch");
if (IsLifted)
output.Write(".lifted");
output.Write(' ');
Type?.WriteTo(output);
output.Write('(');
value.WriteTo(output, options);
output.Write(") ");
output.MarkFoldStart("{...}");
output.WriteLine("{");
output.Indent();
foreach (var section in this.Sections)
{
section.WriteTo(output, options);
output.WriteLine();
}
output.Unindent();
output.Write('}');
output.MarkFoldEnd();
}
finally
{
output.MarkNodeEnd(this);
section.WriteTo(output, options);
output.WriteLine();
}
output.Unindent();
output.Write('}');
output.MarkFoldEnd();
}
protected override int GetChildCount()
@ -232,37 +224,29 @@ namespace ICSharpCode.Decompiler.IL @@ -232,37 +224,29 @@ namespace ICSharpCode.Decompiler.IL
}
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
WriteILRange(output, options);
if (IsCompilerGeneratedDefaultSection)
output.Write("generated.");
output.WriteLocalReference("case", this, isDefinition: true);
output.Write(' ');
if (HasNullLabel)
{
WriteILRange(output, options);
if (IsCompilerGeneratedDefaultSection)
output.Write("generated.");
output.WriteLocalReference("case", this, isDefinition: true);
output.Write(' ');
if (HasNullLabel)
{
output.Write("null");
if (!Labels.IsEmpty)
{
output.Write(", ");
output.Write(Labels.ToString());
}
}
else
output.Write("null");
if (!Labels.IsEmpty)
{
output.Write(", ");
output.Write(Labels.ToString());
}
output.Write(": ");
body.WriteTo(output, options);
}
finally
else
{
output.MarkNodeEnd(this);
output.Write(Labels.ToString());
}
output.Write(": ");
body.WriteTo(output, options);
}
}
}

94
ICSharpCode.Decompiler/IL/Instructions/TryInstruction.cs

@ -68,23 +68,15 @@ namespace ICSharpCode.Decompiler.IL @@ -68,23 +68,15 @@ namespace ICSharpCode.Decompiler.IL
return clone;
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
{
WriteILRange(output, options);
output.Write(".try ");
TryBlock.WriteTo(output, options);
foreach (var handler in Handlers)
{
output.Write(' ');
handler.WriteTo(output, options);
}
}
finally
WriteILRange(output, options);
output.Write(".try ");
TryBlock.WriteTo(output, options);
foreach (var handler in Handlers)
{
output.MarkNodeEnd(this);
output.Write(' ');
handler.WriteTo(output, options);
}
}
@ -172,29 +164,21 @@ namespace ICSharpCode.Decompiler.IL @@ -172,29 +164,21 @@ namespace ICSharpCode.Decompiler.IL
}
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
WriteILRange(output, options);
output.Write("catch ");
if (variable != null)
{
WriteILRange(output, options);
output.Write("catch ");
if (variable != null)
{
output.WriteLocalReference(variable.Name, variable, isDefinition: true);
output.Write(" : ");
Disassembler.DisassemblerHelpers.WriteOperand(output, variable.Type);
}
output.Write(" when (");
filter.WriteTo(output, options);
output.Write(')');
output.Write(' ');
body.WriteTo(output, options);
}
finally
{
output.MarkNodeEnd(this);
output.WriteLocalReference(variable.Name, variable, isDefinition: true);
output.Write(" : ");
Disassembler.DisassemblerHelpers.WriteOperand(output, variable.Type);
}
output.Write(" when (");
filter.WriteTo(output, options);
output.Write(')');
output.Write(' ');
body.WriteTo(output, options);
}
/// <summary>
@ -233,21 +217,13 @@ namespace ICSharpCode.Decompiler.IL @@ -233,21 +217,13 @@ namespace ICSharpCode.Decompiler.IL
return new TryFinally(TryBlock.Clone(), finallyBlock.Clone()).WithILRange(this);
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
{
WriteILRange(output, options);
output.Write(".try ");
TryBlock.WriteTo(output, options);
output.Write(" finally ");
finallyBlock.WriteTo(output, options);
}
finally
{
output.MarkNodeEnd(this);
}
WriteILRange(output, options);
output.Write(".try ");
TryBlock.WriteTo(output, options);
output.Write(" finally ");
finallyBlock.WriteTo(output, options);
}
public override StackType ResultType {
@ -338,21 +314,13 @@ namespace ICSharpCode.Decompiler.IL @@ -338,21 +314,13 @@ namespace ICSharpCode.Decompiler.IL
return new TryFault(TryBlock.Clone(), faultBlock.Clone()).WithILRange(this);
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
{
WriteILRange(output, options);
output.Write(".try ");
TryBlock.WriteTo(output, options);
output.Write(" fault ");
faultBlock.WriteTo(output, options);
}
finally
{
output.MarkNodeEnd(this);
}
WriteILRange(output, options);
output.Write(".try ");
TryBlock.WriteTo(output, options);
output.Write(" fault ");
faultBlock.WriteTo(output, options);
}
public override StackType ResultType {

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

@ -50,25 +50,17 @@ namespace ICSharpCode.Decompiler.IL @@ -50,25 +50,17 @@ namespace ICSharpCode.Decompiler.IL
Debug.Assert(IsLifted || ResultType == UnderlyingResultType);
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
WriteILRange(output, options);
output.Write(OpCode);
if (IsLifted)
{
WriteILRange(output, options);
output.Write(OpCode);
if (IsLifted)
{
output.Write(".lifted");
}
output.Write('(');
this.Argument.WriteTo(output, options);
output.Write(')');
}
finally
{
output.MarkNodeEnd(this);
output.Write(".lifted");
}
output.Write('(');
this.Argument.WriteTo(output, options);
output.Write(')');
}
}
}

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

@ -40,36 +40,28 @@ namespace ICSharpCode.Decompiler.IL @@ -40,36 +40,28 @@ namespace ICSharpCode.Decompiler.IL
public bool IsRefStruct { get; set; }
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
protected override void WriteToCore(ITextOutput output, ILAstWritingOptions options)
{
output.MarkNodeStart(this);
try
WriteILRange(output, options);
output.Write("using");
if (IsAsync)
{
WriteILRange(output, options);
output.Write("using");
if (IsAsync)
{
output.Write(".async");
}
if (IsRefStruct)
{
output.Write(".ref");
}
output.Write(" (");
Variable.WriteTo(output);
output.Write(" = ");
ResourceExpression.WriteTo(output, options);
output.WriteLine(") {");
output.Indent();
Body.WriteTo(output, options);
output.Unindent();
output.WriteLine();
output.Write("}");
output.Write(".async");
}
finally
if (IsRefStruct)
{
output.MarkNodeEnd(this);
output.Write(".ref");
}
output.Write(" (");
Variable.WriteTo(output);
output.Write(" = ");
ResourceExpression.WriteTo(output, options);
output.WriteLine(") {");
output.Indent();
Body.WriteTo(output, options);
output.Unindent();
output.WriteLine();
output.Write("}");
}
}
}

Loading…
Cancel
Save