// Copyright (c) 2014 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.NRefactory.TypeSystem; namespace ICSharpCode.Decompiler.IL { /// /// Enum representing the type of an . /// public enum OpCode { /// Represents invalid IL. Semantically, this instruction is considered to throw some kind of exception. InvalidInstruction, /// 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, /// Unary operator that expects an input of type I4. Returns 1 (of type I4) if the input value is 0. Otherwise, returns 0 (of type I4). LogicNot, /// Common instruction for add, sub, mul, div, rem, bit.and, bit.or, bit.xor, shl and shr. BinaryNumericInstruction, /// Common instruction for compound assignments. CompoundAssignmentInstruction, /// Bitwise NOT BitNot, /// Retrieves the RuntimeArgumentHandle. Arglist, /// Unconditional branch. goto target; Branch, /// Unconditional branch to end of block container. goto container_end;, often break; Leave, /// If statement / conditional expression. if (condition) trueExpr else falseExpr IfInstruction, /// 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, /// 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, /// 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. (starg/stloc) StLoc, /// Stores the value into an anonymous temporary variable, and returns the address of that variable. AddressOf, /// Loads a constant string. LdStr, /// Loads a constant 32-bit integer. LdcI4, /// Loads a constant 64-bit integer. LdcI8, /// Loads a constant floating-point number. LdcF, /// Loads a constant decimal. LdcDecimal, /// Loads the null reference. LdNull, /// Load method pointer LdFtn, /// Load method pointer LdVirtFtn, /// Loads runtime representation of metadata token LdTypeToken, /// Loads runtime representation of metadata token LdMemberToken, /// Allocates space in the stack frame LocAlloc, /// Returns from the current method or lambda. Return, /// 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). 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, /// Converts an array pointer (O) to a reference to the first element, or to a null reference if the array is null or empty. /// Also used to convert a string to a reference to the first character. ArrayToPointer, /// 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, } /// 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; } } } /// 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) { output.Write(OpCode); output.Write('('); this.argument.WriteTo(output); output.Write(')'); } } /// 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) { output.Write(OpCode); output.Write('('); this.left.WriteTo(output); output.Write(", "); this.right.WriteTo(output); output.Write(')'); } } /// 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] = 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 => 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; } } } /// Represents invalid IL. Semantically, this instruction is considered to throw some kind of exception. public sealed partial class InvalidInstruction : SimpleInstruction { public InvalidInstruction() : base(OpCode.InvalidInstruction) { } protected override InstructionFlags ComputeFlags() { return InstructionFlags.MayThrow | InstructionFlags.EndPointUnreachable; } public override InstructionFlags DirectFlags { get { return InstructionFlags.MayThrow | InstructionFlags.EndPointUnreachable; } } public override void AcceptVisitor(ILVisitor visitor) { visitor.VisitInvalidInstruction(this); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitInvalidInstruction(this); } } /// 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); } } /// A container of IL blocks. public sealed partial class ILFunction : ILVariableScope { 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 = (ILFunction)ShallowClone(); clone.Body = this.body.Clone(); return clone; } public override StackType ResultType { get { return StackType.O; } } public override void AcceptVisitor(ILVisitor visitor) { visitor.VisitILFunction(this); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitILFunction(this); } } /// A container of IL blocks. public sealed partial class BlockContainer : ILInstruction { public override StackType ResultType { get { return StackType.Void; } } public override void AcceptVisitor(ILVisitor visitor) { visitor.VisitBlockContainer(this); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitBlockContainer(this); } } /// 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); } } /// A region where a pinned variable is used (initial representation of future fixed statement). public sealed partial class PinnedRegion : ILInstruction, IInstructionWithVariableOperand { 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.StoreCount--; variable = value; if (IsConnected) variable.StoreCount++; } } protected override void Connected() { base.Connected(); variable.StoreCount++; } protected override void Disconnected() { variable.StoreCount--; base.Disconnected(); } internal override void CheckInvariant(ILPhase phase) { base.CheckInvariant(phase); Debug.Assert(phase <= ILPhase.InILReader || this.IsDescendantOf(variable.Scope)); } 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) { output.Write(OpCode); output.Write(' '); variable.WriteTo(output); output.Write('('); this.init.WriteTo(output); output.Write(", "); this.body.WriteTo(output); output.Write(')'); } public override void AcceptVisitor(ILVisitor visitor) { visitor.VisitPinnedRegion(this); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitPinnedRegion(this); } } /// Unary operator that expects an input of type I4. Returns 1 (of type I4) if the input value is 0. Otherwise, returns 0 (of type I4). public sealed partial class LogicNot : UnaryInstruction { public LogicNot(ILInstruction argument) : base(OpCode.LogicNot, argument) { } public override StackType ResultType { get { return StackType.I4; } } public override void AcceptVisitor(ILVisitor visitor) { visitor.VisitLogicNot(this); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitLogicNot(this); } } /// 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); } } /// Common instruction for compound assignments. public sealed 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; } public override StackType ResultType { get { return target.ResultType; } } public override void AcceptVisitor(ILVisitor visitor) { visitor.VisitCompoundAssignmentInstruction(this); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitCompoundAssignmentInstruction(this); } } /// Bitwise NOT public sealed partial class BitNot : UnaryInstruction { public BitNot(ILInstruction argument) : base(OpCode.BitNot, argument) { } public override void AcceptVisitor(ILVisitor visitor) { visitor.VisitBitNot(this); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitBitNot(this); } } /// 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); } } /// Unconditional branch. goto target; public sealed partial class Branch : SimpleInstruction { public override StackType ResultType { get { return StackType.Void; } } public override void AcceptVisitor(ILVisitor visitor) { visitor.VisitBranch(this); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitBranch(this); } } /// Unconditional branch to end of block container. goto container_end;, often break; public sealed partial class Leave : SimpleInstruction { 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); } } /// 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); } } /// Switch statement public sealed partial class SwitchInstruction : ILInstruction { public override StackType ResultType { get { return StackType.Void; } } public override void AcceptVisitor(ILVisitor visitor) { visitor.VisitSwitchInstruction(this); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitSwitchInstruction(this); } } /// 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); } } /// 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); } } /// Catch handler within a try-catch statement. public sealed partial class TryCatchHandler : ILInstruction, IInstructionWithVariableOperand { 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.StoreCount--; variable = value; if (IsConnected) variable.StoreCount++; } } protected override void Connected() { base.Connected(); variable.StoreCount++; } protected override void Disconnected() { variable.StoreCount--; base.Disconnected(); } public override void AcceptVisitor(ILVisitor visitor) { visitor.VisitTryCatchHandler(this); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitTryCatchHandler(this); } } /// 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); } } /// 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); } } /// 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); } } /// 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 StackType ResultType { get { return StackType.I4; } } public override void AcceptVisitor(ILVisitor visitor) { visitor.VisitComp(this); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitComp(this); } } /// 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); } } /// 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); } } /// 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); } } /// 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); } } /// Loads the value of a local variable. (ldarg/ldloc) public sealed partial class LdLoc : SimpleInstruction, IInstructionWithVariableOperand { 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.LoadCount--; variable = value; if (IsConnected) variable.LoadCount++; } } protected override void Connected() { base.Connected(); variable.LoadCount++; } protected override void Disconnected() { variable.LoadCount--; base.Disconnected(); } internal override void CheckInvariant(ILPhase phase) { base.CheckInvariant(phase); Debug.Assert(phase <= ILPhase.InILReader || this.IsDescendantOf(variable.Scope)); } 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) { 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); } } /// Loads the address of a local variable. (ldarga/ldloca) public sealed partial class LdLoca : SimpleInstruction, IInstructionWithVariableOperand { 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.AddressCount--; variable = value; if (IsConnected) variable.AddressCount++; } } protected override void Connected() { base.Connected(); variable.AddressCount++; } protected override void Disconnected() { variable.AddressCount--; base.Disconnected(); } internal override void CheckInvariant(ILPhase phase) { base.CheckInvariant(phase); Debug.Assert(phase <= ILPhase.InILReader || this.IsDescendantOf(variable.Scope)); } public override void WriteTo(ITextOutput output) { 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); } } /// Stores a value into a local variable. (starg/stloc) public sealed partial class StLoc : ILInstruction, IInstructionWithVariableOperand { 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.StoreCount--; variable = value; if (IsConnected) variable.StoreCount++; } } protected override void Connected() { base.Connected(); variable.StoreCount++; } protected override void Disconnected() { variable.StoreCount--; base.Disconnected(); } internal override void CheckInvariant(ILPhase phase) { base.CheckInvariant(phase); Debug.Assert(phase <= ILPhase.InILReader || this.IsDescendantOf(variable.Scope)); } 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) { output.Write(OpCode); output.Write(' '); variable.WriteTo(output); output.Write('('); this.value.WriteTo(output); output.Write(')'); } public override void AcceptVisitor(ILVisitor visitor) { visitor.VisitStLoc(this); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitStLoc(this); } } /// 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) : base(OpCode.AddressOf) { this.Value = value; } 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; } } protected override InstructionFlags ComputeFlags() { return value.Flags; } public override InstructionFlags DirectFlags { get { return InstructionFlags.None; } } public override void WriteTo(ITextOutput output) { output.Write(OpCode); output.Write('('); this.value.WriteTo(output); output.Write(')'); } public override void AcceptVisitor(ILVisitor visitor) { visitor.VisitAddressOf(this); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitAddressOf(this); } } /// 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) { 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); } } /// 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) { 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); } } /// 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) { 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); } } /// Loads a constant floating-point number. public sealed partial class LdcF : SimpleInstruction { public LdcF(double value) : base(OpCode.LdcF) { this.Value = value; } public readonly double Value; public override StackType ResultType { get { return StackType.F; } } public override void WriteTo(ITextOutput output) { output.Write(OpCode); output.Write(' '); Disassembler.DisassemblerHelpers.WriteOperand(output, Value); } public override void AcceptVisitor(ILVisitor visitor) { visitor.VisitLdcF(this); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitLdcF(this); } } /// 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) { 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); } } /// 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); } } /// 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) { output.Write(OpCode); output.Write(' '); Disassembler.DisassemblerHelpers.WriteOperand(output, method); } public override void AcceptVisitor(ILVisitor visitor) { visitor.VisitLdFtn(this); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitLdFtn(this); } } /// 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) { output.Write(OpCode); output.Write(' '); Disassembler.DisassemblerHelpers.WriteOperand(output, method); output.Write('('); Argument.WriteTo(output); output.Write(')'); } public override void AcceptVisitor(ILVisitor visitor) { visitor.VisitLdVirtFtn(this); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitLdVirtFtn(this); } } /// Loads runtime representation of metadata token public sealed partial class LdTypeToken : SimpleInstruction { public LdTypeToken(IType type) : base(OpCode.LdTypeToken) { this.type = type; } readonly IType type; /// Returns the type operand. public IType Type { get { return type; } } public override StackType ResultType { get { return StackType.O; } } public override void WriteTo(ITextOutput output) { output.Write(OpCode); output.Write(' '); Disassembler.DisassemblerHelpers.WriteOperand(output, type); } public override void AcceptVisitor(ILVisitor visitor) { visitor.VisitLdTypeToken(this); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitLdTypeToken(this); } } /// 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) { output.Write(OpCode); output.Write(' '); Disassembler.DisassemblerHelpers.WriteOperand(output, member); } public override void AcceptVisitor(ILVisitor visitor) { visitor.VisitLdMemberToken(this); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitLdMemberToken(this); } } /// 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); } } /// Returns from the current method or lambda. public sealed partial class Return : ILInstruction { public override StackType ResultType { get { return StackType.Void; } } public override void AcceptVisitor(ILVisitor visitor) { visitor.VisitReturn(this); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitReturn(this); } } /// 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; readonly IField field; /// Returns the field operand. public IField Field { get { return field; } } public override StackType ResultType { get { return 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) { output.Write(OpCode); output.Write(' '); Disassembler.DisassemblerHelpers.WriteOperand(output, field); output.Write('('); this.target.WriteTo(output); output.Write(')'); } public override void AcceptVisitor(ILVisitor visitor) { visitor.VisitLdFlda(this); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitLdFlda(this); } } /// 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) { output.Write(OpCode); output.Write(' '); Disassembler.DisassemblerHelpers.WriteOperand(output, field); } public override void AcceptVisitor(ILVisitor visitor) { visitor.VisitLdsFlda(this); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitLdsFlda(this); } } /// 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; } readonly IType type; /// Returns the type operand. public IType Type { get { return type; } } 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) { output.Write(OpCode); output.Write(' '); Disassembler.DisassemblerHelpers.WriteOperand(output, type); output.Write('('); Argument.WriteTo(output); output.Write(')'); } public override void AcceptVisitor(ILVisitor visitor) { visitor.VisitCastClass(this); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitCastClass(this); } } /// 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; } readonly IType type; /// Returns the type operand. public IType Type { get { return type; } } public override StackType ResultType { get { return StackType.O; } } public override void WriteTo(ITextOutput output) { output.Write(OpCode); output.Write(' '); Disassembler.DisassemblerHelpers.WriteOperand(output, type); output.Write('('); Argument.WriteTo(output); output.Write(')'); } public override void AcceptVisitor(ILVisitor visitor) { visitor.VisitIsInst(this); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitIsInst(this); } } /// 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; } readonly IType type; /// Returns the type operand. public IType Type { get { return type; } } /// 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; } } public override void WriteTo(ITextOutput output) { if (IsVolatile) output.Write("volatile."); if (UnalignedPrefix > 0) output.Write("unaligned(" + UnalignedPrefix + ")."); output.Write(OpCode); output.Write(' '); Disassembler.DisassemblerHelpers.WriteOperand(output, type); output.Write('('); this.target.WriteTo(output); output.Write(')'); } public override void AcceptVisitor(ILVisitor visitor) { visitor.VisitLdObj(this); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitLdObj(this); } } /// Indirect store (store to ref/pointer). 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; } readonly IType type; /// Returns the type operand. public IType Type { get { return type; } } /// 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; } } public override void WriteTo(ITextOutput output) { if (IsVolatile) output.Write("volatile."); if (UnalignedPrefix > 0) output.Write("unaligned(" + UnalignedPrefix + ")."); output.Write(OpCode); output.Write(' '); Disassembler.DisassemblerHelpers.WriteOperand(output, type); output.Write('('); this.target.WriteTo(output); output.Write(", "); this.value.WriteTo(output); output.Write(')'); } public override void AcceptVisitor(ILVisitor visitor) { visitor.VisitStObj(this); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitStObj(this); } } /// Boxes a value. public sealed partial class Box : UnaryInstruction { public Box(ILInstruction argument, IType type) : base(OpCode.Box, argument) { this.type = type; } readonly IType type; /// Returns the type operand. public IType Type { get { return type; } } 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) { output.Write(OpCode); output.Write(' '); Disassembler.DisassemblerHelpers.WriteOperand(output, type); output.Write('('); Argument.WriteTo(output); output.Write(')'); } public override void AcceptVisitor(ILVisitor visitor) { visitor.VisitBox(this); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitBox(this); } } /// Compute address inside box. public sealed partial class Unbox : UnaryInstruction { public Unbox(ILInstruction argument, IType type) : base(OpCode.Unbox, argument) { this.type = type; } readonly IType type; /// Returns the type operand. public IType Type { get { return type; } } public override StackType ResultType { get { return StackType.Ref; } } 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) { output.Write(OpCode); output.Write(' '); Disassembler.DisassemblerHelpers.WriteOperand(output, type); output.Write('('); Argument.WriteTo(output); output.Write(')'); } public override void AcceptVisitor(ILVisitor visitor) { visitor.VisitUnbox(this); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitUnbox(this); } } /// Unbox a value. public sealed partial class UnboxAny : UnaryInstruction { public UnboxAny(ILInstruction argument, IType type) : base(OpCode.UnboxAny, argument) { this.type = type; } readonly IType type; /// Returns the type operand. public IType Type { get { return type; } } public override StackType ResultType { get { return type.GetStackType(); } } protected override InstructionFlags ComputeFlags() { return base.ComputeFlags() | InstructionFlags.SideEffect | InstructionFlags.MayThrow; } public override InstructionFlags DirectFlags { get { return base.DirectFlags | InstructionFlags.SideEffect | InstructionFlags.MayThrow; } } public override void WriteTo(ITextOutput output) { output.Write(OpCode); output.Write(' '); Disassembler.DisassemblerHelpers.WriteOperand(output, type); output.Write('('); Argument.WriteTo(output); output.Write(')'); } public override void AcceptVisitor(ILVisitor visitor) { visitor.VisitUnboxAny(this); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitUnboxAny(this); } } /// Creates an object instance and calls the constructor. public sealed partial class NewObj : CallInstruction { public NewObj(IMethod method) : base(OpCode.NewObj, method) { } public override StackType ResultType { get { return Method.DeclaringType.GetStackType(); } } public override void AcceptVisitor(ILVisitor visitor) { visitor.VisitNewObj(this); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitNewObj(this); } } /// Creates an array instance. public sealed partial class NewArr : ILInstruction { public NewArr(IType type, params ILInstruction[] indices) : base(OpCode.NewArr) { this.type = type; this.Indices = new InstructionCollection(this, 0); this.Indices.AddRange(indices); } readonly IType type; /// Returns the type operand. public IType Type { get { return type; } } public static readonly SlotInfo IndicesSlot = new SlotInfo("Indices", canInlineInto: true); public InstructionCollection Indices { get; private set; } protected sealed override int GetChildCount() { return Indices.Count; } protected sealed override ILInstruction GetChild(int index) { switch (index) { default: return this.Indices[index - 0]; } } protected sealed override void SetChild(int index, ILInstruction value) { switch (index) { default: this.Indices[index - 0] = value; break; } } protected sealed override SlotInfo GetChildSlot(int index) { switch (index) { default: return IndicesSlot; } } public sealed override ILInstruction Clone() { var clone = (NewArr)ShallowClone(); clone.Indices = new InstructionCollection(clone, 0); clone.Indices.AddRange(this.Indices.Select(arg => arg.Clone())); return clone; } public override StackType ResultType { get { return StackType.O; } } protected override InstructionFlags ComputeFlags() { return Indices.Aggregate(InstructionFlags.None, (f, arg) => f | arg.Flags) | InstructionFlags.MayThrow; } public override InstructionFlags DirectFlags { get { return InstructionFlags.MayThrow; } } public override void WriteTo(ITextOutput output) { output.Write(OpCode); output.Write(' '); Disassembler.DisassemblerHelpers.WriteOperand(output, type); output.Write('('); bool first = true; foreach (var indices in Indices) { if (!first) output.Write(", "); else first = false; indices.WriteTo(output); } output.Write(')'); } public override void AcceptVisitor(ILVisitor visitor) { visitor.VisitNewArr(this); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitNewArr(this); } } /// Returns the default value for a type. public sealed partial class DefaultValue : SimpleInstruction { public DefaultValue(IType type) : base(OpCode.DefaultValue) { this.type = type; } readonly IType type; /// Returns the type operand. public IType Type { get { return type; } } public override StackType ResultType { get { return type.GetStackType(); } } public override void WriteTo(ITextOutput output) { output.Write(OpCode); output.Write(' '); Disassembler.DisassemblerHelpers.WriteOperand(output, type); } public override void AcceptVisitor(ILVisitor visitor) { visitor.VisitDefaultValue(this); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitDefaultValue(this); } } /// Throws an exception. public sealed partial class Throw : UnaryInstruction { public Throw(ILInstruction argument) : base(OpCode.Throw, argument) { } public override StackType ResultType { get { return StackType.Void; } } protected override InstructionFlags ComputeFlags() { return base.ComputeFlags() | InstructionFlags.MayThrow | InstructionFlags.EndPointUnreachable; } public override InstructionFlags DirectFlags { get { return base.DirectFlags | InstructionFlags.MayThrow | InstructionFlags.EndPointUnreachable; } } public override void AcceptVisitor(ILVisitor visitor) { visitor.VisitThrow(this); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitThrow(this); } } /// Rethrows the current exception. public sealed partial class Rethrow : SimpleInstruction { public Rethrow() : base(OpCode.Rethrow) { } public override StackType ResultType { get { return StackType.Void; } } protected override InstructionFlags ComputeFlags() { return InstructionFlags.MayThrow | InstructionFlags.EndPointUnreachable; } public override InstructionFlags DirectFlags { get { return InstructionFlags.MayThrow | InstructionFlags.EndPointUnreachable; } } public override void AcceptVisitor(ILVisitor visitor) { visitor.VisitRethrow(this); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitRethrow(this); } } /// Gets the size of a type in bytes. public sealed partial class SizeOf : SimpleInstruction { public SizeOf(IType type) : base(OpCode.SizeOf) { this.type = type; } readonly IType type; /// Returns the type operand. public IType Type { get { return type; } } public override StackType ResultType { get { return StackType.I4; } } public override void WriteTo(ITextOutput output) { output.Write(OpCode); output.Write(' '); Disassembler.DisassemblerHelpers.WriteOperand(output, type); } public override void AcceptVisitor(ILVisitor visitor) { visitor.VisitSizeOf(this); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitSizeOf(this); } } /// Returns the length of an array as 'native unsigned int'. public sealed partial class LdLen : ILInstruction { public static readonly SlotInfo ArraySlot = new SlotInfo("Array", canInlineInto: true); ILInstruction array; public ILInstruction Array { get { return this.array; } set { ValidateChild(value); SetChildInstruction(ref this.array, value, 0); } } protected sealed override int GetChildCount() { return 1; } protected sealed override ILInstruction GetChild(int index) { switch (index) { case 0: return this.array; default: throw new IndexOutOfRangeException(); } } protected sealed override void SetChild(int index, ILInstruction value) { switch (index) { case 0: this.Array = value; break; default: throw new IndexOutOfRangeException(); } } protected sealed override SlotInfo GetChildSlot(int index) { switch (index) { case 0: return ArraySlot; default: throw new IndexOutOfRangeException(); } } public sealed override ILInstruction Clone() { var clone = (LdLen)ShallowClone(); clone.Array = this.array.Clone(); return clone; } protected override InstructionFlags ComputeFlags() { return array.Flags | InstructionFlags.MayThrow; } public override InstructionFlags DirectFlags { get { return InstructionFlags.MayThrow; } } public override void AcceptVisitor(ILVisitor visitor) { visitor.VisitLdLen(this); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitLdLen(this); } } /// Load address of array element. public sealed partial class LdElema : ILInstruction { public LdElema(IType type, ILInstruction array, params ILInstruction[] indices) : base(OpCode.LdElema) { this.type = type; this.Array = array; this.Indices = new InstructionCollection(this, 1); this.Indices.AddRange(indices); } readonly IType type; /// Returns the type operand. public IType Type { get { return type; } } public static readonly SlotInfo ArraySlot = new SlotInfo("Array", canInlineInto: true); ILInstruction array; public ILInstruction Array { get { return this.array; } set { ValidateChild(value); SetChildInstruction(ref this.array, value, 0); } } public static readonly SlotInfo IndicesSlot = new SlotInfo("Indices", canInlineInto: true); public InstructionCollection Indices { get; private set; } protected sealed override int GetChildCount() { return 1 + Indices.Count; } protected sealed override ILInstruction GetChild(int index) { switch (index) { case 0: return this.array; default: return this.Indices[index - 1]; } } protected sealed override void SetChild(int index, ILInstruction value) { switch (index) { case 0: this.Array = value; break; default: this.Indices[index - 1] = value; break; } } protected sealed override SlotInfo GetChildSlot(int index) { switch (index) { case 0: return ArraySlot; default: return IndicesSlot; } } public sealed override ILInstruction Clone() { var clone = (LdElema)ShallowClone(); clone.Array = this.array.Clone(); clone.Indices = new InstructionCollection(clone, 1); clone.Indices.AddRange(this.Indices.Select(arg => arg.Clone())); return clone; } public bool DelayExceptions; public override StackType ResultType { get { return StackType.Ref; } } /// Gets whether the 'readonly' prefix was applied to this instruction. public bool IsReadOnly { get; set; } protected override InstructionFlags ComputeFlags() { return array.Flags | Indices.Aggregate(InstructionFlags.None, (f, arg) => f | arg.Flags) | (DelayExceptions ? InstructionFlags.None : InstructionFlags.MayThrow); } public override InstructionFlags DirectFlags { get { return (DelayExceptions ? InstructionFlags.None : InstructionFlags.MayThrow); } } public override void WriteTo(ITextOutput output) { if (IsReadOnly) output.Write("readonly."); output.Write(OpCode); output.Write(' '); Disassembler.DisassemblerHelpers.WriteOperand(output, type); output.Write('('); this.array.WriteTo(output); foreach (var indices in Indices) { output.Write(", "); indices.WriteTo(output); } output.Write(')'); } public override void AcceptVisitor(ILVisitor visitor) { visitor.VisitLdElema(this); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitLdElema(this); } } /// Converts an array pointer (O) to a reference to the first element, or to a null reference if the array is null or empty. /// Also used to convert a string to a reference to the first character. public sealed partial class ArrayToPointer : ILInstruction { public ArrayToPointer(ILInstruction array) : base(OpCode.ArrayToPointer) { this.Array = array; } public static readonly SlotInfo ArraySlot = new SlotInfo("Array", canInlineInto: true); ILInstruction array; public ILInstruction Array { get { return this.array; } set { ValidateChild(value); SetChildInstruction(ref this.array, value, 0); } } protected sealed override int GetChildCount() { return 1; } protected sealed override ILInstruction GetChild(int index) { switch (index) { case 0: return this.array; default: throw new IndexOutOfRangeException(); } } protected sealed override void SetChild(int index, ILInstruction value) { switch (index) { case 0: this.Array = value; break; default: throw new IndexOutOfRangeException(); } } protected sealed override SlotInfo GetChildSlot(int index) { switch (index) { case 0: return ArraySlot; default: throw new IndexOutOfRangeException(); } } public sealed override ILInstruction Clone() { var clone = (ArrayToPointer)ShallowClone(); clone.Array = this.array.Clone(); return clone; } public override StackType ResultType { get { return StackType.Ref; } } protected override InstructionFlags ComputeFlags() { return array.Flags; } public override InstructionFlags DirectFlags { get { return InstructionFlags.None; } } public override void WriteTo(ITextOutput output) { output.Write(OpCode); output.Write('('); this.array.WriteTo(output); output.Write(')'); } public override void AcceptVisitor(ILVisitor visitor) { visitor.VisitArrayToPointer(this); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitArrayToPointer(this); } } /// Push a typed reference of type class onto the stack. public sealed partial class MakeRefAny : UnaryInstruction { public MakeRefAny(ILInstruction argument, IType type) : base(OpCode.MakeRefAny, argument) { this.type = type; } readonly IType type; /// Returns the type operand. public IType Type { get { return type; } } public override StackType ResultType { get { return StackType.O; } } public override void WriteTo(ITextOutput output) { output.Write(OpCode); output.Write(' '); Disassembler.DisassemblerHelpers.WriteOperand(output, type); output.Write('('); Argument.WriteTo(output); output.Write(')'); } public override void AcceptVisitor(ILVisitor visitor) { visitor.VisitMakeRefAny(this); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitMakeRefAny(this); } } /// Push the type token stored in a typed reference. public sealed partial class RefAnyType : UnaryInstruction { public RefAnyType(ILInstruction argument) : base(OpCode.RefAnyType, argument) { } public override StackType ResultType { get { return StackType.O; } } public override void AcceptVisitor(ILVisitor visitor) { visitor.VisitRefAnyType(this); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitRefAnyType(this); } } /// Push the address stored in a typed reference. public sealed partial class RefAnyValue : UnaryInstruction { public RefAnyValue(ILInstruction argument, IType type) : base(OpCode.RefAnyValue, argument) { this.type = type; } readonly IType type; /// Returns the type operand. public IType Type { get { return type; } } public override StackType ResultType { get { return StackType.Ref; } } 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) { output.Write(OpCode); output.Write(' '); Disassembler.DisassemblerHelpers.WriteOperand(output, type); output.Write('('); Argument.WriteTo(output); output.Write(')'); } public override void AcceptVisitor(ILVisitor visitor) { visitor.VisitRefAnyValue(this); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitRefAnyValue(this); } } /// /// Base class for visitor pattern. /// public abstract class ILVisitor { /// Called by Visit*() methods that were not overridden protected abstract void Default(ILInstruction inst); protected internal virtual void VisitInvalidInstruction(InvalidInstruction inst) { Default(inst); } protected internal virtual void VisitNop(Nop inst) { Default(inst); } protected internal virtual void VisitILFunction(ILFunction function) { Default(function); } protected internal virtual void VisitBlockContainer(BlockContainer container) { Default(container); } protected internal virtual void VisitBlock(Block block) { Default(block); } protected internal virtual void VisitPinnedRegion(PinnedRegion inst) { Default(inst); } protected internal virtual void VisitLogicNot(LogicNot inst) { Default(inst); } protected internal virtual void VisitBinaryNumericInstruction(BinaryNumericInstruction inst) { Default(inst); } protected internal virtual void VisitCompoundAssignmentInstruction(CompoundAssignmentInstruction inst) { Default(inst); } protected internal virtual void VisitBitNot(BitNot inst) { Default(inst); } protected internal virtual void VisitArglist(Arglist inst) { Default(inst); } protected internal virtual void VisitBranch(Branch inst) { Default(inst); } protected internal virtual void VisitLeave(Leave inst) { Default(inst); } protected internal virtual void VisitIfInstruction(IfInstruction inst) { Default(inst); } protected internal virtual void VisitSwitchInstruction(SwitchInstruction inst) { Default(inst); } protected internal virtual void VisitSwitchSection(SwitchSection inst) { Default(inst); } protected internal virtual void VisitTryCatch(TryCatch inst) { Default(inst); } protected internal virtual void VisitTryCatchHandler(TryCatchHandler inst) { Default(inst); } protected internal virtual void VisitTryFinally(TryFinally inst) { Default(inst); } protected internal virtual void VisitTryFault(TryFault inst) { Default(inst); } protected internal virtual void VisitDebugBreak(DebugBreak inst) { Default(inst); } protected internal virtual void VisitComp(Comp inst) { Default(inst); } protected internal virtual void VisitCall(Call inst) { Default(inst); } protected internal virtual void VisitCallVirt(CallVirt inst) { Default(inst); } protected internal virtual void VisitCkfinite(Ckfinite inst) { Default(inst); } protected internal virtual void VisitConv(Conv inst) { Default(inst); } protected internal virtual void VisitLdLoc(LdLoc inst) { Default(inst); } protected internal virtual void VisitLdLoca(LdLoca inst) { Default(inst); } protected internal virtual void VisitStLoc(StLoc inst) { Default(inst); } protected internal virtual void VisitAddressOf(AddressOf inst) { Default(inst); } protected internal virtual void VisitLdStr(LdStr inst) { Default(inst); } protected internal virtual void VisitLdcI4(LdcI4 inst) { Default(inst); } protected internal virtual void VisitLdcI8(LdcI8 inst) { Default(inst); } protected internal virtual void VisitLdcF(LdcF inst) { Default(inst); } protected internal virtual void VisitLdcDecimal(LdcDecimal inst) { Default(inst); } protected internal virtual void VisitLdNull(LdNull inst) { Default(inst); } protected internal virtual void VisitLdFtn(LdFtn inst) { Default(inst); } protected internal virtual void VisitLdVirtFtn(LdVirtFtn inst) { Default(inst); } protected internal virtual void VisitLdTypeToken(LdTypeToken inst) { Default(inst); } protected internal virtual void VisitLdMemberToken(LdMemberToken inst) { Default(inst); } protected internal virtual void VisitLocAlloc(LocAlloc inst) { Default(inst); } protected internal virtual void VisitReturn(Return inst) { Default(inst); } protected internal virtual void VisitLdFlda(LdFlda inst) { Default(inst); } protected internal virtual void VisitLdsFlda(LdsFlda inst) { Default(inst); } protected internal virtual void VisitCastClass(CastClass inst) { Default(inst); } protected internal virtual void VisitIsInst(IsInst inst) { Default(inst); } protected internal virtual void VisitLdObj(LdObj inst) { Default(inst); } protected internal virtual void VisitStObj(StObj inst) { Default(inst); } protected internal virtual void VisitBox(Box inst) { Default(inst); } protected internal virtual void VisitUnbox(Unbox inst) { Default(inst); } protected internal virtual void VisitUnboxAny(UnboxAny inst) { Default(inst); } protected internal virtual void VisitNewObj(NewObj inst) { Default(inst); } protected internal virtual void VisitNewArr(NewArr inst) { Default(inst); } protected internal virtual void VisitDefaultValue(DefaultValue inst) { Default(inst); } protected internal virtual void VisitThrow(Throw inst) { Default(inst); } protected internal virtual void VisitRethrow(Rethrow inst) { Default(inst); } protected internal virtual void VisitSizeOf(SizeOf inst) { Default(inst); } protected internal virtual void VisitLdLen(LdLen inst) { Default(inst); } protected internal virtual void VisitLdElema(LdElema inst) { Default(inst); } protected internal virtual void VisitArrayToPointer(ArrayToPointer inst) { Default(inst); } protected internal virtual void VisitMakeRefAny(MakeRefAny inst) { Default(inst); } protected internal virtual void VisitRefAnyType(RefAnyType inst) { Default(inst); } protected internal virtual void VisitRefAnyValue(RefAnyValue inst) { Default(inst); } } /// /// Base class for visitor pattern. /// public abstract class ILVisitor { /// Called by Visit*() methods that were not overridden protected abstract T Default(ILInstruction inst); protected internal virtual T VisitInvalidInstruction(InvalidInstruction inst) { return Default(inst); } protected internal virtual T VisitNop(Nop inst) { return Default(inst); } protected internal virtual T VisitILFunction(ILFunction function) { return Default(function); } protected internal virtual T VisitBlockContainer(BlockContainer container) { return Default(container); } protected internal virtual T VisitBlock(Block block) { return Default(block); } protected internal virtual T VisitPinnedRegion(PinnedRegion inst) { return Default(inst); } protected internal virtual T VisitLogicNot(LogicNot inst) { return Default(inst); } protected internal virtual T VisitBinaryNumericInstruction(BinaryNumericInstruction inst) { return Default(inst); } protected internal virtual T VisitCompoundAssignmentInstruction(CompoundAssignmentInstruction inst) { return Default(inst); } protected internal virtual T VisitBitNot(BitNot inst) { return Default(inst); } protected internal virtual T VisitArglist(Arglist inst) { return Default(inst); } protected internal virtual T VisitBranch(Branch inst) { return Default(inst); } protected internal virtual T VisitLeave(Leave inst) { return Default(inst); } protected internal virtual T VisitIfInstruction(IfInstruction inst) { return Default(inst); } protected internal virtual T VisitSwitchInstruction(SwitchInstruction inst) { return Default(inst); } protected internal virtual T VisitSwitchSection(SwitchSection inst) { return Default(inst); } protected internal virtual T VisitTryCatch(TryCatch inst) { return Default(inst); } protected internal virtual T VisitTryCatchHandler(TryCatchHandler inst) { return Default(inst); } protected internal virtual T VisitTryFinally(TryFinally inst) { return Default(inst); } protected internal virtual T VisitTryFault(TryFault inst) { return Default(inst); } protected internal virtual T VisitDebugBreak(DebugBreak inst) { return Default(inst); } protected internal virtual T VisitComp(Comp inst) { return Default(inst); } protected internal virtual T VisitCall(Call inst) { return Default(inst); } protected internal virtual T VisitCallVirt(CallVirt inst) { return Default(inst); } protected internal virtual T VisitCkfinite(Ckfinite inst) { return Default(inst); } protected internal virtual T VisitConv(Conv inst) { return Default(inst); } protected internal virtual T VisitLdLoc(LdLoc inst) { return Default(inst); } protected internal virtual T VisitLdLoca(LdLoca inst) { return Default(inst); } protected internal virtual T VisitStLoc(StLoc inst) { return Default(inst); } protected internal virtual T VisitAddressOf(AddressOf inst) { return Default(inst); } protected internal virtual T VisitLdStr(LdStr inst) { return Default(inst); } protected internal virtual T VisitLdcI4(LdcI4 inst) { return Default(inst); } protected internal virtual T VisitLdcI8(LdcI8 inst) { return Default(inst); } protected internal virtual T VisitLdcF(LdcF inst) { return Default(inst); } protected internal virtual T VisitLdcDecimal(LdcDecimal inst) { return Default(inst); } protected internal virtual T VisitLdNull(LdNull inst) { return Default(inst); } protected internal virtual T VisitLdFtn(LdFtn inst) { return Default(inst); } protected internal virtual T VisitLdVirtFtn(LdVirtFtn inst) { return Default(inst); } protected internal virtual T VisitLdTypeToken(LdTypeToken inst) { return Default(inst); } protected internal virtual T VisitLdMemberToken(LdMemberToken inst) { return Default(inst); } protected internal virtual T VisitLocAlloc(LocAlloc inst) { return Default(inst); } protected internal virtual T VisitReturn(Return inst) { return Default(inst); } protected internal virtual T VisitLdFlda(LdFlda inst) { return Default(inst); } protected internal virtual T VisitLdsFlda(LdsFlda inst) { return Default(inst); } protected internal virtual T VisitCastClass(CastClass inst) { return Default(inst); } protected internal virtual T VisitIsInst(IsInst inst) { return Default(inst); } protected internal virtual T VisitLdObj(LdObj inst) { return Default(inst); } protected internal virtual T VisitStObj(StObj inst) { return Default(inst); } protected internal virtual T VisitBox(Box inst) { return Default(inst); } protected internal virtual T VisitUnbox(Unbox inst) { return Default(inst); } protected internal virtual T VisitUnboxAny(UnboxAny inst) { return Default(inst); } protected internal virtual T VisitNewObj(NewObj inst) { return Default(inst); } protected internal virtual T VisitNewArr(NewArr inst) { return Default(inst); } protected internal virtual T VisitDefaultValue(DefaultValue inst) { return Default(inst); } protected internal virtual T VisitThrow(Throw inst) { return Default(inst); } protected internal virtual T VisitRethrow(Rethrow inst) { return Default(inst); } protected internal virtual T VisitSizeOf(SizeOf inst) { return Default(inst); } protected internal virtual T VisitLdLen(LdLen inst) { return Default(inst); } protected internal virtual T VisitLdElema(LdElema inst) { return Default(inst); } protected internal virtual T VisitArrayToPointer(ArrayToPointer inst) { return Default(inst); } protected internal virtual T VisitMakeRefAny(MakeRefAny inst) { return Default(inst); } protected internal virtual T VisitRefAnyType(RefAnyType inst) { return Default(inst); } protected internal virtual T VisitRefAnyValue(RefAnyValue inst) { return Default(inst); } } partial class BinaryComparisonInstruction { public static BinaryComparisonInstruction Create(OpCode opCode, ILInstruction left, ILInstruction right) { switch (opCode) { default: throw new ArgumentException("opCode is not a binary comparison instruction"); } } } partial class InstructionOutputExtensions { static readonly string[] originalOpCodeNames = { "invalid", "nop", "ILFunction", "BlockContainer", "Block", "PinnedRegion", "logic.not", "binary", "compound", "bit.not", "arglist", "br", "leave", "if", "switch", "switch.section", "try.catch", "try.catch.handler", "try.finally", "try.fault", "debug.break", "comp", "call", "callvirt", "ckfinite", "conv", "ldloc", "ldloca", "stloc", "addressof", "ldstr", "ldc.i4", "ldc.i8", "ldc.f", "ldc.decimal", "ldnull", "ldftn", "ldvirtftn", "ldtypetoken", "ldmembertoken", "localloc", "ret", "ldflda", "ldsflda", "castclass", "isinst", "ldobj", "stobj", "box", "unbox", "unbox.any", "newobj", "newarr", "default.value", "throw", "rethrow", "sizeof", "ldlen", "ldelema", "array.to.pointer", "mkrefany", "refanytype", "refanyval", }; } partial class ILInstruction { public bool MatchInvalidInstruction() { var inst = this as InvalidInstruction; if (inst != null) { return true; } return false; } public bool MatchNop() { var inst = this as Nop; if (inst != null) { return true; } return false; } public bool MatchPinnedRegion(out ILVariable variable, out ILInstruction init, out ILInstruction body) { var inst = this as PinnedRegion; if (inst != null) { variable = inst.Variable; init = inst.Init; body = inst.Body; return true; } variable = default(ILVariable); init = default(ILInstruction); body = default(ILInstruction); return false; } public bool MatchLogicNot(out ILInstruction argument) { var inst = this as LogicNot; if (inst != null) { argument = inst.Argument; return true; } argument = default(ILInstruction); return false; } public bool MatchBitNot(out ILInstruction argument) { var inst = this as BitNot; if (inst != null) { argument = inst.Argument; return true; } argument = default(ILInstruction); return false; } public bool MatchArglist() { var inst = this as Arglist; if (inst != null) { return true; } return false; } public bool MatchTryCatchHandler(out ILInstruction filter, out ILInstruction body, out ILVariable variable) { var inst = this as TryCatchHandler; if (inst != null) { filter = inst.Filter; body = inst.Body; variable = inst.Variable; return true; } filter = default(ILInstruction); body = default(ILInstruction); variable = default(ILVariable); return false; } public bool MatchDebugBreak() { var inst = this as DebugBreak; if (inst != null) { return true; } return false; } public bool MatchCkfinite(out ILInstruction argument) { var inst = this as Ckfinite; if (inst != null) { argument = inst.Argument; return true; } argument = default(ILInstruction); return false; } public bool MatchLdLoc(out ILVariable variable) { var inst = this as LdLoc; if (inst != null) { variable = inst.Variable; return true; } variable = default(ILVariable); return false; } public bool MatchLdLoca(out ILVariable variable) { var inst = this as LdLoca; if (inst != null) { variable = inst.Variable; return true; } variable = default(ILVariable); return false; } public bool MatchStLoc(out ILVariable variable, out ILInstruction value) { var inst = this as StLoc; if (inst != null) { variable = inst.Variable; value = inst.Value; return true; } variable = default(ILVariable); value = default(ILInstruction); return false; } public bool MatchAddressOf(out ILInstruction value) { var inst = this as AddressOf; if (inst != null) { value = inst.Value; return true; } value = default(ILInstruction); return false; } public bool MatchLdStr(out string value) { var inst = this as LdStr; if (inst != null) { value = inst.Value; return true; } value = default(string); return false; } public bool MatchLdcI4(out int value) { var inst = this as LdcI4; if (inst != null) { value = inst.Value; return true; } value = default(int); return false; } public bool MatchLdcI8(out long value) { var inst = this as LdcI8; if (inst != null) { value = inst.Value; return true; } value = default(long); return false; } public bool MatchLdcF(out double value) { var inst = this as LdcF; if (inst != null) { value = inst.Value; return true; } value = default(double); return false; } public bool MatchLdcDecimal(out decimal value) { var inst = this as LdcDecimal; if (inst != null) { value = inst.Value; return true; } value = default(decimal); return false; } public bool MatchLdNull() { var inst = this as LdNull; if (inst != null) { return true; } return false; } public bool MatchLdFtn(out IMethod method) { var inst = this as LdFtn; if (inst != null) { method = inst.Method; return true; } method = default(IMethod); return false; } public bool MatchLdVirtFtn(out ILInstruction argument, out IMethod method) { var inst = this as LdVirtFtn; if (inst != null) { argument = inst.Argument; method = inst.Method; return true; } argument = default(ILInstruction); method = default(IMethod); return false; } public bool MatchLdTypeToken(out IType type) { var inst = this as LdTypeToken; if (inst != null) { type = inst.Type; return true; } type = default(IType); return false; } public bool MatchLdMemberToken(out IMember member) { var inst = this as LdMemberToken; if (inst != null) { member = inst.Member; return true; } member = default(IMember); return false; } public bool MatchLocAlloc(out ILInstruction argument) { var inst = this as LocAlloc; if (inst != null) { argument = inst.Argument; return true; } argument = default(ILInstruction); return false; } public bool MatchLdFlda(out ILInstruction target, out IField field) { var inst = this as LdFlda; if (inst != null) { target = inst.Target; field = inst.Field; return true; } target = default(ILInstruction); field = default(IField); return false; } public bool MatchLdsFlda(out IField field) { var inst = this as LdsFlda; if (inst != null) { field = inst.Field; return true; } field = default(IField); return false; } public bool MatchCastClass(out ILInstruction argument, out IType type) { var inst = this as CastClass; if (inst != null) { argument = inst.Argument; type = inst.Type; return true; } argument = default(ILInstruction); type = default(IType); return false; } public bool MatchIsInst(out ILInstruction argument, out IType type) { var inst = this as IsInst; if (inst != null) { argument = inst.Argument; type = inst.Type; return true; } argument = default(ILInstruction); type = default(IType); return false; } public bool MatchLdObj(out ILInstruction target, out IType type) { var inst = this as LdObj; if (inst != null) { target = inst.Target; type = inst.Type; return true; } target = default(ILInstruction); type = default(IType); return false; } public bool MatchStObj(out ILInstruction target, out ILInstruction value, out IType type) { var inst = this as StObj; if (inst != null) { target = inst.Target; value = inst.Value; type = inst.Type; return true; } target = default(ILInstruction); value = default(ILInstruction); type = default(IType); return false; } public bool MatchBox(out ILInstruction argument, out IType type) { var inst = this as Box; if (inst != null) { argument = inst.Argument; type = inst.Type; return true; } argument = default(ILInstruction); type = default(IType); return false; } public bool MatchUnbox(out ILInstruction argument, out IType type) { var inst = this as Unbox; if (inst != null) { argument = inst.Argument; type = inst.Type; return true; } argument = default(ILInstruction); type = default(IType); return false; } public bool MatchUnboxAny(out ILInstruction argument, out IType type) { var inst = this as UnboxAny; if (inst != null) { argument = inst.Argument; type = inst.Type; return true; } argument = default(ILInstruction); type = default(IType); return false; } public bool MatchNewArr(out IType type) { var inst = this as NewArr; if (inst != null) { type = inst.Type; return true; } type = default(IType); return false; } public bool MatchDefaultValue(out IType type) { var inst = this as DefaultValue; if (inst != null) { type = inst.Type; return true; } type = default(IType); return false; } public bool MatchThrow(out ILInstruction argument) { var inst = this as Throw; if (inst != null) { argument = inst.Argument; return true; } argument = default(ILInstruction); return false; } public bool MatchRethrow() { var inst = this as Rethrow; if (inst != null) { return true; } return false; } public bool MatchSizeOf(out IType type) { var inst = this as SizeOf; if (inst != null) { type = inst.Type; return true; } type = default(IType); return false; } public bool MatchLdElema(out IType type, out ILInstruction array) { var inst = this as LdElema; if (inst != null) { type = inst.Type; array = inst.Array; return true; } type = default(IType); array = default(ILInstruction); return false; } public bool MatchArrayToPointer(out ILInstruction array) { var inst = this as ArrayToPointer; if (inst != null) { array = inst.Array; return true; } array = default(ILInstruction); return false; } public bool MatchMakeRefAny(out ILInstruction argument, out IType type) { var inst = this as MakeRefAny; if (inst != null) { argument = inst.Argument; type = inst.Type; return true; } argument = default(ILInstruction); type = default(IType); return false; } public bool MatchRefAnyType(out ILInstruction argument) { var inst = this as RefAnyType; if (inst != null) { argument = inst.Argument; return true; } argument = default(ILInstruction); return false; } public bool MatchRefAnyValue(out ILInstruction argument, out IType type) { var inst = this as RefAnyValue; if (inst != null) { argument = inst.Argument; type = inst.Type; return true; } argument = default(ILInstruction); type = default(IType); return false; } } }