Browse Source

Add DynamicCompoundAssign instruction

pull/1165/head
Siegfried Pammer 7 years ago
parent
commit
0bb71f469d
  1. 89
      ICSharpCode.Decompiler/IL/Instructions.cs
  2. 6
      ICSharpCode.Decompiler/IL/Instructions.tt
  3. 68
      ICSharpCode.Decompiler/IL/Instructions/CompoundAssignmentInstruction.cs
  4. 4
      ICSharpCode.Decompiler/IL/Instructions/DynamicInstructions.cs

89
ICSharpCode.Decompiler/IL/Instructions.cs

@ -49,6 +49,8 @@ namespace ICSharpCode.Decompiler.IL
NumericCompoundAssign,
/// <summary>Common instruction for user-defined compound assignments.</summary>
UserDefinedCompoundAssign,
/// <summary>Common instruction for dynamic compound assignments.</summary>
DynamicCompoundAssign,
/// <summary>Bitwise NOT</summary>
BitNot,
/// <summary>Retrieves the RuntimeArgumentHandle.</summary>
@ -497,26 +499,6 @@ namespace ICSharpCode.Decompiler.IL
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Instruction representing a dynamic call site.</summary>
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
{
/// <summary>Base class for pattern matching in ILAst.</summary>
@ -619,6 +601,26 @@ namespace ICSharpCode.Decompiler.IL
}
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Instruction representing a dynamic call site.</summary>
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
{
/// <summary>Represents invalid IL. Semantically, this instruction is considered to throw some kind of exception.</summary>
public sealed partial class InvalidBranch : SimpleInstruction
@ -1089,6 +1091,40 @@ namespace ICSharpCode.Decompiler.IL
}
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Common instruction for dynamic compound assignments.</summary>
public sealed partial class DynamicCompoundAssign : CompoundAssignmentInstruction
{
public override StackType ResultType { get { return StackType.O; } }
protected override InstructionFlags ComputeFlags()
{
return base.ComputeFlags() | InstructionFlags.MayThrow | InstructionFlags.SideEffect;
}
public override InstructionFlags DirectFlags {
get {
return base.DirectFlags | InstructionFlags.MayThrow | InstructionFlags.SideEffect;
}
}
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitDynamicCompoundAssign(this);
}
public override T AcceptVisitor<T>(ILVisitor<T> visitor)
{
return visitor.VisitDynamicCompoundAssign(this);
}
public override T AcceptVisitor<C, T>(ILVisitor<C, T> visitor, C context)
{
return visitor.VisitDynamicCompoundAssign(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as DynamicCompoundAssign;
return o != null && this.CompoundAssignmentType == o.CompoundAssignmentType && Target.PerformMatch(o.Target, ref match) && Value.PerformMatch(o.Value, ref match);
}
}
}
namespace ICSharpCode.Decompiler.IL
{
/// <summary>Bitwise NOT</summary>
public sealed partial class BitNot : UnaryInstruction
@ -6091,6 +6127,10 @@ namespace ICSharpCode.Decompiler.IL
{
Default(inst);
}
protected internal virtual void VisitDynamicCompoundAssign(DynamicCompoundAssign inst)
{
Default(inst);
}
protected internal virtual void VisitBitNot(BitNot inst)
{
Default(inst);
@ -6457,6 +6497,10 @@ namespace ICSharpCode.Decompiler.IL
{
return Default(inst);
}
protected internal virtual T VisitDynamicCompoundAssign(DynamicCompoundAssign inst)
{
return Default(inst);
}
protected internal virtual T VisitBitNot(BitNot inst)
{
return Default(inst);
@ -6823,6 +6867,10 @@ namespace ICSharpCode.Decompiler.IL
{
return Default(inst, context);
}
protected internal virtual T VisitDynamicCompoundAssign(DynamicCompoundAssign inst, C context)
{
return Default(inst, context);
}
protected internal virtual T VisitBitNot(BitNot inst, C context)
{
return Default(inst, context);
@ -7154,6 +7202,7 @@ namespace ICSharpCode.Decompiler.IL
"binary",
"numeric.compound",
"user.compound",
"dynamic.compound",
"bit.not",
"arglist",
"br",

6
ICSharpCode.Decompiler/IL/Instructions.tt

@ -83,6 +83,12 @@
MatchCondition("this.CompoundAssignmentType == o.CompoundAssignmentType"),
MatchCondition("Target.PerformMatch(o.Target, ref match)"),
MatchCondition("Value.PerformMatch(o.Value, ref match)")),
new OpCode("dynamic.compound", "Common instruction for dynamic compound assignments.",
CustomClassName("DynamicCompoundAssign"), BaseClass("CompoundAssignmentInstruction"), CustomConstructor,
MayThrow, SideEffect, CustomWriteTo, ResultType("O"),
MatchCondition("this.CompoundAssignmentType == o.CompoundAssignmentType"),
MatchCondition("Target.PerformMatch(o.Target, ref match)"),
MatchCondition("Value.PerformMatch(o.Value, ref match)")),
new OpCode("bit.not", "Bitwise NOT", Unary, CustomConstructor, MatchCondition("IsLifted == o.IsLifted && UnderlyingResultType == o.UnderlyingResultType")),
new OpCode("arglist", "Retrieves the RuntimeArgumentHandle.", NoArguments, ResultType("O")),
new OpCode("br", "Unconditional branch. <c>goto target;</c>",

68
ICSharpCode.Decompiler/IL/Instructions/CompoundAssignmentInstruction.cs

@ -18,6 +18,7 @@
using System;
using System.Diagnostics;
using System.Linq.Expressions;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.Decompiler.IL
@ -212,6 +213,7 @@ namespace ICSharpCode.Decompiler.IL
{
ILRange.WriteTo(output, options);
output.Write(OpCode);
if (CompoundAssignmentType == CompoundAssignmentType.EvaluatesToNewValue)
output.Write(".new");
else
@ -225,6 +227,72 @@ namespace ICSharpCode.Decompiler.IL
output.Write(')');
}
}
public partial class DynamicCompoundAssign : CompoundAssignmentInstruction
{
public ExpressionType Operation { get; }
public CSharpArgumentInfo TargetArgumentInfo { get; }
public CSharpArgumentInfo ValueArgumentInfo { get; }
public DynamicCompoundAssign(ExpressionType op, ILInstruction target, CSharpArgumentInfo targetArgumentInfo, ILInstruction value, CSharpArgumentInfo valueArgumentInfo)
: base(OpCode.DynamicCompoundAssign, CompoundAssignmentTypeFromOperation(op), target, value)
{
if (!IsExpressionTypeSupported(op))
throw new ArgumentOutOfRangeException("op");
this.Operation = op;
this.TargetArgumentInfo = targetArgumentInfo;
this.ValueArgumentInfo = valueArgumentInfo;
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
{
ILRange.WriteTo(output, options);
output.Write(OpCode);
output.Write("." + Operation.ToString().ToLower());
if (CompoundAssignmentType == CompoundAssignmentType.EvaluatesToNewValue)
output.Write(".new");
else
output.Write(".old");
output.Write(' ');
output.Write('(');
this.Target.WriteTo(output, options);
output.Write(", ");
this.Value.WriteTo(output, options);
output.Write(')');
}
internal static bool IsExpressionTypeSupported(ExpressionType type)
{
return type == ExpressionType.AddAssign
|| type == ExpressionType.AddAssignChecked
|| type == ExpressionType.AndAssign
|| type == ExpressionType.DivideAssign
|| type == ExpressionType.ExclusiveOrAssign
|| type == ExpressionType.LeftShiftAssign
|| type == ExpressionType.ModuloAssign
|| type == ExpressionType.MultiplyAssign
|| type == ExpressionType.MultiplyAssignChecked
|| type == ExpressionType.OrAssign
|| type == ExpressionType.PostDecrementAssign
|| type == ExpressionType.PostIncrementAssign
|| type == ExpressionType.PreDecrementAssign
|| type == ExpressionType.PreIncrementAssign
|| type == ExpressionType.RightShiftAssign
|| type == ExpressionType.SubtractAssign
|| type == ExpressionType.SubtractAssignChecked;
}
static CompoundAssignmentType CompoundAssignmentTypeFromOperation(ExpressionType op)
{
switch (op) {
case ExpressionType.PostIncrementAssign:
case ExpressionType.PostDecrementAssign:
return CompoundAssignmentType.EvaluatesToOldValue;
default:
return CompoundAssignmentType.EvaluatesToNewValue;
}
}
}
}

4
ICSharpCode.Decompiler/IL/Instructions/DynamicInstructions.cs

@ -57,6 +57,7 @@ namespace ICSharpCode.Decompiler.IL
{
public string Name { get; set; }
public CSharpArgumentInfoFlags Flags { get; set; }
public IType CompileTimeType { get; set; }
}
partial class DynamicInstruction
@ -164,6 +165,9 @@ namespace ICSharpCode.Decompiler.IL
foreach (var arg in Arguments) {
if (j > 0)
output.Write(", ");
output.Write("[flags: ");
output.Write(ArgumentInfo[j].Flags.ToString());
output.Write(", name: " + ArgumentInfo[j].Name + "] ");
arg.WriteTo(output, options);
j++;
}

Loading…
Cancel
Save