diff --git a/ICSharpCode.Decompiler/DecompilerSettings.cs b/ICSharpCode.Decompiler/DecompilerSettings.cs
index fc085325b..45dd53dc9 100644
--- a/ICSharpCode.Decompiler/DecompilerSettings.cs
+++ b/ICSharpCode.Decompiler/DecompilerSettings.cs
@@ -59,7 +59,7 @@ namespace ICSharpCode.Decompiler
expressionTrees = false;
}
if (languageVersion < CSharp.LanguageVersion.CSharp4) {
- // * dynamic (not supported yet)
+ dynamicExpressions = false;
// * named and optional arguments (not supported yet)
}
if (languageVersion < CSharp.LanguageVersion.CSharp5) {
@@ -172,6 +172,21 @@ namespace ICSharpCode.Decompiler
}
}
+ bool dynamicExpressions = true;
+
+ ///
+ /// Decompile expressions that use dynamic types.
+ ///
+ public bool DynamicExpressions {
+ get { return dynamicExpressions; }
+ set {
+ if (dynamicExpressions != value) {
+ dynamicExpressions = value;
+ OnPropertyChanged();
+ }
+ }
+ }
+
bool fixedBuffers = true;
///
diff --git a/ICSharpCode.Decompiler/IL/Instructions.cs b/ICSharpCode.Decompiler/IL/Instructions.cs
index f88839143..019fe26ce 100644
--- a/ICSharpCode.Decompiler/IL/Instructions.cs
+++ b/ICSharpCode.Decompiler/IL/Instructions.cs
@@ -183,6 +183,28 @@ namespace ICSharpCode.Decompiler.IL
StringToInt,
/// ILAst representation of Expression.Convert.
ExpressionTreeCast,
+ /// ILAst representation of a binary operator inside a dynamic expression (maps to Binder.BinaryOperation).
+ DynamicBinaryOperatorInstruction,
+ /// ILAst representation of a unary operator inside a dynamic expression (maps to Binder.UnaryOperation).
+ DynamicUnaryOperatorInstruction,
+ /// ILAst representation of a cast inside a dynamic expression (maps to Binder.Convert).
+ DynamicConvertInstruction,
+ /// ILAst representation of a property get method call inside a dynamic expression (maps to Binder.GetMember).
+ DynamicGetMemberInstruction,
+ /// ILAst representation of a property set method call inside a dynamic expression (maps to Binder.SetMember).
+ DynamicSetMemberInstruction,
+ /// ILAst representation of an indexer get method call inside a dynamic expression (maps to Binder.GetIndex).
+ DynamicGetIndexInstruction,
+ /// ILAst representation of an indexer set method call inside a dynamic expression (maps to Binder.SetIndex).
+ DynamicSetIndexInstruction,
+ /// ILAst representation of a method call inside a dynamic expression (maps to Binder.InvokeMember).
+ DynamicInvokeMemberInstruction,
+ /// ILAst representation of a constuctor invocation inside a dynamic expression (maps to Binder.InvokeConstructor).
+ DynamicInvokeConstructorInstruction,
+ /// ILAst representation of a delegate invocation inside a dynamic expression (maps to Binder.Invoke).
+ DynamicInvokeInstruction,
+ /// ILAst representation of a call to the Binder.IsEvent method inside a dynamic expression.
+ DynamicIsEventInstruction,
/// Push a typed reference of type class onto the stack.
MakeRefAny,
/// Push the type token stored in a typed reference.
@@ -473,6 +495,26 @@ namespace ICSharpCode.Decompiler.IL
}
}
}
+namespace ICSharpCode.Decompiler.IL
+{
+ /// Instruction representing a dynamic call site.
+ public abstract partial class DynamicInstruction : ILInstruction
+ {
+ protected DynamicInstruction(OpCode opCode) : base(opCode)
+ {
+ }
+
+ protected override InstructionFlags ComputeFlags()
+ {
+ return InstructionFlags.MayThrow | InstructionFlags.SideEffect;
+ }
+ public override InstructionFlags DirectFlags {
+ get {
+ return InstructionFlags.MayThrow | InstructionFlags.SideEffect;
+ }
+ }
+ }
+}
namespace ICSharpCode.Decompiler.IL.Patterns
{
/// Base class for pattern matching in ILAst.
@@ -4701,147 +4743,199 @@ namespace ICSharpCode.Decompiler.IL
}
namespace ICSharpCode.Decompiler.IL
{
- /// Push a typed reference of type class onto the stack.
- public sealed partial class MakeRefAny : UnaryInstruction
+ /// ILAst representation of a binary operator inside a dynamic expression (maps to Binder.BinaryOperation).
+ public sealed partial class DynamicBinaryOperatorInstruction : DynamicInstruction
{
- public MakeRefAny(ILInstruction argument, IType type) : base(OpCode.MakeRefAny, argument)
- {
- this.type = type;
+ public static readonly SlotInfo LeftSlot = new SlotInfo("Left", canInlineInto: true);
+ ILInstruction left;
+ public ILInstruction Left {
+ get { return this.left; }
+ set {
+ ValidateChild(value);
+ SetChildInstruction(ref this.left, value, 0);
+ }
}
- IType type;
- /// Returns the type operand.
- public IType Type {
- get { return type; }
- set { type = value; InvalidateFlags(); }
+ public static readonly SlotInfo RightSlot = new SlotInfo("Right", canInlineInto: true);
+ ILInstruction right;
+ public ILInstruction Right {
+ get { return this.right; }
+ set {
+ ValidateChild(value);
+ SetChildInstruction(ref this.right, value, 1);
+ }
}
- public override StackType ResultType { get { return StackType.O; } }
- public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
+ protected sealed override int GetChildCount()
{
- ILRange.WriteTo(output, options);
- output.Write(OpCode);
- output.Write(' ');
- type.WriteTo(output);
- output.Write('(');
- Argument.WriteTo(output, options);
- output.Write(')');
+ return 2;
}
- public override void AcceptVisitor(ILVisitor visitor)
+ protected sealed override ILInstruction GetChild(int index)
{
- visitor.VisitMakeRefAny(this);
+ switch (index) {
+ case 0:
+ return this.left;
+ case 1:
+ return this.right;
+ default:
+ throw new IndexOutOfRangeException();
+ }
}
- public override T AcceptVisitor(ILVisitor visitor)
+ protected sealed override void SetChild(int index, ILInstruction value)
{
- return visitor.VisitMakeRefAny(this);
+ switch (index) {
+ case 0:
+ this.Left = value;
+ break;
+ case 1:
+ this.Right = value;
+ break;
+ default:
+ throw new IndexOutOfRangeException();
+ }
}
- public override T AcceptVisitor(ILVisitor visitor, C context)
+ protected sealed override SlotInfo GetChildSlot(int index)
{
- return visitor.VisitMakeRefAny(this, context);
+ switch (index) {
+ case 0:
+ return LeftSlot;
+ case 1:
+ return RightSlot;
+ default:
+ throw new IndexOutOfRangeException();
+ }
}
- protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
+ public sealed override ILInstruction Clone()
{
- var o = other as MakeRefAny;
- return o != null && this.Argument.PerformMatch(o.Argument, ref match) && type.Equals(o.type);
+ var clone = (DynamicBinaryOperatorInstruction)ShallowClone();
+ clone.Left = this.left.Clone();
+ clone.Right = this.right.Clone();
+ return clone;
}
- }
-}
-namespace ICSharpCode.Decompiler.IL
-{
- /// Push the type token stored in a typed reference.
- public sealed partial class RefAnyType : UnaryInstruction
- {
- public RefAnyType(ILInstruction argument) : base(OpCode.RefAnyType, argument)
+ protected override InstructionFlags ComputeFlags()
{
+ return base.ComputeFlags() | left.Flags | right.Flags;
+ }
+ public override InstructionFlags DirectFlags {
+ get {
+ return base.DirectFlags;
+ }
}
- public override StackType ResultType { get { return StackType.O; } }
public override void AcceptVisitor(ILVisitor visitor)
{
- visitor.VisitRefAnyType(this);
+ visitor.VisitDynamicBinaryOperatorInstruction(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
- return visitor.VisitRefAnyType(this);
+ return visitor.VisitDynamicBinaryOperatorInstruction(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
- return visitor.VisitRefAnyType(this, context);
+ return visitor.VisitDynamicBinaryOperatorInstruction(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
- var o = other as RefAnyType;
- return o != null && this.Argument.PerformMatch(o.Argument, ref match);
+ var o = other as DynamicBinaryOperatorInstruction;
+ return o != null && this.left.PerformMatch(o.left, ref match) && this.right.PerformMatch(o.right, ref match);
}
}
}
namespace ICSharpCode.Decompiler.IL
{
- /// Push the address stored in a typed reference.
- public sealed partial class RefAnyValue : UnaryInstruction
+ /// ILAst representation of a unary operator inside a dynamic expression (maps to Binder.UnaryOperation).
+ public sealed partial class DynamicUnaryOperatorInstruction : DynamicInstruction
{
- public RefAnyValue(ILInstruction argument, IType type) : base(OpCode.RefAnyValue, argument)
+ public static readonly SlotInfo OperandSlot = new SlotInfo("Operand", canInlineInto: true);
+ ILInstruction operand;
+ public ILInstruction Operand {
+ get { return this.operand; }
+ set {
+ ValidateChild(value);
+ SetChildInstruction(ref this.operand, value, 0);
+ }
+ }
+ protected sealed override int GetChildCount()
{
- this.type = type;
+ return 1;
}
- IType type;
- /// Returns the type operand.
- public IType Type {
- get { return type; }
- set { type = value; InvalidateFlags(); }
+ protected sealed override ILInstruction GetChild(int index)
+ {
+ switch (index) {
+ case 0:
+ return this.operand;
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+ protected sealed override void SetChild(int index, ILInstruction value)
+ {
+ switch (index) {
+ case 0:
+ this.Operand = value;
+ break;
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+ protected sealed override SlotInfo GetChildSlot(int index)
+ {
+ switch (index) {
+ case 0:
+ return OperandSlot;
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+ public sealed override ILInstruction Clone()
+ {
+ var clone = (DynamicUnaryOperatorInstruction)ShallowClone();
+ clone.Operand = this.operand.Clone();
+ return clone;
}
- public override StackType ResultType { get { return StackType.Ref; } }
protected override InstructionFlags ComputeFlags()
{
- return base.ComputeFlags() | InstructionFlags.MayThrow;
+ return base.ComputeFlags() | operand.Flags;
}
public override InstructionFlags DirectFlags {
get {
- return base.DirectFlags | InstructionFlags.MayThrow;
+ return base.DirectFlags;
}
}
- public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
- {
- ILRange.WriteTo(output, options);
- output.Write(OpCode);
- output.Write(' ');
- type.WriteTo(output);
- output.Write('(');
- Argument.WriteTo(output, options);
- output.Write(')');
- }
public override void AcceptVisitor(ILVisitor visitor)
{
- visitor.VisitRefAnyValue(this);
+ visitor.VisitDynamicUnaryOperatorInstruction(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
- return visitor.VisitRefAnyValue(this);
+ return visitor.VisitDynamicUnaryOperatorInstruction(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
- return visitor.VisitRefAnyValue(this, context);
+ return visitor.VisitDynamicUnaryOperatorInstruction(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
- var o = other as RefAnyValue;
- return o != null && this.Argument.PerformMatch(o.Argument, ref match) && type.Equals(o.type);
+ var o = other as DynamicUnaryOperatorInstruction;
+ return o != null && this.operand.PerformMatch(o.operand, ref match);
}
}
}
namespace ICSharpCode.Decompiler.IL
{
- /// Yield an element from an iterator.
- public sealed partial class YieldReturn : ILInstruction
+ /// ILAst representation of a cast inside a dynamic expression (maps to Binder.Convert).
+ public sealed partial class DynamicConvertInstruction : DynamicInstruction
{
- public YieldReturn(ILInstruction value) : base(OpCode.YieldReturn)
- {
- this.Value = value;
+ IType type;
+ /// Returns the type operand.
+ public IType Type {
+ get { return type; }
+ set { type = value; InvalidateFlags(); }
}
- public static readonly SlotInfo ValueSlot = new SlotInfo("Value", canInlineInto: true);
- ILInstruction value;
- public ILInstruction Value {
- get { return this.value; }
+ public static readonly SlotInfo ArgumentSlot = new SlotInfo("Argument", canInlineInto: true);
+ ILInstruction argument;
+ public ILInstruction Argument {
+ get { return this.argument; }
set {
ValidateChild(value);
- SetChildInstruction(ref this.value, value, 0);
+ SetChildInstruction(ref this.argument, value, 0);
}
}
protected sealed override int GetChildCount()
@@ -4852,7 +4946,7 @@ namespace ICSharpCode.Decompiler.IL
{
switch (index) {
case 0:
- return this.value;
+ return this.argument;
default:
throw new IndexOutOfRangeException();
}
@@ -4861,7 +4955,7 @@ namespace ICSharpCode.Decompiler.IL
{
switch (index) {
case 0:
- this.Value = value;
+ this.Argument = value;
break;
default:
throw new IndexOutOfRangeException();
@@ -4871,70 +4965,62 @@ namespace ICSharpCode.Decompiler.IL
{
switch (index) {
case 0:
- return ValueSlot;
+ return ArgumentSlot;
default:
throw new IndexOutOfRangeException();
}
}
public sealed override ILInstruction Clone()
{
- var clone = (YieldReturn)ShallowClone();
- clone.Value = this.value.Clone();
+ var clone = (DynamicConvertInstruction)ShallowClone();
+ clone.Argument = this.argument.Clone();
return clone;
}
- public override StackType ResultType { get { return StackType.Void; } }
protected override InstructionFlags ComputeFlags()
{
- return InstructionFlags.MayBranch | InstructionFlags.SideEffect | value.Flags;
+ return base.ComputeFlags() | InstructionFlags.MayThrow | argument.Flags;
}
public override InstructionFlags DirectFlags {
get {
- return InstructionFlags.MayBranch | InstructionFlags.SideEffect;
+ return base.DirectFlags | InstructionFlags.MayThrow;
}
}
- public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
- {
- ILRange.WriteTo(output, options);
- output.Write(OpCode);
- output.Write('(');
- this.value.WriteTo(output, options);
- output.Write(')');
- }
public override void AcceptVisitor(ILVisitor visitor)
{
- visitor.VisitYieldReturn(this);
+ visitor.VisitDynamicConvertInstruction(this);
}
public override T AcceptVisitor(ILVisitor visitor)
{
- return visitor.VisitYieldReturn(this);
+ return visitor.VisitDynamicConvertInstruction(this);
}
public override T AcceptVisitor(ILVisitor visitor, C context)
{
- return visitor.VisitYieldReturn(this, context);
+ return visitor.VisitDynamicConvertInstruction(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
- var o = other as YieldReturn;
- return o != null && this.value.PerformMatch(o.value, ref match);
+ var o = other as DynamicConvertInstruction;
+ return o != null && type.Equals(o.type) && this.argument.PerformMatch(o.argument, ref match);
+ }
+ internal override void CheckInvariant(ILPhase phase)
+ {
+ base.CheckInvariant(phase);
+ Debug.Assert(argument.ResultType == StackType.O);
}
}
}
namespace ICSharpCode.Decompiler.IL
{
- /// C# await operator.
- public sealed partial class Await : ILInstruction
+ /// ILAst representation of a property get method call inside a dynamic expression (maps to Binder.GetMember).
+ public sealed partial class DynamicGetMemberInstruction : DynamicInstruction
{
- public Await(ILInstruction value) : base(OpCode.Await)
- {
- this.Value = value;
- }
- public static readonly SlotInfo ValueSlot = new SlotInfo("Value", canInlineInto: true);
- ILInstruction value;
- public ILInstruction Value {
- get { return this.value; }
+ public static readonly SlotInfo TargetSlot = new SlotInfo("Target", canInlineInto: true);
+ ILInstruction target;
+ public ILInstruction Target {
+ get { return this.target; }
set {
ValidateChild(value);
- SetChildInstruction(ref this.value, value, 0);
+ SetChildInstruction(ref this.target, value, 0);
}
}
protected sealed override int GetChildCount()
@@ -4945,7 +5031,7 @@ namespace ICSharpCode.Decompiler.IL
{
switch (index) {
case 0:
- return this.value;
+ return this.target;
default:
throw new IndexOutOfRangeException();
}
@@ -4954,7 +5040,7 @@ namespace ICSharpCode.Decompiler.IL
{
switch (index) {
case 0:
- this.Value = value;
+ this.Target = value;
break;
default:
throw new IndexOutOfRangeException();
@@ -4964,25 +5050,861 @@ namespace ICSharpCode.Decompiler.IL
{
switch (index) {
case 0:
- return ValueSlot;
+ return TargetSlot;
default:
throw new IndexOutOfRangeException();
}
}
public sealed override ILInstruction Clone()
{
- var clone = (Await)ShallowClone();
- clone.Value = this.value.Clone();
+ var clone = (DynamicGetMemberInstruction)ShallowClone();
+ clone.Target = this.target.Clone();
return clone;
}
- public override StackType ResultType { get { return GetResultMethod?.ReturnType.GetStackType() ?? StackType.Unknown; } }
protected override InstructionFlags ComputeFlags()
{
- return InstructionFlags.SideEffect | value.Flags;
+ return base.ComputeFlags() | InstructionFlags.MayThrow | target.Flags;
}
public override InstructionFlags DirectFlags {
get {
- return InstructionFlags.SideEffect;
+ return base.DirectFlags | InstructionFlags.MayThrow;
+ }
+ }
+ public override void AcceptVisitor(ILVisitor visitor)
+ {
+ visitor.VisitDynamicGetMemberInstruction(this);
+ }
+ public override T AcceptVisitor(ILVisitor visitor)
+ {
+ return visitor.VisitDynamicGetMemberInstruction(this);
+ }
+ public override T AcceptVisitor(ILVisitor visitor, C context)
+ {
+ return visitor.VisitDynamicGetMemberInstruction(this, context);
+ }
+ protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
+ {
+ var o = other as DynamicGetMemberInstruction;
+ return o != null && this.target.PerformMatch(o.target, ref match);
+ }
+ internal override void CheckInvariant(ILPhase phase)
+ {
+ base.CheckInvariant(phase);
+ Debug.Assert(target.ResultType == StackType.O);
+ }
+ }
+}
+namespace ICSharpCode.Decompiler.IL
+{
+ /// ILAst representation of a property set method call inside a dynamic expression (maps to Binder.SetMember).
+ public sealed partial class DynamicSetMemberInstruction : DynamicInstruction
+ {
+ public static readonly SlotInfo TargetSlot = new SlotInfo("Target", canInlineInto: true);
+ ILInstruction target;
+ public ILInstruction Target {
+ get { return this.target; }
+ set {
+ ValidateChild(value);
+ SetChildInstruction(ref this.target, value, 0);
+ }
+ }
+ public static readonly SlotInfo ValueSlot = new SlotInfo("Value", canInlineInto: true);
+ ILInstruction value;
+ public ILInstruction Value {
+ get { return this.value; }
+ set {
+ ValidateChild(value);
+ SetChildInstruction(ref this.value, value, 1);
+ }
+ }
+ protected sealed override int GetChildCount()
+ {
+ return 2;
+ }
+ protected sealed override ILInstruction GetChild(int index)
+ {
+ switch (index) {
+ case 0:
+ return this.target;
+ case 1:
+ return this.value;
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+ protected sealed override void SetChild(int index, ILInstruction value)
+ {
+ switch (index) {
+ case 0:
+ this.Target = value;
+ break;
+ case 1:
+ this.Value = value;
+ break;
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+ protected sealed override SlotInfo GetChildSlot(int index)
+ {
+ switch (index) {
+ case 0:
+ return TargetSlot;
+ case 1:
+ return ValueSlot;
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+ public sealed override ILInstruction Clone()
+ {
+ var clone = (DynamicSetMemberInstruction)ShallowClone();
+ clone.Target = this.target.Clone();
+ clone.Value = this.value.Clone();
+ return clone;
+ }
+ protected override InstructionFlags ComputeFlags()
+ {
+ return base.ComputeFlags() | InstructionFlags.MayThrow | target.Flags | value.Flags;
+ }
+ public override InstructionFlags DirectFlags {
+ get {
+ return base.DirectFlags | InstructionFlags.MayThrow;
+ }
+ }
+ public override void AcceptVisitor(ILVisitor visitor)
+ {
+ visitor.VisitDynamicSetMemberInstruction(this);
+ }
+ public override T AcceptVisitor(ILVisitor visitor)
+ {
+ return visitor.VisitDynamicSetMemberInstruction(this);
+ }
+ public override T AcceptVisitor(ILVisitor visitor, C context)
+ {
+ return visitor.VisitDynamicSetMemberInstruction(this, context);
+ }
+ protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
+ {
+ var o = other as DynamicSetMemberInstruction;
+ return o != null && this.target.PerformMatch(o.target, ref match) && this.value.PerformMatch(o.value, ref match);
+ }
+ internal override void CheckInvariant(ILPhase phase)
+ {
+ base.CheckInvariant(phase);
+ Debug.Assert(target.ResultType == StackType.O);
+ }
+ }
+}
+namespace ICSharpCode.Decompiler.IL
+{
+ /// ILAst representation of an indexer get method call inside a dynamic expression (maps to Binder.GetIndex).
+ public sealed partial class DynamicGetIndexInstruction : DynamicInstruction
+ {
+ public static readonly SlotInfo ArgumentsSlot = new SlotInfo("Arguments", canInlineInto: true);
+ public InstructionCollection Arguments { get; private set; }
+ protected sealed override int GetChildCount()
+ {
+ return Arguments.Count;
+ }
+ protected sealed override ILInstruction GetChild(int index)
+ {
+ switch (index) {
+ default:
+ return this.Arguments[index - 0];
+ }
+ }
+ protected sealed override void SetChild(int index, ILInstruction value)
+ {
+ switch (index) {
+ default:
+ this.Arguments[index - 0] = value;
+ break;
+ }
+ }
+ protected sealed override SlotInfo GetChildSlot(int index)
+ {
+ switch (index) {
+ default:
+ return ArgumentsSlot;
+ }
+ }
+ public sealed override ILInstruction Clone()
+ {
+ var clone = (DynamicGetIndexInstruction)ShallowClone();
+ clone.Arguments = new InstructionCollection(clone, 0);
+ clone.Arguments.AddRange(this.Arguments.Select(arg => arg.Clone()));
+ return clone;
+ }
+ protected override InstructionFlags ComputeFlags()
+ {
+ return base.ComputeFlags() | InstructionFlags.MayThrow | Arguments.Aggregate(InstructionFlags.None, (f, arg) => f | arg.Flags);
+ }
+ public override InstructionFlags DirectFlags {
+ get {
+ return base.DirectFlags | InstructionFlags.MayThrow;
+ }
+ }
+ public override void AcceptVisitor(ILVisitor visitor)
+ {
+ visitor.VisitDynamicGetIndexInstruction(this);
+ }
+ public override T AcceptVisitor(ILVisitor visitor)
+ {
+ return visitor.VisitDynamicGetIndexInstruction(this);
+ }
+ public override T AcceptVisitor(ILVisitor visitor, C context)
+ {
+ return visitor.VisitDynamicGetIndexInstruction(this, context);
+ }
+ protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
+ {
+ var o = other as DynamicGetIndexInstruction;
+ return o != null && Patterns.ListMatch.DoMatch(this.Arguments, o.Arguments, ref match);
+ }
+ }
+}
+namespace ICSharpCode.Decompiler.IL
+{
+ /// ILAst representation of an indexer set method call inside a dynamic expression (maps to Binder.SetIndex).
+ public sealed partial class DynamicSetIndexInstruction : DynamicInstruction
+ {
+ public static readonly SlotInfo ArgumentsSlot = new SlotInfo("Arguments", canInlineInto: true);
+ public InstructionCollection Arguments { get; private set; }
+ protected sealed override int GetChildCount()
+ {
+ return Arguments.Count;
+ }
+ protected sealed override ILInstruction GetChild(int index)
+ {
+ switch (index) {
+ default:
+ return this.Arguments[index - 0];
+ }
+ }
+ protected sealed override void SetChild(int index, ILInstruction value)
+ {
+ switch (index) {
+ default:
+ this.Arguments[index - 0] = value;
+ break;
+ }
+ }
+ protected sealed override SlotInfo GetChildSlot(int index)
+ {
+ switch (index) {
+ default:
+ return ArgumentsSlot;
+ }
+ }
+ public sealed override ILInstruction Clone()
+ {
+ var clone = (DynamicSetIndexInstruction)ShallowClone();
+ clone.Arguments = new InstructionCollection(clone, 0);
+ clone.Arguments.AddRange(this.Arguments.Select(arg => arg.Clone()));
+ return clone;
+ }
+ protected override InstructionFlags ComputeFlags()
+ {
+ return base.ComputeFlags() | InstructionFlags.MayThrow | Arguments.Aggregate(InstructionFlags.None, (f, arg) => f | arg.Flags);
+ }
+ public override InstructionFlags DirectFlags {
+ get {
+ return base.DirectFlags | InstructionFlags.MayThrow;
+ }
+ }
+ public override void AcceptVisitor(ILVisitor visitor)
+ {
+ visitor.VisitDynamicSetIndexInstruction(this);
+ }
+ public override T AcceptVisitor(ILVisitor visitor)
+ {
+ return visitor.VisitDynamicSetIndexInstruction(this);
+ }
+ public override T AcceptVisitor(ILVisitor visitor, C context)
+ {
+ return visitor.VisitDynamicSetIndexInstruction(this, context);
+ }
+ protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
+ {
+ var o = other as DynamicSetIndexInstruction;
+ return o != null && Patterns.ListMatch.DoMatch(this.Arguments, o.Arguments, ref match);
+ }
+ }
+}
+namespace ICSharpCode.Decompiler.IL
+{
+ /// ILAst representation of a method call inside a dynamic expression (maps to Binder.InvokeMember).
+ public sealed partial class DynamicInvokeMemberInstruction : DynamicInstruction
+ {
+ public static readonly SlotInfo ArgumentsSlot = new SlotInfo("Arguments", canInlineInto: true);
+ public InstructionCollection Arguments { get; private set; }
+ protected sealed override int GetChildCount()
+ {
+ return Arguments.Count;
+ }
+ protected sealed override ILInstruction GetChild(int index)
+ {
+ switch (index) {
+ default:
+ return this.Arguments[index - 0];
+ }
+ }
+ protected sealed override void SetChild(int index, ILInstruction value)
+ {
+ switch (index) {
+ default:
+ this.Arguments[index - 0] = value;
+ break;
+ }
+ }
+ protected sealed override SlotInfo GetChildSlot(int index)
+ {
+ switch (index) {
+ default:
+ return ArgumentsSlot;
+ }
+ }
+ public sealed override ILInstruction Clone()
+ {
+ var clone = (DynamicInvokeMemberInstruction)ShallowClone();
+ clone.Arguments = new InstructionCollection(clone, 0);
+ clone.Arguments.AddRange(this.Arguments.Select(arg => arg.Clone()));
+ return clone;
+ }
+ protected override InstructionFlags ComputeFlags()
+ {
+ return base.ComputeFlags() | InstructionFlags.MayThrow | Arguments.Aggregate(InstructionFlags.None, (f, arg) => f | arg.Flags);
+ }
+ public override InstructionFlags DirectFlags {
+ get {
+ return base.DirectFlags | InstructionFlags.MayThrow;
+ }
+ }
+ public override void AcceptVisitor(ILVisitor visitor)
+ {
+ visitor.VisitDynamicInvokeMemberInstruction(this);
+ }
+ public override T AcceptVisitor(ILVisitor visitor)
+ {
+ return visitor.VisitDynamicInvokeMemberInstruction(this);
+ }
+ public override T AcceptVisitor(ILVisitor visitor, C context)
+ {
+ return visitor.VisitDynamicInvokeMemberInstruction(this, context);
+ }
+ protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
+ {
+ var o = other as DynamicInvokeMemberInstruction;
+ return o != null && Patterns.ListMatch.DoMatch(this.Arguments, o.Arguments, ref match);
+ }
+ }
+}
+namespace ICSharpCode.Decompiler.IL
+{
+ /// ILAst representation of a constuctor invocation inside a dynamic expression (maps to Binder.InvokeConstructor).
+ public sealed partial class DynamicInvokeConstructorInstruction : DynamicInstruction
+ {
+ public static readonly SlotInfo ArgumentsSlot = new SlotInfo("Arguments", canInlineInto: true);
+ public InstructionCollection Arguments { get; private set; }
+ protected sealed override int GetChildCount()
+ {
+ return Arguments.Count;
+ }
+ protected sealed override ILInstruction GetChild(int index)
+ {
+ switch (index) {
+ default:
+ return this.Arguments[index - 0];
+ }
+ }
+ protected sealed override void SetChild(int index, ILInstruction value)
+ {
+ switch (index) {
+ default:
+ this.Arguments[index - 0] = value;
+ break;
+ }
+ }
+ protected sealed override SlotInfo GetChildSlot(int index)
+ {
+ switch (index) {
+ default:
+ return ArgumentsSlot;
+ }
+ }
+ public sealed override ILInstruction Clone()
+ {
+ var clone = (DynamicInvokeConstructorInstruction)ShallowClone();
+ clone.Arguments = new InstructionCollection(clone, 0);
+ clone.Arguments.AddRange(this.Arguments.Select(arg => arg.Clone()));
+ return clone;
+ }
+ protected override InstructionFlags ComputeFlags()
+ {
+ return base.ComputeFlags() | InstructionFlags.MayThrow | Arguments.Aggregate(InstructionFlags.None, (f, arg) => f | arg.Flags);
+ }
+ public override InstructionFlags DirectFlags {
+ get {
+ return base.DirectFlags | InstructionFlags.MayThrow;
+ }
+ }
+ public override void AcceptVisitor(ILVisitor visitor)
+ {
+ visitor.VisitDynamicInvokeConstructorInstruction(this);
+ }
+ public override T AcceptVisitor(ILVisitor visitor)
+ {
+ return visitor.VisitDynamicInvokeConstructorInstruction(this);
+ }
+ public override T AcceptVisitor(ILVisitor visitor, C context)
+ {
+ return visitor.VisitDynamicInvokeConstructorInstruction(this, context);
+ }
+ protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
+ {
+ var o = other as DynamicInvokeConstructorInstruction;
+ return o != null && Patterns.ListMatch.DoMatch(this.Arguments, o.Arguments, ref match);
+ }
+ }
+}
+namespace ICSharpCode.Decompiler.IL
+{
+ /// ILAst representation of a delegate invocation inside a dynamic expression (maps to Binder.Invoke).
+ public sealed partial class DynamicInvokeInstruction : DynamicInstruction
+ {
+ public static readonly SlotInfo ArgumentsSlot = new SlotInfo("Arguments", canInlineInto: true);
+ public InstructionCollection Arguments { get; private set; }
+ protected sealed override int GetChildCount()
+ {
+ return Arguments.Count;
+ }
+ protected sealed override ILInstruction GetChild(int index)
+ {
+ switch (index) {
+ default:
+ return this.Arguments[index - 0];
+ }
+ }
+ protected sealed override void SetChild(int index, ILInstruction value)
+ {
+ switch (index) {
+ default:
+ this.Arguments[index - 0] = value;
+ break;
+ }
+ }
+ protected sealed override SlotInfo GetChildSlot(int index)
+ {
+ switch (index) {
+ default:
+ return ArgumentsSlot;
+ }
+ }
+ public sealed override ILInstruction Clone()
+ {
+ var clone = (DynamicInvokeInstruction)ShallowClone();
+ clone.Arguments = new InstructionCollection(clone, 0);
+ clone.Arguments.AddRange(this.Arguments.Select(arg => arg.Clone()));
+ return clone;
+ }
+ protected override InstructionFlags ComputeFlags()
+ {
+ return base.ComputeFlags() | InstructionFlags.MayThrow | Arguments.Aggregate(InstructionFlags.None, (f, arg) => f | arg.Flags);
+ }
+ public override InstructionFlags DirectFlags {
+ get {
+ return base.DirectFlags | InstructionFlags.MayThrow;
+ }
+ }
+ public override void AcceptVisitor(ILVisitor visitor)
+ {
+ visitor.VisitDynamicInvokeInstruction(this);
+ }
+ public override T AcceptVisitor(ILVisitor visitor)
+ {
+ return visitor.VisitDynamicInvokeInstruction(this);
+ }
+ public override T AcceptVisitor(ILVisitor visitor, C context)
+ {
+ return visitor.VisitDynamicInvokeInstruction(this, context);
+ }
+ protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
+ {
+ var o = other as DynamicInvokeInstruction;
+ return o != null && Patterns.ListMatch.DoMatch(this.Arguments, o.Arguments, ref match);
+ }
+ }
+}
+namespace ICSharpCode.Decompiler.IL
+{
+ /// ILAst representation of a call to the Binder.IsEvent method inside a dynamic expression.
+ public sealed partial class DynamicIsEventInstruction : DynamicInstruction
+ {
+ public static readonly SlotInfo ArgumentSlot = new SlotInfo("Argument", canInlineInto: true);
+ ILInstruction argument;
+ public ILInstruction Argument {
+ get { return this.argument; }
+ set {
+ ValidateChild(value);
+ SetChildInstruction(ref this.argument, value, 0);
+ }
+ }
+ protected sealed override int GetChildCount()
+ {
+ return 1;
+ }
+ protected sealed override ILInstruction GetChild(int index)
+ {
+ switch (index) {
+ case 0:
+ return this.argument;
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+ protected sealed override void SetChild(int index, ILInstruction value)
+ {
+ switch (index) {
+ case 0:
+ this.Argument = value;
+ break;
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+ protected sealed override SlotInfo GetChildSlot(int index)
+ {
+ switch (index) {
+ case 0:
+ return ArgumentSlot;
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+ public sealed override ILInstruction Clone()
+ {
+ var clone = (DynamicIsEventInstruction)ShallowClone();
+ clone.Argument = this.argument.Clone();
+ return clone;
+ }
+ protected override InstructionFlags ComputeFlags()
+ {
+ return base.ComputeFlags() | InstructionFlags.MayThrow | argument.Flags;
+ }
+ public override InstructionFlags DirectFlags {
+ get {
+ return base.DirectFlags | InstructionFlags.MayThrow;
+ }
+ }
+ public override void AcceptVisitor(ILVisitor visitor)
+ {
+ visitor.VisitDynamicIsEventInstruction(this);
+ }
+ public override T AcceptVisitor(ILVisitor visitor)
+ {
+ return visitor.VisitDynamicIsEventInstruction(this);
+ }
+ public override T AcceptVisitor(ILVisitor visitor, C context)
+ {
+ return visitor.VisitDynamicIsEventInstruction(this, context);
+ }
+ protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
+ {
+ var o = other as DynamicIsEventInstruction;
+ return o != null && this.argument.PerformMatch(o.argument, ref match);
+ }
+ internal override void CheckInvariant(ILPhase phase)
+ {
+ base.CheckInvariant(phase);
+ Debug.Assert(argument.ResultType == StackType.O);
+ }
+ }
+}
+namespace ICSharpCode.Decompiler.IL
+{
+ /// Push a typed reference of type class onto the stack.
+ public sealed partial class MakeRefAny : UnaryInstruction
+ {
+ public MakeRefAny(ILInstruction argument, IType type) : base(OpCode.MakeRefAny, argument)
+ {
+ this.type = type;
+ }
+ IType type;
+ /// Returns the type operand.
+ public IType Type {
+ get { return type; }
+ set { type = value; InvalidateFlags(); }
+ }
+ public override StackType ResultType { get { return StackType.O; } }
+ public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
+ {
+ ILRange.WriteTo(output, options);
+ output.Write(OpCode);
+ output.Write(' ');
+ type.WriteTo(output);
+ output.Write('(');
+ Argument.WriteTo(output, options);
+ output.Write(')');
+ }
+ public override void AcceptVisitor(ILVisitor visitor)
+ {
+ visitor.VisitMakeRefAny(this);
+ }
+ public override T AcceptVisitor(ILVisitor visitor)
+ {
+ return visitor.VisitMakeRefAny(this);
+ }
+ public override T AcceptVisitor(ILVisitor visitor, C context)
+ {
+ return visitor.VisitMakeRefAny(this, context);
+ }
+ protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
+ {
+ var o = other as MakeRefAny;
+ return o != null && this.Argument.PerformMatch(o.Argument, ref match) && type.Equals(o.type);
+ }
+ }
+}
+namespace ICSharpCode.Decompiler.IL
+{
+ /// Push the type token stored in a typed reference.
+ public sealed partial class RefAnyType : UnaryInstruction
+ {
+ public RefAnyType(ILInstruction argument) : base(OpCode.RefAnyType, argument)
+ {
+ }
+ public override StackType ResultType { get { return StackType.O; } }
+ public override void AcceptVisitor(ILVisitor visitor)
+ {
+ visitor.VisitRefAnyType(this);
+ }
+ public override T AcceptVisitor(ILVisitor visitor)
+ {
+ return visitor.VisitRefAnyType(this);
+ }
+ public override T AcceptVisitor(ILVisitor visitor, C context)
+ {
+ return visitor.VisitRefAnyType(this, context);
+ }
+ protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
+ {
+ var o = other as RefAnyType;
+ return o != null && this.Argument.PerformMatch(o.Argument, ref match);
+ }
+ }
+}
+namespace ICSharpCode.Decompiler.IL
+{
+ /// Push the address stored in a typed reference.
+ public sealed partial class RefAnyValue : UnaryInstruction
+ {
+ public RefAnyValue(ILInstruction argument, IType type) : base(OpCode.RefAnyValue, argument)
+ {
+ this.type = type;
+ }
+ IType type;
+ /// Returns the type operand.
+ public IType Type {
+ get { return type; }
+ set { type = value; InvalidateFlags(); }
+ }
+ public override StackType ResultType { get { return StackType.Ref; } }
+ protected override InstructionFlags ComputeFlags()
+ {
+ return base.ComputeFlags() | InstructionFlags.MayThrow;
+ }
+ public override InstructionFlags DirectFlags {
+ get {
+ return base.DirectFlags | InstructionFlags.MayThrow;
+ }
+ }
+ public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
+ {
+ ILRange.WriteTo(output, options);
+ output.Write(OpCode);
+ output.Write(' ');
+ type.WriteTo(output);
+ output.Write('(');
+ Argument.WriteTo(output, options);
+ output.Write(')');
+ }
+ public override void AcceptVisitor(ILVisitor visitor)
+ {
+ visitor.VisitRefAnyValue(this);
+ }
+ public override T AcceptVisitor(ILVisitor visitor)
+ {
+ return visitor.VisitRefAnyValue(this);
+ }
+ public override T AcceptVisitor(ILVisitor visitor, C context)
+ {
+ return visitor.VisitRefAnyValue(this, context);
+ }
+ protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
+ {
+ var o = other as RefAnyValue;
+ return o != null && this.Argument.PerformMatch(o.Argument, ref match) && type.Equals(o.type);
+ }
+ }
+}
+namespace ICSharpCode.Decompiler.IL
+{
+ /// Yield an element from an iterator.
+ public sealed partial class YieldReturn : ILInstruction
+ {
+ public YieldReturn(ILInstruction value) : base(OpCode.YieldReturn)
+ {
+ this.Value = value;
+ }
+ public static readonly SlotInfo ValueSlot = new SlotInfo("Value", canInlineInto: true);
+ ILInstruction value;
+ public ILInstruction Value {
+ get { return this.value; }
+ set {
+ ValidateChild(value);
+ SetChildInstruction(ref this.value, value, 0);
+ }
+ }
+ protected sealed override int GetChildCount()
+ {
+ return 1;
+ }
+ protected sealed override ILInstruction GetChild(int index)
+ {
+ switch (index) {
+ case 0:
+ return this.value;
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+ protected sealed override void SetChild(int index, ILInstruction value)
+ {
+ switch (index) {
+ case 0:
+ this.Value = value;
+ break;
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+ protected sealed override SlotInfo GetChildSlot(int index)
+ {
+ switch (index) {
+ case 0:
+ return ValueSlot;
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+ public sealed override ILInstruction Clone()
+ {
+ var clone = (YieldReturn)ShallowClone();
+ clone.Value = this.value.Clone();
+ return clone;
+ }
+ public override StackType ResultType { get { return StackType.Void; } }
+ protected override InstructionFlags ComputeFlags()
+ {
+ return InstructionFlags.MayBranch | InstructionFlags.SideEffect | value.Flags;
+ }
+ public override InstructionFlags DirectFlags {
+ get {
+ return InstructionFlags.MayBranch | InstructionFlags.SideEffect;
+ }
+ }
+ public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
+ {
+ ILRange.WriteTo(output, options);
+ output.Write(OpCode);
+ output.Write('(');
+ this.value.WriteTo(output, options);
+ output.Write(')');
+ }
+ public override void AcceptVisitor(ILVisitor visitor)
+ {
+ visitor.VisitYieldReturn(this);
+ }
+ public override T AcceptVisitor(ILVisitor visitor)
+ {
+ return visitor.VisitYieldReturn(this);
+ }
+ public override T AcceptVisitor(ILVisitor visitor, C context)
+ {
+ return visitor.VisitYieldReturn(this, context);
+ }
+ protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
+ {
+ var o = other as YieldReturn;
+ return o != null && this.value.PerformMatch(o.value, ref match);
+ }
+ }
+}
+namespace ICSharpCode.Decompiler.IL
+{
+ /// C# await operator.
+ public sealed partial class Await : ILInstruction
+ {
+ public Await(ILInstruction value) : base(OpCode.Await)
+ {
+ this.Value = value;
+ }
+ public static readonly SlotInfo ValueSlot = new SlotInfo("Value", canInlineInto: true);
+ ILInstruction value;
+ public ILInstruction Value {
+ get { return this.value; }
+ set {
+ ValidateChild(value);
+ SetChildInstruction(ref this.value, value, 0);
+ }
+ }
+ protected sealed override int GetChildCount()
+ {
+ return 1;
+ }
+ protected sealed override ILInstruction GetChild(int index)
+ {
+ switch (index) {
+ case 0:
+ return this.value;
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+ protected sealed override void SetChild(int index, ILInstruction value)
+ {
+ switch (index) {
+ case 0:
+ this.Value = value;
+ break;
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+ protected sealed override SlotInfo GetChildSlot(int index)
+ {
+ switch (index) {
+ case 0:
+ return ValueSlot;
+ default:
+ throw new IndexOutOfRangeException();
+ }
+ }
+ public sealed override ILInstruction Clone()
+ {
+ var clone = (Await)ShallowClone();
+ clone.Value = this.value.Clone();
+ return clone;
+ }
+ public override StackType ResultType { get { return GetResultMethod?.ReturnType.GetStackType() ?? StackType.Unknown; } }
+ protected override InstructionFlags ComputeFlags()
+ {
+ return InstructionFlags.SideEffect | value.Flags;
+ }
+ public override InstructionFlags DirectFlags {
+ get {
+ return InstructionFlags.SideEffect;
}
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
@@ -5355,6 +6277,50 @@ namespace ICSharpCode.Decompiler.IL
{
Default(inst);
}
+ protected internal virtual void VisitDynamicBinaryOperatorInstruction(DynamicBinaryOperatorInstruction inst)
+ {
+ Default(inst);
+ }
+ protected internal virtual void VisitDynamicUnaryOperatorInstruction(DynamicUnaryOperatorInstruction inst)
+ {
+ Default(inst);
+ }
+ protected internal virtual void VisitDynamicConvertInstruction(DynamicConvertInstruction inst)
+ {
+ Default(inst);
+ }
+ protected internal virtual void VisitDynamicGetMemberInstruction(DynamicGetMemberInstruction inst)
+ {
+ Default(inst);
+ }
+ protected internal virtual void VisitDynamicSetMemberInstruction(DynamicSetMemberInstruction inst)
+ {
+ Default(inst);
+ }
+ protected internal virtual void VisitDynamicGetIndexInstruction(DynamicGetIndexInstruction inst)
+ {
+ Default(inst);
+ }
+ protected internal virtual void VisitDynamicSetIndexInstruction(DynamicSetIndexInstruction inst)
+ {
+ Default(inst);
+ }
+ protected internal virtual void VisitDynamicInvokeMemberInstruction(DynamicInvokeMemberInstruction inst)
+ {
+ Default(inst);
+ }
+ protected internal virtual void VisitDynamicInvokeConstructorInstruction(DynamicInvokeConstructorInstruction inst)
+ {
+ Default(inst);
+ }
+ protected internal virtual void VisitDynamicInvokeInstruction(DynamicInvokeInstruction inst)
+ {
+ Default(inst);
+ }
+ protected internal virtual void VisitDynamicIsEventInstruction(DynamicIsEventInstruction inst)
+ {
+ Default(inst);
+ }
protected internal virtual void VisitMakeRefAny(MakeRefAny inst)
{
Default(inst);
@@ -5673,6 +6639,50 @@ namespace ICSharpCode.Decompiler.IL
{
return Default(inst);
}
+ protected internal virtual T VisitDynamicBinaryOperatorInstruction(DynamicBinaryOperatorInstruction inst)
+ {
+ return Default(inst);
+ }
+ protected internal virtual T VisitDynamicUnaryOperatorInstruction(DynamicUnaryOperatorInstruction inst)
+ {
+ return Default(inst);
+ }
+ protected internal virtual T VisitDynamicConvertInstruction(DynamicConvertInstruction inst)
+ {
+ return Default(inst);
+ }
+ protected internal virtual T VisitDynamicGetMemberInstruction(DynamicGetMemberInstruction inst)
+ {
+ return Default(inst);
+ }
+ protected internal virtual T VisitDynamicSetMemberInstruction(DynamicSetMemberInstruction inst)
+ {
+ return Default(inst);
+ }
+ protected internal virtual T VisitDynamicGetIndexInstruction(DynamicGetIndexInstruction inst)
+ {
+ return Default(inst);
+ }
+ protected internal virtual T VisitDynamicSetIndexInstruction(DynamicSetIndexInstruction inst)
+ {
+ return Default(inst);
+ }
+ protected internal virtual T VisitDynamicInvokeMemberInstruction(DynamicInvokeMemberInstruction inst)
+ {
+ return Default(inst);
+ }
+ protected internal virtual T VisitDynamicInvokeConstructorInstruction(DynamicInvokeConstructorInstruction inst)
+ {
+ return Default(inst);
+ }
+ protected internal virtual T VisitDynamicInvokeInstruction(DynamicInvokeInstruction inst)
+ {
+ return Default(inst);
+ }
+ protected internal virtual T VisitDynamicIsEventInstruction(DynamicIsEventInstruction inst)
+ {
+ return Default(inst);
+ }
protected internal virtual T VisitMakeRefAny(MakeRefAny inst)
{
return Default(inst);
@@ -5991,6 +7001,50 @@ namespace ICSharpCode.Decompiler.IL
{
return Default(inst, context);
}
+ protected internal virtual T VisitDynamicBinaryOperatorInstruction(DynamicBinaryOperatorInstruction inst, C context)
+ {
+ return Default(inst, context);
+ }
+ protected internal virtual T VisitDynamicUnaryOperatorInstruction(DynamicUnaryOperatorInstruction inst, C context)
+ {
+ return Default(inst, context);
+ }
+ protected internal virtual T VisitDynamicConvertInstruction(DynamicConvertInstruction inst, C context)
+ {
+ return Default(inst, context);
+ }
+ protected internal virtual T VisitDynamicGetMemberInstruction(DynamicGetMemberInstruction inst, C context)
+ {
+ return Default(inst, context);
+ }
+ protected internal virtual T VisitDynamicSetMemberInstruction(DynamicSetMemberInstruction inst, C context)
+ {
+ return Default(inst, context);
+ }
+ protected internal virtual T VisitDynamicGetIndexInstruction(DynamicGetIndexInstruction inst, C context)
+ {
+ return Default(inst, context);
+ }
+ protected internal virtual T VisitDynamicSetIndexInstruction(DynamicSetIndexInstruction inst, C context)
+ {
+ return Default(inst, context);
+ }
+ protected internal virtual T VisitDynamicInvokeMemberInstruction(DynamicInvokeMemberInstruction inst, C context)
+ {
+ return Default(inst, context);
+ }
+ protected internal virtual T VisitDynamicInvokeConstructorInstruction(DynamicInvokeConstructorInstruction inst, C context)
+ {
+ return Default(inst, context);
+ }
+ protected internal virtual T VisitDynamicInvokeInstruction(DynamicInvokeInstruction inst, C context)
+ {
+ return Default(inst, context);
+ }
+ protected internal virtual T VisitDynamicIsEventInstruction(DynamicIsEventInstruction inst, C context)
+ {
+ return Default(inst, context);
+ }
protected internal virtual T VisitMakeRefAny(MakeRefAny inst, C context)
{
return Default(inst, context);
@@ -6088,6 +7142,17 @@ namespace ICSharpCode.Decompiler.IL
"array.to.pointer",
"string.to.int",
"expression.tree.cast",
+ "dynamic.binary.operator",
+ "dynamic.unary.operator",
+ "dynamic.convert",
+ "dynamic.getmember",
+ "dynamic.setmember",
+ "dynamic.getindex",
+ "dynamic.setindex",
+ "dynamic.invokemember",
+ "dynamic.invokeconstructor",
+ "dynamic.invoke",
+ "dynamic.isevent",
"mkrefany",
"refanytype",
"refanyval",
diff --git a/ICSharpCode.Decompiler/IL/Instructions.tt b/ICSharpCode.Decompiler/IL/Instructions.tt
index 667369b9e..6f75055ff 100644
--- a/ICSharpCode.Decompiler/IL/Instructions.tt
+++ b/ICSharpCode.Decompiler/IL/Instructions.tt
@@ -33,6 +33,8 @@
new OpCode("CallInstruction", "Instruction with a list of arguments.",
AbstractBaseClass, CustomChildren(new []{ new ArgumentInfo("arguments") { IsCollection = true }}),
CustomWriteTo, MayThrow, SideEffect),
+ new OpCode("DynamicInstruction", "Instruction representing a dynamic call site.",
+ AbstractBaseClass, CustomWriteTo, MayThrow, SideEffect),
new OpCode("PatternInstruction", "Base class for pattern matching in ILAst.", AbstractBaseClass, ResultType("Unknown")) { Namespace = "ICSharpCode.Decompiler.IL.Patterns" }
};
@@ -260,6 +262,30 @@
CustomClassName("ExpressionTreeCast"), Unary, HasTypeOperand, MayThrow, CustomConstructor, CustomWriteTo, ResultType("type.GetStackType()"),
MatchCondition("this.IsChecked == o.IsChecked")),
+ new OpCode("dynamic.binary.operator", "ILAst representation of a binary operator inside a dynamic expression (maps to Binder.BinaryOperation).",
+ CustomClassName("DynamicBinaryOperatorInstruction"), BaseClass("DynamicInstruction"), CustomArguments(("left", null), ("right", null)), CustomConstructor, CustomWriteTo),
+ new OpCode("dynamic.unary.operator", "ILAst representation of a unary operator inside a dynamic expression (maps to Binder.UnaryOperation).",
+ CustomClassName("DynamicUnaryOperatorInstruction"), BaseClass("DynamicInstruction"), CustomArguments(("operand", null)), CustomConstructor, CustomWriteTo),
+ new OpCode("dynamic.convert", "ILAst representation of a cast inside a dynamic expression (maps to Binder.Convert).",
+ CustomClassName("DynamicConvertInstruction"), BaseClass("DynamicInstruction"), HasTypeOperand, MayThrow, CustomArguments(("argument", new[] { "O" })), CustomConstructor, CustomWriteTo),
+ new OpCode("dynamic.getmember", "ILAst representation of a property get method call inside a dynamic expression (maps to Binder.GetMember).",
+ CustomClassName("DynamicGetMemberInstruction"), BaseClass("DynamicInstruction"), MayThrow, CustomArguments(("target", new[] { "O" })), CustomConstructor, CustomWriteTo),
+ new OpCode("dynamic.setmember", "ILAst representation of a property set method call inside a dynamic expression (maps to Binder.SetMember).",
+ CustomClassName("DynamicSetMemberInstruction"), BaseClass("DynamicInstruction"), MayThrow, CustomArguments(("target", new[] { "O" }), ("value", null)), CustomConstructor, CustomWriteTo),
+ new OpCode("dynamic.getindex", "ILAst representation of an indexer get method call inside a dynamic expression (maps to Binder.GetIndex).",
+ CustomClassName("DynamicGetIndexInstruction"), BaseClass("DynamicInstruction"), MayThrow, CustomChildren(new []{ new ArgumentInfo("arguments") { IsCollection = true }}), CustomConstructor, CustomWriteTo),
+ new OpCode("dynamic.setindex", "ILAst representation of an indexer set method call inside a dynamic expression (maps to Binder.SetIndex).",
+ CustomClassName("DynamicSetIndexInstruction"), BaseClass("DynamicInstruction"), MayThrow, CustomChildren(new []{ new ArgumentInfo("arguments") { IsCollection = true }}), CustomConstructor, CustomWriteTo),
+ new OpCode("dynamic.invokemember", "ILAst representation of a method call inside a dynamic expression (maps to Binder.InvokeMember).",
+ CustomClassName("DynamicInvokeMemberInstruction"), BaseClass("DynamicInstruction"), MayThrow, CustomChildren(new []{ new ArgumentInfo("arguments") { IsCollection = true }}), CustomConstructor, CustomWriteTo),
+ new OpCode("dynamic.invokeconstructor", "ILAst representation of a constuctor invocation inside a dynamic expression (maps to Binder.InvokeConstructor).",
+ CustomClassName("DynamicInvokeConstructorInstruction"), BaseClass("DynamicInstruction"), MayThrow, CustomChildren(new []{ new ArgumentInfo("arguments") { IsCollection = true }}), CustomConstructor, CustomWriteTo),
+ new OpCode("dynamic.invoke", "ILAst representation of a delegate invocation inside a dynamic expression (maps to Binder.Invoke).",
+ CustomClassName("DynamicInvokeInstruction"), BaseClass("DynamicInstruction"), MayThrow, CustomChildren(new []{ new ArgumentInfo("arguments") { IsCollection = true }}), CustomConstructor, CustomWriteTo),
+ new OpCode("dynamic.isevent", "ILAst representation of a call to the Binder.IsEvent method inside a dynamic expression.",
+ CustomClassName("DynamicIsEventInstruction"), BaseClass("DynamicInstruction"), MayThrow, CustomArguments(("argument", new[] { "O" })), CustomConstructor, CustomWriteTo),
+
+
new OpCode("mkrefany", "Push a typed reference of type class onto the stack.",
CustomClassName("MakeRefAny"), Unary, HasTypeOperand, ResultType("O")),
new OpCode("refanytype", "Push the type token stored in a typed reference.",
diff --git a/ICSharpCode.Decompiler/IL/Instructions/DynamicInstructions.cs b/ICSharpCode.Decompiler/IL/Instructions/DynamicInstructions.cs
new file mode 100644
index 000000000..9a9c65694
--- /dev/null
+++ b/ICSharpCode.Decompiler/IL/Instructions/DynamicInstructions.cs
@@ -0,0 +1,463 @@
+// Copyright (c) 2018 Siegfried Pammer
+//
+// 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.Linq.Expressions;
+using System.Text;
+using ICSharpCode.Decompiler.IL.Patterns;
+using ICSharpCode.Decompiler.TypeSystem;
+using ICSharpCode.Decompiler.Util;
+
+namespace ICSharpCode.Decompiler.IL
+{
+ [Flags]
+ public enum CSharpArgumentInfoFlags
+ {
+ None = 0,
+ UseCompileTimeType = 1,
+ Constant = 2,
+ NamedArgument = 4,
+ IsRef = 8,
+ IsOut = 0x10,
+ IsStaticType = 0x20
+ }
+
+ [Flags]
+ public enum CSharpBinderFlags
+ {
+ None = 0,
+ CheckedContext = 1,
+ InvokeSimpleName = 2,
+ InvokeSpecialName = 4,
+ BinaryOperationLogical = 8,
+ ConvertExplicit = 0x10,
+ ConvertArrayIndex = 0x20,
+ ResultIndexed = 0x40,
+ ValueFromCompoundAssignment = 0x80,
+ ResultDiscarded = 0x100
+ }
+
+ public struct CSharpArgumentInfo
+ {
+ public string Name { get; set; }
+ public CSharpArgumentInfoFlags Flags { get; set; }
+ }
+
+ partial class DynamicInstruction
+ {
+ public CSharpBinderFlags BinderFlags { get; }
+ public IType CallingContext { get; }
+
+ protected DynamicInstruction(OpCode opCode, CSharpBinderFlags binderFlags, IType context)
+ : base(opCode)
+ {
+ BinderFlags = binderFlags;
+ CallingContext = context;
+ }
+
+ protected void WriteBinderFlags(ITextOutput output, ILAstWritingOptions options)
+ {
+ if ((BinderFlags & CSharpBinderFlags.BinaryOperationLogical) != 0)
+ output.Write(".logic");
+ if ((BinderFlags & CSharpBinderFlags.CheckedContext) != 0)
+ output.Write(".checked");
+ if ((BinderFlags & CSharpBinderFlags.ConvertArrayIndex) != 0)
+ output.Write(".arrayindex");
+ if ((BinderFlags & CSharpBinderFlags.ConvertExplicit) != 0)
+ output.Write(".explicit");
+ if ((BinderFlags & CSharpBinderFlags.InvokeSimpleName) != 0)
+ output.Write(".invokesimple");
+ if ((BinderFlags & CSharpBinderFlags.InvokeSpecialName) != 0)
+ output.Write(".invokespecial");
+ if ((BinderFlags & CSharpBinderFlags.ResultDiscarded) != 0)
+ output.Write(".discard");
+ if ((BinderFlags & CSharpBinderFlags.ResultIndexed) != 0)
+ output.Write(".resultindexed");
+ if ((BinderFlags & CSharpBinderFlags.ValueFromCompoundAssignment) != 0)
+ output.Write(".compound");
+ }
+ }
+
+ partial class DynamicConvertInstruction
+ {
+ public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
+ {
+ ILRange.WriteTo(output, options);
+ output.Write(OpCode);
+ WriteBinderFlags(output, options);
+ output.Write(' ');
+ type.WriteTo(output);
+ output.Write('(');
+ argument.WriteTo(output, options);
+ output.Write(')');
+ }
+
+ public DynamicConvertInstruction(CSharpBinderFlags binderFlags, IType type, IType context, ILInstruction argument)
+ : base(OpCode.DynamicConvertInstruction, binderFlags, context)
+ {
+ Type = type;
+ Argument = argument;
+ }
+
+ protected internal override bool PerformMatch(ref ListMatch listMatch, ref Match match)
+ {
+ return base.PerformMatch(ref listMatch, ref match);
+ }
+
+ public override StackType ResultType => type.GetStackType();
+
+ public bool IsChecked => (BinderFlags & CSharpBinderFlags.CheckedContext) != 0;
+ }
+
+ partial class DynamicInvokeMemberInstruction
+ {
+ public string Name { get; }
+ public IReadOnlyList TypeArguments { get; }
+ public IReadOnlyList ArgumentInfo { get; }
+
+ public DynamicInvokeMemberInstruction(CSharpBinderFlags binderFlags, string name, IType[] typeArguments, IType context, CSharpArgumentInfo[] argumentInfo, ILInstruction[] arguments)
+ : base(OpCode.DynamicInvokeMemberInstruction, binderFlags, context)
+ {
+ Name = name;
+ TypeArguments = typeArguments ?? Empty.Array;
+ ArgumentInfo = argumentInfo;
+ Arguments = new InstructionCollection(this, 0);
+ Arguments.AddRange(arguments);
+ }
+
+ public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
+ {
+ ILRange.WriteTo(output, options);
+ output.Write(OpCode);
+ WriteBinderFlags(output, options);
+ output.Write(' ');
+ output.Write(Name);
+ if (TypeArguments.Count > 0) {
+ output.Write('<');
+ int i = 0;
+ foreach (var typeArg in TypeArguments) {
+ if (i > 0)
+ output.Write(", ");
+ typeArg.WriteTo(output);
+ i++;
+ }
+ output.Write('>');
+ }
+ output.Write('(');
+ int j = 0;
+ foreach (var arg in Arguments) {
+ if (j > 0)
+ output.Write(", ");
+ arg.WriteTo(output, options);
+ j++;
+ }
+ output.Write(')');
+ }
+
+ public override StackType ResultType => SpecialType.Dynamic.GetStackType();
+ }
+
+ partial class DynamicGetMemberInstruction
+ {
+ public string Name { get; }
+ public CSharpArgumentInfo TargetArgumentInfo { get; }
+
+ public DynamicGetMemberInstruction(CSharpBinderFlags binderFlags, string name, IType context, CSharpArgumentInfo targetArgumentInfo, ILInstruction target)
+ : base(OpCode.DynamicGetMemberInstruction, binderFlags, context)
+ {
+ Name = name;
+ TargetArgumentInfo = targetArgumentInfo;
+ Target = target;
+ }
+
+ public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
+ {
+ ILRange.WriteTo(output, options);
+ output.Write(OpCode);
+ WriteBinderFlags(output, options);
+ output.Write(' ');
+ output.Write(Name);
+ output.Write('(');
+ Target.WriteTo(output, options);
+ output.Write(')');
+ }
+
+ public override StackType ResultType => SpecialType.Dynamic.GetStackType();
+ }
+
+ partial class DynamicSetMemberInstruction
+ {
+ public string Name { get; }
+ public CSharpArgumentInfo TargetArgumentInfo { get; }
+ public CSharpArgumentInfo ValueArgumentInfo { get; }
+
+ public DynamicSetMemberInstruction(CSharpBinderFlags binderFlags, string name, IType context, CSharpArgumentInfo targetArgumentInfo, ILInstruction target, CSharpArgumentInfo valueArgumentInfo, ILInstruction value)
+ : base(OpCode.DynamicSetMemberInstruction, binderFlags, context)
+ {
+ Name = name;
+ TargetArgumentInfo = targetArgumentInfo;
+ Target = target;
+ ValueArgumentInfo = valueArgumentInfo;
+ Value = value;
+ }
+
+ public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
+ {
+ ILRange.WriteTo(output, options);
+ output.Write(OpCode);
+ WriteBinderFlags(output, options);
+ output.Write(' ');
+ output.Write(Name);
+ output.Write('(');
+ Target.WriteTo(output, options);
+ output.Write(", ");
+ Value.WriteTo(output, options);
+ output.Write(')');
+ }
+
+ public override StackType ResultType => SpecialType.Dynamic.GetStackType();
+ }
+
+ partial class DynamicGetIndexInstruction
+ {
+ public IReadOnlyList ArgumentInfo { get; }
+
+ public DynamicGetIndexInstruction(CSharpBinderFlags binderFlags, IType context, CSharpArgumentInfo[] argumentInfo, ILInstruction[] arguments)
+ : base(OpCode.DynamicGetIndexInstruction, binderFlags, context)
+ {
+ ArgumentInfo = argumentInfo;
+ Arguments = new InstructionCollection(this, 0);
+ Arguments.AddRange(arguments);
+ }
+
+ public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
+ {
+ ILRange.WriteTo(output, options);
+ output.Write(OpCode);
+ WriteBinderFlags(output, options);
+ output.Write(' ');
+ output.Write("get_Item");
+ output.Write('(');
+ int j = 0;
+ foreach (var arg in Arguments) {
+ if (j > 0)
+ output.Write(", ");
+ arg.WriteTo(output, options);
+ j++;
+ }
+ output.Write(')');
+ }
+
+ public override StackType ResultType => SpecialType.Dynamic.GetStackType();
+ }
+
+ partial class DynamicSetIndexInstruction
+ {
+ public IReadOnlyList ArgumentInfo { get; }
+
+ public DynamicSetIndexInstruction(CSharpBinderFlags binderFlags, IType context, CSharpArgumentInfo[] argumentInfo, ILInstruction[] arguments)
+ : base(OpCode.DynamicSetIndexInstruction, binderFlags, context)
+ {
+ ArgumentInfo = argumentInfo;
+ Arguments = new InstructionCollection(this, 0);
+ Arguments.AddRange(arguments);
+ }
+
+ public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
+ {
+ ILRange.WriteTo(output, options);
+ output.Write(OpCode);
+ WriteBinderFlags(output, options);
+ output.Write(' ');
+ output.Write("set_Item");
+ output.Write('(');
+ int j = 0;
+ foreach (var arg in Arguments) {
+ if (j > 0)
+ output.Write(", ");
+ arg.WriteTo(output, options);
+ j++;
+ }
+ output.Write(')');
+ }
+
+ public override StackType ResultType => SpecialType.Dynamic.GetStackType();
+ }
+
+ partial class DynamicInvokeConstructorInstruction
+ {
+ public IReadOnlyList ArgumentInfo { get; }
+
+ public DynamicInvokeConstructorInstruction(CSharpBinderFlags binderFlags, IType context, CSharpArgumentInfo[] argumentInfo, ILInstruction[] arguments)
+ : base(OpCode.DynamicInvokeConstructorInstruction, binderFlags, context)
+ {
+ ArgumentInfo = argumentInfo;
+ Arguments = new InstructionCollection(this, 0);
+ Arguments.AddRange(arguments);
+ }
+
+ public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
+ {
+ ILRange.WriteTo(output, options);
+ output.Write(OpCode);
+ WriteBinderFlags(output, options);
+ output.Write(' ');
+ output.Write(".ctor");
+ output.Write('(');
+ int j = 0;
+ foreach (var arg in Arguments) {
+ if (j > 0)
+ output.Write(", ");
+ arg.WriteTo(output, options);
+ j++;
+ }
+ output.Write(')');
+ }
+
+ public override StackType ResultType => SpecialType.Dynamic.GetStackType();
+ }
+
+ partial class DynamicBinaryOperatorInstruction
+ {
+ public CSharpArgumentInfo LeftArgumentInfo { get; }
+ public CSharpArgumentInfo RightArgumentInfo { get; }
+ public ExpressionType Operation { get; }
+
+ public DynamicBinaryOperatorInstruction(CSharpBinderFlags binderFlags, ExpressionType operation, IType context, CSharpArgumentInfo leftArgumentInfo, ILInstruction left, CSharpArgumentInfo rightArgumentInfo, ILInstruction right)
+ : base(OpCode.DynamicBinaryOperatorInstruction, binderFlags, context)
+ {
+ Operation = operation;
+ LeftArgumentInfo = leftArgumentInfo;
+ Left = left;
+ RightArgumentInfo = rightArgumentInfo;
+ Right = right;
+ }
+
+ public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
+ {
+ ILRange.WriteTo(output, options);
+ output.Write(OpCode);
+ WriteBinderFlags(output, options);
+ output.Write(' ');
+ output.Write(Operation.ToString());
+ output.Write('(');
+ Left.WriteTo(output, options);
+ output.Write(", ");
+ Right.WriteTo(output, options);
+ output.Write(')');
+ }
+
+ public override StackType ResultType => SpecialType.Dynamic.GetStackType();
+ }
+
+ partial class DynamicUnaryOperatorInstruction
+ {
+ public CSharpArgumentInfo OperandArgumentInfo { get; }
+ public ExpressionType Operation { get; }
+
+ public DynamicUnaryOperatorInstruction(CSharpBinderFlags binderFlags, ExpressionType operation, IType context, CSharpArgumentInfo operandArgumentInfo, ILInstruction operand)
+ : base(OpCode.DynamicUnaryOperatorInstruction, binderFlags, context)
+ {
+ Operation = operation;
+ OperandArgumentInfo = operandArgumentInfo;
+ Operand = operand;
+ }
+
+ public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
+ {
+ ILRange.WriteTo(output, options);
+ output.Write(OpCode);
+ WriteBinderFlags(output, options);
+ output.Write(' ');
+ output.Write(Operation.ToString());
+ output.Write('(');
+ Operand.WriteTo(output, options);
+ output.Write(')');
+ }
+
+ public override StackType ResultType {
+ get {
+ switch (Operation) {
+ case ExpressionType.IsFalse:
+ case ExpressionType.IsTrue:
+ return StackType.I4; // bool
+ default:
+ return SpecialType.Dynamic.GetStackType();
+ }
+ }
+ }
+ }
+
+ partial class DynamicInvokeInstruction
+ {
+ public IReadOnlyList ArgumentInfo { get; }
+
+ public DynamicInvokeInstruction(CSharpBinderFlags binderFlags, IType context, CSharpArgumentInfo[] argumentInfo, ILInstruction[] arguments)
+ : base(OpCode.DynamicInvokeInstruction, binderFlags, context)
+ {
+ ArgumentInfo = argumentInfo;
+ Arguments = new InstructionCollection(this, 0);
+ Arguments.AddRange(arguments);
+ }
+
+ public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
+ {
+ ILRange.WriteTo(output, options);
+ output.Write(OpCode);
+ WriteBinderFlags(output, options);
+ output.Write(' ');
+ output.Write('(');
+ int j = 0;
+ foreach (var arg in Arguments) {
+ if (j > 0)
+ output.Write(", ");
+ arg.WriteTo(output, options);
+ j++;
+ }
+ output.Write(')');
+ }
+
+ public override StackType ResultType => SpecialType.Dynamic.GetStackType();
+ }
+
+ partial class DynamicIsEventInstruction
+ {
+ public string Name { get; }
+
+ public DynamicIsEventInstruction(CSharpBinderFlags binderFlags, string name, IType context, ILInstruction argument)
+ : base(OpCode.DynamicIsEventInstruction, binderFlags, context)
+ {
+ Name = name;
+ Argument = argument;
+ }
+
+ public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
+ {
+ ILRange.WriteTo(output, options);
+ output.Write(OpCode);
+ WriteBinderFlags(output, options);
+ output.Write(' ');
+ output.Write('(');
+ Argument.WriteTo(output, options);
+ output.Write(')');
+ }
+
+ public override StackType ResultType => StackType.I4;
+ }
+}
diff --git a/ICSharpCode.Decompiler/IL/Transforms/ExpressionTreeCast.cs b/ICSharpCode.Decompiler/IL/Instructions/ExpressionTreeCast.cs
similarity index 100%
rename from ICSharpCode.Decompiler/IL/Transforms/ExpressionTreeCast.cs
rename to ICSharpCode.Decompiler/IL/Instructions/ExpressionTreeCast.cs