Browse Source

Fix various bugs in ExpressionBuilder.VisitDynamic* + refactor DynamicInstructions a bit

pull/1165/head
Siegfried Pammer 8 years ago
parent
commit
904aa5269e
  1. 108
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  2. 4
      ICSharpCode.Decompiler/CSharp/Syntax/Expressions/AssignmentExpression.cs
  3. 44
      ICSharpCode.Decompiler/IL/Instructions.cs
  4. 28
      ICSharpCode.Decompiler/IL/Instructions.tt
  5. 4
      ICSharpCode.Decompiler/IL/Instructions/DynamicInstructions.cs

108
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -2349,7 +2349,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -2349,7 +2349,7 @@ namespace ICSharpCode.Decompiler.CSharp
protected internal override TranslatedExpression VisitDynamicGetIndexInstruction(DynamicGetIndexInstruction inst, TranslationContext context)
{
var target = TranslateDynamicTarget(inst.Arguments[0], inst.ArgumentInfo[0]);
var arguments = TranslateDynamicArguments(inst.Arguments.Skip(1), inst.ArgumentInfo.Skip(1));
var arguments = TranslateDynamicArguments(inst.Arguments.Skip(1), inst.ArgumentInfo.Skip(1)).ToList();
return new IndexerExpression(target, arguments.Select(a => a.Expression))
.WithILInstruction(inst)
.WithRR(new DynamicInvocationResolveResult(target.ResolveResult, DynamicInvocationType.Indexing, arguments.Select(a => a.ResolveResult).ToArray()));
@ -2360,14 +2360,14 @@ namespace ICSharpCode.Decompiler.CSharp @@ -2360,14 +2360,14 @@ namespace ICSharpCode.Decompiler.CSharp
var target = TranslateDynamicTarget(inst.Target, inst.TargetArgumentInfo);
return new MemberReferenceExpression(target, inst.Name)
.WithILInstruction(inst)
.WithRR(new ResolveResult(SpecialType.Dynamic));
.WithRR(new DynamicMemberResolveResult(target.ResolveResult, inst.Name));
}
protected internal override TranslatedExpression VisitDynamicInvokeConstructorInstruction(DynamicInvokeConstructorInstruction inst, TranslationContext context)
{
if (!(inst.ArgumentInfo[0].Flags.HasFlag(CSharpArgumentInfoFlags.IsStaticType) && IL.Transforms.TransformExpressionTrees.MatchGetTypeFromHandle(inst.Arguments[0], out var constructorType)))
throw new NotSupportedException();
var arguments = TranslateDynamicArguments(inst.Arguments.Skip(1), inst.ArgumentInfo.Skip(1));
if (!(inst.ArgumentInfo[0].HasFlag(CSharpArgumentInfoFlags.IsStaticType) && IL.Transforms.TransformExpressionTrees.MatchGetTypeFromHandle(inst.Arguments[0], out var constructorType)))
return ErrorExpression("Could not detect static type for DynamicInvokeConstructorInstruction");
var arguments = TranslateDynamicArguments(inst.Arguments.Skip(1), inst.ArgumentInfo.Skip(1)).ToList();
//var names = inst.ArgumentInfo.Skip(1).Select(a => a.Name).ToArray();
return new ObjectCreateExpression(ConvertType(constructorType), arguments.Select(a => a.Expression))
.WithILInstruction(inst).WithRR(new ResolveResult(constructorType));
@ -2376,7 +2376,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -2376,7 +2376,7 @@ namespace ICSharpCode.Decompiler.CSharp
protected internal override TranslatedExpression VisitDynamicInvokeMemberInstruction(DynamicInvokeMemberInstruction inst, TranslationContext context)
{
var target = TranslateDynamicTarget(inst.Arguments[0], inst.ArgumentInfo[0]);
var arguments = TranslateDynamicArguments(inst.Arguments.Skip(1), inst.ArgumentInfo.Skip(1));
var arguments = TranslateDynamicArguments(inst.Arguments.Skip(1), inst.ArgumentInfo.Skip(1)).ToList();
return new InvocationExpression(new MemberReferenceExpression(target, inst.Name, inst.TypeArguments.Select(ConvertType)), arguments.Select(a => a.Expression))
.WithILInstruction(inst)
.WithRR(new DynamicInvocationResolveResult(target.ResolveResult, DynamicInvocationType.Invocation, arguments.Select(a => a.ResolveResult).ToArray()));
@ -2385,7 +2385,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -2385,7 +2385,7 @@ namespace ICSharpCode.Decompiler.CSharp
protected internal override TranslatedExpression VisitDynamicInvokeInstruction(DynamicInvokeInstruction inst, TranslationContext context)
{
var target = TranslateDynamicTarget(inst.Arguments[0], inst.ArgumentInfo[0]);
var arguments = TranslateDynamicArguments(inst.Arguments.Skip(1), inst.ArgumentInfo.Skip(1));
var arguments = TranslateDynamicArguments(inst.Arguments.Skip(1), inst.ArgumentInfo.Skip(1)).ToList();
return new InvocationExpression(target, arguments.Select(a => a.Expression))
.WithILInstruction(inst)
.WithRR(new DynamicInvocationResolveResult(target.ResolveResult, DynamicInvocationType.Invocation, arguments.Select(a => a.ResolveResult).ToArray()));
@ -2393,43 +2393,57 @@ namespace ICSharpCode.Decompiler.CSharp @@ -2393,43 +2393,57 @@ namespace ICSharpCode.Decompiler.CSharp
TranslatedExpression TranslateDynamicTarget(ILInstruction inst, CSharpArgumentInfo argumentInfo)
{
Debug.Assert(!argumentInfo.Flags.HasFlag(CSharpArgumentInfoFlags.NamedArgument));
Debug.Assert(!argumentInfo.Flags.HasFlag(CSharpArgumentInfoFlags.IsOut));
Debug.Assert(!argumentInfo.Flags.HasFlag(CSharpArgumentInfoFlags.IsRef));
Debug.Assert(!argumentInfo.Flags.HasFlag(CSharpArgumentInfoFlags.Constant));
Debug.Assert(!argumentInfo.HasFlag(CSharpArgumentInfoFlags.NamedArgument));
Debug.Assert(!argumentInfo.HasFlag(CSharpArgumentInfoFlags.IsOut));
Debug.Assert(!argumentInfo.HasFlag(CSharpArgumentInfoFlags.Constant));
if (argumentInfo.Flags.HasFlag(CSharpArgumentInfoFlags.IsStaticType) && IL.Transforms.TransformExpressionTrees.MatchGetTypeFromHandle(inst, out var callTargetType))
if (argumentInfo.HasFlag(CSharpArgumentInfoFlags.IsStaticType) && IL.Transforms.TransformExpressionTrees.MatchGetTypeFromHandle(inst, out var callTargetType)) {
return new TypeReferenceExpression(ConvertType(callTargetType))
.WithoutILInstruction()
.WithRR(new TypeResolveResult(callTargetType));
}
IType targetType = SpecialType.Dynamic;
if (argumentInfo.Flags.HasFlag(CSharpArgumentInfoFlags.UseCompileTimeType))
if (argumentInfo.HasFlag(CSharpArgumentInfoFlags.UseCompileTimeType)) {
targetType = argumentInfo.CompileTimeType;
return Translate(inst, targetType).ConvertTo(targetType, this);
}
var translatedTarget = Translate(inst, targetType).ConvertTo(targetType, this);
if (argumentInfo.HasFlag(CSharpArgumentInfoFlags.IsRef) && translatedTarget.Expression is DirectionExpression) {
// (ref x).member => x.member
translatedTarget = translatedTarget.UnwrapChild(((DirectionExpression)translatedTarget).Expression);
}
return translatedTarget;
}
IEnumerable<TranslatedExpression> TranslateDynamicArguments(IEnumerable<ILInstruction> arguments, IEnumerable<CSharpArgumentInfo> argumentInfo)
{
foreach (var (argument, info) in arguments.Zip(argumentInfo))
foreach (var (argument, info) in arguments.Zip(argumentInfo)) {
yield return TranslateDynamicArgument(argument, info);
}
}
TranslatedExpression TranslateDynamicArgument(ILInstruction argument, CSharpArgumentInfo info)
{
Debug.Assert(!info.Flags.HasFlag(CSharpArgumentInfoFlags.IsStaticType));
Debug.Assert(!info.HasFlag(CSharpArgumentInfoFlags.IsStaticType));
IType typeHint = SpecialType.Dynamic;
if (info.Flags.HasFlag(CSharpArgumentInfoFlags.UseCompileTimeType)) {
if (info.HasFlag(CSharpArgumentInfoFlags.UseCompileTimeType)) {
typeHint = info.CompileTimeType;
}
var translatedExpression = Translate(argument, typeHint);
if (!(typeHint.Equals(SpecialType.Dynamic) && translatedExpression.Type.Equals(SpecialType.NullType)))
if (!(typeHint.Equals(SpecialType.Dynamic) && translatedExpression.Type.Equals(SpecialType.NullType))) {
translatedExpression = translatedExpression.ConvertTo(typeHint, this);
if (info.Flags.HasFlag(CSharpArgumentInfoFlags.IsOut)) {
}
if (info.HasFlag(CSharpArgumentInfoFlags.IsOut)) {
translatedExpression = ChangeDirectionExpressionToOut(translatedExpression);
}
if (info.Flags.HasFlag(CSharpArgumentInfoFlags.NamedArgument) && !string.IsNullOrWhiteSpace(info.Name))
if (info.HasFlag(CSharpArgumentInfoFlags.NamedArgument) && !string.IsNullOrWhiteSpace(info.Name)) {
translatedExpression = new TranslatedExpression(new NamedArgumentExpression(info.Name, translatedExpression.Expression));
}
return translatedExpression;
}
@ -2451,11 +2465,11 @@ namespace ICSharpCode.Decompiler.CSharp @@ -2451,11 +2465,11 @@ namespace ICSharpCode.Decompiler.CSharp
{
Debug.Assert(inst.Arguments.Count >= 3);
var target = TranslateDynamicTarget(inst.Arguments[0], inst.ArgumentInfo[0]);
var arguments = TranslateDynamicArguments(inst.Arguments.Skip(1), inst.ArgumentInfo.Skip(1));
var arguments = TranslateDynamicArguments(inst.Arguments.Skip(1), inst.ArgumentInfo.Skip(1)).ToList();
var value = new TranslatedExpression(arguments.Last());
var indexer = new IndexerExpression(target, arguments.Take(inst.Arguments.Count - 2).Select(a => a.Expression))
var indexer = new IndexerExpression(target, arguments.SkipLast(1).Select(a => a.Expression))
.WithoutILInstruction()
.WithRR(new DynamicInvocationResolveResult(target.ResolveResult, DynamicInvocationType.Indexing, arguments.Take(inst.Arguments.Count - 2).Select(a => a.ResolveResult).ToArray()));
.WithRR(new DynamicInvocationResolveResult(target.ResolveResult, DynamicInvocationType.Indexing, arguments.SkipLast(1).Select(a => a.ResolveResult).ToArray()));
return Assignment(indexer, value).WithILInstruction(inst);
}
@ -2465,7 +2479,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -2465,7 +2479,7 @@ namespace ICSharpCode.Decompiler.CSharp
var value = TranslateDynamicArgument(inst.Value, inst.ValueArgumentInfo);
var member = new MemberReferenceExpression(target, inst.Name)
.WithoutILInstruction()
.WithRR(new ResolveResult(SpecialType.Dynamic));
.WithRR(new DynamicMemberResolveResult(target.ResolveResult, inst.Name));
return Assignment(member, value).WithILInstruction(inst);
}
@ -2492,49 +2506,49 @@ namespace ICSharpCode.Decompiler.CSharp @@ -2492,49 +2506,49 @@ namespace ICSharpCode.Decompiler.CSharp
return CreateBinaryOperator(BinaryOperatorType.Multiply, isChecked: true);
case ExpressionType.Divide:
case ExpressionType.DivideAssign:
return CreateBinaryOperator(BinaryOperatorType.Divide, isChecked: false);
return CreateBinaryOperator(BinaryOperatorType.Divide);
case ExpressionType.Modulo:
case ExpressionType.ModuloAssign:
return CreateBinaryOperator(BinaryOperatorType.Modulus, isChecked: false);
return CreateBinaryOperator(BinaryOperatorType.Modulus);
case ExpressionType.Equal:
return CreateBinaryOperator(BinaryOperatorType.Equality, isChecked: false);
return CreateBinaryOperator(BinaryOperatorType.Equality);
case ExpressionType.NotEqual:
return CreateBinaryOperator(BinaryOperatorType.InEquality, isChecked: false);
return CreateBinaryOperator(BinaryOperatorType.InEquality);
case ExpressionType.LessThan:
return CreateBinaryOperator(BinaryOperatorType.LessThan, isChecked: false);
return CreateBinaryOperator(BinaryOperatorType.LessThan);
case ExpressionType.LessThanOrEqual:
return CreateBinaryOperator(BinaryOperatorType.LessThanOrEqual, isChecked: false);
return CreateBinaryOperator(BinaryOperatorType.LessThanOrEqual);
case ExpressionType.GreaterThan:
return CreateBinaryOperator(BinaryOperatorType.GreaterThan, isChecked: false);
return CreateBinaryOperator(BinaryOperatorType.GreaterThan);
case ExpressionType.GreaterThanOrEqual:
return CreateBinaryOperator(BinaryOperatorType.GreaterThanOrEqual, isChecked: false);
return CreateBinaryOperator(BinaryOperatorType.GreaterThanOrEqual);
case ExpressionType.And:
case ExpressionType.AndAssign:
return CreateBinaryOperator(BinaryOperatorType.BitwiseAnd, isChecked: false);
return CreateBinaryOperator(BinaryOperatorType.BitwiseAnd);
case ExpressionType.Or:
case ExpressionType.OrAssign:
return CreateBinaryOperator(BinaryOperatorType.BitwiseOr, isChecked: false);
return CreateBinaryOperator(BinaryOperatorType.BitwiseOr);
case ExpressionType.ExclusiveOr:
case ExpressionType.ExclusiveOrAssign:
return CreateBinaryOperator(BinaryOperatorType.ExclusiveOr, isChecked: false);
return CreateBinaryOperator(BinaryOperatorType.ExclusiveOr);
case ExpressionType.LeftShift:
case ExpressionType.LeftShiftAssign:
return CreateBinaryOperator(BinaryOperatorType.ShiftLeft, isChecked: false);
return CreateBinaryOperator(BinaryOperatorType.ShiftLeft);
case ExpressionType.RightShift:
case ExpressionType.RightShiftAssign:
return CreateBinaryOperator(BinaryOperatorType.ShiftRight, isChecked: false);
return CreateBinaryOperator(BinaryOperatorType.ShiftRight);
default:
return base.VisitDynamicBinaryOperatorInstruction(inst, context);
}
TranslatedExpression CreateBinaryOperator(BinaryOperatorType operatorType, bool isChecked)
TranslatedExpression CreateBinaryOperator(BinaryOperatorType operatorType, bool? isChecked = null)
{
var left = TranslateDynamicArgument(inst.Left, inst.LeftArgumentInfo);
var right = TranslateDynamicArgument(inst.Right, inst.RightArgumentInfo);
var boe = new BinaryOperatorExpression(left.Expression, operatorType, right.Expression);
if (isChecked)
if (isChecked == true)
boe.AddAnnotation(AddCheckedBlocks.CheckedAnnotation);
else
else if (isChecked == false)
boe.AddAnnotation(AddCheckedBlocks.UncheckedAnnotation);
return boe.WithILInstruction(inst).WithRR(new ResolveResult(SpecialType.Dynamic));
}
@ -2544,11 +2558,11 @@ namespace ICSharpCode.Decompiler.CSharp @@ -2544,11 +2558,11 @@ namespace ICSharpCode.Decompiler.CSharp
{
switch (inst.Operation) {
case ExpressionType.Not:
return CreateUnaryOperator(UnaryOperatorType.Not, isChecked: false);
return CreateUnaryOperator(UnaryOperatorType.Not);
case ExpressionType.Decrement:
return CreateUnaryOperator(UnaryOperatorType.Decrement, isChecked: false);
return CreateUnaryOperator(UnaryOperatorType.Decrement, isChecked: inst.BinderFlags.HasFlag(CSharpBinderFlags.CheckedContext));
case ExpressionType.Increment:
return CreateUnaryOperator(UnaryOperatorType.Increment, isChecked: false);
return CreateUnaryOperator(UnaryOperatorType.Increment, isChecked: inst.BinderFlags.HasFlag(CSharpBinderFlags.CheckedContext));
case ExpressionType.Negate:
return CreateUnaryOperator(UnaryOperatorType.Minus, isChecked: inst.BinderFlags.HasFlag(CSharpBinderFlags.CheckedContext));
case ExpressionType.NegateChecked:
@ -2577,13 +2591,13 @@ namespace ICSharpCode.Decompiler.CSharp @@ -2577,13 +2591,13 @@ namespace ICSharpCode.Decompiler.CSharp
return base.VisitDynamicUnaryOperatorInstruction(inst, context);
}
TranslatedExpression CreateUnaryOperator(UnaryOperatorType operatorType, bool isChecked)
TranslatedExpression CreateUnaryOperator(UnaryOperatorType operatorType, bool? isChecked = null)
{
var operand = TranslateDynamicArgument(inst.Operand, inst.OperandArgumentInfo);
var uoe = new UnaryOperatorExpression(operatorType, operand.Expression);
if (isChecked)
if (isChecked == true)
uoe.AddAnnotation(AddCheckedBlocks.CheckedAnnotation);
else
else if (isChecked == false)
uoe.AddAnnotation(AddCheckedBlocks.UncheckedAnnotation);
return uoe.WithILInstruction(inst).WithRR(new ResolveResult(SpecialType.Dynamic));
}
@ -2594,7 +2608,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -2594,7 +2608,7 @@ namespace ICSharpCode.Decompiler.CSharp
var target = TranslateDynamicArgument(inst.Target, inst.TargetArgumentInfo);
var value = TranslateDynamicArgument(inst.Value, inst.ValueArgumentInfo);
var ae = new AssignmentExpression(target, AssignmentExpression.GetAssignmentOperatorTypeFromExpressionType(inst.Operation), value);
var ae = new AssignmentExpression(target, AssignmentExpression.GetAssignmentOperatorTypeFromExpressionType(inst.Operation).Value, value);
if (inst.BinderFlags.HasFlag(CSharpBinderFlags.CheckedContext))
ae.AddAnnotation(AddCheckedBlocks.CheckedAnnotation);
else

4
ICSharpCode.Decompiler/CSharp/Syntax/Expressions/AssignmentExpression.cs

@ -203,7 +203,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -203,7 +203,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
}
}
public static AssignmentOperatorType GetAssignmentOperatorTypeFromExpressionType(ExpressionType expressionType)
public static AssignmentOperatorType? GetAssignmentOperatorTypeFromExpressionType(ExpressionType expressionType)
{
switch (expressionType) {
case ExpressionType.AddAssign:
@ -230,7 +230,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -230,7 +230,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
case ExpressionType.SubtractAssignChecked:
return AssignmentOperatorType.Subtract;
default:
throw new NotSupportedException($"ExpressionType.{expressionType} not supported!");
return null;
}
}
}

44
ICSharpCode.Decompiler/IL/Instructions.cs

@ -4910,11 +4910,11 @@ namespace ICSharpCode.Decompiler.IL @@ -4910,11 +4910,11 @@ namespace ICSharpCode.Decompiler.IL
}
protected override InstructionFlags ComputeFlags()
{
return base.ComputeFlags() | left.Flags | right.Flags;
return base.ComputeFlags() | InstructionFlags.MayThrow | InstructionFlags.SideEffect | left.Flags | right.Flags;
}
public override InstructionFlags DirectFlags {
get {
return base.DirectFlags;
return base.DirectFlags | InstructionFlags.MayThrow | InstructionFlags.SideEffect;
}
}
public override void AcceptVisitor(ILVisitor visitor)
@ -4990,11 +4990,11 @@ namespace ICSharpCode.Decompiler.IL @@ -4990,11 +4990,11 @@ namespace ICSharpCode.Decompiler.IL
}
protected override InstructionFlags ComputeFlags()
{
return base.ComputeFlags() | operand.Flags;
return base.ComputeFlags() | InstructionFlags.MayThrow | InstructionFlags.SideEffect | operand.Flags;
}
public override InstructionFlags DirectFlags {
get {
return base.DirectFlags;
return base.DirectFlags | InstructionFlags.MayThrow | InstructionFlags.SideEffect;
}
}
public override void AcceptVisitor(ILVisitor visitor)
@ -5076,11 +5076,11 @@ namespace ICSharpCode.Decompiler.IL @@ -5076,11 +5076,11 @@ namespace ICSharpCode.Decompiler.IL
}
protected override InstructionFlags ComputeFlags()
{
return base.ComputeFlags() | InstructionFlags.MayThrow | argument.Flags;
return base.ComputeFlags() | InstructionFlags.MayThrow | InstructionFlags.SideEffect | argument.Flags;
}
public override InstructionFlags DirectFlags {
get {
return base.DirectFlags | InstructionFlags.MayThrow;
return base.DirectFlags | InstructionFlags.MayThrow | InstructionFlags.SideEffect;
}
}
public override void AcceptVisitor(ILVisitor visitor)
@ -5161,11 +5161,11 @@ namespace ICSharpCode.Decompiler.IL @@ -5161,11 +5161,11 @@ namespace ICSharpCode.Decompiler.IL
}
protected override InstructionFlags ComputeFlags()
{
return base.ComputeFlags() | InstructionFlags.MayThrow | target.Flags;
return base.ComputeFlags() | InstructionFlags.MayThrow | InstructionFlags.SideEffect | target.Flags;
}
public override InstructionFlags DirectFlags {
get {
return base.DirectFlags | InstructionFlags.MayThrow;
return base.DirectFlags | InstructionFlags.MayThrow | InstructionFlags.SideEffect;
}
}
public override void AcceptVisitor(ILVisitor visitor)
@ -5263,11 +5263,11 @@ namespace ICSharpCode.Decompiler.IL @@ -5263,11 +5263,11 @@ namespace ICSharpCode.Decompiler.IL
}
protected override InstructionFlags ComputeFlags()
{
return base.ComputeFlags() | InstructionFlags.MayThrow | target.Flags | value.Flags;
return base.ComputeFlags() | InstructionFlags.MayThrow | InstructionFlags.SideEffect | target.Flags | value.Flags;
}
public override InstructionFlags DirectFlags {
get {
return base.DirectFlags | InstructionFlags.MayThrow;
return base.DirectFlags | InstructionFlags.MayThrow | InstructionFlags.SideEffect;
}
}
public override void AcceptVisitor(ILVisitor visitor)
@ -5336,11 +5336,11 @@ namespace ICSharpCode.Decompiler.IL @@ -5336,11 +5336,11 @@ namespace ICSharpCode.Decompiler.IL
}
protected override InstructionFlags ComputeFlags()
{
return base.ComputeFlags() | InstructionFlags.MayThrow | Arguments.Aggregate(InstructionFlags.None, (f, arg) => f | arg.Flags);
return base.ComputeFlags() | InstructionFlags.MayThrow | InstructionFlags.SideEffect | Arguments.Aggregate(InstructionFlags.None, (f, arg) => f | arg.Flags);
}
public override InstructionFlags DirectFlags {
get {
return base.DirectFlags | InstructionFlags.MayThrow;
return base.DirectFlags | InstructionFlags.MayThrow | InstructionFlags.SideEffect;
}
}
public override void AcceptVisitor(ILVisitor visitor)
@ -5404,11 +5404,11 @@ namespace ICSharpCode.Decompiler.IL @@ -5404,11 +5404,11 @@ namespace ICSharpCode.Decompiler.IL
}
protected override InstructionFlags ComputeFlags()
{
return base.ComputeFlags() | InstructionFlags.MayThrow | Arguments.Aggregate(InstructionFlags.None, (f, arg) => f | arg.Flags);
return base.ComputeFlags() | InstructionFlags.MayThrow | InstructionFlags.SideEffect | Arguments.Aggregate(InstructionFlags.None, (f, arg) => f | arg.Flags);
}
public override InstructionFlags DirectFlags {
get {
return base.DirectFlags | InstructionFlags.MayThrow;
return base.DirectFlags | InstructionFlags.MayThrow | InstructionFlags.SideEffect;
}
}
public override void AcceptVisitor(ILVisitor visitor)
@ -5472,11 +5472,11 @@ namespace ICSharpCode.Decompiler.IL @@ -5472,11 +5472,11 @@ namespace ICSharpCode.Decompiler.IL
}
protected override InstructionFlags ComputeFlags()
{
return base.ComputeFlags() | InstructionFlags.MayThrow | Arguments.Aggregate(InstructionFlags.None, (f, arg) => f | arg.Flags);
return base.ComputeFlags() | InstructionFlags.MayThrow | InstructionFlags.SideEffect | Arguments.Aggregate(InstructionFlags.None, (f, arg) => f | arg.Flags);
}
public override InstructionFlags DirectFlags {
get {
return base.DirectFlags | InstructionFlags.MayThrow;
return base.DirectFlags | InstructionFlags.MayThrow | InstructionFlags.SideEffect;
}
}
public override void AcceptVisitor(ILVisitor visitor)
@ -5540,11 +5540,11 @@ namespace ICSharpCode.Decompiler.IL @@ -5540,11 +5540,11 @@ namespace ICSharpCode.Decompiler.IL
}
protected override InstructionFlags ComputeFlags()
{
return base.ComputeFlags() | InstructionFlags.MayThrow | Arguments.Aggregate(InstructionFlags.None, (f, arg) => f | arg.Flags);
return base.ComputeFlags() | InstructionFlags.MayThrow | InstructionFlags.SideEffect | Arguments.Aggregate(InstructionFlags.None, (f, arg) => f | arg.Flags);
}
public override InstructionFlags DirectFlags {
get {
return base.DirectFlags | InstructionFlags.MayThrow;
return base.DirectFlags | InstructionFlags.MayThrow | InstructionFlags.SideEffect;
}
}
public override void AcceptVisitor(ILVisitor visitor)
@ -5608,11 +5608,11 @@ namespace ICSharpCode.Decompiler.IL @@ -5608,11 +5608,11 @@ namespace ICSharpCode.Decompiler.IL
}
protected override InstructionFlags ComputeFlags()
{
return base.ComputeFlags() | InstructionFlags.MayThrow | Arguments.Aggregate(InstructionFlags.None, (f, arg) => f | arg.Flags);
return base.ComputeFlags() | InstructionFlags.MayThrow | InstructionFlags.SideEffect | Arguments.Aggregate(InstructionFlags.None, (f, arg) => f | arg.Flags);
}
public override InstructionFlags DirectFlags {
get {
return base.DirectFlags | InstructionFlags.MayThrow;
return base.DirectFlags | InstructionFlags.MayThrow | InstructionFlags.SideEffect;
}
}
public override void AcceptVisitor(ILVisitor visitor)
@ -5688,11 +5688,11 @@ namespace ICSharpCode.Decompiler.IL @@ -5688,11 +5688,11 @@ namespace ICSharpCode.Decompiler.IL
}
protected override InstructionFlags ComputeFlags()
{
return base.ComputeFlags() | InstructionFlags.MayThrow | argument.Flags;
return base.ComputeFlags() | InstructionFlags.MayThrow | InstructionFlags.SideEffect | argument.Flags;
}
public override InstructionFlags DirectFlags {
get {
return base.DirectFlags | InstructionFlags.MayThrow;
return base.DirectFlags | InstructionFlags.MayThrow | InstructionFlags.SideEffect;
}
}
public override void AcceptVisitor(ILVisitor visitor)

