Ejemplo n.º 1
0
        /// <summary>
        /// This handles the case MethodInvocationExpr(...).
        /// If the MethodInvocationExpr is appropriate for inlining then we inline it or if it is not appropriate
        /// we check if there is in the arguments something to be inlined.
        /// For example:
        /// <code> MethodInv1(somearg1, Inlinee(...), someargs...) </code>
        /// In that case we make the substitution:
        /// <code>
        /// sometype somevar = Inlinee(...);//here we inline the actual code of the method
        /// MethodInv1(somearg1, somevar, someargs...)
        /// </code>
        /// </summary>
        /// <param name="node">
        /// A <see cref="MethodInvocationExpression"/>
        /// </param>
        /// <returns>
        /// A <see cref="ICodeNode"/>
        /// </returns>
        public override ICodeNode VisitMethodInvocationExpression(MethodInvocationExpression node)
        {
            MethodReferenceExpression methodRef = (MethodReferenceExpression)node.Method;

            if (IsInlineable(methodRef.Method))
            {
                currentSideEffect.mInvokeNode = node;
                VariableReferenceExpression varRefExp = null;
                //Mono.Cecil 0.9.3 migration: if (methodRef.Method.ReturnType.ReturnType.FullName != "System.Void") {
                //Mono.Cecil 0.9.3 migration:   currentSideEffect.mInvokeNodeVar = RegisterVariable(methodRef.Method.ReturnType.ReturnType, source.Method);
                if (methodRef.Method.ReturnType.FullName != "System.Void")
                {
                    currentSideEffect.mInvokeNodeVar = RegisterVariable(methodRef.Method.ReturnType, source.Method);
                    varRefExp = new VariableReferenceExpression(currentSideEffect.mInvokeNodeVar);
                }
                sideEffects.Add(currentSideEffect);
                currentSideEffect = new SideEffectInfo();
                return(varRefExp);
            }
//      else if (HasSideEffects(methodRef.Method)) {
//        currentSideEffect.SideEffectsInNode.Add(node);
//        VariableDefinition @var = RegisterVariable(methodRef.Method.ReturnType.ReturnType, source.Method);
//        currentSideEffect.SideEffectsInNodeVar.Add(@var);
//        return new VariableReferenceExpression(@var);
//
//      }

            //node.Method = (Expression) Visit(node.Method);

            var argExpand = new CodeNodeCollection <Expression>();

            for (int i = 0; i < node.Arguments.Count; i++)
            {
                ICodeNode currentArgument = (ICodeNode)Visit(node.Arguments[i]);
                var       argAsCollection = currentArgument as CodeNodeCollection <Expression>;

                if (argAsCollection != null)
                {
                    for (int j = 0; j < argAsCollection.Count - 1; j++)
                    {
                        argExpand.Add(argAsCollection[j]);
                    }
                    node.Arguments[i] = argAsCollection[argAsCollection.Count - 1];
                }
            }
            if (argExpand.Count > 0)
            {
                argExpand.Add(node);
                return(argExpand);
            }
            else
            {
                return(node);
            }
        }
