// 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 ICSharpCode.NRefactory.TypeSystem; namespace ICSharpCode.Decompiler.IL { /// /// Enum representing the type of an . /// public enum OpCode { /// No operation. Takes 0 arguments and returns void. Nop, /// Pops the top of the evaluation stack and returns the value. Pop, /// Peeks at the top of the evaluation stack and returns the value. Corresponds to IL 'dup'. Peek, /// Ignore the arguments and produce void. Used to prevent the end result of an instruction from being pushed to the evaluation stack. Void, /// A container of IL blocks. ILFunction, /// A container of IL blocks. BlockContainer, /// A block of IL instructions. Block, /// 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, /// Adds two numbers. Add, /// Subtracts two numbers Sub, /// Multiplies two numbers Mul, /// Divides two numbers Div, /// Division remainder Rem, /// Bitwise AND BitAnd, /// Bitwise OR BitOr, /// Bitwise XOR BitXor, /// Bitwise NOT BitNot, /// Retrieves the RuntimeArgumentHandle. Arglist, /// Unconditional branch. goto target; Branch, /// Marks the end of an finally, fault or exception filter block. EndFinally, /// If statement / conditional expression. if (condition) trueExpr else falseExpr IfInstruction, /// Try-catch statement. TryCatch, /// Catch handler within a try-catch statement. TryCatchHandler, /// Try-finally statement TryFinally, /// Try-fault statement TryFault, /// Breakpoint instruction DebugBreak, /// Compare equal. Returns 1 (of type I4) if two numbers or object references are equal; 0 otherwise. Ceq, /// Compare greater than. For integers, perform a signed comparison. For floating-point numbers, return 0 for unordered numbers. Cgt, /// Compare greater than (unordered/unsigned). For integers, perform a signed comparison. For floating-point numbers, return 1 for unordered numbers. Cgt_Un, /// Compare less than. For integers, perform a signed comparison. For floating-point numbers, return 0 for unordered numbers. Clt, /// Compare less than (unordered/unsigned). For integers, perform a signed comparison. For floating-point numbers, return 1 for unordered numbers. Clt_Un, /// 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, /// 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 the null reference. LdNull, /// Load method pointer LdFtn, /// Load method pointer LdVirtFtn, /// Loads runtime representation of metadata token LdToken, /// Allocates space in the stack frame LocAlloc, /// Returns from the current method or lambda. Return, /// Shift left Shl, /// Shift right Shr, /// Load instance field LdFld, /// Load address of instance field LdFlda, /// Store value to instance field StFld, /// Load static field LdsFld, /// Load static field address LdsFlda, /// Store value to static field StsFld, /// 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, /// Initializes the value at an address. InitObj, /// 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, } /// Instruction with a single argument public abstract partial class UnaryInstruction : ILInstruction { protected UnaryInstruction(OpCode opCode, ILInstruction argument) : base(opCode) { this.Argument = argument; } ILInstruction argument; public ILInstruction Argument { get { return this.argument; } set { ValidateArgument(value); SetChildInstruction(ref this.argument, value); } } public override IEnumerable Children { get { yield return this.argument; } } public override void TransformChildren(ILVisitor visitor) { this.Argument = this.argument.AcceptVisitor(visitor); } internal override ILInstruction Inline(InstructionFlags flagsBefore, IInlineContext context) { this.Argument = this.argument.Inline(flagsBefore, context); return this; } internal override void TransformStackIntoVariables(TransformStackIntoVariablesState state) { Argument.TransformStackIntoVariables(state); } protected override InstructionFlags ComputeFlags() { return argument.Flags; } 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; } ILInstruction left; public ILInstruction Left { get { return this.left; } set { ValidateArgument(value); SetChildInstruction(ref this.left, value); } } ILInstruction right; public ILInstruction Right { get { return this.right; } set { ValidateArgument(value); SetChildInstruction(ref this.right, value); } } public override IEnumerable Children { get { yield return this.left; yield return this.right; } } public override void TransformChildren(ILVisitor visitor) { this.Left = this.left.AcceptVisitor(visitor); this.Right = this.right.AcceptVisitor(visitor); } internal override ILInstruction Inline(InstructionFlags flagsBefore, IInlineContext context) { this.Right = this.right.Inline(flagsBefore | ((this.left.Flags) & ~(InstructionFlags.MayPeek | InstructionFlags.MayPop)), context); this.Left = this.left.Inline(flagsBefore, context); return this; } internal override void TransformStackIntoVariables(TransformStackIntoVariablesState state) { Left.TransformStackIntoVariables(state); Right.TransformStackIntoVariables(state); } protected override InstructionFlags ComputeFlags() { return left.Flags | right.Flags; } public override void WriteTo(ITextOutput output) { output.Write(OpCode); output.Write('('); this.left.WriteTo(output); output.Write(", "); this.right.WriteTo(output); output.Write(')'); } } /// 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 T AcceptVisitor(ILVisitor visitor) { return visitor.VisitNop(this); } } /// Pops the top of the evaluation stack and returns the value. public sealed partial class Pop : SimpleInstruction { public Pop(StackType resultType) : base(OpCode.Pop) { this.resultType = resultType; } StackType resultType; public override StackType ResultType { get { return resultType; } } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitPop(this); } } /// Peeks at the top of the evaluation stack and returns the value. Corresponds to IL 'dup'. public sealed partial class Peek : SimpleInstruction { public Peek(StackType resultType) : base(OpCode.Peek) { this.resultType = resultType; } StackType resultType; public override StackType ResultType { get { return resultType; } } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitPeek(this); } } /// Ignore the arguments and produce void. Used to prevent the end result of an instruction from being pushed to the evaluation stack. public sealed partial class Void : UnaryInstruction { public Void(ILInstruction argument) : base(OpCode.Void, argument) { } public override StackType ResultType { get { return StackType.Void; } } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitVoid(this); } } /// A container of IL blocks. public sealed partial class ILFunction : ILInstruction { ILInstruction body; public ILInstruction Body { get { return this.body; } set { ValidateChild(value); SetChildInstruction(ref this.body, value); } } public override IEnumerable Children { get { yield return this.body; } } public override void TransformChildren(ILVisitor visitor) { this.Body = this.body.AcceptVisitor(visitor); } public override StackType ResultType { get { return StackType.O; } } 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 T AcceptVisitor(ILVisitor visitor) { return visitor.VisitBlockContainer(this); } } /// A block of IL instructions. public sealed partial class Block : ILInstruction { public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitBlock(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 T AcceptVisitor(ILVisitor visitor) { return visitor.VisitLogicNot(this); } } /// Adds two numbers. public sealed partial class Add : BinaryNumericInstruction { public Add(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign, CompoundAssignmentType compoundAssignmentType = CompoundAssignmentType.None) : base(OpCode.Add, left, right, checkForOverflow, sign, compoundAssignmentType) { } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitAdd(this); } } /// Subtracts two numbers public sealed partial class Sub : BinaryNumericInstruction { public Sub(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign, CompoundAssignmentType compoundAssignmentType = CompoundAssignmentType.None) : base(OpCode.Sub, left, right, checkForOverflow, sign, compoundAssignmentType) { } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitSub(this); } } /// Multiplies two numbers public sealed partial class Mul : BinaryNumericInstruction { public Mul(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign, CompoundAssignmentType compoundAssignmentType = CompoundAssignmentType.None) : base(OpCode.Mul, left, right, checkForOverflow, sign, compoundAssignmentType) { } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitMul(this); } } /// Divides two numbers public sealed partial class Div : BinaryNumericInstruction { public Div(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign, CompoundAssignmentType compoundAssignmentType = CompoundAssignmentType.None) : base(OpCode.Div, left, right, checkForOverflow, sign, compoundAssignmentType) { } protected override InstructionFlags ComputeFlags() { return base.ComputeFlags() | InstructionFlags.MayThrow; } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitDiv(this); } } /// Division remainder public sealed partial class Rem : BinaryNumericInstruction { public Rem(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign, CompoundAssignmentType compoundAssignmentType = CompoundAssignmentType.None) : base(OpCode.Rem, left, right, checkForOverflow, sign, compoundAssignmentType) { } protected override InstructionFlags ComputeFlags() { return base.ComputeFlags() | InstructionFlags.MayThrow; } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitRem(this); } } /// Bitwise AND public sealed partial class BitAnd : BinaryNumericInstruction { public BitAnd(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign, CompoundAssignmentType compoundAssignmentType = CompoundAssignmentType.None) : base(OpCode.BitAnd, left, right, checkForOverflow, sign, compoundAssignmentType) { } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitBitAnd(this); } } /// Bitwise OR public sealed partial class BitOr : BinaryNumericInstruction { public BitOr(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign, CompoundAssignmentType compoundAssignmentType = CompoundAssignmentType.None) : base(OpCode.BitOr, left, right, checkForOverflow, sign, compoundAssignmentType) { } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitBitOr(this); } } /// Bitwise XOR public sealed partial class BitXor : BinaryNumericInstruction { public BitXor(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign, CompoundAssignmentType compoundAssignmentType = CompoundAssignmentType.None) : base(OpCode.BitXor, left, right, checkForOverflow, sign, compoundAssignmentType) { } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitBitXor(this); } } /// Bitwise NOT public sealed partial class BitNot : UnaryInstruction { public BitNot(ILInstruction argument) : base(OpCode.BitNot, argument) { } 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 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 T AcceptVisitor(ILVisitor visitor) { return visitor.VisitBranch(this); } } /// Marks the end of an finally, fault or exception filter block. public sealed partial class EndFinally : SimpleInstruction { public EndFinally() : base(OpCode.EndFinally) { } public override StackType ResultType { get { return StackType.Void; } } protected override InstructionFlags ComputeFlags() { return InstructionFlags.EndPointUnreachable | InstructionFlags.MayBranch; } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitEndFinally(this); } } /// If statement / conditional expression. if (condition) trueExpr else falseExpr public sealed partial class IfInstruction : ILInstruction { ILInstruction condition; public ILInstruction Condition { get { return this.condition; } set { ValidateArgument(value); SetChildInstruction(ref this.condition, value); } } ILInstruction trueInst; public ILInstruction TrueInst { get { return this.trueInst; } set { ValidateChild(value); SetChildInstruction(ref this.trueInst, value); } } ILInstruction falseInst; public ILInstruction FalseInst { get { return this.falseInst; } set { ValidateChild(value); SetChildInstruction(ref this.falseInst, value); } } public override IEnumerable Children { get { yield return this.condition; yield return this.trueInst; yield return this.falseInst; } } public override void TransformChildren(ILVisitor visitor) { this.Condition = this.condition.AcceptVisitor(visitor); this.TrueInst = this.trueInst.AcceptVisitor(visitor); this.FalseInst = this.falseInst.AcceptVisitor(visitor); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitIfInstruction(this); } } /// Try-catch statement. public sealed partial class TryCatch : TryInstruction { public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitTryCatch(this); } } /// Catch handler within a try-catch statement. public sealed partial class TryCatchHandler : ILInstruction { public TryCatchHandler(ILInstruction filter, ILInstruction body, ILVariable variable) : base(OpCode.TryCatchHandler) { this.Filter = filter; this.Body = body; Debug.Assert(variable != null); this.variable = variable; } ILInstruction filter; public ILInstruction Filter { get { return this.filter; } set { ValidateArgument(value); SetChildInstruction(ref this.filter, value); } } ILInstruction body; public ILInstruction Body { get { return this.body; } set { ValidateChild(value); SetChildInstruction(ref this.body, value); } } public override IEnumerable Children { get { yield return this.filter; yield return this.body; } } public override void TransformChildren(ILVisitor visitor) { this.Filter = this.filter.AcceptVisitor(visitor); this.Body = this.body.AcceptVisitor(visitor); } readonly ILVariable variable; /// Returns the variable operand. public ILVariable Variable { get { return variable; } } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitTryCatchHandler(this); } } /// Try-finally statement public sealed partial class TryFinally : TryInstruction { public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitTryFinally(this); } } /// Try-fault statement public sealed partial class TryFault : TryInstruction { 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 T AcceptVisitor(ILVisitor visitor) { return visitor.VisitDebugBreak(this); } } /// Compare equal. Returns 1 (of type I4) if two numbers or object references are equal; 0 otherwise. public sealed partial class Ceq : BinaryComparisonInstruction { public Ceq(ILInstruction left, ILInstruction right) : base(OpCode.Ceq, left, right) { } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitCeq(this); } } /// Compare greater than. For integers, perform a signed comparison. For floating-point numbers, return 0 for unordered numbers. public sealed partial class Cgt : BinaryComparisonInstruction { public Cgt(ILInstruction left, ILInstruction right) : base(OpCode.Cgt, left, right) { } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitCgt(this); } } /// Compare greater than (unordered/unsigned). For integers, perform a signed comparison. For floating-point numbers, return 1 for unordered numbers. public sealed partial class Cgt_Un : BinaryComparisonInstruction { public Cgt_Un(ILInstruction left, ILInstruction right) : base(OpCode.Cgt_Un, left, right) { } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitCgt_Un(this); } } /// Compare less than. For integers, perform a signed comparison. For floating-point numbers, return 0 for unordered numbers. public sealed partial class Clt : BinaryComparisonInstruction { public Clt(ILInstruction left, ILInstruction right) : base(OpCode.Clt, left, right) { } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitClt(this); } } /// Compare less than (unordered/unsigned). For integers, perform a signed comparison. For floating-point numbers, return 1 for unordered numbers. public sealed partial class Clt_Un : BinaryComparisonInstruction { public Clt_Un(ILInstruction left, ILInstruction right) : base(OpCode.Clt_Un, left, right) { } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitClt_Un(this); } } /// Non-virtual method call. public sealed partial class Call : CallInstruction { public Call(IMethod method) : base(OpCode.Call, method) { } 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 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 T AcceptVisitor(ILVisitor visitor) { return visitor.VisitCkfinite(this); } } /// Numeric cast. public sealed partial class Conv : UnaryInstruction { 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 { public LdLoc(ILVariable variable) : base(OpCode.LdLoc) { Debug.Assert(variable != null); this.variable = variable; } readonly ILVariable variable; /// Returns the variable operand. public ILVariable Variable { get { return variable; } } public override StackType ResultType { get { return variable.Type.GetStackType(); } } public override void WriteTo(ITextOutput output) { output.Write(OpCode); output.Write(' '); variable.WriteTo(output); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitLdLoc(this); } } /// Loads the address of a local variable. (ldarga/ldloca) public sealed partial class LdLoca : SimpleInstruction { public LdLoca(ILVariable variable) : base(OpCode.LdLoca) { Debug.Assert(variable != null); this.variable = variable; } public override StackType ResultType { get { return StackType.Ref; } } readonly ILVariable variable; /// Returns the variable operand. public ILVariable Variable { get { return variable; } } public override void WriteTo(ITextOutput output) { output.Write(OpCode); output.Write(' '); variable.WriteTo(output); } 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 { public StLoc(ILInstruction value, ILVariable variable) : base(OpCode.StLoc) { this.Value = value; Debug.Assert(variable != null); this.variable = variable; } ILInstruction value; public ILInstruction Value { get { return this.value; } set { ValidateArgument(value); SetChildInstruction(ref this.value, value); } } public override IEnumerable Children { get { yield return this.value; } } public override void TransformChildren(ILVisitor visitor) { this.Value = this.value.AcceptVisitor(visitor); } internal override ILInstruction Inline(InstructionFlags flagsBefore, IInlineContext context) { this.Value = this.value.Inline(flagsBefore, context); return this; } internal override void TransformStackIntoVariables(TransformStackIntoVariablesState state) { Value.TransformStackIntoVariables(state); } readonly ILVariable variable; /// Returns the variable operand. public ILVariable Variable { get { return variable; } } public override StackType ResultType { get { return variable.Type.GetStackType(); } } protected override InstructionFlags ComputeFlags() { return value.Flags; } public override void WriteTo(ITextOutput output) { output.Write(OpCode); output.Write(' '); variable.WriteTo(output); output.Write('('); this.value.WriteTo(output); output.Write(')'); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitStLoc(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 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 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 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 T AcceptVisitor(ILVisitor visitor) { return visitor.VisitLdcF(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 T AcceptVisitor(ILVisitor visitor) { return visitor.VisitLdNull(this); } } /// Load method pointer public sealed partial class LdFtn : SimpleInstruction { 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 T AcceptVisitor(ILVisitor visitor) { return visitor.VisitLdFtn(this); } } /// Load method pointer public sealed partial class LdVirtFtn : UnaryInstruction { 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 void WriteTo(ITextOutput output) { output.Write(OpCode); output.Write(' '); Disassembler.DisassemblerHelpers.WriteOperand(output, method); output.Write('('); Argument.WriteTo(output); output.Write(')'); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitLdVirtFtn(this); } } /// Loads runtime representation of metadata token public sealed partial class LdToken : SimpleInstruction { public LdToken(Mono.Cecil.MemberReference member) : base(OpCode.LdToken) { this.member = member; } readonly Mono.Cecil.MemberReference member; /// Returns the token operand. public Mono.Cecil.MemberReference 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 T AcceptVisitor(ILVisitor visitor) { return visitor.VisitLdToken(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 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 T AcceptVisitor(ILVisitor visitor) { return visitor.VisitReturn(this); } } /// Shift left public sealed partial class Shl : BinaryNumericInstruction { public Shl(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign, CompoundAssignmentType compoundAssignmentType = CompoundAssignmentType.None) : base(OpCode.Shl, left, right, checkForOverflow, sign, compoundAssignmentType) { } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitShl(this); } } /// Shift right public sealed partial class Shr : BinaryNumericInstruction { public Shr(ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign, CompoundAssignmentType compoundAssignmentType = CompoundAssignmentType.None) : base(OpCode.Shr, left, right, checkForOverflow, sign, compoundAssignmentType) { } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitShr(this); } } /// Load instance field public sealed partial class LdFld : ILInstruction, ISupportsVolatilePrefix, ISupportsUnalignedPrefix { public LdFld(ILInstruction target, IField field) : base(OpCode.LdFld) { this.Target = target; this.field = field; } ILInstruction target; public ILInstruction Target { get { return this.target; } set { ValidateArgument(value); SetChildInstruction(ref this.target, value); } } public override IEnumerable Children { get { yield return this.target; } } public override void TransformChildren(ILVisitor visitor) { this.Target = this.target.AcceptVisitor(visitor); } internal override ILInstruction Inline(InstructionFlags flagsBefore, IInlineContext context) { this.Target = this.target.Inline(flagsBefore, context); return this; } internal override void TransformStackIntoVariables(TransformStackIntoVariablesState state) { Target.TransformStackIntoVariables(state); } /// 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; } readonly IField field; /// Returns the field operand. public IField Field { get { return field; } } public override StackType ResultType { get { return field.Type.GetStackType(); } } protected override InstructionFlags ComputeFlags() { return target.Flags | InstructionFlags.SideEffect | InstructionFlags.MayThrow; } public override void WriteTo(ITextOutput output) { if (IsVolatile) output.Write("volatile."); if (UnalignedPrefix > 0) output.Write("unaligned(" + UnalignedPrefix + ")."); output.Write(OpCode); output.Write(' '); Disassembler.DisassemblerHelpers.WriteOperand(output, field); output.Write('('); this.target.WriteTo(output); output.Write(')'); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitLdFld(this); } } /// Load address of instance field public sealed partial class LdFlda : ILInstruction { public LdFlda(ILInstruction target, IField field) : base(OpCode.LdFlda) { this.Target = target; this.field = field; } ILInstruction target; public ILInstruction Target { get { return this.target; } set { ValidateArgument(value); SetChildInstruction(ref this.target, value); } } public override IEnumerable Children { get { yield return this.target; } } public override void TransformChildren(ILVisitor visitor) { this.Target = this.target.AcceptVisitor(visitor); } internal override ILInstruction Inline(InstructionFlags flagsBefore, IInlineContext context) { this.Target = this.target.Inline(flagsBefore, context); return this; } internal override void TransformStackIntoVariables(TransformStackIntoVariablesState state) { Target.TransformStackIntoVariables(state); } 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 | 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 T AcceptVisitor(ILVisitor visitor) { return visitor.VisitLdFlda(this); } } /// Store value to instance field public sealed partial class StFld : ILInstruction, ISupportsVolatilePrefix, ISupportsUnalignedPrefix { public StFld(ILInstruction target, ILInstruction value, IField field) : base(OpCode.StFld) { this.Target = target; this.Value = value; this.field = field; } ILInstruction target; public ILInstruction Target { get { return this.target; } set { ValidateArgument(value); SetChildInstruction(ref this.target, value); } } ILInstruction value; public ILInstruction Value { get { return this.value; } set { ValidateArgument(value); SetChildInstruction(ref this.value, value); } } public override IEnumerable Children { get { yield return this.target; yield return this.value; } } public override void TransformChildren(ILVisitor visitor) { this.Target = this.target.AcceptVisitor(visitor); this.Value = this.value.AcceptVisitor(visitor); } internal override ILInstruction Inline(InstructionFlags flagsBefore, IInlineContext context) { this.Value = this.value.Inline(flagsBefore | ((this.target.Flags) & ~(InstructionFlags.MayPeek | InstructionFlags.MayPop)), context); this.Target = this.target.Inline(flagsBefore, context); return this; } internal override void TransformStackIntoVariables(TransformStackIntoVariablesState state) { Target.TransformStackIntoVariables(state); Value.TransformStackIntoVariables(state); } /// 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; } readonly IField field; /// Returns the field operand. public IField Field { get { return field; } } public override StackType ResultType { get { return field.Type.GetStackType(); } } protected override InstructionFlags ComputeFlags() { return target.Flags | value.Flags | InstructionFlags.SideEffect | InstructionFlags.MayThrow; } public override void WriteTo(ITextOutput output) { if (IsVolatile) output.Write("volatile."); if (UnalignedPrefix > 0) output.Write("unaligned(" + UnalignedPrefix + ")."); output.Write(OpCode); output.Write(' '); Disassembler.DisassemblerHelpers.WriteOperand(output, field); output.Write('('); this.target.WriteTo(output); output.Write(", "); this.value.WriteTo(output); output.Write(')'); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitStFld(this); } } /// Load static field public sealed partial class LdsFld : SimpleInstruction, ISupportsVolatilePrefix, ISupportsUnalignedPrefix { public LdsFld(IField field) : base(OpCode.LdsFld) { this.field = field; } /// 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; } readonly IField field; /// Returns the field operand. public IField Field { get { return field; } } public override StackType ResultType { get { return field.Type.GetStackType(); } } protected override InstructionFlags ComputeFlags() { return InstructionFlags.SideEffect; } public override void WriteTo(ITextOutput output) { if (IsVolatile) output.Write("volatile."); if (UnalignedPrefix > 0) output.Write("unaligned(" + UnalignedPrefix + ")."); output.Write(OpCode); output.Write(' '); Disassembler.DisassemblerHelpers.WriteOperand(output, field); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitLdsFld(this); } } /// Load static field address public sealed partial class LdsFlda : SimpleInstruction { 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 T AcceptVisitor(ILVisitor visitor) { return visitor.VisitLdsFlda(this); } } /// Store value to static field public sealed partial class StsFld : ILInstruction, ISupportsVolatilePrefix, ISupportsUnalignedPrefix { public StsFld(ILInstruction value, IField field) : base(OpCode.StsFld) { this.Value = value; this.field = field; } ILInstruction value; public ILInstruction Value { get { return this.value; } set { ValidateArgument(value); SetChildInstruction(ref this.value, value); } } public override IEnumerable Children { get { yield return this.value; } } public override void TransformChildren(ILVisitor visitor) { this.Value = this.value.AcceptVisitor(visitor); } internal override ILInstruction Inline(InstructionFlags flagsBefore, IInlineContext context) { this.Value = this.value.Inline(flagsBefore, context); return this; } internal override void TransformStackIntoVariables(TransformStackIntoVariablesState state) { Value.TransformStackIntoVariables(state); } /// 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; } readonly IField field; /// Returns the field operand. public IField Field { get { return field; } } public override StackType ResultType { get { return field.Type.GetStackType(); } } protected override InstructionFlags ComputeFlags() { return value.Flags | InstructionFlags.SideEffect; } public override void WriteTo(ITextOutput output) { if (IsVolatile) output.Write("volatile."); if (UnalignedPrefix > 0) output.Write("unaligned(" + UnalignedPrefix + ")."); output.Write(OpCode); output.Write(' '); Disassembler.DisassemblerHelpers.WriteOperand(output, field); output.Write('('); this.value.WriteTo(output); output.Write(')'); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitStsFld(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 void WriteTo(ITextOutput output) { output.Write(OpCode); output.Write(' '); Disassembler.DisassemblerHelpers.WriteOperand(output, type); output.Write('('); Argument.WriteTo(output); output.Write(')'); } public override T AcceptVisitor(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 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; } ILInstruction target; public ILInstruction Target { get { return this.target; } set { ValidateArgument(value); SetChildInstruction(ref this.target, value); } } public override IEnumerable Children { get { yield return this.target; } } public override void TransformChildren(ILVisitor visitor) { this.Target = this.target.AcceptVisitor(visitor); } internal override ILInstruction Inline(InstructionFlags flagsBefore, IInlineContext context) { this.Target = this.target.Inline(flagsBefore, context); return this; } internal override void TransformStackIntoVariables(TransformStackIntoVariablesState state) { Target.TransformStackIntoVariables(state); } 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 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 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; } ILInstruction target; public ILInstruction Target { get { return this.target; } set { ValidateArgument(value); SetChildInstruction(ref this.target, value); } } ILInstruction value; public ILInstruction Value { get { return this.value; } set { ValidateArgument(value); SetChildInstruction(ref this.value, value); } } public override IEnumerable Children { get { yield return this.target; yield return this.value; } } public override void TransformChildren(ILVisitor visitor) { this.Target = this.target.AcceptVisitor(visitor); this.Value = this.value.AcceptVisitor(visitor); } internal override ILInstruction Inline(InstructionFlags flagsBefore, IInlineContext context) { this.Value = this.value.Inline(flagsBefore | ((this.target.Flags) & ~(InstructionFlags.MayPeek | InstructionFlags.MayPop)), context); this.Target = this.target.Inline(flagsBefore, context); return this; } internal override void TransformStackIntoVariables(TransformStackIntoVariablesState state) { Target.TransformStackIntoVariables(state); Value.TransformStackIntoVariables(state); } 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 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 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 void WriteTo(ITextOutput output) { output.Write(OpCode); output.Write(' '); Disassembler.DisassemblerHelpers.WriteOperand(output, type); output.Write('('); Argument.WriteTo(output); output.Write(')'); } public override T AcceptVisitor(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 void WriteTo(ITextOutput output) { output.Write(OpCode); output.Write(' '); Disassembler.DisassemblerHelpers.WriteOperand(output, type); output.Write('('); Argument.WriteTo(output); output.Write(')'); } public override T AcceptVisitor(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 void WriteTo(ITextOutput output) { output.Write(OpCode); output.Write(' '); Disassembler.DisassemblerHelpers.WriteOperand(output, type); output.Write('('); Argument.WriteTo(output); output.Write(')'); } public override T AcceptVisitor(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 StackType.O; } } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitNewObj(this); } } /// Initializes the value at an address. public sealed partial class InitObj : UnaryInstruction { public InitObj(ILInstruction argument, IType type) : base(OpCode.InitObj, argument) { this.type = type; } readonly IType type; /// Returns the type operand. public IType Type { get { return type; } } public override StackType ResultType { get { return StackType.Void; } } public override void WriteTo(ITextOutput output) { output.Write(OpCode); output.Write(' '); Disassembler.DisassemblerHelpers.WriteOperand(output, type); output.Write('('); Argument.WriteTo(output); output.Write(')'); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitInitObj(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 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 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 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 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 LdLen(ILInstruction target) : base(OpCode.LdLen) { this.Target = target; } ILInstruction target; public ILInstruction Target { get { return this.target; } set { ValidateArgument(value); SetChildInstruction(ref this.target, value); } } public override IEnumerable Children { get { yield return this.target; } } public override void TransformChildren(ILVisitor visitor) { this.Target = this.target.AcceptVisitor(visitor); } internal override ILInstruction Inline(InstructionFlags flagsBefore, IInlineContext context) { this.Target = this.target.Inline(flagsBefore, context); return this; } internal override void TransformStackIntoVariables(TransformStackIntoVariablesState state) { Target.TransformStackIntoVariables(state); } public override StackType ResultType { get { return StackType.I; } } protected override InstructionFlags ComputeFlags() { return target.Flags | InstructionFlags.MayThrow; } public override void WriteTo(ITextOutput output) { output.Write(OpCode); output.Write('('); this.target.WriteTo(output); output.Write(')'); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitLdLen(this); } } /// Load address of array element. public sealed partial class LdElema : ILInstruction { public LdElema(ILInstruction array, ILInstruction index, IType type) : base(OpCode.LdElema) { this.Array = array; this.Index = index; this.type = type; } ILInstruction array; public ILInstruction Array { get { return this.array; } set { ValidateArgument(value); SetChildInstruction(ref this.array, value); } } ILInstruction index; public ILInstruction Index { get { return this.index; } set { ValidateArgument(value); SetChildInstruction(ref this.index, value); } } public override IEnumerable Children { get { yield return this.array; yield return this.index; } } public override void TransformChildren(ILVisitor visitor) { this.Array = this.array.AcceptVisitor(visitor); this.Index = this.index.AcceptVisitor(visitor); } internal override ILInstruction Inline(InstructionFlags flagsBefore, IInlineContext context) { this.Index = this.index.Inline(flagsBefore | ((this.array.Flags) & ~(InstructionFlags.MayPeek | InstructionFlags.MayPop)), context); this.Array = this.array.Inline(flagsBefore, context); return this; } internal override void TransformStackIntoVariables(TransformStackIntoVariablesState state) { Array.TransformStackIntoVariables(state); Index.TransformStackIntoVariables(state); } readonly IType type; /// Returns the type operand. public IType Type { get { return type; } } 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 | index.Flags | 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); output.Write(", "); this.index.WriteTo(output); output.Write(')'); } public override T AcceptVisitor(ILVisitor visitor) { return visitor.VisitLdElema(this); } } /// /// 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 VisitNop(Nop inst) { return Default(inst); } protected internal virtual T VisitPop(Pop inst) { return Default(inst); } protected internal virtual T VisitPeek(Peek inst) { return Default(inst); } protected internal virtual T VisitVoid(Void 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 VisitLogicNot(LogicNot inst) { return Default(inst); } protected internal virtual T VisitAdd(Add inst) { return Default(inst); } protected internal virtual T VisitSub(Sub inst) { return Default(inst); } protected internal virtual T VisitMul(Mul inst) { return Default(inst); } protected internal virtual T VisitDiv(Div inst) { return Default(inst); } protected internal virtual T VisitRem(Rem inst) { return Default(inst); } protected internal virtual T VisitBitAnd(BitAnd inst) { return Default(inst); } protected internal virtual T VisitBitOr(BitOr inst) { return Default(inst); } protected internal virtual T VisitBitXor(BitXor 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 VisitEndFinally(EndFinally inst) { return Default(inst); } protected internal virtual T VisitIfInstruction(IfInstruction 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 VisitCeq(Ceq inst) { return Default(inst); } protected internal virtual T VisitCgt(Cgt inst) { return Default(inst); } protected internal virtual T VisitCgt_Un(Cgt_Un inst) { return Default(inst); } protected internal virtual T VisitClt(Clt inst) { return Default(inst); } protected internal virtual T VisitClt_Un(Clt_Un 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 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 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 VisitLdToken(LdToken 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 VisitShl(Shl inst) { return Default(inst); } protected internal virtual T VisitShr(Shr inst) { return Default(inst); } protected internal virtual T VisitLdFld(LdFld inst) { return Default(inst); } protected internal virtual T VisitLdFlda(LdFlda inst) { return Default(inst); } protected internal virtual T VisitStFld(StFld inst) { return Default(inst); } protected internal virtual T VisitLdsFld(LdsFld inst) { return Default(inst); } protected internal virtual T VisitLdsFlda(LdsFlda inst) { return Default(inst); } protected internal virtual T VisitStsFld(StsFld 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 VisitInitObj(InitObj 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); } } partial class BinaryNumericInstruction { public static BinaryNumericInstruction Create(OpCode opCode, ILInstruction left, ILInstruction right, bool checkForOverflow, Sign sign, CompoundAssignmentType compoundAssignmentType = CompoundAssignmentType.None) { switch (opCode) { case OpCode.Add: return new Add(left, right, checkForOverflow, sign, compoundAssignmentType); case OpCode.Sub: return new Sub(left, right, checkForOverflow, sign, compoundAssignmentType); case OpCode.Mul: return new Mul(left, right, checkForOverflow, sign, compoundAssignmentType); case OpCode.Div: return new Div(left, right, checkForOverflow, sign, compoundAssignmentType); case OpCode.Rem: return new Rem(left, right, checkForOverflow, sign, compoundAssignmentType); case OpCode.BitAnd: return new BitAnd(left, right, checkForOverflow, sign, compoundAssignmentType); case OpCode.BitOr: return new BitOr(left, right, checkForOverflow, sign, compoundAssignmentType); case OpCode.BitXor: return new BitXor(left, right, checkForOverflow, sign, compoundAssignmentType); case OpCode.Shl: return new Shl(left, right, checkForOverflow, sign, compoundAssignmentType); case OpCode.Shr: return new Shr(left, right, checkForOverflow, sign, compoundAssignmentType); default: throw new ArgumentException("opCode is not a binary numeric instruction"); } } } partial class BinaryComparisonInstruction { public static BinaryComparisonInstruction Create(OpCode opCode, ILInstruction left, ILInstruction right) { switch (opCode) { case OpCode.Ceq: return new Ceq(left, right); case OpCode.Cgt: return new Cgt(left, right); case OpCode.Cgt_Un: return new Cgt_Un(left, right); case OpCode.Clt: return new Clt(left, right); case OpCode.Clt_Un: return new Clt_Un(left, right); default: throw new ArgumentException("opCode is not a binary comparison instruction"); } } } partial class InstructionOutputExtensions { static readonly string[] originalOpCodeNames = { "nop", "pop", "peek", "void", "ILFunction", "BlockContainer", "Block", "logic.not", "add", "sub", "mul", "div", "rem", "bit.and", "bit.or", "bit.xor", "bit.not", "arglist", "br", "endfinally", "if", "try.catch", "try.catch.handler", "try.finally", "try.fault", "debug.break", "ceq", "cgt", "cgt.un", "clt", "clt.un", "call", "callvirt", "ckfinite", "conv", "ldloc", "ldloca", "stloc", "ldstr", "ldc.i4", "ldc.i8", "ldc.f", "ldnull", "ldftn", "ldvirtftn", "ldtoken", "localloc", "ret", "shl", "shr", "ldfld", "ldflda", "stfld", "ldsfld", "ldsflda", "stsfld", "castclass", "isinst", "ldobj", "stobj", "box", "unbox", "unbox.any", "newobj", "initobj", "default.value", "throw", "rethrow", "sizeof", "ldlen", "ldelema", }; } }