public override bool VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, object data) { bool result = base.VisitUnaryOperatorExpression(unaryOperatorExpression, data); if (unaryOperatorExpression.Operator == UnaryOperatorType.Dereference) { BinaryOperatorExpression bop = unaryOperatorExpression.Expression as BinaryOperatorExpression; if (bop != null && bop.Operator == BinaryOperatorType.Add && bop.Annotation <PointerArithmetic>() != null) { // transform "*(ptr + int)" to "ptr[int]" IndexerExpression indexer = new IndexerExpression(); indexer.Target = bop.Left.Detach(); indexer.Arguments.Add(bop.Right.Detach()); indexer.CopyAnnotationsFrom(unaryOperatorExpression); indexer.CopyAnnotationsFrom(bop); unaryOperatorExpression.ReplaceWith(indexer); } return(true); } else if (unaryOperatorExpression.Operator == UnaryOperatorType.AddressOf) { return(true); } else { return(result); } }
public override bool VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression) { bool result = base.VisitUnaryOperatorExpression(unaryOperatorExpression); if (unaryOperatorExpression.Operator == UnaryOperatorType.Dereference) { var bop = unaryOperatorExpression.Expression as BinaryOperatorExpression; if (bop != null && bop.Operator == BinaryOperatorType.Add && bop.GetResolveResult() is OperatorResolveResult orr && orr.Operands.FirstOrDefault()?.Type.Kind == TypeKind.Pointer) { // transform "*(ptr + int)" to "ptr[int]" IndexerExpression indexer = new IndexerExpression(); indexer.Target = bop.Left.Detach(); indexer.Arguments.Add(bop.Right.Detach()); indexer.CopyAnnotationsFrom(unaryOperatorExpression); indexer.CopyAnnotationsFrom(bop); unaryOperatorExpression.ReplaceWith(indexer); } return(true); } else if (unaryOperatorExpression.Operator == UnaryOperatorType.AddressOf) { return(true); } else { return(result); } }
void ProcessInvocationExpression(InvocationExpression invocationExpression) { var method = invocationExpression.GetSymbol() as IMethod; if (method == null) { return; } var arguments = invocationExpression.Arguments.ToArray(); // Reduce "String.Concat(a, b)" to "a + b" if (IsStringConcat(method) && CheckArgumentsForStringConcat(arguments)) { bool isInExpressionTree = invocationExpression.Ancestors.OfType <LambdaExpression>().Any( lambda => lambda.Annotation <IL.ILFunction>()?.Kind == IL.ILFunctionKind.ExpressionTree); Expression arg0 = arguments[0].Detach(); Expression arg1 = arguments[1].Detach(); if (!isInExpressionTree) { arg1 = RemoveRedundantToStringInConcat(arg1, method, isLastArgument: arguments.Length == 2).Detach(); if (arg1.GetResolveResult().Type.IsKnownType(KnownTypeCode.String)) { arg0 = RemoveRedundantToStringInConcat(arg0, method, isLastArgument: false).Detach(); } } var expr = new BinaryOperatorExpression(arg0, BinaryOperatorType.Add, arg1); for (int i = 2; i < arguments.Length; i++) { var arg = arguments[i].Detach(); if (!isInExpressionTree) { arg = RemoveRedundantToStringInConcat(arg, method, isLastArgument: i == arguments.Length - 1).Detach(); } expr = new BinaryOperatorExpression(expr, BinaryOperatorType.Add, arg); } expr.CopyAnnotationsFrom(invocationExpression); invocationExpression.ReplaceWith(expr); return; } switch (method.FullName) { case "System.Type.GetTypeFromHandle": if (arguments.Length == 1) { if (typeHandleOnTypeOfPattern.IsMatch(arguments[0])) { Expression target = ((MemberReferenceExpression)arguments[0]).Target; target.CopyInstructionsFrom(invocationExpression); invocationExpression.ReplaceWith(target); return; } } break; /* * case "System.Reflection.FieldInfo.GetFieldFromHandle": * // TODO : This is dead code because LdTokenAnnotation is not added anywhere: * if (arguments.Length == 1) { * MemberReferenceExpression mre = arguments[0] as MemberReferenceExpression; * if (mre != null && mre.MemberName == "FieldHandle" && mre.Target.Annotation<LdTokenAnnotation>() != null) { * invocationExpression.ReplaceWith(mre.Target); * return; * } * } else if (arguments.Length == 2) { * MemberReferenceExpression mre1 = arguments[0] as MemberReferenceExpression; * MemberReferenceExpression mre2 = arguments[1] as MemberReferenceExpression; * if (mre1 != null && mre1.MemberName == "FieldHandle" && mre1.Target.Annotation<LdTokenAnnotation>() != null) { * if (mre2 != null && mre2.MemberName == "TypeHandle" && mre2.Target is TypeOfExpression) { * Expression oldArg = ((InvocationExpression)mre1.Target).Arguments.Single(); * FieldReference field = oldArg.Annotation<FieldReference>(); * if (field != null) { * AstType declaringType = ((TypeOfExpression)mre2.Target).Type.Detach(); * oldArg.ReplaceWith(new MemberReferenceExpression(new TypeReferenceExpression(declaringType), field.Name).CopyAnnotationsFrom(oldArg)); * invocationExpression.ReplaceWith(mre1.Target); * return; * } * } * } * } * break; */ case "System.Activator.CreateInstance": if (arguments.Length == 0 && method.TypeArguments.Count == 1 && IsInstantiableTypeParameter(method.TypeArguments[0])) { invocationExpression.ReplaceWith(new ObjectCreateExpression(context.TypeSystemAstBuilder.ConvertType(method.TypeArguments.First()))); } break; case "System.Runtime.CompilerServices.RuntimeHelpers.GetSubArray": if (arguments.Length == 2 && context.Settings.Ranges) { var slicing = new IndexerExpression(arguments[0].Detach(), arguments[1].Detach()); slicing.CopyAnnotationsFrom(invocationExpression); invocationExpression.ReplaceWith(slicing); } break; } BinaryOperatorType?bop = GetBinaryOperatorTypeFromMetadataName(method.Name); if (bop != null && arguments.Length == 2) { invocationExpression.Arguments.Clear(); // detach arguments from invocationExpression invocationExpression.ReplaceWith( new BinaryOperatorExpression( arguments[0].UnwrapInDirectionExpression(), bop.Value, arguments[1].UnwrapInDirectionExpression() ).CopyAnnotationsFrom(invocationExpression) ); return; } UnaryOperatorType?uop = GetUnaryOperatorTypeFromMetadataName(method.Name); if (uop != null && arguments.Length == 1) { if (uop == UnaryOperatorType.Increment || uop == UnaryOperatorType.Decrement) { // `op_Increment(a)` is not equivalent to `++a`, // because it doesn't assign the incremented value to a. if (method.DeclaringType.IsKnownType(KnownTypeCode.Decimal)) { // Legacy csc optimizes "d + 1m" to "op_Increment(d)", // so reverse that optimization here: invocationExpression.ReplaceWith( new BinaryOperatorExpression( arguments[0].UnwrapInDirectionExpression().Detach(), (uop == UnaryOperatorType.Increment ? BinaryOperatorType.Add : BinaryOperatorType.Subtract), new PrimitiveExpression(1m) ).CopyAnnotationsFrom(invocationExpression) ); } return; } arguments[0].Remove(); // detach argument invocationExpression.ReplaceWith( new UnaryOperatorExpression(uop.Value, arguments[0].UnwrapInDirectionExpression()).CopyAnnotationsFrom(invocationExpression) ); return; } if (method.Name == "op_Explicit" && arguments.Length == 1) { arguments[0].Remove(); // detach argument invocationExpression.ReplaceWith( new CastExpression(context.TypeSystemAstBuilder.ConvertType(method.ReturnType), arguments[0].UnwrapInDirectionExpression()) .CopyAnnotationsFrom(invocationExpression) ); return; } if (method.Name == "op_True" && arguments.Length == 1 && invocationExpression.Role == Roles.Condition) { invocationExpression.ReplaceWith(arguments[0].UnwrapInDirectionExpression()); return; } return; }