Browse Source

Add ExpressionTreeCast instruction

pull/988/head
Siegfried Pammer 8 years ago
parent
commit
21dfa43dab
  1. 7
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  2. 1
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  3. 55
      ICSharpCode.Decompiler/IL/Instructions.cs
  4. 4
      ICSharpCode.Decompiler/IL/Instructions.tt
  5. 31
      ICSharpCode.Decompiler/IL/Transforms/ExpressionTreeCast.cs

7
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -1701,7 +1701,12 @@ namespace ICSharpCode.Decompiler.CSharp
{ {
return Translate(inst.Argument).ConvertTo(inst.Type, this); return Translate(inst.Argument).ConvertTo(inst.Type, this);
} }
protected internal override TranslatedExpression VisitExpressionTreeCast(ExpressionTreeCast inst, TranslationContext context)
{
return Translate(inst.Argument).ConvertTo(inst.Type, this, inst.IsChecked);
}
protected internal override TranslatedExpression VisitArglist(Arglist inst, TranslationContext context) protected internal override TranslatedExpression VisitArglist(Arglist inst, TranslationContext context)
{ {
return new UndocumentedExpression { UndocumentedExpressionType = UndocumentedExpressionType.ArgListAccess } return new UndocumentedExpression { UndocumentedExpressionType = UndocumentedExpressionType.ArgListAccess }

1
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -283,6 +283,7 @@
<Compile Include="IL\Instructions\CallIndirect.cs" /> <Compile Include="IL\Instructions\CallIndirect.cs" />
<Compile Include="IL\Instructions\DefaultValue.cs" /> <Compile Include="IL\Instructions\DefaultValue.cs" />
<Compile Include="IL\Transforms\EarlyExpressionTransforms.cs" /> <Compile Include="IL\Transforms\EarlyExpressionTransforms.cs" />
<Compile Include="IL\Transforms\ExpressionTreeCast.cs" />
<Compile Include="IL\Transforms\HighLevelLoopTransform.cs" /> <Compile Include="IL\Transforms\HighLevelLoopTransform.cs" />
<Compile Include="IL\Transforms\ProxyCallReplacer.cs" /> <Compile Include="IL\Transforms\ProxyCallReplacer.cs" />
<Compile Include="IL\Instructions\StringToInt.cs" /> <Compile Include="IL\Instructions\StringToInt.cs" />

55
ICSharpCode.Decompiler/IL/Instructions.cs

@ -168,6 +168,8 @@ namespace ICSharpCode.Decompiler.IL
ArrayToPointer, ArrayToPointer,
/// <summary>Maps a string value to an integer. This is used in switch(string).</summary> /// <summary>Maps a string value to an integer. This is used in switch(string).</summary>
StringToInt, StringToInt,
/// <summary>ILAst representation of Expression.Convert.</summary>
ExpressionTreeCast,
/// <summary>Push a typed reference of type class onto the stack.</summary> /// <summary>Push a typed reference of type class onto the stack.</summary>
MakeRefAny, MakeRefAny,
/// <summary>Push the type token stored in a typed reference.</summary> /// <summary>Push the type token stored in a typed reference.</summary>
@ -4493,6 +4495,46 @@ namespace ICSharpCode.Decompiler.IL
} }
} }
namespace ICSharpCode.Decompiler.IL namespace ICSharpCode.Decompiler.IL
{
/// <summary>ILAst representation of Expression.Convert.</summary>
public sealed partial class ExpressionTreeCast : UnaryInstruction
{
IType type;
/// <summary>Returns the type operand.</summary>
public IType Type {
get { return type; }
set { type = value; InvalidateFlags(); }
}
public override StackType ResultType { get { return type.GetStackType(); } }
protected override InstructionFlags ComputeFlags()
{
return base.ComputeFlags() | InstructionFlags.MayThrow;
}
public override InstructionFlags DirectFlags {
get {
return base.DirectFlags | InstructionFlags.MayThrow;
}
}
public override void AcceptVisitor(ILVisitor visitor)
{
visitor.VisitExpressionTreeCast(this);
}
public override T AcceptVisitor<T>(ILVisitor<T> visitor)
{
return visitor.VisitExpressionTreeCast(this);
}
public override T AcceptVisitor<C, T>(ILVisitor<C, T> visitor, C context)
{
return visitor.VisitExpressionTreeCast(this, context);
}
protected internal override bool PerformMatch(ILInstruction other, ref Patterns.Match match)
{
var o = other as ExpressionTreeCast;
return o != null && this.Argument.PerformMatch(o.Argument, ref match) && type.Equals(o.type) && this.IsChecked == o.IsChecked;
}
}
}
namespace ICSharpCode.Decompiler.IL
{ {
/// <summary>Push a typed reference of type class onto the stack.</summary> /// <summary>Push a typed reference of type class onto the stack.</summary>
public sealed partial class MakeRefAny : UnaryInstruction public sealed partial class MakeRefAny : UnaryInstruction
@ -5132,6 +5174,10 @@ namespace ICSharpCode.Decompiler.IL
{ {
Default(inst); Default(inst);
} }
protected internal virtual void VisitExpressionTreeCast(ExpressionTreeCast inst)
{
Default(inst);
}
protected internal virtual void VisitMakeRefAny(MakeRefAny inst) protected internal virtual void VisitMakeRefAny(MakeRefAny inst)
{ {
Default(inst); Default(inst);
@ -5434,6 +5480,10 @@ namespace ICSharpCode.Decompiler.IL
{ {
return Default(inst); return Default(inst);
} }
protected internal virtual T VisitExpressionTreeCast(ExpressionTreeCast inst)
{
return Default(inst);
}
protected internal virtual T VisitMakeRefAny(MakeRefAny inst) protected internal virtual T VisitMakeRefAny(MakeRefAny inst)
{ {
return Default(inst); return Default(inst);
@ -5736,6 +5786,10 @@ namespace ICSharpCode.Decompiler.IL
{ {
return Default(inst, context); return Default(inst, context);
} }
protected internal virtual T VisitExpressionTreeCast(ExpressionTreeCast inst, C context)
{
return Default(inst, context);
}
protected internal virtual T VisitMakeRefAny(MakeRefAny inst, C context) protected internal virtual T VisitMakeRefAny(MakeRefAny inst, C context)
{ {
return Default(inst, context); return Default(inst, context);
@ -5829,6 +5883,7 @@ namespace ICSharpCode.Decompiler.IL
"ldelema", "ldelema",
"array.to.pointer", "array.to.pointer",
"string.to.int", "string.to.int",
"expression.tree.cast",
"mkrefany", "mkrefany",
"refanytype", "refanytype",
"refanyval", "refanyval",

4
ICSharpCode.Decompiler/IL/Instructions.tt

@ -240,6 +240,10 @@
new OpCode("string.to.int", "Maps a string value to an integer. This is used in switch(string).", new OpCode("string.to.int", "Maps a string value to an integer. This is used in switch(string).",
CustomArguments("argument"), CustomConstructor, CustomWriteTo, ResultType("I4")), CustomArguments("argument"), CustomConstructor, CustomWriteTo, ResultType("I4")),
new OpCode("expression.tree.cast", "ILAst representation of Expression.Convert.",
CustomClassName("ExpressionTreeCast"), Unary, HasTypeOperand, MayThrow, CustomConstructor, CustomWriteTo, ResultType("type.GetStackType()"),
MatchCondition("this.IsChecked == o.IsChecked")),
new OpCode("mkrefany", "Push a typed reference of type class onto the stack.", new OpCode("mkrefany", "Push a typed reference of type class onto the stack.",
CustomClassName("MakeRefAny"), Unary, HasTypeOperand, ResultType("O")), CustomClassName("MakeRefAny"), Unary, HasTypeOperand, ResultType("O")),
new OpCode("refanytype", "Push the type token stored in a typed reference.", new OpCode("refanytype", "Push the type token stored in a typed reference.",

31
ICSharpCode.Decompiler/IL/Transforms/ExpressionTreeCast.cs

@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Text;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.Decompiler.IL
{
partial class ExpressionTreeCast
{
public bool IsChecked { get; set; }
public ExpressionTreeCast(IType type, ILInstruction argument, bool isChecked)
: base(OpCode.ExpressionTreeCast, argument)
{
this.Type = type;
this.IsChecked = isChecked;
}
public override void WriteTo(ITextOutput output, ILAstWritingOptions options)
{
ILRange.WriteTo(output, options);
output.Write(OpCode);
if (IsChecked) output.Write(".checked");
output.Write(' ');
type.WriteTo(output);
output.Write('(');
Argument.WriteTo(output, options);
output.Write(')');
}
}
}
Loading…
Cancel
Save