28
ICSharpCode.Decompiler/IL/Instructions.tt

@ -84,8 +84,8 @@ @@ -84,8 +84,8 @@
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"),
CustomClassName("DynamicCompoundAssign"), BaseClass("CompoundAssignmentInstruction"),
MayThrow, SideEffect, CustomWriteTo, CustomConstructor, ResultType("O"),
MatchCondition("this.CompoundAssignmentType == o.CompoundAssignmentType"),
MatchCondition("Target.PerformMatch(o.Target, ref match)"),
MatchCondition("Value.PerformMatch(o.Value, ref match)")),
@ -280,27 +280,27 @@ @@ -280,27 +280,27 @@
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),
CustomClassName("DynamicBinaryOperatorInstruction"), Dynamic, CustomArguments(("left", null), ("right", null)), 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),
CustomClassName("DynamicUnaryOperatorInstruction"), Dynamic, CustomArguments(("operand", null)), 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),
CustomClassName("DynamicConvertInstruction"), Dynamic, HasTypeOperand, CustomArguments(("argument", new[] { "O" })), 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),
CustomClassName("DynamicGetMemberInstruction"), Dynamic, 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),
CustomClassName("DynamicSetMemberInstruction"), Dynamic, CustomArguments(("target", new[] { "O" }), ("value", null)), 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),
CustomClassName("DynamicGetIndexInstruction"), Dynamic, CustomChildren(new []{ new ArgumentInfo("arguments") { IsCollection = true }}), 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),
CustomClassName("DynamicSetIndexInstruction"), Dynamic, CustomChildren(new []{ new ArgumentInfo("arguments") { IsCollection = true }}), 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),
CustomClassName("DynamicInvokeMemberInstruction"), Dynamic, CustomChildren(new []{ new ArgumentInfo("arguments") { IsCollection = true }}), 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),
CustomClassName("DynamicInvokeConstructorInstruction"), Dynamic, CustomChildren(new []{ new ArgumentInfo("arguments") { IsCollection = true }}), 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),
CustomClassName("DynamicInvokeInstruction"), Dynamic, CustomChildren(new []{ new ArgumentInfo("arguments") { IsCollection = true }}), 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),
CustomClassName("DynamicIsEventInstruction"), Dynamic, CustomArguments(("argument", new[] { "O" })), CustomWriteTo),
new OpCode("mkrefany", "Push a typed reference of type class onto the stack.",
@ -1118,4 +1118,6 @@ protected override void Disconnected() @@ -1118,4 +1118,6 @@ protected override void Disconnected()
opCode.GenerateMatch = false;
opCode.GeneratePerformMatch = false;
};
static Action<OpCode> Dynamic = BaseClass("DynamicInstruction") + MayThrow + SideEffect + CustomConstructor;
#>

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

@ -57,6 +57,8 @@ namespace ICSharpCode.Decompiler.IL @@ -57,6 +57,8 @@ namespace ICSharpCode.Decompiler.IL
public string Name { get; set; }
public CSharpArgumentInfoFlags Flags { get; set; }
public IType CompileTimeType { get; set; }
public bool HasFlag(CSharpArgumentInfoFlags flag) => (Flags & flag) != 0;
}
partial class DynamicInstruction
@ -521,7 +523,7 @@ namespace ICSharpCode.Decompiler.IL @@ -521,7 +523,7 @@ namespace ICSharpCode.Decompiler.IL
public override CSharpArgumentInfo GetArgumentInfoOfChild(int index)
{
throw new ArgumentOutOfRangeException(nameof(index));
return default(CSharpArgumentInfo);
}
}
}

Loading…
Cancel
Save