/// <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); } }
// 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); } } } }