/* 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.tree;
import java.util.*;
import EDU.purdue.cs.bloat.cfg.*;
/**
* <tt>PhiJoinStmt</tt> represents a phi-function inserted into a control flow
* graph during conversion of variables to static single-assignment form. A
* <tt>PhiJoinStmt</tt> at a point of control flow convergence.
*
* @see EDU.purdue.cs.bloat.ssa.SSAConstructionInfo SSAConstructionInfo
*/
public class PhiJoinStmt extends PhiStmt {
Map operands; // Operands to a PhiStmt (mapping between a Block
// and a VarExpr occurring at that block)
Block block; // Basic block containing this PhiJoinStmt
/**
* Constructor.
*
* @param target
* The target of this PhiStmt.
* @param block
* The basic Block in which this PhiJoinStmt resides.
*/
public PhiJoinStmt(final VarExpr target, final Block block) {
super(target);
this.block = block;
this.operands = new HashMap();
final Iterator preds = block.graph().preds(block).iterator();
while (preds.hasNext()) {
final Block pred = (Block) preds.next();
final VarExpr operand = (VarExpr) target.clone();
operands.put(pred, operand);
operand.setParent(this);
operand.setDef(null);
}
}
/**
* Set the operand to this PhiJoinStmt for a given Block to a given
* expression.
*
* @param block
*
* @param expr
*
*/
public void setOperandAt(final Block block, final Expr expr) {
final Expr operand = (Expr) operands.get(block);
if (operand != null) {
operand.cleanup();
}
if (expr != null) {
operands.put(block, expr);
expr.setParent(this);
} else {
operands.remove(block);
}
}
/**
* Returns the occurrence of the variable with which this PhiJoinStmt is
* concerned (usually represented by a VarExpr) at a given block.
*
* @param block
* The block at which an occurrence of the variable occurs.
*
* @see VarExpr
*/
public Expr operandAt(final Block block) {
return (Expr) operands.get(block);
}
/**
* Returns the number of operands that this PhiJoinStmt has.
*/
public int numOperands() {
return block.graph().preds(block).size();
}
/**
* Returns the predacessor nodes (in the CFG not dominator graph) of the
* block in which this PhiJoinStmt occurs.
*/
public Collection preds() {
return block.graph().preds(block);
}
/**
* Returns the operands of this PhiJoinStmt. They are usually of type
* VarExpr.
*
* @see VarExpr
*/
public Collection operands() {
if (operands != null) {
operands.keySet().retainAll(preds());
return operands.values();
}
return new ArrayList();
}
public void visitForceChildren(final TreeVisitor visitor) {
if (visitor.reverse()) {
target.visit(visitor);
}
final Iterator e = operands().iterator();
while (e.hasNext()) {
final Expr operand = (Expr) e.next();
operand.visit(visitor);
}
if (!visitor.reverse()) {
target.visit(visitor);
}
}
public void visit(final TreeVisitor visitor) {
visitor.visitPhiJoinStmt(this);
}
}