// Copyright (c) 2014-2020 Daniel Grunwald
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.Decompiler.IL
{
///
/// Enum representing the type of an .
///
public enum OpCode : byte
{
/// Represents invalid IL. Semantically, this instruction is considered to throw some kind of exception.
InvalidBranch,
/// Represents invalid IL. Semantically, this instruction is considered to produce some kind of value.
InvalidExpression,
/// No operation. Takes 0 arguments and returns void.
Nop,
/// A container of IL blocks.
ILFunction,
/// A container of IL blocks.
BlockContainer,
/// A block of IL instructions.
Block,
/// A region where a pinned variable is used (initial representation of future fixed statement).
PinnedRegion,
/// Common instruction for add, sub, mul, div, rem, bit.and, bit.or, bit.xor, shl and shr.
BinaryNumericInstruction,
/// Common instruction for numeric compound assignments.
NumericCompoundAssign,
/// Common instruction for user-defined compound assignments.
UserDefinedCompoundAssign,
/// Common instruction for dynamic compound assignments.
DynamicCompoundAssign,
/// Bitwise NOT
BitNot,
/// Retrieves the RuntimeArgumentHandle.
Arglist,
/// Unconditional branch. goto target;
Branch,
/// Unconditional branch to end of block container. Return is represented using IsLeavingFunction and an (optional) return value. The block container evaluates to the value produced by the argument of the leave instruction.
Leave,
/// If statement / conditional expression. if (condition) trueExpr else falseExpr
IfInstruction,
/// Null coalescing operator expression. if.notnull(valueInst, fallbackInst)
NullCoalescingInstruction,
/// Switch statement
SwitchInstruction,
/// Switch section within a switch statement
SwitchSection,
/// Try-catch statement.
TryCatch,
/// Catch handler within a try-catch statement.
TryCatchHandler,
/// Try-finally statement
TryFinally,
/// Try-fault statement
TryFault,
/// Lock statement
LockInstruction,
/// Using statement
UsingInstruction,
/// Breakpoint instruction
DebugBreak,
/// 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).
Comp,
/// Non-virtual method call.
Call,
/// Virtual method call.
CallVirt,
/// Unsafe function pointer call.
CallIndirect,
/// Checks that the input float is not NaN or infinite.
Ckfinite,
/// Numeric cast.
Conv,
/// Loads the value of a local variable. (ldarg/ldloc)
LdLoc,
/// Loads the address of a local variable. (ldarga/ldloca)
LdLoca,
/// Stores a value into a local variable. (IL: starg/stloc)
/// Evaluates to the value that was stored (for byte/short variables: evaluates to the truncated value, sign/zero extended back to I4 based on variable.Type.GetSign())
StLoc,
/// Stores the value into an anonymous temporary variable, and returns the address of that variable.
AddressOf,
/// Three valued logic and. Inputs are of type bool? or I4, output is of type bool?. Unlike logic.and(), does not have short-circuiting behavior.
ThreeValuedBoolAnd,
/// Three valued logic or. Inputs are of type bool? or I4, output is of type bool?. Unlike logic.or(), does not have short-circuiting behavior.
ThreeValuedBoolOr,
/// The input operand must be one of:
/// 1. a nullable value type
/// 2. a reference type
/// 3. a managed reference to a type parameter.
/// If the input is non-null, evaluates to the (unwrapped) input.
/// If the input is null, jumps to the innermost nullable.rewrap instruction that contains this instruction.
/// In case 3 (managed reference), the dereferenced value is the input being tested, and the nullable.unwrap instruction returns the managed reference unmodified (if the value is non-null).
NullableUnwrap,
/// Serves as jump target for the nullable.unwrap instruction.
/// If the input evaluates normally, evaluates to the input value (wrapped in Nullable<T> if the input is a non-nullable value type).If a nullable.unwrap instruction encounters a null input and jumps to the (endpoint of the) nullable.rewrap instruction,the nullable.rewrap instruction evaluates to null.
NullableRewrap,
/// Loads a constant string.
LdStr,
/// Loads a constant 32-bit integer.
LdcI4,
/// Loads a constant 64-bit integer.
LdcI8,
/// Loads a constant 32-bit floating-point number.
LdcF4,
/// Loads a constant 64-bit floating-point number.
LdcF8,
/// Loads a constant decimal.
LdcDecimal,
/// Loads the null reference.
LdNull,
/// Load method pointer
LdFtn,
/// Load method pointer
LdVirtFtn,
/// Virtual delegate construction
LdVirtDelegate,
/// Loads runtime representation of metadata token
LdTypeToken,
/// Loads runtime representation of metadata token
LdMemberToken,
/// Allocates space in the stack frame
LocAlloc,
/// Allocates space in the stack frame and wraps it in a Span
LocAllocSpan,
/// memcpy(destAddress, sourceAddress, size);
Cpblk,
/// memset(address, value, size)
Initblk,
/// Load address of instance field
LdFlda,
/// Load static field address
LdsFlda,
/// Casts an object to a class.
CastClass,
/// Test if object is instance of class or interface.
IsInst,
/// Indirect load (ref/pointer dereference).
LdObj,
/// Indirect store (store to ref/pointer).
/// Evaluates to the value that was stored (when using type byte/short: evaluates to the truncated value, sign/zero extended back to I4 based on type.GetSign())
StObj,
/// Boxes a value.
Box,
/// Compute address inside box.
Unbox,
/// Unbox a value.
UnboxAny,
/// Creates an object instance and calls the constructor.
NewObj,
/// Creates an array instance.
NewArr,
/// Returns the default value for a type.
DefaultValue,
/// Throws an exception.
Throw,
/// Rethrows the current exception.
Rethrow,
/// Gets the size of a type in bytes.
SizeOf,
/// Returns the length of an array as 'native unsigned int'.
LdLen,
/// Load address of array element.
LdElema,
/// Retrieves a pinnable reference for the input object.
/// The input must be an object reference (O).
/// If the input is an array/string, evaluates to a reference to the first element/character, or to a null reference if the array is null or empty.
/// Otherwise, uses the GetPinnableReference method to get the reference, or evaluates to a null reference if the input is null.
///
GetPinnableReference,
/// Maps a string value to an integer. This is used in switch(string).
StringToInt,
/// ILAst representation of Expression.Convert.
ExpressionTreeCast,
/// Use of user-defined && or || operator.
UserDefinedLogicOperator,
/// ILAst representation of a short-circuiting binary operator inside a dynamic expression.
DynamicLogicOperatorInstruction,
/// ILAst representation of a binary operator inside a dynamic expression (maps to Binder.BinaryOperation).
DynamicBinaryOperatorInstruction,
/// ILAst representation of a unary operator inside a dynamic expression (maps to Binder.UnaryOperation).
DynamicUnaryOperatorInstruction,
/// ILAst representation of a cast inside a dynamic expression (maps to Binder.Convert).
DynamicConvertInstruction,
/// ILAst representation of a property get method call inside a dynamic expression (maps to Binder.GetMember).
DynamicGetMemberInstruction,
/// ILAst representation of a property set method call inside a dynamic expression (maps to Binder.SetMember).
DynamicSetMemberInstruction,
/// ILAst representation of an indexer get method call inside a dynamic expression (maps to Binder.GetIndex).
DynamicGetIndexInstruction,
/// ILAst representation of an indexer set method call inside a dynamic expression (maps to Binder.SetIndex).
DynamicSetIndexInstruction,
/// ILAst representation of a method call inside a dynamic expression (maps to Binder.InvokeMember).
DynamicInvokeMemberInstruction,
/// ILAst representation of a constuctor invocation inside a dynamic expression (maps to Binder.InvokeConstructor).
DynamicInvokeConstructorInstruction,
/// ILAst representation of a delegate invocation inside a dynamic expression (maps to Binder.Invoke).
DynamicInvokeInstruction,
/// ILAst representation of a call to the Binder.IsEvent method inside a dynamic expression.
DynamicIsEventInstruction,
/// ILAst representation of C# patterns
MatchInstruction,
/// Push a typed reference of type class onto the stack.
MakeRefAny,
/// Push the type token stored in a typed reference.
RefAnyType,
/// Push the address stored in a typed reference.
RefAnyValue,
/// Yield an element from an iterator.
YieldReturn,
/// C# await operator.
Await,
/// Deconstruction statement
DeconstructInstruction,
/// Represents a deconstructed value
DeconstructResultInstruction,
/// Matches any node
AnyNode,
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Instruction without any arguments
public abstract partial class SimpleInstruction : ILInstruction
{
protected SimpleInstruction(OpCode opCode) : base(opCode)
{
}
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 = (SimpleInstruction)ShallowClone();
return clone;
}
protected override InstructionFlags ComputeFlags()
{
return InstructionFlags.None;
}
public override InstructionFlags DirectFlags {
get {
return InstructionFlags.None;
}
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Instruction with a single argument
public abstract partial class UnaryInstruction : ILInstruction
{
protected UnaryInstruction(OpCode opCode, ILInstruction argument) : base(opCode)
{
this.Argument = argument;
}
public static readonly SlotInfo ArgumentSlot = new SlotInfo("Argument", canInlineInto: true);
ILInstruction argument;
public ILInstruction Argument {
get { return this.argument; }
set {
ValidateChild(value);
SetChildInstruction(ref this.argument, value, 0);
}
}
protected sealed override int GetChildCount()
{
return 1;
}
protected sealed override ILInstruction GetChild(int index)
{
switch (index) {
case 0:
return this.argument;
default:
throw new IndexOutOfRangeException();
}
}
protected sealed override void SetChild(int index, ILInstruction value)
{
switch (index) {
case 0:
this.Argument = value;
break;
default:
throw new IndexOutOfRangeException();
}
}
protected sealed override SlotInfo GetChildSlot(int index)
{
switch (index) {
case 0:
return ArgumentSlot;
default:
throw new IndexOutOfRangeException();
}
}
public sealed override ILInstruction Clone()
{
var clone = (UnaryInstruction)ShallowClone();
clone.Argument = this.argument.Clone();
return clone;
}
protected override InstructionFlags ComputeFlags()
{
return argument.Flags | InstructionFlags.None;
}
public override InstructionFlags DirectFlags {
get {
return InstructionFlags.None;
}
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
{
WriteILRange(output, options);
output.Write(OpCode);
output.Write('(');
this.argument.WriteTo(output, options);
output.Write(')');
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Instruction with two arguments: Left and Right
public abstract partial class BinaryInstruction : ILInstruction
{
protected BinaryInstruction(OpCode opCode, ILInstruction left, ILInstruction right) : base(opCode)
{
this.Left = left;
this.Right = right;
}
public static readonly SlotInfo LeftSlot = new SlotInfo("Left", canInlineInto: true);
ILInstruction left;
public ILInstruction Left {
get { return this.left; }
set {
ValidateChild(value);
SetChildInstruction(ref this.left, value, 0);
}
}
public static readonly SlotInfo RightSlot = new SlotInfo("Right", canInlineInto: true);
ILInstruction right;
public ILInstruction Right {
get { return this.right; }
set {
ValidateChild(value);
SetChildInstruction(ref this.right, value, 1);
}
}
protected sealed override int GetChildCount()
{
return 2;
}
protected sealed override ILInstruction GetChild(int index)
{
switch (index) {
case 0:
return this.left;
case 1:
return this.right;
default:
throw new IndexOutOfRangeException();
}
}
protected sealed override void SetChild(int index, ILInstruction value)
{
switch (index) {
case 0:
this.Left = value;
break;
case 1:
this.Right = value;
break;
default:
throw new IndexOutOfRangeException();
}
}
protected sealed override SlotInfo GetChildSlot(int index)
{
switch (index) {
case 0:
return LeftSlot;
case 1:
return RightSlot;
default:
throw new IndexOutOfRangeException();
}
}
public sealed override ILInstruction Clone()
{
var clone = (BinaryInstruction)ShallowClone();
clone.Left = this.left.Clone();
clone.Right = this.right.Clone();
return clone;
}
protected override InstructionFlags ComputeFlags()
{
return left.Flags | right.Flags | InstructionFlags.None;
}
public override InstructionFlags DirectFlags {
get {
return InstructionFlags.None;
}
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
{
WriteILRange(output, options);
output.Write(OpCode);
output.Write('(');
this.left.WriteTo(output, options);
output.Write(", ");
this.right.WriteTo(output, options);
output.Write(')');
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Instruction with a list of arguments.
public abstract partial class CallInstruction : ILInstruction
{
protected CallInstruction(OpCode opCode, params ILInstruction[] arguments) : base(opCode)
{
this.Arguments = new InstructionCollection(this, 0);
this.Arguments.AddRange(arguments);
}
public static readonly SlotInfo ArgumentsSlot = new SlotInfo("Arguments", canInlineInto: true);
public InstructionCollection Arguments { get; private set; }
protected sealed override int GetChildCount()
{
return Arguments.Count;
}
protected sealed override ILInstruction GetChild(int index)
{
switch (index) {
default:
return this.Arguments[index - 0];
}
}
protected sealed override void SetChild(int index, ILInstruction value)
{
switch (index) {
default:
this.Arguments[index - 0] = (ILInstruction)value;
break;
}
}
protected sealed override SlotInfo GetChildSlot(int index)
{
switch (index) {
default:
return ArgumentsSlot;
}
}
public sealed override ILInstruction Clone()
{
var clone = (CallInstruction)ShallowClone();
clone.Arguments = new InstructionCollection(clone, 0);
clone.Arguments.AddRange(this.Arguments.Select(arg => (ILInstruction)arg.Clone()));
return clone;
}
protected override InstructionFlags ComputeFlags()
{
return Arguments.Aggregate(InstructionFlags.None, (f, arg) => f | arg.Flags) | InstructionFlags.MayThrow | InstructionFlags.SideEffect;
}
public override InstructionFlags DirectFlags {
get {
return InstructionFlags.MayThrow | InstructionFlags.SideEffect;
}
}
}
}
namespace ICSharpCode.Decompiler.IL.Patterns
{
/// Base class for pattern matching in ILAst.
public abstract partial class PatternInstruction : ILInstruction
{
protected PatternInstruction(OpCode opCode) : base(opCode)
{
}
public override StackType ResultType { get { return StackType.Unknown; } }
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Common instruction for compound assignments.
public abstract partial class CompoundAssignmentInstruction : ILInstruction
{
public static readonly SlotInfo TargetSlot = new SlotInfo("Target", canInlineInto: true);
ILInstruction target;
public ILInstruction Target {
get { return this.target; }
set {
ValidateChild(value);
SetChildInstruction(ref this.target, value, 0);
}
}
public static readonly SlotInfo ValueSlot = new SlotInfo("Value", canInlineInto: true);
ILInstruction value;
public ILInstruction Value {
get { return this.value; }
set {
ValidateChild(value);
SetChildInstruction(ref this.value, value, 1);
}
}
protected sealed override int GetChildCount()
{
return 2;
}
protected sealed override ILInstruction GetChild(int index)
{
switch (index) {
case 0:
return this.target;
case 1:
return this.value;
default:
throw new IndexOutOfRangeException();
}
}
protected sealed override void SetChild(int index, ILInstruction value)
{
switch (index) {
case 0:
this.Target = value;
break;
case 1:
this.Value = value;
break;
default:
throw new IndexOutOfRangeException();
}
}
protected sealed override SlotInfo GetChildSlot(int index)
{
switch (index) {
case 0:
return TargetSlot;
case 1:
return ValueSlot;
default:
throw new IndexOutOfRangeException();
}
}
public sealed override ILInstruction Clone()
{
var clone = (CompoundAssignmentInstruction)ShallowClone();
clone.Target = this.target.Clone();
clone.Value = this.value.Clone();
return clone;
}
protected override InstructionFlags ComputeFlags()
{
return target.Flags | value.Flags;
}
public override InstructionFlags DirectFlags {
get {
return InstructionFlags.None;
}
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
{
WriteILRange(output, options);
output.Write(OpCode);
output.Write('(');
this.target.WriteTo(output, options);
output.Write(", ");
this.value.WriteTo(output, options);
output.Write(')');
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Instruction representing a dynamic call site.
public abstract partial class DynamicInstruction : ILInstruction
{
protected DynamicInstruction(OpCode opCode) : base(opCode)
{
}
protected override InstructionFlags ComputeFlags()
{
return InstructionFlags.MayThrow | InstructionFlags.SideEffect;
}
public override InstructionFlags DirectFlags {
get {
return InstructionFlags.MayThrow | InstructionFlags.SideEffect;
}
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Represents invalid IL. Semantically, this instruction is considered to throw some kind of exception.
public sealed partial class InvalidBranch : SimpleInstruction
{
public InvalidBranch() : base(OpCode.InvalidBranch)
{
}
protected override InstructionFlags ComputeFlags()
{
return InstructionFlags.MayThrow | InstructionFlags.SideEffect | InstructionFlags.EndPointUnreachable;
}
public override InstructionFlags DirectFlags {
get {
return InstructionFlags.MayThrow | InstructionFlags.SideEffect | InstructionFlags.EndPointUnreachable;
}
}
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitInvalidBranch(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitInvalidBranch(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitInvalidBranch(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as InvalidBranch;
return o != null;
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Represents invalid IL. Semantically, this instruction is considered to produce some kind of value.
public sealed partial class InvalidExpression : SimpleInstruction
{
public InvalidExpression() : base(OpCode.InvalidExpression)
{
}
protected override InstructionFlags ComputeFlags()
{
return InstructionFlags.MayThrow | InstructionFlags.SideEffect;
}
public override InstructionFlags DirectFlags {
get {
return InstructionFlags.MayThrow | InstructionFlags.SideEffect;
}
}
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitInvalidExpression(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitInvalidExpression(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitInvalidExpression(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as InvalidExpression;
return o != null;
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// No operation. Takes 0 arguments and returns void.
public sealed partial class Nop : SimpleInstruction
{
public Nop() : base(OpCode.Nop)
{
}
public override StackType ResultType { get { return StackType.Void; } }
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitNop(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitNop(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitNop(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as Nop;
return o != null;
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// A container of IL blocks.
public sealed partial class ILFunction : ILInstruction
{
public static readonly SlotInfo BodySlot = new SlotInfo("Body");
ILInstruction body;
public ILInstruction Body {
get { return this.body; }
set {
ValidateChild(value);
SetChildInstruction(ref this.body, value, 0);
}
}
public static readonly SlotInfo LocalFunctionsSlot = new SlotInfo("LocalFunctions");
public InstructionCollection LocalFunctions { get; private set; }
protected sealed override int GetChildCount()
{
return 1 + LocalFunctions.Count;
}
protected sealed override ILInstruction GetChild(int index)
{
switch (index) {
case 0:
return this.body;
default:
return this.LocalFunctions[index - 1];
}
}
protected sealed override void SetChild(int index, ILInstruction value)
{
switch (index) {
case 0:
this.Body = value;
break;
default:
this.LocalFunctions[index - 1] = (ILFunction)value;
break;
}
}
protected sealed override SlotInfo GetChildSlot(int index)
{
switch (index) {
case 0:
return BodySlot;
default:
return LocalFunctionsSlot;
}
}
public sealed override ILInstruction Clone()
{
var clone = (ILFunction)ShallowClone();
clone.Body = this.body.Clone();
clone.LocalFunctions = new InstructionCollection(clone, 1);
clone.LocalFunctions.AddRange(this.LocalFunctions.Select(arg => (ILFunction)arg.Clone()));
clone.CloneVariables();
return clone;
}
public override StackType ResultType { get { return DelegateType?.GetStackType() ?? StackType.O; } }
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitILFunction(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitILFunction(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitILFunction(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as ILFunction;
return o != null && this.body.PerformMatch(o.body, ref match) && Patterns.ListMatch.DoMatch(this.LocalFunctions, o.LocalFunctions, ref match);
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// A container of IL blocks.
public sealed partial class BlockContainer : ILInstruction
{
public override StackType ResultType { get { return this.ExpectedResultType; } }
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitBlockContainer(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitBlockContainer(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitBlockContainer(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as BlockContainer;
return o != null && Patterns.ListMatch.DoMatch(this.Blocks, o.Blocks, ref match);
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// A block of IL instructions.
public sealed partial class Block : ILInstruction
{
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitBlock(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitBlock(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitBlock(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as Block;
return o != null && this.Kind == o.Kind && Patterns.ListMatch.DoMatch(this.Instructions, o.Instructions, ref match) && this.FinalInstruction.PerformMatch(o.FinalInstruction, ref match);
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// A region where a pinned variable is used (initial representation of future fixed statement).
public sealed partial class PinnedRegion : ILInstruction, IStoreInstruction
{
public PinnedRegion(ILVariable variable, ILInstruction init, ILInstruction body) : base(OpCode.PinnedRegion)
{
Debug.Assert(variable != null);
this.variable = variable;
this.Init = init;
this.Body = body;
}
public override StackType ResultType { get { return StackType.Void; } }
ILVariable variable;
public ILVariable Variable {
get { return variable; }
set {
Debug.Assert(value != null);
if (IsConnected)
variable.RemoveStoreInstruction(this);
variable = value;
if (IsConnected)
variable.AddStoreInstruction(this);
}
}
public int IndexInStoreInstructionList { get; set; } = -1;
int IInstructionWithVariableOperand.IndexInVariableInstructionMapping {
get { return ((IStoreInstruction)this).IndexInStoreInstructionList; }
set { ((IStoreInstruction)this).IndexInStoreInstructionList = value; }
}
protected override void Connected()
{
base.Connected();
variable.AddStoreInstruction(this);
}
protected override void Disconnected()
{
variable.RemoveStoreInstruction(this);
base.Disconnected();
}
public static readonly SlotInfo InitSlot = new SlotInfo("Init", canInlineInto: true);
ILInstruction init;
public ILInstruction Init {
get { return this.init; }
set {
ValidateChild(value);
SetChildInstruction(ref this.init, value, 0);
}
}
public static readonly SlotInfo BodySlot = new SlotInfo("Body");
ILInstruction body;
public ILInstruction Body {
get { return this.body; }
set {
ValidateChild(value);
SetChildInstruction(ref this.body, value, 1);
}
}
protected sealed override int GetChildCount()
{
return 2;
}
protected sealed override ILInstruction GetChild(int index)
{
switch (index) {
case 0:
return this.init;
case 1:
return this.body;
default:
throw new IndexOutOfRangeException();
}
}
protected sealed override void SetChild(int index, ILInstruction value)
{
switch (index) {
case 0:
this.Init = value;
break;
case 1:
this.Body = value;
break;
default:
throw new IndexOutOfRangeException();
}
}
protected sealed override SlotInfo GetChildSlot(int index)
{
switch (index) {
case 0:
return InitSlot;
case 1:
return BodySlot;
default:
throw new IndexOutOfRangeException();
}
}
public sealed override ILInstruction Clone()
{
var clone = (PinnedRegion)ShallowClone();
clone.Init = this.init.Clone();
clone.Body = this.body.Clone();
return clone;
}
protected override InstructionFlags ComputeFlags()
{
return InstructionFlags.MayWriteLocals | init.Flags | body.Flags;
}
public override InstructionFlags DirectFlags {
get {
return InstructionFlags.MayWriteLocals;
}
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
{
WriteILRange(output, options);
output.Write(OpCode);
output.Write(' ');
variable.WriteTo(output);
output.Write('(');
this.init.WriteTo(output, options);
output.Write(", ");
this.body.WriteTo(output, options);
output.Write(')');
}
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitPinnedRegion(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitPinnedRegion(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitPinnedRegion(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as PinnedRegion;
return o != null && variable == o.variable && this.init.PerformMatch(o.init, ref match) && this.body.PerformMatch(o.body, ref match);
}
internal override void CheckInvariant(ILPhase phase)
{
base.CheckInvariant(phase);
Debug.Assert(phase <= ILPhase.InILReader || this.IsDescendantOf(variable.Function));
Debug.Assert(phase <= ILPhase.InILReader || variable.Function.Variables[variable.IndexInFunction] == variable);
Debug.Assert(Variable.Kind == VariableKind.PinnedRegionLocal);
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Common instruction for add, sub, mul, div, rem, bit.and, bit.or, bit.xor, shl and shr.
public sealed partial class BinaryNumericInstruction : BinaryInstruction
{
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitBinaryNumericInstruction(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitBinaryNumericInstruction(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitBinaryNumericInstruction(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as BinaryNumericInstruction;
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 && IsLifted == o.IsLifted;
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Common instruction for numeric compound assignments.
public sealed partial class NumericCompoundAssign : CompoundAssignmentInstruction
{
IType type;
/// Returns the type operand.
public IType Type {
get { return type; }
set { type = value; InvalidateFlags(); }
}
public override StackType ResultType { get { return type.GetStackType(); } }
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitNumericCompoundAssign(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitNumericCompoundAssign(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitNumericCompoundAssign(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as NumericCompoundAssign;
return o != null && type.Equals(o.type) && CheckForOverflow == o.CheckForOverflow && Sign == o.Sign && Operator == o.Operator && this.EvalMode == o.EvalMode && this.TargetKind == o.TargetKind && Target.PerformMatch(o.Target, ref match) && Value.PerformMatch(o.Value, ref match);
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Common instruction for user-defined compound assignments.
public sealed partial class UserDefinedCompoundAssign : CompoundAssignmentInstruction
{
protected override InstructionFlags ComputeFlags()
{
return base.ComputeFlags() | InstructionFlags.MayThrow | InstructionFlags.SideEffect;
}
public override InstructionFlags DirectFlags {
get {
return base.DirectFlags | InstructionFlags.MayThrow | InstructionFlags.SideEffect;
}
}
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitUserDefinedCompoundAssign(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitUserDefinedCompoundAssign(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitUserDefinedCompoundAssign(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as UserDefinedCompoundAssign;
return o != null && this.Method.Equals(o.Method) && this.EvalMode == o.EvalMode && this.TargetKind == o.TargetKind && Target.PerformMatch(o.Target, ref match) && Value.PerformMatch(o.Value, ref match);
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Common instruction for dynamic compound assignments.
public sealed partial class DynamicCompoundAssign : CompoundAssignmentInstruction
{
public override StackType ResultType { get { return StackType.O; } }
protected override InstructionFlags ComputeFlags()
{
return base.ComputeFlags() | InstructionFlags.MayThrow | InstructionFlags.SideEffect;
}
public override InstructionFlags DirectFlags {
get {
return base.DirectFlags | InstructionFlags.MayThrow | InstructionFlags.SideEffect;
}
}
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitDynamicCompoundAssign(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitDynamicCompoundAssign(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitDynamicCompoundAssign(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as DynamicCompoundAssign;
return o != null && this.EvalMode == o.EvalMode && this.TargetKind == o.TargetKind && Target.PerformMatch(o.Target, ref match) && Value.PerformMatch(o.Value, ref match);
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Bitwise NOT
public sealed partial class BitNot : UnaryInstruction
{
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitBitNot(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitBitNot(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitBitNot(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as BitNot;
return o != null && this.Argument.PerformMatch(o.Argument, ref match) && IsLifted == o.IsLifted && UnderlyingResultType == o.UnderlyingResultType;
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Retrieves the RuntimeArgumentHandle.
public sealed partial class Arglist : SimpleInstruction
{
public Arglist() : base(OpCode.Arglist)
{
}
public override StackType ResultType { get { return StackType.O; } }
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitArglist(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitArglist(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitArglist(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as Arglist;
return o != null;
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Unconditional branch. goto target;
public sealed partial class Branch : SimpleInstruction
{
public override StackType ResultType { get { return StackType.Void; } }
protected override InstructionFlags ComputeFlags()
{
return InstructionFlags.EndPointUnreachable | InstructionFlags.MayBranch;
}
public override InstructionFlags DirectFlags {
get {
return InstructionFlags.EndPointUnreachable | InstructionFlags.MayBranch;
}
}
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitBranch(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitBranch(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitBranch(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as Branch;
return o != null && this.TargetBlock == o.TargetBlock;
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Unconditional branch to end of block container. Return is represented using IsLeavingFunction and an (optional) return value. The block container evaluates to the value produced by the argument of the leave instruction.
public sealed partial class Leave : ILInstruction
{
public static readonly SlotInfo ValueSlot = new SlotInfo("Value", canInlineInto: true);
ILInstruction value;
public ILInstruction Value {
get { return this.value; }
set {
ValidateChild(value);
SetChildInstruction(ref this.value, value, 0);
}
}
protected sealed override int GetChildCount()
{
return 1;
}
protected sealed override ILInstruction GetChild(int index)
{
switch (index) {
case 0:
return this.value;
default:
throw new IndexOutOfRangeException();
}
}
protected sealed override void SetChild(int index, ILInstruction value)
{
switch (index) {
case 0:
this.Value = value;
break;
default:
throw new IndexOutOfRangeException();
}
}
protected sealed override SlotInfo GetChildSlot(int index)
{
switch (index) {
case 0:
return ValueSlot;
default:
throw new IndexOutOfRangeException();
}
}
public sealed override ILInstruction Clone()
{
var clone = (Leave)ShallowClone();
clone.Value = this.value.Clone();
return clone;
}
public override StackType ResultType { get { return StackType.Void; } }
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitLeave(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitLeave(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitLeave(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as Leave;
return o != null && this.value.PerformMatch(o.value, ref match) && this.TargetContainer == o.TargetContainer;
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// If statement / conditional expression. if (condition) trueExpr else falseExpr
public sealed partial class IfInstruction : ILInstruction
{
public static readonly SlotInfo ConditionSlot = new SlotInfo("Condition", canInlineInto: true);
ILInstruction condition;
public ILInstruction Condition {
get { return this.condition; }
set {
ValidateChild(value);
SetChildInstruction(ref this.condition, value, 0);
}
}
public static readonly SlotInfo TrueInstSlot = new SlotInfo("TrueInst");
ILInstruction trueInst;
public ILInstruction TrueInst {
get { return this.trueInst; }
set {
ValidateChild(value);
SetChildInstruction(ref this.trueInst, value, 1);
}
}
public static readonly SlotInfo FalseInstSlot = new SlotInfo("FalseInst");
ILInstruction falseInst;
public ILInstruction FalseInst {
get { return this.falseInst; }
set {
ValidateChild(value);
SetChildInstruction(ref this.falseInst, value, 2);
}
}
protected sealed override int GetChildCount()
{
return 3;
}
protected sealed override ILInstruction GetChild(int index)
{
switch (index) {
case 0:
return this.condition;
case 1:
return this.trueInst;
case 2:
return this.falseInst;
default:
throw new IndexOutOfRangeException();
}
}
protected sealed override void SetChild(int index, ILInstruction value)
{
switch (index) {
case 0:
this.Condition = value;
break;
case 1:
this.TrueInst = value;
break;
case 2:
this.FalseInst = value;
break;
default:
throw new IndexOutOfRangeException();
}
}
protected sealed override SlotInfo GetChildSlot(int index)
{
switch (index) {
case 0:
return ConditionSlot;
case 1:
return TrueInstSlot;
case 2:
return FalseInstSlot;
default:
throw new IndexOutOfRangeException();
}
}
public sealed override ILInstruction Clone()
{
var clone = (IfInstruction)ShallowClone();
clone.Condition = this.condition.Clone();
clone.TrueInst = this.trueInst.Clone();
clone.FalseInst = this.falseInst.Clone();
return clone;
}
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitIfInstruction(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitIfInstruction(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitIfInstruction(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as IfInstruction;
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
{
/// Null coalescing operator expression. if.notnull(valueInst, fallbackInst)
public sealed partial class NullCoalescingInstruction : ILInstruction
{
public static readonly SlotInfo ValueInstSlot = new SlotInfo("ValueInst", canInlineInto: true);
ILInstruction valueInst;
public ILInstruction ValueInst {
get { return this.valueInst; }
set {
ValidateChild(value);
SetChildInstruction(ref this.valueInst, value, 0);
}
}
public static readonly SlotInfo FallbackInstSlot = new SlotInfo("FallbackInst");
ILInstruction fallbackInst;
public ILInstruction FallbackInst {
get { return this.fallbackInst; }
set {
ValidateChild(value);
SetChildInstruction(ref this.fallbackInst, value, 1);
}
}
protected sealed override int GetChildCount()
{
return 2;
}
protected sealed override ILInstruction GetChild(int index)
{
switch (index) {
case 0:
return this.valueInst;
case 1:
return this.fallbackInst;
default:
throw new IndexOutOfRangeException();
}
}
protected sealed override void SetChild(int index, ILInstruction value)
{
switch (index) {
case 0:
this.ValueInst = value;
break;
case 1:
this.FallbackInst = value;
break;
default:
throw new IndexOutOfRangeException();
}
}
protected sealed override SlotInfo GetChildSlot(int index)
{
switch (index) {
case 0:
return ValueInstSlot;
case 1:
return FallbackInstSlot;
default:
throw new IndexOutOfRangeException();
}
}
public sealed override ILInstruction Clone()
{
var clone = (NullCoalescingInstruction)ShallowClone();
clone.ValueInst = this.valueInst.Clone();
clone.FallbackInst = this.fallbackInst.Clone();
return clone;
}
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitNullCoalescingInstruction(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitNullCoalescingInstruction(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitNullCoalescingInstruction(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as NullCoalescingInstruction;
return o != null && this.valueInst.PerformMatch(o.valueInst, ref match) && this.fallbackInst.PerformMatch(o.fallbackInst, ref match);
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Switch statement
public sealed partial class SwitchInstruction : ILInstruction
{
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitSwitchInstruction(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitSwitchInstruction(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitSwitchInstruction(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as SwitchInstruction;
return o != null && IsLifted == o.IsLifted && Value.PerformMatch(o.Value, ref match) && Patterns.ListMatch.DoMatch(this.Sections, o.Sections, ref match);
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Switch section within a switch statement
public sealed partial class SwitchSection : ILInstruction
{
public static readonly SlotInfo BodySlot = new SlotInfo("Body");
ILInstruction body;
public ILInstruction Body {
get { return this.body; }
set {
ValidateChild(value);
SetChildInstruction(ref this.body, value, 0);
}
}
protected sealed override int GetChildCount()
{
return 1;
}
protected sealed override ILInstruction GetChild(int index)
{
switch (index) {
case 0:
return this.body;
default:
throw new IndexOutOfRangeException();
}
}
protected sealed override void SetChild(int index, ILInstruction value)
{
switch (index) {
case 0:
this.Body = value;
break;
default:
throw new IndexOutOfRangeException();
}
}
protected sealed override SlotInfo GetChildSlot(int index)
{
switch (index) {
case 0:
return BodySlot;
default:
throw new IndexOutOfRangeException();
}
}
public sealed override ILInstruction Clone()
{
var clone = (SwitchSection)ShallowClone();
clone.Body = this.body.Clone();
return clone;
}
public override StackType ResultType { get { return StackType.Void; } }
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitSwitchSection(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitSwitchSection(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitSwitchSection(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as SwitchSection;
return o != null && this.body.PerformMatch(o.body, ref match) && this.Labels.SetEquals(o.Labels) && this.HasNullLabel == o.HasNullLabel;
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Try-catch statement.
public sealed partial class TryCatch : TryInstruction
{
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitTryCatch(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitTryCatch(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitTryCatch(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as TryCatch;
return o != null && TryBlock.PerformMatch(o.TryBlock, ref match) && Patterns.ListMatch.DoMatch(Handlers, o.Handlers, ref match);
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Catch handler within a try-catch statement.
public sealed partial class TryCatchHandler : ILInstruction, IStoreInstruction
{
public TryCatchHandler(ILInstruction filter, ILInstruction body, ILVariable variable) : base(OpCode.TryCatchHandler)
{
this.Filter = filter;
this.Body = body;
Debug.Assert(variable != null);
this.variable = variable;
}
public static readonly SlotInfo FilterSlot = new SlotInfo("Filter");
ILInstruction filter;
public ILInstruction Filter {
get { return this.filter; }
set {
ValidateChild(value);
SetChildInstruction(ref this.filter, value, 0);
}
}
public static readonly SlotInfo BodySlot = new SlotInfo("Body");
ILInstruction body;
public ILInstruction Body {
get { return this.body; }
set {
ValidateChild(value);
SetChildInstruction(ref this.body, value, 1);
}
}
protected sealed override int GetChildCount()
{
return 2;
}
protected sealed override ILInstruction GetChild(int index)
{
switch (index) {
case 0:
return this.filter;
case 1:
return this.body;
default:
throw new IndexOutOfRangeException();
}
}
protected sealed override void SetChild(int index, ILInstruction value)
{
switch (index) {
case 0:
this.Filter = value;
break;
case 1:
this.Body = value;
break;
default:
throw new IndexOutOfRangeException();
}
}
protected sealed override SlotInfo GetChildSlot(int index)
{
switch (index) {
case 0:
return FilterSlot;
case 1:
return BodySlot;
default:
throw new IndexOutOfRangeException();
}
}
public sealed override ILInstruction Clone()
{
var clone = (TryCatchHandler)ShallowClone();
clone.Filter = this.filter.Clone();
clone.Body = this.body.Clone();
return clone;
}
ILVariable variable;
public ILVariable Variable {
get { return variable; }
set {
Debug.Assert(value != null);
if (IsConnected)
variable.RemoveStoreInstruction(this);
variable = value;
if (IsConnected)
variable.AddStoreInstruction(this);
}
}
public int IndexInStoreInstructionList { get; set; } = -1;
int IInstructionWithVariableOperand.IndexInVariableInstructionMapping {
get { return ((IStoreInstruction)this).IndexInStoreInstructionList; }
set { ((IStoreInstruction)this).IndexInStoreInstructionList = value; }
}
protected override void Connected()
{
base.Connected();
variable.AddStoreInstruction(this);
}
protected override void Disconnected()
{
variable.RemoveStoreInstruction(this);
base.Disconnected();
}
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitTryCatchHandler(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitTryCatchHandler(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitTryCatchHandler(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as TryCatchHandler;
return o != null && this.filter.PerformMatch(o.filter, ref match) && this.body.PerformMatch(o.body, ref match) && variable == o.variable;
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Try-finally statement
public sealed partial class TryFinally : TryInstruction
{
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitTryFinally(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitTryFinally(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitTryFinally(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as TryFinally;
return o != null && TryBlock.PerformMatch(o.TryBlock, ref match) && finallyBlock.PerformMatch(o.finallyBlock, ref match);
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Try-fault statement
public sealed partial class TryFault : TryInstruction
{
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitTryFault(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitTryFault(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitTryFault(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as TryFault;
return o != null && TryBlock.PerformMatch(o.TryBlock, ref match) && faultBlock.PerformMatch(o.faultBlock, ref match);
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Lock statement
public sealed partial class LockInstruction : ILInstruction
{
public LockInstruction(ILInstruction onExpression, ILInstruction body) : base(OpCode.LockInstruction)
{
this.OnExpression = onExpression;
this.Body = body;
}
public static readonly SlotInfo OnExpressionSlot = new SlotInfo("OnExpression", canInlineInto: true);
ILInstruction onExpression;
public ILInstruction OnExpression {
get { return this.onExpression; }
set {
ValidateChild(value);
SetChildInstruction(ref this.onExpression, value, 0);
}
}
public static readonly SlotInfo BodySlot = new SlotInfo("Body");
ILInstruction body;
public ILInstruction Body {
get { return this.body; }
set {
ValidateChild(value);
SetChildInstruction(ref this.body, value, 1);
}
}
protected sealed override int GetChildCount()
{
return 2;
}
protected sealed override ILInstruction GetChild(int index)
{
switch (index) {
case 0:
return this.onExpression;
case 1:
return this.body;
default:
throw new IndexOutOfRangeException();
}
}
protected sealed override void SetChild(int index, ILInstruction value)
{
switch (index) {
case 0:
this.OnExpression = value;
break;
case 1:
this.Body = value;
break;
default:
throw new IndexOutOfRangeException();
}
}
protected sealed override SlotInfo GetChildSlot(int index)
{
switch (index) {
case 0:
return OnExpressionSlot;
case 1:
return BodySlot;
default:
throw new IndexOutOfRangeException();
}
}
public sealed override ILInstruction Clone()
{
var clone = (LockInstruction)ShallowClone();
clone.OnExpression = this.onExpression.Clone();
clone.Body = this.body.Clone();
return clone;
}
public override StackType ResultType { get { return StackType.Void; } }
protected override InstructionFlags ComputeFlags()
{
return onExpression.Flags | body.Flags | InstructionFlags.ControlFlow | InstructionFlags.SideEffect;
}
public override InstructionFlags DirectFlags {
get {
return InstructionFlags.ControlFlow | InstructionFlags.SideEffect;
}
}
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitLockInstruction(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitLockInstruction(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitLockInstruction(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as LockInstruction;
return o != null && this.onExpression.PerformMatch(o.onExpression, ref match) && this.body.PerformMatch(o.body, ref match);
}
internal override void CheckInvariant(ILPhase phase)
{
base.CheckInvariant(phase);
Debug.Assert(onExpression.ResultType == StackType.O);
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Using statement
public sealed partial class UsingInstruction : ILInstruction, IStoreInstruction
{
public UsingInstruction(ILVariable variable, ILInstruction resourceExpression, ILInstruction body) : base(OpCode.UsingInstruction)
{
Debug.Assert(variable != null);
this.variable = variable;
this.ResourceExpression = resourceExpression;
this.Body = body;
}
ILVariable variable;
public ILVariable Variable {
get { return variable; }
set {
Debug.Assert(value != null);
if (IsConnected)
variable.RemoveStoreInstruction(this);
variable = value;
if (IsConnected)
variable.AddStoreInstruction(this);
}
}
public int IndexInStoreInstructionList { get; set; } = -1;
int IInstructionWithVariableOperand.IndexInVariableInstructionMapping {
get { return ((IStoreInstruction)this).IndexInStoreInstructionList; }
set { ((IStoreInstruction)this).IndexInStoreInstructionList = value; }
}
protected override void Connected()
{
base.Connected();
variable.AddStoreInstruction(this);
}
protected override void Disconnected()
{
variable.RemoveStoreInstruction(this);
base.Disconnected();
}
public static readonly SlotInfo ResourceExpressionSlot = new SlotInfo("ResourceExpression", canInlineInto: true);
ILInstruction resourceExpression;
public ILInstruction ResourceExpression {
get { return this.resourceExpression; }
set {
ValidateChild(value);
SetChildInstruction(ref this.resourceExpression, value, 0);
}
}
public static readonly SlotInfo BodySlot = new SlotInfo("Body");
ILInstruction body;
public ILInstruction Body {
get { return this.body; }
set {
ValidateChild(value);
SetChildInstruction(ref this.body, value, 1);
}
}
protected sealed override int GetChildCount()
{
return 2;
}
protected sealed override ILInstruction GetChild(int index)
{
switch (index) {
case 0:
return this.resourceExpression;
case 1:
return this.body;
default:
throw new IndexOutOfRangeException();
}
}
protected sealed override void SetChild(int index, ILInstruction value)
{
switch (index) {
case 0:
this.ResourceExpression = value;
break;
case 1:
this.Body = value;
break;
default:
throw new IndexOutOfRangeException();
}
}
protected sealed override SlotInfo GetChildSlot(int index)
{
switch (index) {
case 0:
return ResourceExpressionSlot;
case 1:
return BodySlot;
default:
throw new IndexOutOfRangeException();
}
}
public sealed override ILInstruction Clone()
{
var clone = (UsingInstruction)ShallowClone();
clone.ResourceExpression = this.resourceExpression.Clone();
clone.Body = this.body.Clone();
return clone;
}
public override StackType ResultType { get { return StackType.Void; } }
protected override InstructionFlags ComputeFlags()
{
return InstructionFlags.MayWriteLocals | resourceExpression.Flags | body.Flags | InstructionFlags.ControlFlow | InstructionFlags.SideEffect;
}
public override InstructionFlags DirectFlags {
get {
return InstructionFlags.MayWriteLocals | InstructionFlags.ControlFlow | InstructionFlags.SideEffect;
}
}
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitUsingInstruction(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitUsingInstruction(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitUsingInstruction(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as UsingInstruction;
return o != null && variable == o.variable && this.resourceExpression.PerformMatch(o.resourceExpression, ref match) && this.body.PerformMatch(o.body, ref match);
}
internal override void CheckInvariant(ILPhase phase)
{
base.CheckInvariant(phase);
Debug.Assert(phase <= ILPhase.InILReader || this.IsDescendantOf(variable.Function));
Debug.Assert(phase <= ILPhase.InILReader || variable.Function.Variables[variable.IndexInFunction] == variable);
Debug.Assert(resourceExpression.ResultType == StackType.O);
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Breakpoint instruction
public sealed partial class DebugBreak : SimpleInstruction
{
public DebugBreak() : base(OpCode.DebugBreak)
{
}
public override StackType ResultType { get { return StackType.Void; } }
protected override InstructionFlags ComputeFlags()
{
return InstructionFlags.SideEffect;
}
public override InstructionFlags DirectFlags {
get {
return InstructionFlags.SideEffect;
}
}
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitDebugBreak(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitDebugBreak(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitDebugBreak(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as DebugBreak;
return o != null;
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// 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).
public sealed partial class Comp : BinaryInstruction
{
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitComp(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitComp(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitComp(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as Comp;
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 && this.LiftingKind == o.LiftingKind;
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Non-virtual method call.
public sealed partial class Call : CallInstruction
{
public Call(IMethod method) : base(OpCode.Call, method)
{
}
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitCall(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitCall(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitCall(this, context);
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Virtual method call.
public sealed partial class CallVirt : CallInstruction
{
public CallVirt(IMethod method) : base(OpCode.CallVirt, method)
{
}
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitCallVirt(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitCallVirt(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitCallVirt(this, context);
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Unsafe function pointer call.
public sealed partial class CallIndirect : ILInstruction
{
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitCallIndirect(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitCallIndirect(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitCallIndirect(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as CallIndirect;
return o != null && EqualSignature(o) && Patterns.ListMatch.DoMatch(this.Arguments, o.Arguments, ref match) && this.FunctionPointer.PerformMatch(o.FunctionPointer, ref match);
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Checks that the input float is not NaN or infinite.
public sealed partial class Ckfinite : UnaryInstruction
{
public Ckfinite(ILInstruction argument) : base(OpCode.Ckfinite, argument)
{
}
public override StackType ResultType { get { return StackType.Void; } }
protected override InstructionFlags ComputeFlags()
{
return base.ComputeFlags() | InstructionFlags.MayThrow;
}
public override InstructionFlags DirectFlags {
get {
return base.DirectFlags | InstructionFlags.MayThrow;
}
}
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitCkfinite(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitCkfinite(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitCkfinite(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as Ckfinite;
return o != null && this.Argument.PerformMatch(o.Argument, ref match);
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Numeric cast.
public sealed partial class Conv : UnaryInstruction
{
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitConv(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitConv(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitConv(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as Conv;
return o != null && this.Argument.PerformMatch(o.Argument, ref match) && CheckForOverflow == o.CheckForOverflow && Kind == o.Kind && InputSign == o.InputSign && TargetType == o.TargetType && IsLifted == o.IsLifted;
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Loads the value of a local variable. (ldarg/ldloc)
public sealed partial class LdLoc : SimpleInstruction, ILoadInstruction
{
public LdLoc(ILVariable variable) : base(OpCode.LdLoc)
{
Debug.Assert(variable != null);
this.variable = variable;
}
ILVariable variable;
public ILVariable Variable {
get { return variable; }
set {
Debug.Assert(value != null);
if (IsConnected)
variable.RemoveLoadInstruction(this);
variable = value;
if (IsConnected)
variable.AddLoadInstruction(this);
}
}
public int IndexInLoadInstructionList { get; set; } = -1;
int IInstructionWithVariableOperand.IndexInVariableInstructionMapping {
get { return ((ILoadInstruction)this).IndexInLoadInstructionList; }
set { ((ILoadInstruction)this).IndexInLoadInstructionList = value; }
}
protected override void Connected()
{
base.Connected();
variable.AddLoadInstruction(this);
}
protected override void Disconnected()
{
variable.RemoveLoadInstruction(this);
base.Disconnected();
}
public override StackType ResultType { get { return variable.StackType; } }
protected override InstructionFlags ComputeFlags()
{
return InstructionFlags.MayReadLocals;
}
public override InstructionFlags DirectFlags {
get {
return InstructionFlags.MayReadLocals;
}
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
{
WriteILRange(output, options);
output.Write(OpCode);
output.Write(' ');
variable.WriteTo(output);
}
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitLdLoc(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitLdLoc(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitLdLoc(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as LdLoc;
return o != null && variable == o.variable;
}
internal override void CheckInvariant(ILPhase phase)
{
base.CheckInvariant(phase);
Debug.Assert(phase <= ILPhase.InILReader || this.IsDescendantOf(variable.Function));
Debug.Assert(phase <= ILPhase.InILReader || variable.Function.Variables[variable.IndexInFunction] == variable);
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Loads the address of a local variable. (ldarga/ldloca)
public sealed partial class LdLoca : SimpleInstruction, IAddressInstruction
{
public LdLoca(ILVariable variable) : base(OpCode.LdLoca)
{
Debug.Assert(variable != null);
this.variable = variable;
}
public override StackType ResultType { get { return StackType.Ref; } }
ILVariable variable;
public ILVariable Variable {
get { return variable; }
set {
Debug.Assert(value != null);
if (IsConnected)
variable.RemoveAddressInstruction(this);
variable = value;
if (IsConnected)
variable.AddAddressInstruction(this);
}
}
public int IndexInAddressInstructionList { get; set; } = -1;
int IInstructionWithVariableOperand.IndexInVariableInstructionMapping {
get { return ((IAddressInstruction)this).IndexInAddressInstructionList; }
set { ((IAddressInstruction)this).IndexInAddressInstructionList = value; }
}
protected override void Connected()
{
base.Connected();
variable.AddAddressInstruction(this);
}
protected override void Disconnected()
{
variable.RemoveAddressInstruction(this);
base.Disconnected();
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
{
WriteILRange(output, options);
output.Write(OpCode);
output.Write(' ');
variable.WriteTo(output);
}
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitLdLoca(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitLdLoca(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitLdLoca(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as LdLoca;
return o != null && variable == o.variable;
}
internal override void CheckInvariant(ILPhase phase)
{
base.CheckInvariant(phase);
Debug.Assert(phase <= ILPhase.InILReader || this.IsDescendantOf(variable.Function));
Debug.Assert(phase <= ILPhase.InILReader || variable.Function.Variables[variable.IndexInFunction] == variable);
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Stores a value into a local variable. (IL: starg/stloc)
/// Evaluates to the value that was stored (for byte/short variables: evaluates to the truncated value, sign/zero extended back to I4 based on variable.Type.GetSign())
public sealed partial class StLoc : ILInstruction, IStoreInstruction
{
public StLoc(ILVariable variable, ILInstruction value) : base(OpCode.StLoc)
{
Debug.Assert(variable != null);
this.variable = variable;
this.Value = value;
}
ILVariable variable;
public ILVariable Variable {
get { return variable; }
set {
Debug.Assert(value != null);
if (IsConnected)
variable.RemoveStoreInstruction(this);
variable = value;
if (IsConnected)
variable.AddStoreInstruction(this);
}
}
public int IndexInStoreInstructionList { get; set; } = -1;
int IInstructionWithVariableOperand.IndexInVariableInstructionMapping {
get { return ((IStoreInstruction)this).IndexInStoreInstructionList; }
set { ((IStoreInstruction)this).IndexInStoreInstructionList = value; }
}
protected override void Connected()
{
base.Connected();
variable.AddStoreInstruction(this);
}
protected override void Disconnected()
{
variable.RemoveStoreInstruction(this);
base.Disconnected();
}
public static readonly SlotInfo ValueSlot = new SlotInfo("Value", canInlineInto: true);
ILInstruction value;
public ILInstruction Value {
get { return this.value; }
set {
ValidateChild(value);
SetChildInstruction(ref this.value, value, 0);
}
}
protected sealed override int GetChildCount()
{
return 1;
}
protected sealed override ILInstruction GetChild(int index)
{
switch (index) {
case 0:
return this.value;
default:
throw new IndexOutOfRangeException();
}
}
protected sealed override void SetChild(int index, ILInstruction value)
{
switch (index) {
case 0:
this.Value = value;
break;
default:
throw new IndexOutOfRangeException();
}
}
protected sealed override SlotInfo GetChildSlot(int index)
{
switch (index) {
case 0:
return ValueSlot;
default:
throw new IndexOutOfRangeException();
}
}
public sealed override ILInstruction Clone()
{
var clone = (StLoc)ShallowClone();
clone.Value = this.value.Clone();
return clone;
}
public override StackType ResultType { get { return variable.StackType; } }
protected override InstructionFlags ComputeFlags()
{
return InstructionFlags.MayWriteLocals | value.Flags;
}
public override InstructionFlags DirectFlags {
get {
return InstructionFlags.MayWriteLocals;
}
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
{
WriteILRange(output, options);
output.Write(OpCode);
output.Write(' ');
variable.WriteTo(output);
output.Write('(');
this.value.WriteTo(output, options);
output.Write(')');
}
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitStLoc(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitStLoc(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitStLoc(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as StLoc;
return o != null && variable == o.variable && this.value.PerformMatch(o.value, ref match);
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Stores the value into an anonymous temporary variable, and returns the address of that variable.
public sealed partial class AddressOf : ILInstruction
{
public AddressOf(ILInstruction value, IType type) : base(OpCode.AddressOf)
{
this.Value = value;
this.type = type;
}
public static readonly SlotInfo ValueSlot = new SlotInfo("Value", canInlineInto: true);
ILInstruction value;
public ILInstruction Value {
get { return this.value; }
set {
ValidateChild(value);
SetChildInstruction(ref this.value, value, 0);
}
}
protected sealed override int GetChildCount()
{
return 1;
}
protected sealed override ILInstruction GetChild(int index)
{
switch (index) {
case 0:
return this.value;
default:
throw new IndexOutOfRangeException();
}
}
protected sealed override void SetChild(int index, ILInstruction value)
{
switch (index) {
case 0:
this.Value = value;
break;
default:
throw new IndexOutOfRangeException();
}
}
protected sealed override SlotInfo GetChildSlot(int index)
{
switch (index) {
case 0:
return ValueSlot;
default:
throw new IndexOutOfRangeException();
}
}
public sealed override ILInstruction Clone()
{
var clone = (AddressOf)ShallowClone();
clone.Value = this.value.Clone();
return clone;
}
public override StackType ResultType { get { return StackType.Ref; } }
IType type;
/// Returns the type operand.
public IType Type {
get { return type; }
set { type = value; InvalidateFlags(); }
}
protected override InstructionFlags ComputeFlags()
{
return value.Flags;
}
public override InstructionFlags DirectFlags {
get {
return InstructionFlags.None;
}
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
{
WriteILRange(output, options);
output.Write(OpCode);
output.Write(' ');
type.WriteTo(output);
output.Write('(');
this.value.WriteTo(output, options);
output.Write(')');
}
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitAddressOf(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitAddressOf(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitAddressOf(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as AddressOf;
return o != null && this.value.PerformMatch(o.value, ref match) && type.Equals(o.type);
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Three valued logic and. Inputs are of type bool? or I4, output is of type bool?. Unlike logic.and(), does not have short-circuiting behavior.
public sealed partial class ThreeValuedBoolAnd : BinaryInstruction
{
public ThreeValuedBoolAnd(ILInstruction left, ILInstruction right) : base(OpCode.ThreeValuedBoolAnd, left, right)
{
}
public override StackType ResultType { get { return StackType.O; } }
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitThreeValuedBoolAnd(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitThreeValuedBoolAnd(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitThreeValuedBoolAnd(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as ThreeValuedBoolAnd;
return o != null && this.Left.PerformMatch(o.Left, ref match) && this.Right.PerformMatch(o.Right, ref match);
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Three valued logic or. Inputs are of type bool? or I4, output is of type bool?. Unlike logic.or(), does not have short-circuiting behavior.
public sealed partial class ThreeValuedBoolOr : BinaryInstruction
{
public ThreeValuedBoolOr(ILInstruction left, ILInstruction right) : base(OpCode.ThreeValuedBoolOr, left, right)
{
}
public override StackType ResultType { get { return StackType.O; } }
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitThreeValuedBoolOr(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitThreeValuedBoolOr(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitThreeValuedBoolOr(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as ThreeValuedBoolOr;
return o != null && this.Left.PerformMatch(o.Left, ref match) && this.Right.PerformMatch(o.Right, ref match);
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// The input operand must be one of:
/// 1. a nullable value type
/// 2. a reference type
/// 3. a managed reference to a type parameter.
/// If the input is non-null, evaluates to the (unwrapped) input.
/// If the input is null, jumps to the innermost nullable.rewrap instruction that contains this instruction.
/// In case 3 (managed reference), the dereferenced value is the input being tested, and the nullable.unwrap instruction returns the managed reference unmodified (if the value is non-null).
public sealed partial class NullableUnwrap : UnaryInstruction
{
protected override InstructionFlags ComputeFlags()
{
return base.ComputeFlags() | InstructionFlags.MayUnwrapNull;
}
public override InstructionFlags DirectFlags {
get {
return base.DirectFlags | InstructionFlags.MayUnwrapNull;
}
}
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitNullableUnwrap(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitNullableUnwrap(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitNullableUnwrap(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as NullableUnwrap;
return o != null && this.Argument.PerformMatch(o.Argument, ref match);
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Serves as jump target for the nullable.unwrap instruction.
/// If the input evaluates normally, evaluates to the input value (wrapped in Nullable<T> if the input is a non-nullable value type).If a nullable.unwrap instruction encounters a null input and jumps to the (endpoint of the) nullable.rewrap instruction,the nullable.rewrap instruction evaluates to null.
public sealed partial class NullableRewrap : UnaryInstruction
{
public NullableRewrap(ILInstruction argument) : base(OpCode.NullableRewrap, argument)
{
}
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitNullableRewrap(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitNullableRewrap(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitNullableRewrap(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as NullableRewrap;
return o != null && this.Argument.PerformMatch(o.Argument, ref match);
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Loads a constant string.
public sealed partial class LdStr : SimpleInstruction
{
public LdStr(string value) : base(OpCode.LdStr)
{
this.Value = value;
}
public readonly string Value;
public override StackType ResultType { get { return StackType.O; } }
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
{
WriteILRange(output, options);
output.Write(OpCode);
output.Write(' ');
Disassembler.DisassemblerHelpers.WriteOperand(output, Value);
}
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitLdStr(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitLdStr(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitLdStr(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as LdStr;
return o != null && this.Value == o.Value;
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Loads a constant 32-bit integer.
public sealed partial class LdcI4 : SimpleInstruction
{
public LdcI4(int value) : base(OpCode.LdcI4)
{
this.Value = value;
}
public readonly int Value;
public override StackType ResultType { get { return StackType.I4; } }
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
{
WriteILRange(output, options);
output.Write(OpCode);
output.Write(' ');
Disassembler.DisassemblerHelpers.WriteOperand(output, Value);
}
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitLdcI4(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitLdcI4(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitLdcI4(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as LdcI4;
return o != null && this.Value == o.Value;
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Loads a constant 64-bit integer.
public sealed partial class LdcI8 : SimpleInstruction
{
public LdcI8(long value) : base(OpCode.LdcI8)
{
this.Value = value;
}
public readonly long Value;
public override StackType ResultType { get { return StackType.I8; } }
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
{
WriteILRange(output, options);
output.Write(OpCode);
output.Write(' ');
Disassembler.DisassemblerHelpers.WriteOperand(output, Value);
}
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitLdcI8(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitLdcI8(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitLdcI8(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as LdcI8;
return o != null && this.Value == o.Value;
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Loads a constant 32-bit floating-point number.
public sealed partial class LdcF4 : SimpleInstruction
{
public LdcF4(float value) : base(OpCode.LdcF4)
{
this.Value = value;
}
public readonly float Value;
public override StackType ResultType { get { return StackType.F4; } }
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
{
WriteILRange(output, options);
output.Write(OpCode);
output.Write(' ');
Disassembler.DisassemblerHelpers.WriteOperand(output, Value);
}
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitLdcF4(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitLdcF4(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitLdcF4(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as LdcF4;
return o != null && this.Value == o.Value;
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Loads a constant 64-bit floating-point number.
public sealed partial class LdcF8 : SimpleInstruction
{
public LdcF8(double value) : base(OpCode.LdcF8)
{
this.Value = value;
}
public readonly double Value;
public override StackType ResultType { get { return StackType.F8; } }
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
{
WriteILRange(output, options);
output.Write(OpCode);
output.Write(' ');
Disassembler.DisassemblerHelpers.WriteOperand(output, Value);
}
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitLdcF8(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitLdcF8(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitLdcF8(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as LdcF8;
return o != null && this.Value == o.Value;
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Loads a constant decimal.
public sealed partial class LdcDecimal : SimpleInstruction
{
public LdcDecimal(decimal value) : base(OpCode.LdcDecimal)
{
this.Value = value;
}
public readonly decimal Value;
public override StackType ResultType { get { return StackType.O; } }
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
{
WriteILRange(output, options);
output.Write(OpCode);
output.Write(' ');
Disassembler.DisassemblerHelpers.WriteOperand(output, Value);
}
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitLdcDecimal(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitLdcDecimal(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitLdcDecimal(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as LdcDecimal;
return o != null && this.Value == o.Value;
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Loads the null reference.
public sealed partial class LdNull : SimpleInstruction
{
public LdNull() : base(OpCode.LdNull)
{
}
public override StackType ResultType { get { return StackType.O; } }
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitLdNull(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitLdNull(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitLdNull(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as LdNull;
return o != null;
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Load method pointer
public sealed partial class LdFtn : SimpleInstruction, IInstructionWithMethodOperand
{
public LdFtn(IMethod method) : base(OpCode.LdFtn)
{
this.method = method;
}
readonly IMethod method;
/// Returns the method operand.
public IMethod Method { get { return method; } }
public override StackType ResultType { get { return StackType.I; } }
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
{
WriteILRange(output, options);
output.Write(OpCode);
if (method != null) {
output.Write(' ');
method.WriteTo(output);
}
}
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitLdFtn(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitLdFtn(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitLdFtn(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as LdFtn;
return o != null && object.Equals(method, o.method);
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Load method pointer
public sealed partial class LdVirtFtn : UnaryInstruction, IInstructionWithMethodOperand
{
public LdVirtFtn(ILInstruction argument, IMethod method) : base(OpCode.LdVirtFtn, argument)
{
this.method = method;
}
readonly IMethod method;
/// Returns the method operand.
public IMethod Method { get { return method; } }
public override StackType ResultType { get { return StackType.I; } }
protected override InstructionFlags ComputeFlags()
{
return base.ComputeFlags() | InstructionFlags.MayThrow;
}
public override InstructionFlags DirectFlags {
get {
return base.DirectFlags | InstructionFlags.MayThrow;
}
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
{
WriteILRange(output, options);
output.Write(OpCode);
if (method != null) {
output.Write(' ');
method.WriteTo(output);
}
output.Write('(');
Argument.WriteTo(output, options);
output.Write(')');
}
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitLdVirtFtn(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitLdVirtFtn(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitLdVirtFtn(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as LdVirtFtn;
return o != null && this.Argument.PerformMatch(o.Argument, ref match) && object.Equals(method, o.method);
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Virtual delegate construction
public sealed partial class LdVirtDelegate : UnaryInstruction, IInstructionWithMethodOperand
{
public LdVirtDelegate(ILInstruction argument, IType type, IMethod method) : base(OpCode.LdVirtDelegate, argument)
{
this.type = type;
this.method = method;
}
IType type;
/// Returns the type operand.
public IType Type {
get { return type; }
set { type = value; InvalidateFlags(); }
}
readonly IMethod method;
/// Returns the method operand.
public IMethod Method { get { return method; } }
public override StackType ResultType { get { return StackType.O; } }
protected override InstructionFlags ComputeFlags()
{
return base.ComputeFlags() | InstructionFlags.MayThrow;
}
public override InstructionFlags DirectFlags {
get {
return base.DirectFlags | InstructionFlags.MayThrow;
}
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
{
WriteILRange(output, options);
output.Write(OpCode);
output.Write(' ');
type.WriteTo(output);
if (method != null) {
output.Write(' ');
method.WriteTo(output);
}
output.Write('(');
Argument.WriteTo(output, options);
output.Write(')');
}
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitLdVirtDelegate(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitLdVirtDelegate(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitLdVirtDelegate(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as LdVirtDelegate;
return o != null && this.Argument.PerformMatch(o.Argument, ref match) && type.Equals(o.type) && object.Equals(method, o.method);
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Loads runtime representation of metadata token
public sealed partial class LdTypeToken : SimpleInstruction
{
public LdTypeToken(IType type) : base(OpCode.LdTypeToken)
{
this.type = type;
}
IType type;
/// Returns the type operand.
public IType Type {
get { return type; }
set { type = value; InvalidateFlags(); }
}
public override StackType ResultType { get { return StackType.O; } }
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
{
WriteILRange(output, options);
output.Write(OpCode);
output.Write(' ');
type.WriteTo(output);
}
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitLdTypeToken(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitLdTypeToken(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitLdTypeToken(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as LdTypeToken;
return o != null && type.Equals(o.type);
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Loads runtime representation of metadata token
public sealed partial class LdMemberToken : SimpleInstruction
{
public LdMemberToken(IMember member) : base(OpCode.LdMemberToken)
{
this.member = member;
}
readonly IMember member;
/// Returns the token operand.
public IMember Member { get { return member; } }
public override StackType ResultType { get { return StackType.O; } }
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
{
WriteILRange(output, options);
output.Write(OpCode);
output.Write(' ');
member.WriteTo(output);
}
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitLdMemberToken(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitLdMemberToken(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitLdMemberToken(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as LdMemberToken;
return o != null && member.Equals(o.member);
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Allocates space in the stack frame
public sealed partial class LocAlloc : UnaryInstruction
{
public LocAlloc(ILInstruction argument) : base(OpCode.LocAlloc, argument)
{
}
public override StackType ResultType { get { return StackType.I; } }
protected override InstructionFlags ComputeFlags()
{
return base.ComputeFlags() | InstructionFlags.MayThrow;
}
public override InstructionFlags DirectFlags {
get {
return base.DirectFlags | InstructionFlags.MayThrow;
}
}
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitLocAlloc(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitLocAlloc(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitLocAlloc(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as LocAlloc;
return o != null && this.Argument.PerformMatch(o.Argument, ref match);
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Allocates space in the stack frame and wraps it in a Span
public sealed partial class LocAllocSpan : UnaryInstruction
{
public LocAllocSpan(ILInstruction argument, IType type) : base(OpCode.LocAllocSpan, argument)
{
this.type = type;
}
IType type;
/// Returns the type operand.
public IType Type {
get { return type; }
set { type = value; InvalidateFlags(); }
}
public override StackType ResultType { get { return StackType.O; } }
protected override InstructionFlags ComputeFlags()
{
return base.ComputeFlags() | InstructionFlags.MayThrow;
}
public override InstructionFlags DirectFlags {
get {
return base.DirectFlags | InstructionFlags.MayThrow;
}
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
{
WriteILRange(output, options);
output.Write(OpCode);
output.Write(' ');
type.WriteTo(output);
output.Write('(');
Argument.WriteTo(output, options);
output.Write(')');
}
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitLocAllocSpan(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitLocAllocSpan(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitLocAllocSpan(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as LocAllocSpan;
return o != null && this.Argument.PerformMatch(o.Argument, ref match) && type.Equals(o.type);
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// memcpy(destAddress, sourceAddress, size);
public sealed partial class Cpblk : ILInstruction, ISupportsVolatilePrefix, ISupportsUnalignedPrefix
{
public Cpblk(ILInstruction destAddress, ILInstruction sourceAddress, ILInstruction size) : base(OpCode.Cpblk)
{
this.DestAddress = destAddress;
this.SourceAddress = sourceAddress;
this.Size = size;
}
public static readonly SlotInfo DestAddressSlot = new SlotInfo("DestAddress", canInlineInto: true);
ILInstruction destAddress;
public ILInstruction DestAddress {
get { return this.destAddress; }
set {
ValidateChild(value);
SetChildInstruction(ref this.destAddress, value, 0);
}
}
public static readonly SlotInfo SourceAddressSlot = new SlotInfo("SourceAddress", canInlineInto: true);
ILInstruction sourceAddress;
public ILInstruction SourceAddress {
get { return this.sourceAddress; }
set {
ValidateChild(value);
SetChildInstruction(ref this.sourceAddress, value, 1);
}
}
public static readonly SlotInfo SizeSlot = new SlotInfo("Size", canInlineInto: true);
ILInstruction size;
public ILInstruction Size {
get { return this.size; }
set {
ValidateChild(value);
SetChildInstruction(ref this.size, value, 2);
}
}
protected sealed override int GetChildCount()
{
return 3;
}
protected sealed override ILInstruction GetChild(int index)
{
switch (index) {
case 0:
return this.destAddress;
case 1:
return this.sourceAddress;
case 2:
return this.size;
default:
throw new IndexOutOfRangeException();
}
}
protected sealed override void SetChild(int index, ILInstruction value)
{
switch (index) {
case 0:
this.DestAddress = value;
break;
case 1:
this.SourceAddress = value;
break;
case 2:
this.Size = value;
break;
default:
throw new IndexOutOfRangeException();
}
}
protected sealed override SlotInfo GetChildSlot(int index)
{
switch (index) {
case 0:
return DestAddressSlot;
case 1:
return SourceAddressSlot;
case 2:
return SizeSlot;
default:
throw new IndexOutOfRangeException();
}
}
public sealed override ILInstruction Clone()
{
var clone = (Cpblk)ShallowClone();
clone.DestAddress = this.destAddress.Clone();
clone.SourceAddress = this.sourceAddress.Clone();
clone.Size = this.size.Clone();
return clone;
}
/// Gets/Sets whether the memory access is volatile.
public bool IsVolatile { get; set; }
/// Returns the alignment specified by the 'unaligned' prefix; or 0 if there was no 'unaligned' prefix.
public byte UnalignedPrefix { get; set; }
public override StackType ResultType { get { return StackType.Void; } }
protected override InstructionFlags ComputeFlags()
{
return destAddress.Flags | sourceAddress.Flags | size.Flags | InstructionFlags.MayThrow | InstructionFlags.SideEffect;
}
public override InstructionFlags DirectFlags {
get {
return InstructionFlags.MayThrow | InstructionFlags.SideEffect;
}
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
{
WriteILRange(output, options);
if (IsVolatile)
output.Write("volatile.");
if (UnalignedPrefix > 0)
output.Write("unaligned(" + UnalignedPrefix + ").");
output.Write(OpCode);
output.Write('(');
this.destAddress.WriteTo(output, options);
output.Write(", ");
this.sourceAddress.WriteTo(output, options);
output.Write(", ");
this.size.WriteTo(output, options);
output.Write(')');
}
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitCpblk(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitCpblk(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitCpblk(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as Cpblk;
return o != null && this.destAddress.PerformMatch(o.destAddress, ref match) && this.sourceAddress.PerformMatch(o.sourceAddress, ref match) && this.size.PerformMatch(o.size, ref match) && IsVolatile == o.IsVolatile && UnalignedPrefix == o.UnalignedPrefix;
}
internal override void CheckInvariant(ILPhase phase)
{
base.CheckInvariant(phase);
Debug.Assert(destAddress.ResultType == StackType.I || destAddress.ResultType == StackType.Ref);
Debug.Assert(sourceAddress.ResultType == StackType.I || sourceAddress.ResultType == StackType.Ref);
Debug.Assert(size.ResultType == StackType.I4);
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// memset(address, value, size)
public sealed partial class Initblk : ILInstruction, ISupportsVolatilePrefix, ISupportsUnalignedPrefix
{
public Initblk(ILInstruction address, ILInstruction value, ILInstruction size) : base(OpCode.Initblk)
{
this.Address = address;
this.Value = value;
this.Size = size;
}
public static readonly SlotInfo AddressSlot = new SlotInfo("Address", canInlineInto: true);
ILInstruction address;
public ILInstruction Address {
get { return this.address; }
set {
ValidateChild(value);
SetChildInstruction(ref this.address, value, 0);
}
}
public static readonly SlotInfo ValueSlot = new SlotInfo("Value", canInlineInto: true);
ILInstruction value;
public ILInstruction Value {
get { return this.value; }
set {
ValidateChild(value);
SetChildInstruction(ref this.value, value, 1);
}
}
public static readonly SlotInfo SizeSlot = new SlotInfo("Size", canInlineInto: true);
ILInstruction size;
public ILInstruction Size {
get { return this.size; }
set {
ValidateChild(value);
SetChildInstruction(ref this.size, value, 2);
}
}
protected sealed override int GetChildCount()
{
return 3;
}
protected sealed override ILInstruction GetChild(int index)
{
switch (index) {
case 0:
return this.address;
case 1:
return this.value;
case 2:
return this.size;
default:
throw new IndexOutOfRangeException();
}
}
protected sealed override void SetChild(int index, ILInstruction value)
{
switch (index) {
case 0:
this.Address = value;
break;
case 1:
this.Value = value;
break;
case 2:
this.Size = value;
break;
default:
throw new IndexOutOfRangeException();
}
}
protected sealed override SlotInfo GetChildSlot(int index)
{
switch (index) {
case 0:
return AddressSlot;
case 1:
return ValueSlot;
case 2:
return SizeSlot;
default:
throw new IndexOutOfRangeException();
}
}
public sealed override ILInstruction Clone()
{
var clone = (Initblk)ShallowClone();
clone.Address = this.address.Clone();
clone.Value = this.value.Clone();
clone.Size = this.size.Clone();
return clone;
}
/// Gets/Sets whether the memory access is volatile.
public bool IsVolatile { get; set; }
/// Returns the alignment specified by the 'unaligned' prefix; or 0 if there was no 'unaligned' prefix.
public byte UnalignedPrefix { get; set; }
public override StackType ResultType { get { return StackType.Void; } }
protected override InstructionFlags ComputeFlags()
{
return address.Flags | value.Flags | size.Flags | InstructionFlags.MayThrow | InstructionFlags.SideEffect;
}
public override InstructionFlags DirectFlags {
get {
return InstructionFlags.MayThrow | InstructionFlags.SideEffect;
}
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
{
WriteILRange(output, options);
if (IsVolatile)
output.Write("volatile.");
if (UnalignedPrefix > 0)
output.Write("unaligned(" + UnalignedPrefix + ").");
output.Write(OpCode);
output.Write('(');
this.address.WriteTo(output, options);
output.Write(", ");
this.value.WriteTo(output, options);
output.Write(", ");
this.size.WriteTo(output, options);
output.Write(')');
}
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitInitblk(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitInitblk(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitInitblk(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as Initblk;
return o != null && this.address.PerformMatch(o.address, ref match) && this.value.PerformMatch(o.value, ref match) && this.size.PerformMatch(o.size, ref match) && IsVolatile == o.IsVolatile && UnalignedPrefix == o.UnalignedPrefix;
}
internal override void CheckInvariant(ILPhase phase)
{
base.CheckInvariant(phase);
Debug.Assert(address.ResultType == StackType.I || address.ResultType == StackType.Ref);
Debug.Assert(value.ResultType == StackType.I4);
Debug.Assert(size.ResultType == StackType.I4);
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Load address of instance field
public sealed partial class LdFlda : ILInstruction, IInstructionWithFieldOperand
{
public LdFlda(ILInstruction target, IField field) : base(OpCode.LdFlda)
{
this.Target = target;
this.field = field;
}
public static readonly SlotInfo TargetSlot = new SlotInfo("Target", canInlineInto: true);
ILInstruction target;
public ILInstruction Target {
get { return this.target; }
set {
ValidateChild(value);
SetChildInstruction(ref this.target, value, 0);
}
}
protected sealed override int GetChildCount()
{
return 1;
}
protected sealed override ILInstruction GetChild(int index)
{
switch (index) {
case 0:
return this.target;
default:
throw new IndexOutOfRangeException();
}
}
protected sealed override void SetChild(int index, ILInstruction value)
{
switch (index) {
case 0:
this.Target = value;
break;
default:
throw new IndexOutOfRangeException();
}
}
protected sealed override SlotInfo GetChildSlot(int index)
{
switch (index) {
case 0:
return TargetSlot;
default:
throw new IndexOutOfRangeException();
}
}
public sealed override ILInstruction Clone()
{
var clone = (LdFlda)ShallowClone();
clone.Target = this.target.Clone();
return clone;
}
public bool DelayExceptions; // NullReferenceException/IndexOutOfBoundsException only occurs when the reference is dereferenced
readonly IField field;
/// Returns the field operand.
public IField Field { get { return field; } }
public override StackType ResultType { get { return target.ResultType.IsIntegerType() ? StackType.I : StackType.Ref; } }
protected override InstructionFlags ComputeFlags()
{
return target.Flags | (DelayExceptions ? InstructionFlags.None : InstructionFlags.MayThrow);
}
public override InstructionFlags DirectFlags {
get {
return (DelayExceptions ? InstructionFlags.None : InstructionFlags.MayThrow);
}
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
{
WriteILRange(output, options);
if (DelayExceptions)
output.Write("delayex.");
output.Write(OpCode);
output.Write(' ');
field.WriteTo(output);
output.Write('(');
this.target.WriteTo(output, options);
output.Write(')');
}
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitLdFlda(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitLdFlda(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitLdFlda(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as LdFlda;
return o != null && this.target.PerformMatch(o.target, ref match) && DelayExceptions == o.DelayExceptions && field.Equals(o.field);
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Load static field address
public sealed partial class LdsFlda : SimpleInstruction, IInstructionWithFieldOperand
{
public LdsFlda(IField field) : base(OpCode.LdsFlda)
{
this.field = field;
}
public override StackType ResultType { get { return StackType.Ref; } }
readonly IField field;
/// Returns the field operand.
public IField Field { get { return field; } }
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
{
WriteILRange(output, options);
output.Write(OpCode);
output.Write(' ');
field.WriteTo(output);
}
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitLdsFlda(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitLdsFlda(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitLdsFlda(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as LdsFlda;
return o != null && field.Equals(o.field);
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Casts an object to a class.
public sealed partial class CastClass : UnaryInstruction
{
public CastClass(ILInstruction argument, IType type) : base(OpCode.CastClass, argument)
{
this.type = type;
}
IType type;
/// Returns the type operand.
public IType Type {
get { return type; }
set { type = value; InvalidateFlags(); }
}
public override StackType ResultType { get { return type.GetStackType(); } }
protected override InstructionFlags ComputeFlags()
{
return base.ComputeFlags() | InstructionFlags.MayThrow;
}
public override InstructionFlags DirectFlags {
get {
return base.DirectFlags | InstructionFlags.MayThrow;
}
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
{
WriteILRange(output, options);
output.Write(OpCode);
output.Write(' ');
type.WriteTo(output);
output.Write('(');
Argument.WriteTo(output, options);
output.Write(')');
}
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitCastClass(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitCastClass(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitCastClass(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as CastClass;
return o != null && this.Argument.PerformMatch(o.Argument, ref match) && type.Equals(o.type);
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Test if object is instance of class or interface.
public sealed partial class IsInst : UnaryInstruction
{
public IsInst(ILInstruction argument, IType type) : base(OpCode.IsInst, argument)
{
this.type = type;
}
IType type;
/// Returns the type operand.
public IType Type {
get { return type; }
set { type = value; InvalidateFlags(); }
}
public override StackType ResultType { get { return StackType.O; } }
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
{
WriteILRange(output, options);
output.Write(OpCode);
output.Write(' ');
type.WriteTo(output);
output.Write('(');
Argument.WriteTo(output, options);
output.Write(')');
}
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitIsInst(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitIsInst(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitIsInst(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as IsInst;
return o != null && this.Argument.PerformMatch(o.Argument, ref match) && type.Equals(o.type);
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Indirect load (ref/pointer dereference).
public sealed partial class LdObj : ILInstruction, ISupportsVolatilePrefix, ISupportsUnalignedPrefix
{
public LdObj(ILInstruction target, IType type) : base(OpCode.LdObj)
{
this.Target = target;
this.type = type;
}
public static readonly SlotInfo TargetSlot = new SlotInfo("Target", canInlineInto: true);
ILInstruction target;
public ILInstruction Target {
get { return this.target; }
set {
ValidateChild(value);
SetChildInstruction(ref this.target, value, 0);
}
}
protected sealed override int GetChildCount()
{
return 1;
}
protected sealed override ILInstruction GetChild(int index)
{
switch (index) {
case 0:
return this.target;
default:
throw new IndexOutOfRangeException();
}
}
protected sealed override void SetChild(int index, ILInstruction value)
{
switch (index) {
case 0:
this.Target = value;
break;
default:
throw new IndexOutOfRangeException();
}
}
protected sealed override SlotInfo GetChildSlot(int index)
{
switch (index) {
case 0:
return TargetSlot;
default:
throw new IndexOutOfRangeException();
}
}
public sealed override ILInstruction Clone()
{
var clone = (LdObj)ShallowClone();
clone.Target = this.target.Clone();
return clone;
}
IType type;
/// Returns the type operand.
public IType Type {
get { return type; }
set { type = value; InvalidateFlags(); }
}
/// Gets/Sets whether the memory access is volatile.
public bool IsVolatile { get; set; }
/// Returns the alignment specified by the 'unaligned' prefix; or 0 if there was no 'unaligned' prefix.
public byte UnalignedPrefix { get; set; }
public override StackType ResultType { get { return type.GetStackType(); } }
protected override InstructionFlags ComputeFlags()
{
return target.Flags | InstructionFlags.SideEffect | InstructionFlags.MayThrow;
}
public override InstructionFlags DirectFlags {
get {
return InstructionFlags.SideEffect | InstructionFlags.MayThrow;
}
}
void OriginalWriteTo(ITextOutput output, ILAstWritingOptions options)
{
WriteILRange(output, options);
if (IsVolatile)
output.Write("volatile.");
if (UnalignedPrefix > 0)
output.Write("unaligned(" + UnalignedPrefix + ").");
output.Write(OpCode);
output.Write(' ');
type.WriteTo(output);
output.Write('(');
this.target.WriteTo(output, options);
output.Write(')');
}
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitLdObj(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitLdObj(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitLdObj(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as LdObj;
return o != null && this.target.PerformMatch(o.target, ref match) && type.Equals(o.type) && IsVolatile == o.IsVolatile && UnalignedPrefix == o.UnalignedPrefix;
}
internal override void CheckInvariant(ILPhase phase)
{
base.CheckInvariant(phase);
Debug.Assert(target.ResultType == StackType.Ref || target.ResultType == StackType.I);
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Indirect store (store to ref/pointer).
/// Evaluates to the value that was stored (when using type byte/short: evaluates to the truncated value, sign/zero extended back to I4 based on type.GetSign())
public sealed partial class StObj : ILInstruction, ISupportsVolatilePrefix, ISupportsUnalignedPrefix
{
public StObj(ILInstruction target, ILInstruction value, IType type) : base(OpCode.StObj)
{
this.Target = target;
this.Value = value;
this.type = type;
}
public static readonly SlotInfo TargetSlot = new SlotInfo("Target", canInlineInto: true);
ILInstruction target;
public ILInstruction Target {
get { return this.target; }
set {
ValidateChild(value);
SetChildInstruction(ref this.target, value, 0);
}
}
public static readonly SlotInfo ValueSlot = new SlotInfo("Value", canInlineInto: true);
ILInstruction value;
public ILInstruction Value {
get { return this.value; }
set {
ValidateChild(value);
SetChildInstruction(ref this.value, value, 1);
}
}
protected sealed override int GetChildCount()
{
return 2;
}
protected sealed override ILInstruction GetChild(int index)
{
switch (index) {
case 0:
return this.target;
case 1:
return this.value;
default:
throw new IndexOutOfRangeException();
}
}
protected sealed override void SetChild(int index, ILInstruction value)
{
switch (index) {
case 0:
this.Target = value;
break;
case 1:
this.Value = value;
break;
default:
throw new IndexOutOfRangeException();
}
}
protected sealed override SlotInfo GetChildSlot(int index)
{
switch (index) {
case 0:
return TargetSlot;
case 1:
return ValueSlot;
default:
throw new IndexOutOfRangeException();
}
}
public sealed override ILInstruction Clone()
{
var clone = (StObj)ShallowClone();
clone.Target = this.target.Clone();
clone.Value = this.value.Clone();
return clone;
}
IType type;
/// Returns the type operand.
public IType Type {
get { return type; }
set { type = value; InvalidateFlags(); }
}
/// Gets/Sets whether the memory access is volatile.
public bool IsVolatile { get; set; }
/// Returns the alignment specified by the 'unaligned' prefix; or 0 if there was no 'unaligned' prefix.
public byte UnalignedPrefix { get; set; }
public override StackType ResultType { get { return type.GetStackType(); } }
protected override InstructionFlags ComputeFlags()
{
return target.Flags | value.Flags | InstructionFlags.SideEffect | InstructionFlags.MayThrow;
}
public override InstructionFlags DirectFlags {
get {
return InstructionFlags.SideEffect | InstructionFlags.MayThrow;
}
}
void OriginalWriteTo(ITextOutput output, ILAstWritingOptions options)
{
WriteILRange(output, options);
if (IsVolatile)
output.Write("volatile.");
if (UnalignedPrefix > 0)
output.Write("unaligned(" + UnalignedPrefix + ").");
output.Write(OpCode);
output.Write(' ');
type.WriteTo(output);
output.Write('(');
this.target.WriteTo(output, options);
output.Write(", ");
this.value.WriteTo(output, options);
output.Write(')');
}
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitStObj(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
return visitor.VisitStObj(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
return visitor.VisitStObj(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as StObj;
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;
}
internal override void CheckInvariant(ILPhase phase)
{
base.CheckInvariant(phase);
Debug.Assert(target.ResultType == StackType.Ref || target.ResultType == StackType.I);
Debug.Assert(value.ResultType == type.GetStackType());
CheckTargetSlot();
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// Boxes a value.
public sealed partial class Box : UnaryInstruction
{
public Box(ILInstruction argument, IType type) : base(OpCode.Box, argument)
{
this.type = type;
}
IType type;
/// Returns the type operand.
public IType Type {
get { return type; }
set { type = value; InvalidateFlags(); }
}
public override StackType ResultType { get { return StackType.O; } }
protected override InstructionFlags ComputeFlags()
{
return base.ComputeFlags() | InstructionFlags.SideEffect | InstructionFlags.MayThrow;
}
public override InstructionFlags DirectFlags {
get {
return base.DirectFlags | InstructionFlags.SideEffect | InstructionFlags.MayThrow;
}
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
{
WriteILRange(output, options);
output.Write(OpCode);
output.Write(' ');
type.WriteTo(output);
output.Write('(');
Argument.WriteTo(output, options);
output.Write(')');
}
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitBox(this);
}
public override T AcceptVisitor(ILVisitor