Ejemplo n.º 2
0
//    public override ICodeNode VisitAssignExpression(AssignExpression node)
//    {
//      CodeNodeCollection<Expression> collection = new CodeNodeCollection<Expression>();
//      collection.Add(node.Expression);
//      collection = (CodeNodeCollection<Expression>) Visit (collection);
//
//      if (collection.Count > 0 && collection[0].Equals(node.Expression)) {
//        return node;
//      }
//
//      node.Expression = collection[collection.Count - 1];
//      collection[collection.Count - 1] = node;
//      return collection;
//    }

        public override ICodeNode VisitExpressionStatement(ExpressionStatement node)
        {
            sideEffects.Clear();
            currentSideEffect = new SideEffectInfo();

            ICodeNode result = (ICodeNode)Visit(node.Expression);
            CodeNodeCollection <Expression> original = result as CodeNodeCollection <Expression>;

            if (original != null)
            {
                var collection = new CodeNodeCollection <Statement>();

                for (int i = 0; i < original.Count; i++)
                {
                    collection.Add(new ExpressionStatement(original[i]));
                }

                return((CodeNodeCollection <Statement>)Visit(collection));
            }
            else
            {
                node.Expression = (Expression)result;

                var assignExp = result as AssignExpression;
                if (assignExp != null)
                {
                    var mInvoke = assignExp.Expression as MethodInvocationExpression;
                    if (mInvoke != null && IsSimpleInlineCase(mInvoke))
                    {
                        return(InlineExpansion(mInvoke, assignExp.Target, source));
                    }
                    else
                    {
                        return(node);
                    }
                }
                else
                {
                    SideEffectInfo             row;
                    MethodInvocationExpression mInvoke;
                    MethodReferenceExpression  mRef;
                    var expansion = new CodeNodeCollection <Statement>();

                    for (int i = 0; i < sideEffects.Count; i++)
                    {
                        row = sideEffects[i];
                        VariableDefinition @var;

                        for (int j = 0; j < row.SideEffectsInNode.Count; j++)
                        {
                            mInvoke = row.SideEffectsInNode[j];
                            mRef    = mInvoke.Method as MethodReferenceExpression;
                            //Mono.Cecil 0.9.3 migration: if (mRef.Method.ReturnType.ReturnType.Name != "Void") {
                            if (mRef.Method.ReturnType.Name != "Void")
                            {
                                expansion.Add(new ExpressionStatement(new AssignExpression(
                                                                          new VariableReferenceExpression(row.SideEffectsInNodeVar[j]), mInvoke)));
                            }
                            else
                            {
                                expansion.Add(new ExpressionStatement(mInvoke));
                            }
                        }
                        mRef = row.mInvokeNode.Method as MethodReferenceExpression;
                        for (int j = 0; j < row.mInvokeNode.Arguments.Count; j++)
                        {
                            ParameterDefinition paramDef = mRef.Method.Parameters[j];

                            //enable constant folding
                            Expression arg = row.mInvokeNode.Arguments[j];
                            if (!(arg is ArgumentReferenceExpression || arg is VariableReferenceExpression ||
                                  arg is LiteralExpression))
                            {
                                @var = RegisterVariable(paramDef.ParameterType, source.Method);

                                expansion.Add(new ExpressionStatement(new AssignExpression(
                                                                          new VariableReferenceExpression(@var), arg)));
                                row.mInvokeNode.Arguments[j] = new VariableReferenceExpression(@var);
                            }
//              @var = RegisterVariable(paramDef.ParameterType, source.Method);

//              expansion.Add(new ExpressionStatement(new AssignExpression(
//                new VariableReferenceExpression(@var), row.mInvokeNode.Arguments[j])));
//              row.mInvokeNode.Arguments[j] = new VariableReferenceExpression(@var);
                        }

                        //TODO: Трябва да се оптимизира в случая когато има странични ефекти, а няма инлайн
                        //или има странични ефекти останали след последния инлайн.
                        for (int j = 0; j < currentSideEffect.SideEffectsInNode.Count; j++)
                        {
                            mInvoke = currentSideEffect.SideEffectsInNode[j];
                            mRef    = mInvoke.Method as MethodReferenceExpression;
                            expansion.Add(new ExpressionStatement(new AssignExpression(
                                                                      new VariableReferenceExpression(currentSideEffect.SideEffectsInNodeVar[j]), mInvoke)));
                        }
                        //endtodo.

                        mRef = row.mInvokeNode.Method as MethodReferenceExpression;

                        //Mono.Cecil 0.9.3 migration: if (mRef.Method.ReturnType.ReturnType.Name != "Void") {
                        if (mRef.Method.ReturnType.Name != "Void")
                        {
                            expansion.Add(new ExpressionStatement(new AssignExpression(
                                                                      new VariableReferenceExpression(row.mInvokeNodeVar), row.mInvokeNode)));
                        }
                        else
                        {
                            expansion.Add(new ExpressionStatement(row.mInvokeNode));
                        }
                    }

                    expansion.Add(node);

                    if (expansion.Count > 1)
                    {
                        return((CodeNodeCollection <Statement>)Visit(expansion));
                    }
                    else
                    {
                        return(node);
                    }
                }
            }
        }