/* This file is part of the db4o object database http://www.db4o.com
Copyright (C) 2004 - 2011 Versant Corporation http://www.versant.com
db4o is free software; you can redistribute it and/or modify it under
the terms of version 3 of the GNU General Public License as published
by the Free Software Foundation.
db4o is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License along
with this program. If not, see http://www.gnu.org/licenses/. */
package EDU.purdue.cs.bloat.ssa;
import java.util.*;
import EDU.purdue.cs.bloat.cfg.*;
import EDU.purdue.cs.bloat.tree.*;
/**
* A PhiReturnStmt is placed at the return site of a subroutine. This is
* necessary because variables that are not referrenced inside a subroutine
* (finally block) retain their value. This is a problem for SSA when a variable
* is assigned to inside an exception handler. At the beginning of the finally
* block, there would be a merge of two occurrences of the variable (one from
* the the exception handler and another from the "outside world") and a phi
* function should be placed accordingly. If the type of the variable was
* changed inside the exception handler, the operands of phi function would be
* of different types and that would be bad. To avoid this situation
* PhiReturnStmt are placed before the next instruction to be executed after the
* subroutine has returned. Note that each PhiReturnStmt has only one operand
* that is the same variable as its target. The two variables will have
* different version numbers, however.
* <p>
* The following diagram demonstrates PhiReturnStmt:
*
* <pre>
* a1 = 1 a2 = 2
* b1 = 1 b2 = 2
* jsr jsr
* \ /
* \ /
* \ /
* *
* a3 = PhiJoinStmt(a1, a2)
* b3 = PhiJoinStmt(b1, b2)
* |
* b4 = 4 // b is defined in subrountine
* |
* ret
* *
* / \
* / \
* / \
* / \
* a4 = PhiReturnStmt(a3) a5 = PhiReturnStmt(a3)
* b5 = PhiReturnStmt(b4) b6 = PhiReturnStmt(b4)
* </pre>
*
* After transformation, the PhiReturnStmts will become
*
* <pre>
* a1 a2
* b4 b4
* </pre>
*
* The variable <tt>a</tt> is not modified in the subroutine, so it retains
* its value from before the jsr. The variable <tt>b</tt> is modified in the
* subroutine, so its value after the ret is the value it was assigned in the
* subroutine.
*/
class PhiReturnStmt extends PhiStmt {
Subroutine sub;
Expr operand;
/**
* Constructor.
*
* @param target
* Local variable to which the result of this phi statement is to
* be assigned.
* @param sub
* The subroutine from which we are returning.
*/
public PhiReturnStmt(final VarExpr target, final Subroutine sub) {
super(target);
this.sub = sub;
this.operand = (VarExpr) target.clone();
operand.setParent(this);
operand.setDef(null);
}
public void visitForceChildren(final TreeVisitor visitor) {
operand.visit(visitor);
}
public void visit(final TreeVisitor visitor) {
visitChildren(visitor);
}
/**
* Returns the subroutine associated with this <tt>PhiReturnStmt</tt>.
*/
public Subroutine sub() {
return sub;
}
/**
* Returns a collection containing the operands to the phi statement. In
* this case the collection contains the one operand.
*/
public Collection operands() {
final ArrayList v = new ArrayList();
v.add(operand);
return v;
}
/**
* Returns the operand of this <tt>PhiReturnStmt</tt> statement. A
* <tt>PhiReturnStmt</tt> has only one operand because the block that
* begins an exception handler may have only one incoming edge (critical
* edges were split).
*/
public Expr operand() {
return operand;
}
public String toString() {
return "" + target() + " := Phi-Return(" + operand + ", " + sub + ")";
}
}