Ejemplo n.º 1
0
            /// <summary>
            /// Replaces the return statements with goto in the end of the inlined method.
            /// </summary>
            /// <param name="node">
            /// A <see cref="ReturnStatement"/>
            /// </param>
            /// <returns>
            /// A <see cref="ICodeNode"/>
            /// </returns>
            public override ICodeNode VisitReturnStatement(ReturnStatement node)
            {
                GotoStatement @goto = new GotoStatement(exitLabel.Label);

                if (node.Expression != null)
                {
                    CodeNodeCollection <Statement> collection = new CodeNodeCollection <Statement>();
                    if (ReturnVariable != null)
                    {
                        collection.Add(new ExpressionStatement(
                                           new AssignExpression(new VariableReferenceExpression(ReturnVariable), node.Expression)));
                    }
                    else if (ReturnParameter != null)
                    {
                        collection.Add(new ExpressionStatement(
                                           new AssignExpression(new ArgumentReferenceExpression(ReturnParameter), node.Expression)));
                    }
                    else
                    {
                        collection.Add(new ExpressionStatement(node.Expression));
                    }
                    collection.Add(@goto);
                    return(Visit <CodeNodeCollection <Statement>, Statement>(collection));
                }

                return(@goto);
            }
Ejemplo n.º 2
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.º 3
0
        /// <summary>
        /// This handles the cases MethodInvocationExpr BinaryOp MethodInvocationExpr.
        /// For example:
        /// <code>MethodInv1(...) == MethodInv2(...)</code>
        /// We make the substitution
        /// <code>
        /// sometype1 somevar1 = MethodInv1(...);
        /// sometype2 somevar2 = MethodInv2(...);
        /// somevar1 == somevar2
        /// </code>
        /// </summary>
        /// <param name="node">
        /// A <see cref="BinaryExpression"/>
        /// </param>
        /// <returns>
        /// A <see cref="ICodeNode"/>
        /// </returns>
        public override ICodeNode VisitBinaryExpression(BinaryExpression node)
        {
            ICodeNode currentLeft  = (ICodeNode)Visit(node.Left);
            ICodeNode currentRight = (ICodeNode)Visit(node.Right);

            var argExpand = new CodeNodeCollection <Expression>();

            var argAsCollection = currentLeft as CodeNodeCollection <Expression>;

            if (argAsCollection != null)
            {
                for (int j = 0; j < argAsCollection.Count - 1; j++)
                {
                    argExpand.Add(argAsCollection[j]);
                }
                node.Left = argAsCollection[argAsCollection.Count - 1];
            }
            else
            {
                node.Left = (Expression)currentLeft;
            }

            argAsCollection = currentRight as CodeNodeCollection <Expression>;
            if (argAsCollection != null)
            {
                for (int j = 0; j < argAsCollection.Count - 1; j++)
                {
                    argExpand.Add(argAsCollection[j]);
                }
                node.Right = argAsCollection[argAsCollection.Count - 1];
            }
            else
            {
                node.Right = (Expression)currentRight;
            }

            if (argExpand.Count > 0)
            {
                argExpand.Add(node);
                return(argExpand);
            }
            else
            {
                return(node);
            }
        }
Ejemplo n.º 4
0
 protected override void FillScope(CodeNodeCollection nodes)
 {
     base.FillScope(nodes);
     nodes.AddIfNotExists(this.Name, this);
 }
Ejemplo n.º 5
0
        InlineExpansion(MethodInvocationExpression mInvoke, Expression target, AstMethodDefinition source)
        {
            ILtoASTTransformer  il2astTransformer = new ILtoASTTransformer();
            AstMethodDefinition ast;

            AstPreInsertFixer preFixer = new AstPreInsertFixer();

            MethodReferenceExpression mRef = mInvoke.Method as MethodReferenceExpression;

            MethodDefinition mDef = mRef.Method.Resolve();
            var result            = new CodeNodeCollection <Statement> ();
            ParameterDefinition paramDef;
            Expression          arg;

            ReturnVariable  = null;
            ReturnParameter = null;
            if (target == null)
            {
                //Mono.Cecil 0.9.3 migration: if (mDef.ReturnType.ReturnType.FullName != "System.Void") {
                //Mono.Cecil 0.9.3 migration:   ReturnVariable = RegisterVariable(mDef.ReturnType.ReturnType, source.Method);
                if (mDef.ReturnType.FullName != "System.Void")
                {
                    ReturnVariable = RegisterVariable(mDef.ReturnType, source.Method);
                }
            }
            else if (target is VariableReferenceExpression)
            {
                ReturnVariable = (target as VariableReferenceExpression).Variable;
            }
            else if (target is VariableDeclarationExpression)
            {
                //Mono.Cecil 0.9.3 migration: ReturnVariable = RegisterVariable(mDef.ReturnType.ReturnType, source.Method);
                ReturnVariable = RegisterVariable(mDef.ReturnType, source.Method);
            }
            else if (target is ArgumentReferenceExpression)
            {
                ReturnParameter = (target as ArgumentReferenceExpression).Parameter;
            }

            //заместване на this

            if (mRef.Target != null)
            {
                thisSubstitution = new VariableReferenceExpression(
                    //Mono.Cecil 0.9.3 migration: RegisterVariable(mDef.This.ParameterType, source.Method));
                    //new ParameterDefinition ("this", (ParameterAttributes) 0, null);
                    RegisterVariable(null, source.Method));
            }
            else
            {
                thisSubstitution = null;
            }

            for (int current = mInvoke.Arguments.Count - 1; current >= 0; current--)
            {
                arg      = mInvoke.Arguments[current];
                paramDef = mRef.Method.Parameters[current];
                paramVarSubstitution[paramDef] = arg;
            }

            //Ако вече е inline-вано
            if (mDef.Body.Variables.Count != 0 && (!localVarSubstitution.ContainsKey(mDef.Body.Variables[0])))
            {
                foreach (VariableDefinition variable in mDef.Body.Variables)
                {
                    localVarSubstitution[variable] = RegisterVariable(variable.VariableType, source.Method);
                }
            }

//      foreach (KeyValuePair<VariableDefinition, VariableDefinition> pair in localVarSubstitution) {
//        Console.WriteLine("!!! {0} -> {1}", pair.Key.Name, pair.Value.Name);
//      }

            ast = preFixer.FixUp(il2astTransformer.Decompile(mDef), paramVarSubstitution, thisSubstitution);


            //this
            if (thisSubstitution != null)
            {
                result.Add(new ExpressionStatement(new AssignExpression(thisSubstitution, mRef.Target)));
            }

            for (int i = 0; i < ast.Block.Statements.Count; i++)
            {
                result.Add(ast.CecilBlock.Statements[i]);
            }

            return(result);
        }
Ejemplo n.º 6
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);
                    }
                }
            }
        }