All Downloads are FREE. Search and download functionalities are using the official Maven repository.

wyil.transform.MoveAnalysis Maven / Gradle / Ivy

// Copyright 2011 The Whiley Project Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package wyil.transform;

import static wyil.lang.WyilFile.*;

import wyil.lang.Compiler;
import wyil.lang.WyilFile;
import wyil.lang.WyilFile.Decl;
import wyil.lang.WyilFile.Expr;
import wyil.lang.WyilFile.Stmt;
import wyil.util.AbstractConsumer;

/**
 * 

* Responsible for determining when a value of a dynamically sized data type can * be "moved" or must be "copied". Moving is preferable (when permitted) because * then the original reference can be used without copying the underlying data * (hence, is significantly more efficient). The following provides a useful * example: *

* *
 * function g(int[] xs, int i) -> (int[] ys):
 *     xs[j] = f(xs)
 *     return xs
 * 
* *

* In the invocation f(xs) the array xs cannot be * moved since it is live afterwards. Instead, we must clone xs at * this point. However, the subsequent use of xs in the * return statement does not require a clone and can be moved * (since xs is no longer live). *

* *

* The following illustrates another situation where temporary moves or * "borrows" are permitted: *

* *
 * function get(int[] xs, int i, int j) -> (int r):
 *     int sum = xs[i]
 *     sum = sum + xs[j]
 *     return sum
 * 
* * Clearly, there is no need to clone xs when it is used in the * initialiser for sum. This is because the use is temporary and * does not modify xs. We say that xs is not * consumed. * * @author David J. Pearce * */ public class MoveAnalysis extends AbstractConsumer implements Compiler.Transform { @Override public void apply(WyilFile module) { visitModule(module, null); } // =========================================================================== // DECLARATIONS // =========================================================================== @Override public void visitExternalUnit(Decl.Unit unit, Boolean consumed) { // NOTE: we override this to prevent unnecessarily traversing statements } @Override public void visitType(Decl.Type t, Boolean consumed) { visitExpressions(t.getInvariant(), false); } @Override public void visitFunctionOrMethod(Decl.FunctionOrMethod fm, Boolean consumed) { visitExpressions(fm.getRequires(), false); visitExpressions(fm.getEnsures(), false); visitStatement((fm.getBody()), false); } @Override public void visitProperty(Decl.Property fm, Boolean consumed) { visitStatement((fm.getBody()), false); } @Override public void visitStaticVariable(Decl.StaticVariable stmt, Boolean consumed) { visitExpression(stmt.getInitialiser(), true); } // =========================================================================== // STATEMENTS // =========================================================================== @Override public void visitAssert(Stmt.Assert stmt, Boolean consumed) { visitExpression(stmt.getCondition(), false); } @Override public void visitAssign(Stmt.Assign stmt, Boolean consumed) { visitLVals(stmt.getLeftHandSide(), false); visitExpressions(stmt.getRightHandSide(), true); } @Override public void visitAssume(Stmt.Assume stmt, Boolean consumed) { visitExpression(stmt.getCondition(), false); } @Override public void visitDebug(Stmt.Debug stmt, Boolean consumed) { visitExpression(stmt.getOperand(), false); } @Override public void visitDoWhile(Stmt.DoWhile stmt, Boolean consumed) { visitStatement(stmt.getBody(), null); visitExpression(stmt.getCondition(), false); visitExpressions(stmt.getInvariant(), false); } @Override public void visitIfElse(Stmt.IfElse stmt, Boolean consumed) { visitExpression(stmt.getCondition(), false); visitStatement(stmt.getTrueBranch(), null); if (stmt.hasFalseBranch()) { visitStatement(stmt.getFalseBranch(), null); } } @Override public void visitInitialiser(Stmt.Initialiser stmt, Boolean consumed) { if(stmt.hasInitialiser()) { visitExpression(stmt.getInitialiser(), true); } } @Override public void visitReturn(Stmt.Return stmt, Boolean consumed) { if(stmt.hasReturn()) { visitExpression(stmt.getReturn(), true); } } @Override public void visitSwitch(Stmt.Switch stmt, Boolean consumed) { visitExpression(stmt.getCondition(), false); Tuple cases = stmt.getCases(); for (int i = 0; i != cases.size(); ++i) { visitCase(cases.get(i), null); } } @Override public void visitCase(Stmt.Case stmt, Boolean consume) { visitExpressions(stmt.getConditions(), false); visitStatement(stmt.getBlock(), null); } @Override public void visitWhile(Stmt.While stmt, Boolean consumed) { visitExpression(stmt.getCondition(), false); visitExpressions(stmt.getInvariant(), false); visitStatement(stmt.getBody(), null); } // =========================================================================== // GENERAL EXPRESSIONS // =========================================================================== @Override public void visitInvoke(Expr.Invoke expr, Boolean consumed) { visitExpressions(expr.getOperands(), true); } @Override public void visitIndirectInvoke(Expr.IndirectInvoke expr, Boolean consumed) { visitExpression(expr.getSource(), false); visitExpressions(expr.getArguments(), true); } @Override public void visitIs(Expr.Is expr, Boolean consumed) { visitExpression(expr.getOperand(), false); } @Override public void visitVariableAccess(Expr.VariableAccess expr, Boolean consumed) { if (!consumed) { // In this case, we have identified a variable access which is // not consumed and therefore can be implemented as a move. expr.setMove(); } } @Override public void visitStaticVariableAccess(Expr.StaticVariableAccess expr, Boolean consumed) { } @Override public void visitCast(Expr.Cast expr, Boolean consumed) { visitExpression(expr.getOperand(), false); } @Override public void visitConstant(Expr.Constant expr, Boolean consumed) { } @Override public void visitEqual(Expr.Equal expr, Boolean consumed) { visitExpression(expr.getFirstOperand(), false); visitExpression(expr.getSecondOperand(), false); } @Override public void visitNotEqual(Expr.NotEqual expr, Boolean consumed) { visitExpression(expr.getFirstOperand(), false); visitExpression(expr.getSecondOperand(), false); } // =========================================================================== // ARRAY EXPRESSIONS // =========================================================================== @Override public void visitArrayAccess(Expr.ArrayAccess expr, Boolean consumed) { visitExpression(expr.getFirstOperand(), false); visitExpression(expr.getSecondOperand(), false); if (!consumed) { expr.setMove(); } } @Override public void visitArrayLength(Expr.ArrayLength expr, Boolean consumed) { visitExpression(expr.getOperand(), false); } @Override public void visitArrayGenerator(Expr.ArrayGenerator expr, Boolean consumed) { // FIXME: am unsure about this one. visitExpression(expr.getFirstOperand(), false); visitExpression(expr.getSecondOperand(), false); } @Override public void visitArrayInitialiser(Expr.ArrayInitialiser expr, Boolean consumed) { visitExpressions(expr.getOperands(), true); } @Override public void visitArrayRange(Expr.ArrayRange expr, Boolean consumed) { visitExpression(expr.getFirstOperand(), false); visitExpression(expr.getSecondOperand(), false); } @Override public void visitArrayUpdate(Expr.ArrayUpdate expr, Boolean consumed) { visitExpression(expr.getFirstOperand(), false); visitExpression(expr.getSecondOperand(), false); visitExpression(expr.getThirdOperand(), true); } // =========================================================================== // BITWISE EXPRESSIONS // =========================================================================== @Override public void visitBitwiseComplement(Expr.BitwiseComplement expr, Boolean consumed) { visitExpression(expr.getOperand(), false); } @Override public void visitBitwiseAnd(Expr.BitwiseAnd expr, Boolean consumed) { visitExpressions(expr.getOperands(), false); } @Override public void visitBitwiseOr(Expr.BitwiseOr expr, Boolean consumed) { visitExpressions(expr.getOperands(), false); } @Override public void visitBitwiseXor(Expr.BitwiseXor expr, Boolean consumed) { visitExpressions(expr.getOperands(), false); } @Override public void visitBitwiseShiftLeft(Expr.BitwiseShiftLeft expr, Boolean consumed) { visitExpression(expr.getFirstOperand(), false); visitExpression(expr.getSecondOperand(), false); } @Override public void visitBitwiseShiftRight(Expr.BitwiseShiftRight expr, Boolean consumed) { visitExpression(expr.getFirstOperand(), false); visitExpression(expr.getSecondOperand(), false); } // =========================================================================== // INTEGER EXPRESSIONS // =========================================================================== @Override public void visitIntegerLessThan(Expr.IntegerLessThan expr, Boolean consumed) { visitExpression(expr.getFirstOperand(), false); visitExpression(expr.getSecondOperand(), false); } @Override public void visitIntegerLessThanOrEqual(Expr.IntegerLessThanOrEqual expr, Boolean consumed) { visitExpression(expr.getFirstOperand(), false); visitExpression(expr.getSecondOperand(), false); } @Override public void visitIntegerGreaterThan(Expr.IntegerGreaterThan expr, Boolean consumed) { visitExpression(expr.getFirstOperand(), false); visitExpression(expr.getSecondOperand(), false); } @Override public void visitIntegerGreaterThanOrEqual(Expr.IntegerGreaterThanOrEqual expr, Boolean consumed) { visitExpression(expr.getFirstOperand(), false); visitExpression(expr.getSecondOperand(), false); } @Override public void visitIntegerNegation(Expr.IntegerNegation expr, Boolean consumed) { visitExpression(expr.getOperand(), false); } @Override public void visitIntegerAddition(Expr.IntegerAddition expr, Boolean consumed) { visitExpression(expr.getFirstOperand(), false); visitExpression(expr.getSecondOperand(), false); } @Override public void visitIntegerSubtraction(Expr.IntegerSubtraction expr, Boolean consumed) { visitExpression(expr.getFirstOperand(), false); visitExpression(expr.getSecondOperand(), false); } @Override public void visitIntegerMultiplication(Expr.IntegerMultiplication expr, Boolean consumed) { visitExpression(expr.getFirstOperand(), false); visitExpression(expr.getSecondOperand(), false); } @Override public void visitIntegerDivision(Expr.IntegerDivision expr, Boolean consumed) { visitExpression(expr.getFirstOperand(), false); visitExpression(expr.getSecondOperand(), false); } @Override public void visitIntegerRemainder(Expr.IntegerRemainder expr, Boolean consumed) { visitExpression(expr.getFirstOperand(), false); visitExpression(expr.getSecondOperand(), false); } // =========================================================================== // LOGICAL EXPRESSIONS // =========================================================================== @Override public void visitLogicalAnd(Expr.LogicalAnd expr, Boolean consumed) { visitExpressions(expr.getOperands(), false); } @Override public void visitLogicalImplication(Expr.LogicalImplication expr, Boolean consumed) { visitExpression(expr.getFirstOperand(), false); visitExpression(expr.getSecondOperand(), false); } @Override public void visitLogicalIff(Expr.LogicalIff expr, Boolean consumed) { visitExpression(expr.getFirstOperand(), false); visitExpression(expr.getSecondOperand(), false); } @Override public void visitLogicalNot(Expr.LogicalNot expr, Boolean consumed) { visitExpression(expr.getOperand(), false); } @Override public void visitLogicalOr(Expr.LogicalOr expr, Boolean consumed) { visitExpressions(expr.getOperands(), false); } @Override public void visitUniversalQuantifier(Expr.UniversalQuantifier expr, Boolean consumed) { visitStaticVariables(expr.getParameters(), true); visitExpression(expr.getOperand(), false); } @Override public void visitExistentialQuantifier(Expr.ExistentialQuantifier expr, Boolean consumed) { visitStaticVariables(expr.getParameters(), true); visitExpression(expr.getOperand(), false); } // =========================================================================== // RECORD EXPRESSIONS // =========================================================================== @Override public void visitRecordAccess(Expr.RecordAccess expr, Boolean consumed) { visitExpression(expr.getOperand(), false); if (!consumed) { expr.setMove(); } } @Override public void visitRecordInitialiser(Expr.RecordInitialiser expr, Boolean consumed) { visitExpressions(expr.getOperands(), true); } @Override public void visitRecordUpdate(Expr.RecordUpdate expr, Boolean consumed) { visitExpression(expr.getFirstOperand(), false); visitExpression(expr.getSecondOperand(), true); } // =========================================================================== // REFERENCE EXPRESSIONS // =========================================================================== @Override public void visitDereference(Expr.Dereference expr, Boolean consumed) { visitExpression(expr.getOperand(), false); } @Override public void visitNew(Expr.New expr, Boolean consumed) { visitExpression(expr.getOperand(), true); } // =========================================================================== // TYPES // =========================================================================== @Override public void visitType(Type type, Boolean consumed) { // no need to visit types at all return; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy