Browse Source

Try to detect while conditions, do-while-loops and for-loops

pull/728/merge
Siegfried Pammer 9 years ago
parent
commit
fc8825d895
  1. 73
      ICSharpCode.Decompiler/CSharp/StatementBuilder.cs
  2. 16
      ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs
  3. 1
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  4. 329
      ICSharpCode.Decompiler/IL/Instructions.cs
  5. 26
      ICSharpCode.Decompiler/IL/Instructions.tt
  6. 57
      ICSharpCode.Decompiler/IL/Patterns/AnyNode.cs

73
ICSharpCode.Decompiler/CSharp/StatementBuilder.cs

@ -24,6 +24,7 @@ using ICSharpCode.Decompiler.CSharp.Syntax;
using ICSharpCode.Decompiler.Semantics; using ICSharpCode.Decompiler.Semantics;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util; using ICSharpCode.Decompiler.Util;
using ICSharpCode.Decompiler.IL.Patterns;
namespace ICSharpCode.Decompiler.CSharp namespace ICSharpCode.Decompiler.CSharp
{ {
@ -267,25 +268,87 @@ namespace ICSharpCode.Decompiler.CSharp
} }
} }
WhileStatement ConvertLoop(BlockContainer container) Statement ConvertLoop(BlockContainer container)
{ {
continueTarget = container.EntryPoint; continueTarget = container.EntryPoint;
continueCount = 0; continueCount = 0;
breakTarget = container; breakTarget = container;
var blockStatement = ConvertBlockContainer(container, true); Expression conditionExpr = new PrimitiveExpression(true);
BlockStatement blockStatement;
if (container.EntryPoint.Instructions.Count == 2
&& container.EntryPoint.Instructions[0].MatchIfInstruction(out var conditionInst, out var trueInst)
&& container.EntryPoint.Instructions[1].MatchLeave(container)) {
// detected while(condition)-loop or for-loop
conditionExpr = exprBuilder.TranslateCondition(conditionInst);
if (container.EntryPoint.IncomingEdgeCount == 2) {
var incrementBlock = container.Blocks.SingleOrDefault(b => b.Instructions.Last().MatchBranch(container.EntryPoint));
if (incrementBlock != null) {
// for-loop
continueTarget = incrementBlock;
var forStmt = new ForStatement() {
Condition = conditionExpr,
EmbeddedStatement = ConvertBlockContainer(ConvertAsBlock(trueInst), container, container.Blocks.Skip(1).Where(b => b != incrementBlock), true)
};
for (int i = 0; i < incrementBlock.Instructions.Count - 1; i++) {
forStmt.Iterators.Add(Convert(incrementBlock.Instructions[i]));
}
return forStmt;
}
}
blockStatement = ConvertBlockContainer(ConvertAsBlock(trueInst), container, container.Blocks.Skip(1), true);
} else {
// do-while or while(true)-loop
if (container.EntryPoint.IncomingEdgeCount == 2) {
Block conditionBlock = FindDoWhileConditionBlock(container, out var condition);
if (conditionBlock != null) {
continueTarget = conditionBlock;
return new DoWhileStatement {
EmbeddedStatement = ConvertBlockContainer(new BlockStatement(), container, container.Blocks.Where(b => b != conditionBlock), true),
Condition = exprBuilder.TranslateCondition(condition)
};
}
}
blockStatement = ConvertBlockContainer(container, true);
Debug.Assert(continueCount < container.EntryPoint.IncomingEdgeCount); Debug.Assert(continueCount < container.EntryPoint.IncomingEdgeCount);
Debug.Assert(blockStatement.Statements.First() is LabelStatement); Debug.Assert(blockStatement.Statements.First() is LabelStatement);
if (container.EntryPoint.IncomingEdgeCount == continueCount + 1) { if (container.EntryPoint.IncomingEdgeCount == continueCount + 1) {
// Remove the entrypoint label if all jumps to the label were replaced with 'continue;' statements // Remove the entrypoint label if all jumps to the label were replaced with 'continue;' statements
blockStatement.Statements.First().Remove(); blockStatement.Statements.First().Remove();
} }
return new WhileStatement(new PrimitiveExpression(true), blockStatement); }
if (blockStatement.LastOrDefault() is ContinueStatement stmt)
stmt.Remove();
return new WhileStatement(conditionExpr, blockStatement);
}
private static Block FindDoWhileConditionBlock(BlockContainer container, out ILInstruction condition)
{
var conditionGroup = new CaptureGroup();
var conditionBlockPattern = new Block {
Instructions = {
new IfInstruction(new AnyNode(conditionGroup), new Branch(container.EntryPoint)),
new Leave(container)
}
};
foreach (var b in container.Blocks) {
var match = conditionBlockPattern.Match(b);
if (match.Success) {
condition = match.Get(conditionGroup).Single();
return b;
}
}
condition = null;
return null;
} }
BlockStatement ConvertBlockContainer(BlockContainer container, bool isLoop) BlockStatement ConvertBlockContainer(BlockContainer container, bool isLoop)
{ {
BlockStatement blockStatement = new BlockStatement(); return ConvertBlockContainer(new BlockStatement(), container, container.Blocks, isLoop);
foreach (var block in container.Blocks) { }
BlockStatement ConvertBlockContainer(BlockStatement blockStatement, BlockContainer container, IEnumerable<Block> blocks, bool isLoop)
{
foreach (var block in blocks) {
if (block.IncomingEdgeCount > 1 || block != container.EntryPoint) { if (block.IncomingEdgeCount > 1 || block != container.EntryPoint) {
// If there are any incoming branches to this block, add a label: // If there are any incoming branches to this block, add a label:
blockStatement.Add(new LabelStatement { Label = block.Label }); blockStatement.Add(new LabelStatement { Label = block.Label });

16
ICSharpCode.Decompiler/CSharp/Transforms/DeclareVariables.cs

@ -33,6 +33,10 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
/// </summary> /// </summary>
public class DeclareVariables : IAstTransform public class DeclareVariables : IAstTransform
{ {
/// <summary>
/// Represents a position immediately before nextNode.
/// nextNode is either an ExpressionStatement in a BlockStatement, or an initializer in a for-loop.
/// </summary>
struct InsertionPoint struct InsertionPoint
{ {
internal int level; internal int level;
@ -212,6 +216,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
// guarantee that it finds only blocks. // guarantee that it finds only blocks.
// Fix that up now. // Fix that up now.
while (!(v.InsertionPoint.nextNode.Parent is BlockStatement)) { while (!(v.InsertionPoint.nextNode.Parent is BlockStatement)) {
if (v.InsertionPoint.nextNode.Parent is ForStatement f && v.InsertionPoint.nextNode == f.Initializers.FirstOrDefault())
break;
v.InsertionPoint = v.InsertionPoint.Up(); v.InsertionPoint = v.InsertionPoint.Up();
} }
@ -254,22 +260,22 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
if (v.RemovedDueToCollision) if (v.RemovedDueToCollision)
continue; continue;
var boe = (v.InsertionPoint.nextNode as ExpressionStatement)?.Expression as AssignmentExpression; var assignment = (v.InsertionPoint.nextNode as ExpressionStatement)?.Expression as AssignmentExpression;
Expression expectedExpr = new IdentifierExpression(v.Name); Expression expectedExpr = new IdentifierExpression(v.Name);
if (v.Type.Kind == TypeKind.ByReference) { if (v.Type.Kind == TypeKind.ByReference) {
expectedExpr = new DirectionExpression(FieldDirection.Ref, expectedExpr); expectedExpr = new DirectionExpression(FieldDirection.Ref, expectedExpr);
} }
if (boe != null && boe.Left.IsMatch(expectedExpr)) { if (assignment != null && assignment.Left.IsMatch(expectedExpr)) {
AstType type; AstType type;
if (v.Type.ContainsAnonymousType()) { if (v.Type.ContainsAnonymousType()) {
type = new SimpleType("var"); type = new SimpleType("var");
} else { } else {
type = context.TypeSystemAstBuilder.ConvertType(v.Type); type = context.TypeSystemAstBuilder.ConvertType(v.Type);
} }
var vds = new VariableDeclarationStatement(type, v.Name, boe.Right.Detach()); var vds = new VariableDeclarationStatement(type, v.Name, assignment.Right.Detach());
var init = vds.Variables.Single(); var init = vds.Variables.Single();
init.AddAnnotation(boe.Left.GetResolveResult()); init.AddAnnotation(assignment.Left.GetResolveResult());
foreach (object annotation in boe.Left.Annotations.Concat(boe.Annotations)) { foreach (object annotation in assignment.Left.Annotations.Concat(assignment.Annotations)) {
if (!(annotation is ResolveResult)) { if (!(annotation is ResolveResult)) {
init.AddAnnotation(annotation); init.AddAnnotation(annotation);
} }

1
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -275,6 +275,7 @@
<Compile Include="Documentation\IdStringMemberReference.cs" /> <Compile Include="Documentation\IdStringMemberReference.cs" />
<Compile Include="Documentation\IdStringProvider.cs" /> <Compile Include="Documentation\IdStringProvider.cs" />
<Compile Include="Documentation\XmlDocumentationProvider.cs" /> <Compile Include="Documentation\XmlDocumentationProvider.cs" />
<Compile Include="IL\Patterns\AnyNode.cs" />
<Compile Include="Util\UnicodeNewline.cs" /> <Compile Include="Util\UnicodeNewline.cs" />
<Compile Include="FlowAnalysis\ControlFlowNode.cs" /> <Compile Include="FlowAnalysis\ControlFlowNode.cs" />
<Compile Include="FlowAnalysis\DataFlowVisitor.cs" /> <Compile Include="FlowAnalysis\DataFlowVisitor.cs" />

329
ICSharpCode.Decompiler/IL/Instructions.cs

@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
@ -155,8 +156,13 @@ namespace ICSharpCode.Decompiler.IL
RefAnyType, RefAnyType,
/// <summary>Push the address stored in a typed reference.</summary> /// <summary>Push the address stored in a typed reference.</summary>
RefAnyValue, RefAnyValue,
/// <summary>Matches any node</summary>
AnyNode,
}
} }
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Instruction without any arguments</summary> /// <summary>Instruction without any arguments</summary>
public abstract partial class SimpleInstruction : ILInstruction public abstract partial class SimpleInstruction : ILInstruction
{ {
@ -203,7 +209,9 @@ namespace ICSharpCode.Decompiler.IL
} }
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Instruction with a single argument</summary> /// <summary>Instruction with a single argument</summary>
public abstract partial class UnaryInstruction : ILInstruction public abstract partial class UnaryInstruction : ILInstruction
{ {
@ -275,7 +283,9 @@ namespace ICSharpCode.Decompiler.IL
output.Write(')'); output.Write(')');
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Instruction with two arguments: Left and Right</summary> /// <summary>Instruction with two arguments: Left and Right</summary>
public abstract partial class BinaryInstruction : ILInstruction public abstract partial class BinaryInstruction : ILInstruction
{ {
@ -367,7 +377,9 @@ namespace ICSharpCode.Decompiler.IL
output.Write(')'); output.Write(')');
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Instruction with a list of arguments.</summary> /// <summary>Instruction with a list of arguments.</summary>
public abstract partial class CallInstruction : ILInstruction public abstract partial class CallInstruction : ILInstruction
{ {
@ -421,7 +433,20 @@ namespace ICSharpCode.Decompiler.IL
} }
} }
} }
}
namespace ICSharpCode.Decompiler.IL.Patterns
{
/// <summary>Base class for pattern matching in ILAst.</summary>
public abstract partial class PatternInstruction : ILInstruction
{
protected PatternInstruction(OpCode opCode) : base(opCode)
{
}
public override StackType ResultType { get { return StackType.Unknown; } }
}
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Represents invalid IL. Semantically, this instruction is considered to throw some kind of exception.</summary> /// <summary>Represents invalid IL. Semantically, this instruction is considered to throw some kind of exception.</summary>
public sealed partial class InvalidInstruction : SimpleInstruction public sealed partial class InvalidInstruction : SimpleInstruction
{ {
@ -456,7 +481,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null; return o != null;
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>No operation. Takes 0 arguments and returns void.</summary> /// <summary>No operation. Takes 0 arguments and returns void.</summary>
public sealed partial class Nop : SimpleInstruction public sealed partial class Nop : SimpleInstruction
{ {
@ -482,7 +509,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null; return o != null;
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>A container of IL blocks.</summary> /// <summary>A container of IL blocks.</summary>
public sealed partial class ILFunction : ILVariableScope public sealed partial class ILFunction : ILVariableScope
{ {
@ -553,7 +582,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && this.body.PerformMatch(o.body, ref match); return o != null && this.body.PerformMatch(o.body, ref match);
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>A container of IL blocks.</summary> /// <summary>A container of IL blocks.</summary>
public sealed partial class BlockContainer : ILInstruction public sealed partial class BlockContainer : ILInstruction
{ {
@ -576,7 +607,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && Patterns.ListMatch.DoMatch(this.Blocks, o.Blocks, ref match); return o != null && Patterns.ListMatch.DoMatch(this.Blocks, o.Blocks, ref match);
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>A block of IL instructions.</summary> /// <summary>A block of IL instructions.</summary>
public sealed partial class Block : ILInstruction public sealed partial class Block : ILInstruction
{ {
@ -599,7 +632,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && this.Type == o.Type && Patterns.ListMatch.DoMatch(this.Instructions, o.Instructions, ref match) && this.FinalInstruction.PerformMatch(o.FinalInstruction, ref match); return o != null && this.Type == o.Type && Patterns.ListMatch.DoMatch(this.Instructions, o.Instructions, ref match) && this.FinalInstruction.PerformMatch(o.FinalInstruction, ref match);
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>A region where a pinned variable is used (initial representation of future fixed statement).</summary> /// <summary>A region where a pinned variable is used (initial representation of future fixed statement).</summary>
public sealed partial class PinnedRegion : ILInstruction, IInstructionWithVariableOperand public sealed partial class PinnedRegion : ILInstruction, IInstructionWithVariableOperand
{ {
@ -742,7 +777,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && variable == o.variable && this.init.PerformMatch(o.init, ref match) && this.body.PerformMatch(o.body, ref match); return o != null && variable == o.variable && this.init.PerformMatch(o.init, ref match) && this.body.PerformMatch(o.body, ref match);
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Unary operator that expects an input of type I4. Returns 1 (of type I4) if the input value is 0. Otherwise, returns 0 (of type I4).</summary> /// <summary>Unary operator that expects an input of type I4. Returns 1 (of type I4) if the input value is 0. Otherwise, returns 0 (of type I4).</summary>
public sealed partial class LogicNot : UnaryInstruction public sealed partial class LogicNot : UnaryInstruction
{ {
@ -768,7 +805,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && this.Argument.PerformMatch(o.Argument, ref match); return o != null && this.Argument.PerformMatch(o.Argument, ref match);
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Common instruction for add, sub, mul, div, rem, bit.and, bit.or, bit.xor, shl and shr.</summary> /// <summary>Common instruction for add, sub, mul, div, rem, bit.and, bit.or, bit.xor, shl and shr.</summary>
public sealed partial class BinaryNumericInstruction : BinaryInstruction public sealed partial class BinaryNumericInstruction : BinaryInstruction
{ {
@ -791,7 +830,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && this.Left.PerformMatch(o.Left, ref match) && this.Right.PerformMatch(o.Right, ref match) && CheckForOverflow == o.CheckForOverflow && Sign == o.Sign && Operator == o.Operator; return o != null && this.Left.PerformMatch(o.Left, ref match) && this.Right.PerformMatch(o.Right, ref match) && CheckForOverflow == o.CheckForOverflow && Sign == o.Sign && Operator == o.Operator;
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Common instruction for compound assignments.</summary> /// <summary>Common instruction for compound assignments.</summary>
public sealed partial class CompoundAssignmentInstruction : ILInstruction public sealed partial class CompoundAssignmentInstruction : ILInstruction
{ {
@ -881,7 +922,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && this.target.PerformMatch(o.target, ref match) && this.value.PerformMatch(o.value, ref match) && type.Equals(o.type) && CheckForOverflow == o.CheckForOverflow && Sign == o.Sign && Operator == o.Operator; return o != null && this.target.PerformMatch(o.target, ref match) && this.value.PerformMatch(o.value, ref match) && type.Equals(o.type) && CheckForOverflow == o.CheckForOverflow && Sign == o.Sign && Operator == o.Operator;
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Bitwise NOT</summary> /// <summary>Bitwise NOT</summary>
public sealed partial class BitNot : UnaryInstruction public sealed partial class BitNot : UnaryInstruction
{ {
@ -907,7 +950,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && this.Argument.PerformMatch(o.Argument, ref match); return o != null && this.Argument.PerformMatch(o.Argument, ref match);
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Retrieves the RuntimeArgumentHandle.</summary> /// <summary>Retrieves the RuntimeArgumentHandle.</summary>
public sealed partial class Arglist : SimpleInstruction public sealed partial class Arglist : SimpleInstruction
{ {
@ -933,7 +978,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null; return o != null;
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Unconditional branch. <c>goto target;</c></summary> /// <summary>Unconditional branch. <c>goto target;</c></summary>
public sealed partial class Branch : SimpleInstruction public sealed partial class Branch : SimpleInstruction
{ {
@ -956,7 +1003,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && this.TargetBlock == o.TargetBlock; return o != null && this.TargetBlock == o.TargetBlock;
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Unconditional branch to end of block container. <c>goto container_end;</c>, often <c>break;</c></summary> /// <summary>Unconditional branch to end of block container. <c>goto container_end;</c>, often <c>break;</c></summary>
public sealed partial class Leave : SimpleInstruction public sealed partial class Leave : SimpleInstruction
{ {
@ -979,7 +1028,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && this.TargetContainer == o.TargetContainer; return o != null && this.TargetContainer == o.TargetContainer;
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>If statement / conditional expression. <c>if (condition) trueExpr else falseExpr</c></summary> /// <summary>If statement / conditional expression. <c>if (condition) trueExpr else falseExpr</c></summary>
public sealed partial class IfInstruction : ILInstruction public sealed partial class IfInstruction : ILInstruction
{ {
@ -1082,7 +1133,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && this.condition.PerformMatch(o.condition, ref match) && this.trueInst.PerformMatch(o.trueInst, ref match) && this.falseInst.PerformMatch(o.falseInst, ref match); return o != null && this.condition.PerformMatch(o.condition, ref match) && this.trueInst.PerformMatch(o.trueInst, ref match) && this.falseInst.PerformMatch(o.falseInst, ref match);
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Switch statement</summary> /// <summary>Switch statement</summary>
public sealed partial class SwitchInstruction : ILInstruction public sealed partial class SwitchInstruction : ILInstruction
{ {
@ -1105,7 +1158,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && Value.PerformMatch(o.Value, ref match) && DefaultBody.PerformMatch(o.DefaultBody, ref match) && Patterns.ListMatch.DoMatch(this.Sections, o.Sections, ref match); return o != null && Value.PerformMatch(o.Value, ref match) && DefaultBody.PerformMatch(o.DefaultBody, ref match) && Patterns.ListMatch.DoMatch(this.Sections, o.Sections, ref match);
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Switch section within a switch statement</summary> /// <summary>Switch section within a switch statement</summary>
public sealed partial class SwitchSection : ILInstruction public sealed partial class SwitchSection : ILInstruction
{ {
@ -1175,7 +1230,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && this.body.PerformMatch(o.body, ref match) && this.Labels.Intervals.SequenceEqual(o.Labels.Intervals); return o != null && this.body.PerformMatch(o.body, ref match) && this.Labels.Intervals.SequenceEqual(o.Labels.Intervals);
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Try-catch statement.</summary> /// <summary>Try-catch statement.</summary>
public sealed partial class TryCatch : TryInstruction public sealed partial class TryCatch : TryInstruction
{ {
@ -1198,7 +1255,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && TryBlock.PerformMatch(o.TryBlock, ref match) && Patterns.ListMatch.DoMatch(Handlers, o.Handlers, ref match); return o != null && TryBlock.PerformMatch(o.TryBlock, ref match) && Patterns.ListMatch.DoMatch(Handlers, o.Handlers, ref match);
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Catch handler within a try-catch statement.</summary> /// <summary>Catch handler within a try-catch statement.</summary>
public sealed partial class TryCatchHandler : ILInstruction, IInstructionWithVariableOperand public sealed partial class TryCatchHandler : ILInstruction, IInstructionWithVariableOperand
{ {
@ -1315,7 +1374,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && this.filter.PerformMatch(o.filter, ref match) && this.body.PerformMatch(o.body, ref match) && variable == o.variable; return o != null && this.filter.PerformMatch(o.filter, ref match) && this.body.PerformMatch(o.body, ref match) && variable == o.variable;
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Try-finally statement</summary> /// <summary>Try-finally statement</summary>
public sealed partial class TryFinally : TryInstruction public sealed partial class TryFinally : TryInstruction
{ {
@ -1338,7 +1399,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && TryBlock.PerformMatch(o.TryBlock, ref match) && finallyBlock.PerformMatch(o.finallyBlock, ref match); return o != null && TryBlock.PerformMatch(o.TryBlock, ref match) && finallyBlock.PerformMatch(o.finallyBlock, ref match);
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Try-fault statement</summary> /// <summary>Try-fault statement</summary>
public sealed partial class TryFault : TryInstruction public sealed partial class TryFault : TryInstruction
{ {
@ -1361,7 +1424,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && TryBlock.PerformMatch(o.TryBlock, ref match) && faultBlock.PerformMatch(o.faultBlock, ref match); return o != null && TryBlock.PerformMatch(o.TryBlock, ref match) && faultBlock.PerformMatch(o.faultBlock, ref match);
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Breakpoint instruction</summary> /// <summary>Breakpoint instruction</summary>
public sealed partial class DebugBreak : SimpleInstruction public sealed partial class DebugBreak : SimpleInstruction
{ {
@ -1396,7 +1461,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null; return o != null;
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Comparison. The inputs must be both integers; or both floats; or both object references. Object references can only be compared for equality or inequality. Floating-point comparisons evaluate to 0 (false) when an input is NaN, except for 'NaN != NaN' which evaluates to 1 (true).</summary> /// <summary>Comparison. The inputs must be both integers; or both floats; or both object references. Object references can only be compared for equality or inequality. Floating-point comparisons evaluate to 0 (false) when an input is NaN, except for 'NaN != NaN' which evaluates to 1 (true).</summary>
public sealed partial class Comp : BinaryInstruction public sealed partial class Comp : BinaryInstruction
{ {
@ -1419,7 +1486,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && this.Left.PerformMatch(o.Left, ref match) && this.Right.PerformMatch(o.Right, ref match) && this.Kind == o.Kind && this.Sign == o.Sign; return o != null && this.Left.PerformMatch(o.Left, ref match) && this.Right.PerformMatch(o.Right, ref match) && this.Kind == o.Kind && this.Sign == o.Sign;
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Non-virtual method call.</summary> /// <summary>Non-virtual method call.</summary>
public sealed partial class Call : CallInstruction public sealed partial class Call : CallInstruction
{ {
@ -1440,7 +1509,9 @@ namespace ICSharpCode.Decompiler.IL
return visitor.VisitCall(this, context); return visitor.VisitCall(this, context);
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Virtual method call.</summary> /// <summary>Virtual method call.</summary>
public sealed partial class CallVirt : CallInstruction public sealed partial class CallVirt : CallInstruction
{ {
@ -1461,7 +1532,9 @@ namespace ICSharpCode.Decompiler.IL
return visitor.VisitCallVirt(this, context); return visitor.VisitCallVirt(this, context);
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Checks that the input float is not NaN or infinite.</summary> /// <summary>Checks that the input float is not NaN or infinite.</summary>
public sealed partial class Ckfinite : UnaryInstruction public sealed partial class Ckfinite : UnaryInstruction
{ {
@ -1496,7 +1569,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && this.Argument.PerformMatch(o.Argument, ref match); return o != null && this.Argument.PerformMatch(o.Argument, ref match);
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Numeric cast.</summary> /// <summary>Numeric cast.</summary>
public sealed partial class Conv : UnaryInstruction public sealed partial class Conv : UnaryInstruction
{ {
@ -1519,7 +1594,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && this.Argument.PerformMatch(o.Argument, ref match) && CheckForOverflow == o.CheckForOverflow && Kind == o.Kind && InputSign == o.InputSign && TargetType == o.TargetType; return o != null && this.Argument.PerformMatch(o.Argument, ref match) && CheckForOverflow == o.CheckForOverflow && Kind == o.Kind && InputSign == o.InputSign && TargetType == o.TargetType;
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Loads the value of a local variable. (ldarg/ldloc)</summary> /// <summary>Loads the value of a local variable. (ldarg/ldloc)</summary>
public sealed partial class LdLoc : SimpleInstruction, IInstructionWithVariableOperand public sealed partial class LdLoc : SimpleInstruction, IInstructionWithVariableOperand
{ {
@ -1591,7 +1668,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && variable == o.variable; return o != null && variable == o.variable;
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Loads the address of a local variable. (ldarga/ldloca)</summary> /// <summary>Loads the address of a local variable. (ldarga/ldloca)</summary>
public sealed partial class LdLoca : SimpleInstruction, IInstructionWithVariableOperand public sealed partial class LdLoca : SimpleInstruction, IInstructionWithVariableOperand
{ {
@ -1654,7 +1733,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && variable == o.variable; return o != null && variable == o.variable;
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Stores a value into a local variable. (starg/stloc)</summary> /// <summary>Stores a value into a local variable. (starg/stloc)</summary>
public sealed partial class StLoc : ILInstruction, IInstructionWithVariableOperand public sealed partial class StLoc : ILInstruction, IInstructionWithVariableOperand
{ {
@ -1777,7 +1858,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && variable == o.variable && this.value.PerformMatch(o.value, ref match); return o != null && variable == o.variable && this.value.PerformMatch(o.value, ref match);
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Stores the value into an anonymous temporary variable, and returns the address of that variable.</summary> /// <summary>Stores the value into an anonymous temporary variable, and returns the address of that variable.</summary>
public sealed partial class AddressOf : ILInstruction public sealed partial class AddressOf : ILInstruction
{ {
@ -1867,7 +1950,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && this.value.PerformMatch(o.value, ref match); return o != null && this.value.PerformMatch(o.value, ref match);
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Loads a constant string.</summary> /// <summary>Loads a constant string.</summary>
public sealed partial class LdStr : SimpleInstruction public sealed partial class LdStr : SimpleInstruction
{ {
@ -1901,7 +1986,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && this.Value == o.Value; return o != null && this.Value == o.Value;
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Loads a constant 32-bit integer.</summary> /// <summary>Loads a constant 32-bit integer.</summary>
public sealed partial class LdcI4 : SimpleInstruction public sealed partial class LdcI4 : SimpleInstruction
{ {
@ -1935,7 +2022,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && this.Value == o.Value; return o != null && this.Value == o.Value;
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Loads a constant 64-bit integer.</summary> /// <summary>Loads a constant 64-bit integer.</summary>
public sealed partial class LdcI8 : SimpleInstruction public sealed partial class LdcI8 : SimpleInstruction
{ {
@ -1969,7 +2058,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && this.Value == o.Value; return o != null && this.Value == o.Value;
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Loads a constant floating-point number.</summary> /// <summary>Loads a constant floating-point number.</summary>
public sealed partial class LdcF : SimpleInstruction public sealed partial class LdcF : SimpleInstruction
{ {
@ -2003,7 +2094,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && this.Value == o.Value; return o != null && this.Value == o.Value;
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Loads a constant decimal.</summary> /// <summary>Loads a constant decimal.</summary>
public sealed partial class LdcDecimal : SimpleInstruction public sealed partial class LdcDecimal : SimpleInstruction
{ {
@ -2037,7 +2130,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && this.Value == o.Value; return o != null && this.Value == o.Value;
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Loads the null reference.</summary> /// <summary>Loads the null reference.</summary>
public sealed partial class LdNull : SimpleInstruction public sealed partial class LdNull : SimpleInstruction
{ {
@ -2063,7 +2158,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null; return o != null;
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Load method pointer</summary> /// <summary>Load method pointer</summary>
public sealed partial class LdFtn : SimpleInstruction, IInstructionWithMethodOperand public sealed partial class LdFtn : SimpleInstruction, IInstructionWithMethodOperand
{ {
@ -2099,7 +2196,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && method.Equals(o.method); return o != null && method.Equals(o.method);
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Load method pointer</summary> /// <summary>Load method pointer</summary>
public sealed partial class LdVirtFtn : UnaryInstruction, IInstructionWithMethodOperand public sealed partial class LdVirtFtn : UnaryInstruction, IInstructionWithMethodOperand
{ {
@ -2147,7 +2246,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && this.Argument.PerformMatch(o.Argument, ref match) && method.Equals(o.method); return o != null && this.Argument.PerformMatch(o.Argument, ref match) && method.Equals(o.method);
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Loads runtime representation of metadata token</summary> /// <summary>Loads runtime representation of metadata token</summary>
public sealed partial class LdTypeToken : SimpleInstruction public sealed partial class LdTypeToken : SimpleInstruction
{ {
@ -2183,7 +2284,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && type.Equals(o.type); return o != null && type.Equals(o.type);
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Loads runtime representation of metadata token</summary> /// <summary>Loads runtime representation of metadata token</summary>
public sealed partial class LdMemberToken : SimpleInstruction public sealed partial class LdMemberToken : SimpleInstruction
{ {
@ -2219,7 +2322,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && member.Equals(o.member); return o != null && member.Equals(o.member);
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Allocates space in the stack frame</summary> /// <summary>Allocates space in the stack frame</summary>
public sealed partial class LocAlloc : UnaryInstruction public sealed partial class LocAlloc : UnaryInstruction
{ {
@ -2254,7 +2359,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && this.Argument.PerformMatch(o.Argument, ref match); return o != null && this.Argument.PerformMatch(o.Argument, ref match);
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Returns from the current method or lambda.</summary> /// <summary>Returns from the current method or lambda.</summary>
public sealed partial class Return : ILInstruction public sealed partial class Return : ILInstruction
{ {
@ -2277,7 +2384,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && this.hasArgument == o.hasArgument && (!hasArgument || this.ReturnValue.PerformMatch(o.ReturnValue, ref match)); return o != null && this.hasArgument == o.hasArgument && (!hasArgument || this.ReturnValue.PerformMatch(o.ReturnValue, ref match));
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Load address of instance field</summary> /// <summary>Load address of instance field</summary>
public sealed partial class LdFlda : ILInstruction, IInstructionWithFieldOperand public sealed partial class LdFlda : ILInstruction, IInstructionWithFieldOperand
{ {
@ -2374,7 +2483,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && this.target.PerformMatch(o.target, ref match) && field.Equals(o.field); return o != null && this.target.PerformMatch(o.target, ref match) && field.Equals(o.field);
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Load static field address</summary> /// <summary>Load static field address</summary>
public sealed partial class LdsFlda : SimpleInstruction, IInstructionWithFieldOperand public sealed partial class LdsFlda : SimpleInstruction, IInstructionWithFieldOperand
{ {
@ -2410,7 +2521,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && field.Equals(o.field); return o != null && field.Equals(o.field);
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Casts an object to a class.</summary> /// <summary>Casts an object to a class.</summary>
public sealed partial class CastClass : UnaryInstruction public sealed partial class CastClass : UnaryInstruction
{ {
@ -2458,7 +2571,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && this.Argument.PerformMatch(o.Argument, ref match) && type.Equals(o.type); return o != null && this.Argument.PerformMatch(o.Argument, ref match) && type.Equals(o.type);
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Test if object is instance of class or interface.</summary> /// <summary>Test if object is instance of class or interface.</summary>
public sealed partial class IsInst : UnaryInstruction public sealed partial class IsInst : UnaryInstruction
{ {
@ -2497,7 +2612,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && this.Argument.PerformMatch(o.Argument, ref match) && type.Equals(o.type); return o != null && this.Argument.PerformMatch(o.Argument, ref match) && type.Equals(o.type);
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Indirect load (ref/pointer dereference).</summary> /// <summary>Indirect load (ref/pointer dereference).</summary>
public sealed partial class LdObj : ILInstruction, ISupportsVolatilePrefix, ISupportsUnalignedPrefix public sealed partial class LdObj : ILInstruction, ISupportsVolatilePrefix, ISupportsUnalignedPrefix
{ {
@ -2601,7 +2718,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && this.target.PerformMatch(o.target, ref match) && type.Equals(o.type) && IsVolatile == o.IsVolatile && UnalignedPrefix == o.UnalignedPrefix; return o != null && this.target.PerformMatch(o.target, ref match) && type.Equals(o.type) && IsVolatile == o.IsVolatile && UnalignedPrefix == o.UnalignedPrefix;
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Indirect store (store to ref/pointer).</summary> /// <summary>Indirect store (store to ref/pointer).</summary>
public sealed partial class StObj : ILInstruction, ISupportsVolatilePrefix, ISupportsUnalignedPrefix public sealed partial class StObj : ILInstruction, ISupportsVolatilePrefix, ISupportsUnalignedPrefix
{ {
@ -2725,7 +2844,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && this.target.PerformMatch(o.target, ref match) && this.value.PerformMatch(o.value, ref match) && type.Equals(o.type) && IsVolatile == o.IsVolatile && UnalignedPrefix == o.UnalignedPrefix; return o != null && this.target.PerformMatch(o.target, ref match) && this.value.PerformMatch(o.value, ref match) && type.Equals(o.type) && IsVolatile == o.IsVolatile && UnalignedPrefix == o.UnalignedPrefix;
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Boxes a value.</summary> /// <summary>Boxes a value.</summary>
public sealed partial class Box : UnaryInstruction public sealed partial class Box : UnaryInstruction
{ {
@ -2773,7 +2894,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && this.Argument.PerformMatch(o.Argument, ref match) && type.Equals(o.type); return o != null && this.Argument.PerformMatch(o.Argument, ref match) && type.Equals(o.type);
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Compute address inside box.</summary> /// <summary>Compute address inside box.</summary>
public sealed partial class Unbox : UnaryInstruction public sealed partial class Unbox : UnaryInstruction
{ {
@ -2821,7 +2944,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && this.Argument.PerformMatch(o.Argument, ref match) && type.Equals(o.type); return o != null && this.Argument.PerformMatch(o.Argument, ref match) && type.Equals(o.type);
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Unbox a value.</summary> /// <summary>Unbox a value.</summary>
public sealed partial class UnboxAny : UnaryInstruction public sealed partial class UnboxAny : UnaryInstruction
{ {
@ -2869,7 +2994,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && this.Argument.PerformMatch(o.Argument, ref match) && type.Equals(o.type); return o != null && this.Argument.PerformMatch(o.Argument, ref match) && type.Equals(o.type);
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Creates an object instance and calls the constructor.</summary> /// <summary>Creates an object instance and calls the constructor.</summary>
public sealed partial class NewObj : CallInstruction public sealed partial class NewObj : CallInstruction
{ {
@ -2890,7 +3017,9 @@ namespace ICSharpCode.Decompiler.IL
return visitor.VisitNewObj(this, context); return visitor.VisitNewObj(this, context);
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Creates an array instance.</summary> /// <summary>Creates an array instance.</summary>
public sealed partial class NewArr : ILInstruction public sealed partial class NewArr : ILInstruction
{ {
@ -2979,7 +3108,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && type.Equals(o.type) && Patterns.ListMatch.DoMatch(this.Indices, o.Indices, ref match); return o != null && type.Equals(o.type) && Patterns.ListMatch.DoMatch(this.Indices, o.Indices, ref match);
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Returns the default value for a type.</summary> /// <summary>Returns the default value for a type.</summary>
public sealed partial class DefaultValue : SimpleInstruction public sealed partial class DefaultValue : SimpleInstruction
{ {
@ -3015,7 +3146,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && type.Equals(o.type); return o != null && type.Equals(o.type);
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Throws an exception.</summary> /// <summary>Throws an exception.</summary>
public sealed partial class Throw : UnaryInstruction public sealed partial class Throw : UnaryInstruction
{ {
@ -3050,7 +3183,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && this.Argument.PerformMatch(o.Argument, ref match); return o != null && this.Argument.PerformMatch(o.Argument, ref match);
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Rethrows the current exception.</summary> /// <summary>Rethrows the current exception.</summary>
public sealed partial class Rethrow : SimpleInstruction public sealed partial class Rethrow : SimpleInstruction
{ {
@ -3085,7 +3220,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null; return o != null;
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Gets the size of a type in bytes.</summary> /// <summary>Gets the size of a type in bytes.</summary>
public sealed partial class SizeOf : SimpleInstruction public sealed partial class SizeOf : SimpleInstruction
{ {
@ -3121,7 +3258,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && type.Equals(o.type); return o != null && type.Equals(o.type);
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Returns the length of an array as 'native unsigned int'.</summary> /// <summary>Returns the length of an array as 'native unsigned int'.</summary>
public sealed partial class LdLen : ILInstruction public sealed partial class LdLen : ILInstruction
{ {
@ -3199,7 +3338,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && this.array.PerformMatch(o.array, ref match); return o != null && this.array.PerformMatch(o.array, ref match);
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Load address of array element.</summary> /// <summary>Load address of array element.</summary>
public sealed partial class LdElema : ILInstruction public sealed partial class LdElema : ILInstruction
{ {
@ -3311,7 +3452,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && type.Equals(o.type) && this.array.PerformMatch(o.array, ref match) && Patterns.ListMatch.DoMatch(this.Indices, o.Indices, ref match) && IsReadOnly == o.IsReadOnly; return o != null && type.Equals(o.type) && this.array.PerformMatch(o.array, ref match) && Patterns.ListMatch.DoMatch(this.Indices, o.Indices, ref match) && IsReadOnly == o.IsReadOnly;
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Converts an array pointer (O) to a reference to the first element, or to a null reference if the array is null or empty. /// <summary>Converts an array pointer (O) to a reference to the first element, or to a null reference if the array is null or empty.
/// Also used to convert a string to a reference to the first character.</summary> /// Also used to convert a string to a reference to the first character.</summary>
public sealed partial class ArrayToPointer : ILInstruction public sealed partial class ArrayToPointer : ILInstruction
@ -3402,7 +3545,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && this.array.PerformMatch(o.array, ref match); return o != null && this.array.PerformMatch(o.array, ref match);
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Push a typed reference of type class onto the stack.</summary> /// <summary>Push a typed reference of type class onto the stack.</summary>
public sealed partial class MakeRefAny : UnaryInstruction public sealed partial class MakeRefAny : UnaryInstruction
{ {
@ -3441,7 +3586,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && this.Argument.PerformMatch(o.Argument, ref match) && type.Equals(o.type); return o != null && this.Argument.PerformMatch(o.Argument, ref match) && type.Equals(o.type);
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Push the type token stored in a typed reference.</summary> /// <summary>Push the type token stored in a typed reference.</summary>
public sealed partial class RefAnyType : UnaryInstruction public sealed partial class RefAnyType : UnaryInstruction
{ {
@ -3467,7 +3614,9 @@ namespace ICSharpCode.Decompiler.IL
return o != null && this.Argument.PerformMatch(o.Argument, ref match); return o != null && this.Argument.PerformMatch(o.Argument, ref match);
} }
} }
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Push the address stored in a typed reference.</summary> /// <summary>Push the address stored in a typed reference.</summary>
public sealed partial class RefAnyValue : UnaryInstruction public sealed partial class RefAnyValue : UnaryInstruction
{ {
@ -3515,8 +3664,53 @@ namespace ICSharpCode.Decompiler.IL
return o != null && this.Argument.PerformMatch(o.Argument, ref match) && type.Equals(o.type); return o != null && this.Argument.PerformMatch(o.Argument, ref match) && type.Equals(o.type);
} }
} }
}
namespace ICSharpCode.Decompiler.IL.Patterns
{
/// <summary>Matches any node</summary>
public sealed partial class AnyNode : PatternInstruction
{
protected sealed override int GetChildCount()
{
return 0;
}
protected sealed override ILInstruction GetChild(int index)
{
switch (index) {
default:
throw new IndexOutOfRangeException();
}
}
protected sealed override void SetChild(int index, ILInstruction value)
{
switch (index) {
default:
throw new IndexOutOfRangeException();
}
}
protected sealed override SlotInfo GetChildSlot(int index)
{
switch (index) {
default:
throw new IndexOutOfRangeException();
}
}
public sealed override ILInstruction Clone()
{
var clone = (AnyNode)ShallowClone();
return clone;
}
public override void WriteTo(ITextOutput output)
{
output.Write(OpCode);
output.Write('(');
output.Write(')');
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary> /// <summary>
/// Base class for visitor pattern. /// Base class for visitor pattern.
/// </summary> /// </summary>
@ -4369,6 +4563,7 @@ namespace ICSharpCode.Decompiler.IL
"mkrefany", "mkrefany",
"refanytype", "refanytype",
"refanyval", "refanyval",
"AnyNode",
}; };
} }

26
ICSharpCode.Decompiler/IL/Instructions.tt

@ -33,6 +33,7 @@
new OpCode("CallInstruction", "Instruction with a list of arguments.", new OpCode("CallInstruction", "Instruction with a list of arguments.",
AbstractBaseClass, CustomChildren(new []{ new ArgumentInfo("arguments") { IsCollection = true }}), AbstractBaseClass, CustomChildren(new []{ new ArgumentInfo("arguments") { IsCollection = true }}),
CustomWriteTo, MayThrow, SideEffect), CustomWriteTo, MayThrow, SideEffect),
new OpCode("PatternInstruction", "Base class for pattern matching in ILAst.", AbstractBaseClass, ResultType("Unknown")) { Namespace = "ICSharpCode.Decompiler.IL.Patterns" }
}; };
OpCode[] opCodes = { OpCode[] opCodes = {
@ -209,6 +210,9 @@
CustomClassName("RefAnyType"), Unary, ResultType("O")), CustomClassName("RefAnyType"), Unary, ResultType("O")),
new OpCode("refanyval", "Push the address stored in a typed reference.", new OpCode("refanyval", "Push the address stored in a typed reference.",
CustomClassName("RefAnyValue"), Unary, HasTypeOperand, MayThrow, ResultType("Ref")), CustomClassName("RefAnyValue"), Unary, HasTypeOperand, MayThrow, ResultType("Ref")),
// patterns
new OpCode("AnyNode", "Matches any node", Pattern, CustomArguments(), CustomConstructor),
}; };
#> #>
using System; using System;
@ -229,8 +233,11 @@ namespace ICSharpCode.Decompiler.IL
<#=opCode.Name#>, <#=opCode.Name#>,
<# } #> <# } #>
} }
}
<# foreach (OpCode opCode in baseClasses.Concat(opCodes)) { #> <# foreach (OpCode opCode in baseClasses.Concat(opCodes)) { #>
namespace <#=opCode.Namespace#>
{
/// <summary><#=opCode.Description.Replace("\n", "\n\t/// ")#></summary> /// <summary><#=opCode.Description.Replace("\n", "\n\t/// ")#></summary>
<#=opCode.ClassModifiers#> partial class <#=opCode.Name#> : <#=string.Join(", ", new[]{opCode.BaseClass}.Concat(opCode.Interfaces))#> <#=opCode.ClassModifiers#> partial class <#=opCode.Name#> : <#=string.Join(", ", new[]{opCode.BaseClass}.Concat(opCode.Interfaces))#>
{ {
@ -278,9 +285,11 @@ namespace ICSharpCode.Decompiler.IL
} }
<# } #> <# } #>
} }
}
<# } #> <# } #>
namespace ICSharpCode.Decompiler.IL
{
/// <summary> /// <summary>
/// Base class for visitor pattern. /// Base class for visitor pattern.
/// </summary> /// </summary>
@ -289,7 +298,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Called by Visit*() methods that were not overridden</summary> /// <summary>Called by Visit*() methods that were not overridden</summary>
protected abstract void Default(ILInstruction inst); protected abstract void Default(ILInstruction inst);
<# foreach (OpCode opCode in opCodes) { #> <# foreach (OpCode opCode in opCodes.Where(o => o.GenerateAcceptVisitor)) { #>
protected internal virtual void Visit<#=opCode.Name#>(<#=opCode.Name#> <#=opCode.VariableName#>) protected internal virtual void Visit<#=opCode.Name#>(<#=opCode.Name#> <#=opCode.VariableName#>)
{ {
Default(<#=opCode.VariableName#>); Default(<#=opCode.VariableName#>);
@ -305,7 +314,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Called by Visit*() methods that were not overridden</summary> /// <summary>Called by Visit*() methods that were not overridden</summary>
protected abstract T Default(ILInstruction inst); protected abstract T Default(ILInstruction inst);
<# foreach (OpCode opCode in opCodes) { #> <# foreach (OpCode opCode in opCodes.Where(o => o.GenerateAcceptVisitor)) { #>
protected internal virtual T Visit<#=opCode.Name#>(<#=opCode.Name#> <#=opCode.VariableName#>) protected internal virtual T Visit<#=opCode.Name#>(<#=opCode.Name#> <#=opCode.VariableName#>)
{ {
return Default(<#=opCode.VariableName#>); return Default(<#=opCode.VariableName#>);
@ -321,7 +330,7 @@ namespace ICSharpCode.Decompiler.IL
/// <summary>Called by Visit*() methods that were not overridden</summary> /// <summary>Called by Visit*() methods that were not overridden</summary>
protected abstract T Default(ILInstruction inst, C context); protected abstract T Default(ILInstruction inst, C context);
<# foreach (OpCode opCode in opCodes) { #> <# foreach (OpCode opCode in opCodes.Where(o => o.GenerateAcceptVisitor)) { #>
protected internal virtual T Visit<#=opCode.Name#>(<#=opCode.Name#> <#=opCode.VariableName#>, C context) protected internal virtual T Visit<#=opCode.Name#>(<#=opCode.Name#> <#=opCode.VariableName#>, C context)
{ {
return Default(<#=opCode.VariableName#>, context); return Default(<#=opCode.VariableName#>, context);
@ -395,6 +404,7 @@ namespace ICSharpCode.Decompiler.IL
{ {
public readonly string OriginalName; public readonly string OriginalName;
public string Name; public string Name;
public string Namespace = "ICSharpCode.Decompiler.IL";
public readonly string Description; public readonly string Description;
public string VariableName = "inst"; public string VariableName = "inst";
@ -944,4 +954,12 @@ protected override void Disconnected()
opCode.WriteOpCodePrefix.Add("if (IsReadOnly)" + Environment.NewLine + "\toutput.Write(\"readonly.\");"); opCode.WriteOpCodePrefix.Add("if (IsReadOnly)" + Environment.NewLine + "\toutput.Write(\"readonly.\");");
opCode.PerformMatchConditions.Add("IsReadOnly == o.IsReadOnly"); opCode.PerformMatchConditions.Add("IsReadOnly == o.IsReadOnly");
}; };
static Action<OpCode> Pattern = opCode => {
BaseClass("PatternInstruction")(opCode);
opCode.Namespace = "ICSharpCode.Decompiler.IL.Patterns";
opCode.GenerateAcceptVisitor = false;
opCode.GenerateMatch = false;
opCode.GeneratePerformMatch = false;
};
#> #>

57
ICSharpCode.Decompiler/IL/Patterns/AnyNode.cs

@ -0,0 +1,57 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ICSharpCode.Decompiler.IL.Patterns
{
partial class PatternInstruction : ILInstruction
{
public override void AcceptVisitor(ILVisitor visitor)
{
throw new NotSupportedException();
}
public override T AcceptVisitor<C, T>(ILVisitor<C, T> visitor, C context)
{
throw new NotSupportedException();
}
public override T AcceptVisitor<T>(ILVisitor<T> visitor)
{
throw new NotSupportedException();
}
protected override InstructionFlags ComputeFlags()
{
throw new NotSupportedException();
}
public override InstructionFlags DirectFlags
{
get {
throw new NotSupportedException();
}
}
}
partial class AnyNode : PatternInstruction
{
CaptureGroup group;
public AnyNode(CaptureGroup group = null)
: base(OpCode.AnyNode)
{
this.group = group;
}
protected internal override bool PerformMatch(ILInstruction other, ref Match match)
{
if (other == null)
return false;
match.Add(group, other);
return true;
}
}
}
Loading…
Cancel
Save