mirror of https://github.com/icsharpcode/ILSpy.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2398 lines
69 KiB
2398 lines
69 KiB
// 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 |
|
{ |
|
/// <summary> |
|
/// Enum representing the type of an <see cref="ILInstruction"/>. |
|
/// </summary> |
|
public enum OpCode |
|
{ |
|
/// <summary>No operation. Takes 0 arguments and returns void.</summary> |
|
Nop, |
|
/// <summary>Pops the top of the evaluation stack and returns the value.</summary> |
|
Pop, |
|
/// <summary>Peeks at the top of the evaluation stack and returns the value. Corresponds to IL 'dup'.</summary> |
|
Peek, |
|
/// <summary>Ignore the arguments and produce void. Used to prevent the end result of an instruction from being pushed to the evaluation stack.</summary> |
|
Void, |
|
/// <summary>A container of IL blocks.</summary> |
|
ILFunction, |
|
/// <summary>A container of IL blocks.</summary> |
|
BlockContainer, |
|
/// <summary>A block of IL instructions.</summary> |
|
Block, |
|
/// <summary>Unary operator that expects an input of type I4. Returns 1 (of type I4) if the input value is 0. Otherwise, returns 0 (of type I4).</summary> |
|
LogicNot, |
|
/// <summary>Adds two numbers.</summary> |
|
Add, |
|
/// <summary>Subtracts two numbers</summary> |
|
Sub, |
|
/// <summary>Multiplies two numbers</summary> |
|
Mul, |
|
/// <summary>Divides two numbers</summary> |
|
Div, |
|
/// <summary>Division remainder</summary> |
|
Rem, |
|
/// <summary>Bitwise AND</summary> |
|
BitAnd, |
|
/// <summary>Bitwise OR</summary> |
|
BitOr, |
|
/// <summary>Bitwise XOR</summary> |
|
BitXor, |
|
/// <summary>Bitwise NOT</summary> |
|
BitNot, |
|
/// <summary>Retrieves the RuntimeArgumentHandle.</summary> |
|
Arglist, |
|
/// <summary>Unconditional branch. <c>goto target;</c></summary> |
|
Branch, |
|
/// <summary>Marks the end of an finally, fault or exception filter block.</summary> |
|
EndFinally, |
|
/// <summary>If statement / conditional expression. <c>if (condition) trueExpr else falseExpr</c></summary> |
|
IfInstruction, |
|
/// <summary>Try-catch statement.</summary> |
|
TryCatch, |
|
/// <summary>Catch handler within a try-catch statement.</summary> |
|
TryCatchHandler, |
|
/// <summary>Try-finally statement</summary> |
|
TryFinally, |
|
/// <summary>Try-fault statement</summary> |
|
TryFault, |
|
/// <summary>Breakpoint instruction</summary> |
|
DebugBreak, |
|
/// <summary>Compare equal. Returns 1 (of type I4) if two numbers or object references are equal; 0 otherwise.</summary> |
|
Ceq, |
|
/// <summary>Compare greater than. For integers, perform a signed comparison. For floating-point numbers, return 0 for unordered numbers.</summary> |
|
Cgt, |
|
/// <summary>Compare greater than (unordered/unsigned). For integers, perform a signed comparison. For floating-point numbers, return 1 for unordered numbers.</summary> |
|
Cgt_Un, |
|
/// <summary>Compare less than. For integers, perform a signed comparison. For floating-point numbers, return 0 for unordered numbers.</summary> |
|
Clt, |
|
/// <summary>Compare less than (unordered/unsigned). For integers, perform a signed comparison. For floating-point numbers, return 1 for unordered numbers.</summary> |
|
Clt_Un, |
|
/// <summary>Non-virtual method call.</summary> |
|
Call, |
|
/// <summary>Virtual method call.</summary> |
|
CallVirt, |
|
/// <summary>Checks that the float on top of the stack is not NaN or infinite.</summary> |
|
Ckfinite, |
|
/// <summary>Numeric cast.</summary> |
|
Conv, |
|
/// <summary>Loads the value of a local variable. (ldarg/ldloc)</summary> |
|
LdLoc, |
|
/// <summary>Loads the address of a local variable. (ldarga/ldloca)</summary> |
|
LdLoca, |
|
/// <summary>Stores a value into a local variable. (starg/stloc)</summary> |
|
StLoc, |
|
/// <summary>Loads a constant string.</summary> |
|
LdStr, |
|
/// <summary>Loads a constant 32-bit integer.</summary> |
|
LdcI4, |
|
/// <summary>Loads a constant 64-bit integer.</summary> |
|
LdcI8, |
|
/// <summary>Loads a constant floating-point number.</summary> |
|
LdcF, |
|
/// <summary>Loads the null reference.</summary> |
|
LdNull, |
|
/// <summary>Load method pointer</summary> |
|
LdFtn, |
|
/// <summary>Load method pointer</summary> |
|
LdVirtFtn, |
|
/// <summary>Loads runtime representation of metadata token</summary> |
|
LdToken, |
|
/// <summary>Allocates space in the stack frame</summary> |
|
LocAlloc, |
|
/// <summary>Returns from the current method or lambda.</summary> |
|
Return, |
|
/// <summary>Shift left</summary> |
|
Shl, |
|
/// <summary>Shift right</summary> |
|
Shr, |
|
/// <summary>Load instance field</summary> |
|
LdFld, |
|
/// <summary>Load address of instance field</summary> |
|
LdFlda, |
|
/// <summary>Store value to instance field</summary> |
|
StFld, |
|
/// <summary>Load static field</summary> |
|
LdsFld, |
|
/// <summary>Load static field address</summary> |
|
LdsFlda, |
|
/// <summary>Store value to static field</summary> |
|
StsFld, |
|
/// <summary>Casts an object to a class.</summary> |
|
CastClass, |
|
/// <summary>Test if object is instance of class or interface.</summary> |
|
IsInst, |
|
/// <summary>Indirect load (ref/pointer dereference).</summary> |
|
LdObj, |
|
/// <summary>Indirect store (store to ref/pointer).</summary> |
|
StObj, |
|
/// <summary>Boxes a value.</summary> |
|
Box, |
|
/// <summary>Compute address inside box.</summary> |
|
Unbox, |
|
/// <summary>Unbox a value.</summary> |
|
UnboxAny, |
|
/// <summary>Creates an object instance and calls the constructor.</summary> |
|
NewObj, |
|
/// <summary>Initializes the value at an address.</summary> |
|
InitObj, |
|
/// <summary>Returns the default value for a type.</summary> |
|
DefaultValue, |
|
/// <summary>Throws an exception.</summary> |
|
Throw, |
|
/// <summary>Rethrows the current exception.</summary> |
|
Rethrow, |
|
/// <summary>Gets the size of a type in bytes.</summary> |
|
SizeOf, |
|
/// <summary>Returns the length of an array as 'native unsigned int'.</summary> |
|
LdLen, |
|
/// <summary>Load address of array element.</summary> |
|
LdElema, |
|
} |
|
|
|
/// <summary>Instruction with a single argument</summary> |
|
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<ILInstruction> Children { |
|
get { |
|
yield return this.argument; |
|
} |
|
} |
|
public override void TransformChildren(ILVisitor<ILInstruction> visitor) |
|
{ |
|
this.Argument = this.argument.AcceptVisitor(visitor); |
|
} |
|
internal override ILInstruction Inline(InstructionFlags flagsBefore, IInlineContext context) |
|
{ |
|
this.Argument = this.argument.Inline(flagsBefore, context); |
|
return this; |
|
} |
|
protected override InstructionFlags ComputeFlags() |
|
{ |
|
return argument.Flags; |
|
} |
|
public override void WriteTo(ITextOutput output) |
|
{ |
|
output.Write(OpCode); |
|
output.Write('('); |
|
this.argument.WriteTo(output); |
|
output.Write(')'); |
|
} |
|
} |
|
|
|
/// <summary>Instruction with two arguments: Left and Right</summary> |
|
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<ILInstruction> Children { |
|
get { |
|
yield return this.left; |
|
yield return this.right; |
|
} |
|
} |
|
public override void TransformChildren(ILVisitor<ILInstruction> 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; |
|
} |
|
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(')'); |
|
} |
|
} |
|
|
|
/// <summary>No operation. Takes 0 arguments and returns void.</summary> |
|
public sealed partial class Nop : SimpleInstruction |
|
{ |
|
public Nop() : base(OpCode.Nop) |
|
{ |
|
} |
|
public override StackType ResultType { get { return StackType.Void; } } |
|
public override T AcceptVisitor<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitNop(this); |
|
} |
|
} |
|
|
|
/// <summary>Pops the top of the evaluation stack and returns the value.</summary> |
|
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<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitPop(this); |
|
} |
|
} |
|
|
|
/// <summary>Peeks at the top of the evaluation stack and returns the value. Corresponds to IL 'dup'.</summary> |
|
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; } } |
|
protected override InstructionFlags ComputeFlags() |
|
{ |
|
return InstructionFlags.MayPeek; |
|
} |
|
public override T AcceptVisitor<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitPeek(this); |
|
} |
|
} |
|
|
|
/// <summary>Ignore the arguments and produce void. Used to prevent the end result of an instruction from being pushed to the evaluation stack.</summary> |
|
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<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitVoid(this); |
|
} |
|
} |
|
|
|
/// <summary>A container of IL blocks.</summary> |
|
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<ILInstruction> Children { |
|
get { |
|
yield return this.body; |
|
} |
|
} |
|
public override void TransformChildren(ILVisitor<ILInstruction> visitor) |
|
{ |
|
this.Body = this.body.AcceptVisitor(visitor); |
|
} |
|
public override StackType ResultType { get { return StackType.O; } } |
|
public override T AcceptVisitor<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitILFunction(this); |
|
} |
|
} |
|
|
|
/// <summary>A container of IL blocks.</summary> |
|
public sealed partial class BlockContainer : ILInstruction |
|
{ |
|
public override StackType ResultType { get { return StackType.Void; } } |
|
public override T AcceptVisitor<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitBlockContainer(this); |
|
} |
|
} |
|
|
|
/// <summary>A block of IL instructions.</summary> |
|
public sealed partial class Block : ILInstruction |
|
{ |
|
|
|
public override T AcceptVisitor<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitBlock(this); |
|
} |
|
} |
|
|
|
/// <summary>Unary operator that expects an input of type I4. Returns 1 (of type I4) if the input value is 0. Otherwise, returns 0 (of type I4).</summary> |
|
public sealed partial class LogicNot : UnaryInstruction |
|
{ |
|
public LogicNot(ILInstruction argument) : base(OpCode.LogicNot, argument) |
|
{ |
|
} |
|
public override StackType ResultType { get { return StackType.I4; } } |
|
public override T AcceptVisitor<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitLogicNot(this); |
|
} |
|
} |
|
|
|
/// <summary>Adds two numbers.</summary> |
|
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<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitAdd(this); |
|
} |
|
} |
|
|
|
/// <summary>Subtracts two numbers</summary> |
|
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<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitSub(this); |
|
} |
|
} |
|
|
|
/// <summary>Multiplies two numbers</summary> |
|
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<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitMul(this); |
|
} |
|
} |
|
|
|
/// <summary>Divides two numbers</summary> |
|
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<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitDiv(this); |
|
} |
|
} |
|
|
|
/// <summary>Division remainder</summary> |
|
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<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitRem(this); |
|
} |
|
} |
|
|
|
/// <summary>Bitwise AND</summary> |
|
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<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitBitAnd(this); |
|
} |
|
} |
|
|
|
/// <summary>Bitwise OR</summary> |
|
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<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitBitOr(this); |
|
} |
|
} |
|
|
|
/// <summary>Bitwise XOR</summary> |
|
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<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitBitXor(this); |
|
} |
|
} |
|
|
|
/// <summary>Bitwise NOT</summary> |
|
public sealed partial class BitNot : UnaryInstruction |
|
{ |
|
public BitNot(ILInstruction argument) : base(OpCode.BitNot, argument) |
|
{ |
|
} |
|
|
|
public override T AcceptVisitor<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitBitNot(this); |
|
} |
|
} |
|
|
|
/// <summary>Retrieves the RuntimeArgumentHandle.</summary> |
|
public sealed partial class Arglist : SimpleInstruction |
|
{ |
|
public Arglist() : base(OpCode.Arglist) |
|
{ |
|
} |
|
public override StackType ResultType { get { return StackType.O; } } |
|
public override T AcceptVisitor<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitArglist(this); |
|
} |
|
} |
|
|
|
/// <summary>Unconditional branch. <c>goto target;</c></summary> |
|
public sealed partial class Branch : SimpleInstruction |
|
{ |
|
public override StackType ResultType { get { return StackType.Void; } } |
|
protected override InstructionFlags ComputeFlags() |
|
{ |
|
return InstructionFlags.EndPointUnreachable | InstructionFlags.MayBranch; |
|
} |
|
public override T AcceptVisitor<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitBranch(this); |
|
} |
|
} |
|
|
|
/// <summary>Marks the end of an finally, fault or exception filter block.</summary> |
|
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<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitEndFinally(this); |
|
} |
|
} |
|
|
|
/// <summary>If statement / conditional expression. <c>if (condition) trueExpr else falseExpr</c></summary> |
|
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<ILInstruction> Children { |
|
get { |
|
yield return this.condition; |
|
yield return this.trueInst; |
|
yield return this.falseInst; |
|
} |
|
} |
|
public override void TransformChildren(ILVisitor<ILInstruction> visitor) |
|
{ |
|
this.Condition = this.condition.AcceptVisitor(visitor); |
|
this.TrueInst = this.trueInst.AcceptVisitor(visitor); |
|
this.FalseInst = this.falseInst.AcceptVisitor(visitor); |
|
} |
|
public override T AcceptVisitor<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitIfInstruction(this); |
|
} |
|
} |
|
|
|
/// <summary>Try-catch statement.</summary> |
|
public sealed partial class TryCatch : TryInstruction |
|
{ |
|
|
|
public override T AcceptVisitor<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitTryCatch(this); |
|
} |
|
} |
|
|
|
/// <summary>Catch handler within a try-catch statement.</summary> |
|
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<ILInstruction> Children { |
|
get { |
|
yield return this.filter; |
|
yield return this.body; |
|
} |
|
} |
|
public override void TransformChildren(ILVisitor<ILInstruction> visitor) |
|
{ |
|
this.Filter = this.filter.AcceptVisitor(visitor); |
|
this.Body = this.body.AcceptVisitor(visitor); |
|
} |
|
readonly ILVariable variable; |
|
/// <summary>Returns the variable operand.</summary> |
|
public ILVariable Variable { get { return variable; } } |
|
public override T AcceptVisitor<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitTryCatchHandler(this); |
|
} |
|
} |
|
|
|
/// <summary>Try-finally statement</summary> |
|
public sealed partial class TryFinally : TryInstruction |
|
{ |
|
|
|
public override T AcceptVisitor<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitTryFinally(this); |
|
} |
|
} |
|
|
|
/// <summary>Try-fault statement</summary> |
|
public sealed partial class TryFault : TryInstruction |
|
{ |
|
|
|
public override T AcceptVisitor<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitTryFault(this); |
|
} |
|
} |
|
|
|
/// <summary>Breakpoint instruction</summary> |
|
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<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitDebugBreak(this); |
|
} |
|
} |
|
|
|
/// <summary>Compare equal. Returns 1 (of type I4) if two numbers or object references are equal; 0 otherwise.</summary> |
|
public sealed partial class Ceq : BinaryComparisonInstruction |
|
{ |
|
public Ceq(ILInstruction left, ILInstruction right) : base(OpCode.Ceq, left, right) |
|
{ |
|
} |
|
|
|
public override T AcceptVisitor<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitCeq(this); |
|
} |
|
} |
|
|
|
/// <summary>Compare greater than. For integers, perform a signed comparison. For floating-point numbers, return 0 for unordered numbers.</summary> |
|
public sealed partial class Cgt : BinaryComparisonInstruction |
|
{ |
|
public Cgt(ILInstruction left, ILInstruction right) : base(OpCode.Cgt, left, right) |
|
{ |
|
} |
|
|
|
public override T AcceptVisitor<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitCgt(this); |
|
} |
|
} |
|
|
|
/// <summary>Compare greater than (unordered/unsigned). For integers, perform a signed comparison. For floating-point numbers, return 1 for unordered numbers.</summary> |
|
public sealed partial class Cgt_Un : BinaryComparisonInstruction |
|
{ |
|
public Cgt_Un(ILInstruction left, ILInstruction right) : base(OpCode.Cgt_Un, left, right) |
|
{ |
|
} |
|
|
|
public override T AcceptVisitor<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitCgt_Un(this); |
|
} |
|
} |
|
|
|
/// <summary>Compare less than. For integers, perform a signed comparison. For floating-point numbers, return 0 for unordered numbers.</summary> |
|
public sealed partial class Clt : BinaryComparisonInstruction |
|
{ |
|
public Clt(ILInstruction left, ILInstruction right) : base(OpCode.Clt, left, right) |
|
{ |
|
} |
|
|
|
public override T AcceptVisitor<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitClt(this); |
|
} |
|
} |
|
|
|
/// <summary>Compare less than (unordered/unsigned). For integers, perform a signed comparison. For floating-point numbers, return 1 for unordered numbers.</summary> |
|
public sealed partial class Clt_Un : BinaryComparisonInstruction |
|
{ |
|
public Clt_Un(ILInstruction left, ILInstruction right) : base(OpCode.Clt_Un, left, right) |
|
{ |
|
} |
|
|
|
public override T AcceptVisitor<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitClt_Un(this); |
|
} |
|
} |
|
|
|
/// <summary>Non-virtual method call.</summary> |
|
public sealed partial class Call : CallInstruction |
|
{ |
|
public Call(IMethod method) : base(OpCode.Call, method) |
|
{ |
|
} |
|
|
|
public override T AcceptVisitor<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitCall(this); |
|
} |
|
} |
|
|
|
/// <summary>Virtual method call.</summary> |
|
public sealed partial class CallVirt : CallInstruction |
|
{ |
|
public CallVirt(IMethod method) : base(OpCode.CallVirt, method) |
|
{ |
|
} |
|
|
|
public override T AcceptVisitor<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitCallVirt(this); |
|
} |
|
} |
|
|
|
/// <summary>Checks that the float on top of the stack is not NaN or infinite.</summary> |
|
public sealed partial class Ckfinite : SimpleInstruction |
|
{ |
|
public Ckfinite() : base(OpCode.Ckfinite) |
|
{ |
|
} |
|
public override StackType ResultType { get { return StackType.Void; } } |
|
protected override InstructionFlags ComputeFlags() |
|
{ |
|
return InstructionFlags.MayPeek | InstructionFlags.MayThrow; |
|
} |
|
public override T AcceptVisitor<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitCkfinite(this); |
|
} |
|
} |
|
|
|
/// <summary>Numeric cast.</summary> |
|
public sealed partial class Conv : UnaryInstruction |
|
{ |
|
|
|
public override T AcceptVisitor<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitConv(this); |
|
} |
|
} |
|
|
|
/// <summary>Loads the value of a local variable. (ldarg/ldloc)</summary> |
|
public sealed partial class LdLoc : SimpleInstruction |
|
{ |
|
public LdLoc(ILVariable variable) : base(OpCode.LdLoc) |
|
{ |
|
Debug.Assert(variable != null); |
|
this.variable = variable; |
|
} |
|
readonly ILVariable variable; |
|
/// <summary>Returns the variable operand.</summary> |
|
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<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitLdLoc(this); |
|
} |
|
} |
|
|
|
/// <summary>Loads the address of a local variable. (ldarga/ldloca)</summary> |
|
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; |
|
/// <summary>Returns the variable operand.</summary> |
|
public ILVariable Variable { get { return variable; } } |
|
public override void WriteTo(ITextOutput output) |
|
{ |
|
output.Write(OpCode); |
|
output.Write(' '); |
|
variable.WriteTo(output); |
|
} |
|
public override T AcceptVisitor<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitLdLoca(this); |
|
} |
|
} |
|
|
|
/// <summary>Stores a value into a local variable. (starg/stloc)</summary> |
|
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<ILInstruction> Children { |
|
get { |
|
yield return this.value; |
|
} |
|
} |
|
public override void TransformChildren(ILVisitor<ILInstruction> visitor) |
|
{ |
|
this.Value = this.value.AcceptVisitor(visitor); |
|
} |
|
internal override ILInstruction Inline(InstructionFlags flagsBefore, IInlineContext context) |
|
{ |
|
this.Value = this.value.Inline(flagsBefore, context); |
|
return this; |
|
} |
|
readonly ILVariable variable; |
|
/// <summary>Returns the variable operand.</summary> |
|
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<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitStLoc(this); |
|
} |
|
} |
|
|
|
/// <summary>Loads a constant string.</summary> |
|
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<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitLdStr(this); |
|
} |
|
} |
|
|
|
/// <summary>Loads a constant 32-bit integer.</summary> |
|
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<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitLdcI4(this); |
|
} |
|
} |
|
|
|
/// <summary>Loads a constant 64-bit integer.</summary> |
|
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<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitLdcI8(this); |
|
} |
|
} |
|
|
|
/// <summary>Loads a constant floating-point number.</summary> |
|
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<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitLdcF(this); |
|
} |
|
} |
|
|
|
/// <summary>Loads the null reference.</summary> |
|
public sealed partial class LdNull : SimpleInstruction |
|
{ |
|
public LdNull() : base(OpCode.LdNull) |
|
{ |
|
} |
|
public override StackType ResultType { get { return StackType.O; } } |
|
public override T AcceptVisitor<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitLdNull(this); |
|
} |
|
} |
|
|
|
/// <summary>Load method pointer</summary> |
|
public sealed partial class LdFtn : SimpleInstruction |
|
{ |
|
public LdFtn(IMethod method) : base(OpCode.LdFtn) |
|
{ |
|
this.method = method; |
|
} |
|
readonly IMethod method; |
|
/// <summary>Returns the method operand.</summary> |
|
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<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitLdFtn(this); |
|
} |
|
} |
|
|
|
/// <summary>Load method pointer</summary> |
|
public sealed partial class LdVirtFtn : UnaryInstruction |
|
{ |
|
public LdVirtFtn(ILInstruction argument, IMethod method) : base(OpCode.LdVirtFtn, argument) |
|
{ |
|
this.method = method; |
|
} |
|
readonly IMethod method; |
|
/// <summary>Returns the method operand.</summary> |
|
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<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitLdVirtFtn(this); |
|
} |
|
} |
|
|
|
/// <summary>Loads runtime representation of metadata token</summary> |
|
public sealed partial class LdToken : SimpleInstruction |
|
{ |
|
public LdToken(Mono.Cecil.MemberReference member) : base(OpCode.LdToken) |
|
{ |
|
this.member = member; |
|
} |
|
readonly Mono.Cecil.MemberReference member; |
|
/// <summary>Returns the token operand.</summary> |
|
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<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitLdToken(this); |
|
} |
|
} |
|
|
|
/// <summary>Allocates space in the stack frame</summary> |
|
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<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitLocAlloc(this); |
|
} |
|
} |
|
|
|
/// <summary>Returns from the current method or lambda.</summary> |
|
public sealed partial class Return : ILInstruction |
|
{ |
|
public override StackType ResultType { get { return StackType.Void; } } |
|
public override T AcceptVisitor<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitReturn(this); |
|
} |
|
} |
|
|
|
/// <summary>Shift left</summary> |
|
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<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitShl(this); |
|
} |
|
} |
|
|
|
/// <summary>Shift right</summary> |
|
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<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitShr(this); |
|
} |
|
} |
|
|
|
/// <summary>Load instance field</summary> |
|
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<ILInstruction> Children { |
|
get { |
|
yield return this.target; |
|
} |
|
} |
|
public override void TransformChildren(ILVisitor<ILInstruction> visitor) |
|
{ |
|
this.Target = this.target.AcceptVisitor(visitor); |
|
} |
|
internal override ILInstruction Inline(InstructionFlags flagsBefore, IInlineContext context) |
|
{ |
|
this.Target = this.target.Inline(flagsBefore, context); |
|
return this; |
|
} |
|
/// <summary>Gets/Sets whether the memory access is volatile.</summary> |
|
public bool IsVolatile { get; set; } |
|
/// <summary>Returns the alignment specified by the 'unaligned' prefix; or 0 if there was no 'unaligned' prefix.</summary> |
|
public byte UnalignedPrefix { get; set; } |
|
readonly IField field; |
|
/// <summary>Returns the field operand.</summary> |
|
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<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitLdFld(this); |
|
} |
|
} |
|
|
|
/// <summary>Load address of instance field</summary> |
|
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<ILInstruction> Children { |
|
get { |
|
yield return this.target; |
|
} |
|
} |
|
public override void TransformChildren(ILVisitor<ILInstruction> visitor) |
|
{ |
|
this.Target = this.target.AcceptVisitor(visitor); |
|
} |
|
internal override ILInstruction Inline(InstructionFlags flagsBefore, IInlineContext context) |
|
{ |
|
this.Target = this.target.Inline(flagsBefore, context); |
|
return this; |
|
} |
|
readonly IField field; |
|
/// <summary>Returns the field operand.</summary> |
|
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<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitLdFlda(this); |
|
} |
|
} |
|
|
|
/// <summary>Store value to instance field</summary> |
|
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<ILInstruction> Children { |
|
get { |
|
yield return this.target; |
|
yield return this.value; |
|
} |
|
} |
|
public override void TransformChildren(ILVisitor<ILInstruction> 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; |
|
} |
|
/// <summary>Gets/Sets whether the memory access is volatile.</summary> |
|
public bool IsVolatile { get; set; } |
|
/// <summary>Returns the alignment specified by the 'unaligned' prefix; or 0 if there was no 'unaligned' prefix.</summary> |
|
public byte UnalignedPrefix { get; set; } |
|
readonly IField field; |
|
/// <summary>Returns the field operand.</summary> |
|
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<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitStFld(this); |
|
} |
|
} |
|
|
|
/// <summary>Load static field</summary> |
|
public sealed partial class LdsFld : SimpleInstruction, ISupportsVolatilePrefix, ISupportsUnalignedPrefix |
|
{ |
|
public LdsFld(IField field) : base(OpCode.LdsFld) |
|
{ |
|
this.field = field; |
|
} |
|
/// <summary>Gets/Sets whether the memory access is volatile.</summary> |
|
public bool IsVolatile { get; set; } |
|
/// <summary>Returns the alignment specified by the 'unaligned' prefix; or 0 if there was no 'unaligned' prefix.</summary> |
|
public byte UnalignedPrefix { get; set; } |
|
readonly IField field; |
|
/// <summary>Returns the field operand.</summary> |
|
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<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitLdsFld(this); |
|
} |
|
} |
|
|
|
/// <summary>Load static field address</summary> |
|
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; |
|
/// <summary>Returns the field operand.</summary> |
|
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<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitLdsFlda(this); |
|
} |
|
} |
|
|
|
/// <summary>Store value to static field</summary> |
|
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<ILInstruction> Children { |
|
get { |
|
yield return this.value; |
|
} |
|
} |
|
public override void TransformChildren(ILVisitor<ILInstruction> visitor) |
|
{ |
|
this.Value = this.value.AcceptVisitor(visitor); |
|
} |
|
internal override ILInstruction Inline(InstructionFlags flagsBefore, IInlineContext context) |
|
{ |
|
this.Value = this.value.Inline(flagsBefore, context); |
|
return this; |
|
} |
|
/// <summary>Gets/Sets whether the memory access is volatile.</summary> |
|
public bool IsVolatile { get; set; } |
|
/// <summary>Returns the alignment specified by the 'unaligned' prefix; or 0 if there was no 'unaligned' prefix.</summary> |
|
public byte UnalignedPrefix { get; set; } |
|
readonly IField field; |
|
/// <summary>Returns the field operand.</summary> |
|
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<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitStsFld(this); |
|
} |
|
} |
|
|
|
/// <summary>Casts an object to a class.</summary> |
|
public sealed partial class CastClass : UnaryInstruction |
|
{ |
|
public CastClass(ILInstruction argument, IType type) : base(OpCode.CastClass, argument) |
|
{ |
|
this.type = type; |
|
} |
|
readonly IType type; |
|
/// <summary>Returns the type operand.</summary> |
|
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<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitCastClass(this); |
|
} |
|
} |
|
|
|
/// <summary>Test if object is instance of class or interface.</summary> |
|
public sealed partial class IsInst : UnaryInstruction |
|
{ |
|
public IsInst(ILInstruction argument, IType type) : base(OpCode.IsInst, argument) |
|
{ |
|
this.type = type; |
|
} |
|
readonly IType type; |
|
/// <summary>Returns the type operand.</summary> |
|
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<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitIsInst(this); |
|
} |
|
} |
|
|
|
/// <summary>Indirect load (ref/pointer dereference).</summary> |
|
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<ILInstruction> Children { |
|
get { |
|
yield return this.target; |
|
} |
|
} |
|
public override void TransformChildren(ILVisitor<ILInstruction> visitor) |
|
{ |
|
this.Target = this.target.AcceptVisitor(visitor); |
|
} |
|
internal override ILInstruction Inline(InstructionFlags flagsBefore, IInlineContext context) |
|
{ |
|
this.Target = this.target.Inline(flagsBefore, context); |
|
return this; |
|
} |
|
readonly IType type; |
|
/// <summary>Returns the type operand.</summary> |
|
public IType Type { get { return type; } } |
|
/// <summary>Gets/Sets whether the memory access is volatile.</summary> |
|
public bool IsVolatile { get; set; } |
|
/// <summary>Returns the alignment specified by the 'unaligned' prefix; or 0 if there was no 'unaligned' prefix.</summary> |
|
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<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitLdObj(this); |
|
} |
|
} |
|
|
|
/// <summary>Indirect store (store to ref/pointer).</summary> |
|
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<ILInstruction> Children { |
|
get { |
|
yield return this.target; |
|
yield return this.value; |
|
} |
|
} |
|
public override void TransformChildren(ILVisitor<ILInstruction> 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; |
|
} |
|
readonly IType type; |
|
/// <summary>Returns the type operand.</summary> |
|
public IType Type { get { return type; } } |
|
/// <summary>Gets/Sets whether the memory access is volatile.</summary> |
|
public bool IsVolatile { get; set; } |
|
/// <summary>Returns the alignment specified by the 'unaligned' prefix; or 0 if there was no 'unaligned' prefix.</summary> |
|
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<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitStObj(this); |
|
} |
|
} |
|
|
|
/// <summary>Boxes a value.</summary> |
|
public sealed partial class Box : UnaryInstruction |
|
{ |
|
public Box(ILInstruction argument, IType type) : base(OpCode.Box, argument) |
|
{ |
|
this.type = type; |
|
} |
|
readonly IType type; |
|
/// <summary>Returns the type operand.</summary> |
|
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<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitBox(this); |
|
} |
|
} |
|
|
|
/// <summary>Compute address inside box.</summary> |
|
public sealed partial class Unbox : UnaryInstruction |
|
{ |
|
public Unbox(ILInstruction argument, IType type) : base(OpCode.Unbox, argument) |
|
{ |
|
this.type = type; |
|
} |
|
readonly IType type; |
|
/// <summary>Returns the type operand.</summary> |
|
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<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitUnbox(this); |
|
} |
|
} |
|
|
|
/// <summary>Unbox a value.</summary> |
|
public sealed partial class UnboxAny : UnaryInstruction |
|
{ |
|
public UnboxAny(ILInstruction argument, IType type) : base(OpCode.UnboxAny, argument) |
|
{ |
|
this.type = type; |
|
} |
|
readonly IType type; |
|
/// <summary>Returns the type operand.</summary> |
|
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<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitUnboxAny(this); |
|
} |
|
} |
|
|
|
/// <summary>Creates an object instance and calls the constructor.</summary> |
|
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<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitNewObj(this); |
|
} |
|
} |
|
|
|
/// <summary>Initializes the value at an address.</summary> |
|
public sealed partial class InitObj : UnaryInstruction |
|
{ |
|
public InitObj(ILInstruction argument, IType type) : base(OpCode.InitObj, argument) |
|
{ |
|
this.type = type; |
|
} |
|
readonly IType type; |
|
/// <summary>Returns the type operand.</summary> |
|
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<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitInitObj(this); |
|
} |
|
} |
|
|
|
/// <summary>Returns the default value for a type.</summary> |
|
public sealed partial class DefaultValue : SimpleInstruction |
|
{ |
|
public DefaultValue(IType type) : base(OpCode.DefaultValue) |
|
{ |
|
this.type = type; |
|
} |
|
readonly IType type; |
|
/// <summary>Returns the type operand.</summary> |
|
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<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitDefaultValue(this); |
|
} |
|
} |
|
|
|
/// <summary>Throws an exception.</summary> |
|
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<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitThrow(this); |
|
} |
|
} |
|
|
|
/// <summary>Rethrows the current exception.</summary> |
|
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<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitRethrow(this); |
|
} |
|
} |
|
|
|
/// <summary>Gets the size of a type in bytes.</summary> |
|
public sealed partial class SizeOf : SimpleInstruction |
|
{ |
|
public SizeOf(IType type) : base(OpCode.SizeOf) |
|
{ |
|
this.type = type; |
|
} |
|
readonly IType type; |
|
/// <summary>Returns the type operand.</summary> |
|
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<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitSizeOf(this); |
|
} |
|
} |
|
|
|
/// <summary>Returns the length of an array as 'native unsigned int'.</summary> |
|
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<ILInstruction> Children { |
|
get { |
|
yield return this.target; |
|
} |
|
} |
|
public override void TransformChildren(ILVisitor<ILInstruction> visitor) |
|
{ |
|
this.Target = this.target.AcceptVisitor(visitor); |
|
} |
|
internal override ILInstruction Inline(InstructionFlags flagsBefore, IInlineContext context) |
|
{ |
|
this.Target = this.target.Inline(flagsBefore, context); |
|
return this; |
|
} |
|
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<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitLdLen(this); |
|
} |
|
} |
|
|
|
/// <summary>Load address of array element.</summary> |
|
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<ILInstruction> Children { |
|
get { |
|
yield return this.array; |
|
yield return this.index; |
|
} |
|
} |
|
public override void TransformChildren(ILVisitor<ILInstruction> 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; |
|
} |
|
readonly IType type; |
|
/// <summary>Returns the type operand.</summary> |
|
public IType Type { get { return type; } } |
|
public override StackType ResultType { get { return StackType.Ref; } } |
|
/// <summary>Gets whether the 'readonly' prefix was applied to this instruction.</summary> |
|
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<T>(ILVisitor<T> visitor) |
|
{ |
|
return visitor.VisitLdElema(this); |
|
} |
|
} |
|
|
|
|
|
/// <summary> |
|
/// Base class for visitor pattern. |
|
/// </summary> |
|
public abstract class ILVisitor<T> |
|
{ |
|
/// <summary>Called by Visit*() methods that were not overridden</summary> |
|
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", |
|
}; |
|
} |
|
} |
|
|
|
|