Пример #1
0
        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);
            }
        }
Пример #2
0
        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);
            }
        }
Пример #3
0
        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;
        }