blob: 94355c84da7686cdb2b3f04011101c129510aa84 [file] [log] [blame]
/**********************************************************************
* Copyright (c) 2007 IBM Corporation.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.ptp.pldt.mpi.analysis.analysis;
import java.util.ArrayList;
import java.util.List;
import java.util.Iterator;
import org.eclipse.cdt.core.dom.ast.*;
import org.eclipse.ptp.pldt.mpi.analysis.cdt.graphs.IBlock;
import org.eclipse.ptp.pldt.mpi.analysis.cdt.graphs.impl.Block;
import org.eclipse.ptp.pldt.mpi.analysis.cdt.graphs.impl.ControlFlowGraph;
public class MPIControlFlowGraph extends ControlFlowGraph{
/** a set of return statement flowing to the exit block */
protected List<IBlock> returnBlocks_;
private static final boolean traceOn = false;
public MPIControlFlowGraph(IASTStatement funcBody){
super(funcBody);
}
public List<IBlock> getReturnBlocks(){return returnBlocks_;}
protected void collectBlocks(){
entry_ = new MPIBlock();
exit_ = new MPIBlock();
MPIBlockCollector mbc = new MPIBlockCollector();
mbc.run();
}
class MPIBlockCollector extends ASTVisitor{
public void run(){
this.shouldVisitStatements = true;
this.shouldVisitDeclarations = true;
prog_.accept(this);
}
public int visit(IASTStatement stmt)
{
MPIBlock block;
if(stmt instanceof IASTBreakStatement){
block = new MPIBlock(stmt);
addBlock(block);
}
else if(stmt instanceof IASTCaseStatement){
block = new MPIBlock(stmt);
addBlock(block);
}
else if(stmt instanceof IASTCompoundStatement){
}
else if(stmt instanceof IASTContinueStatement){
block = new MPIBlock(stmt);
addBlock(block);
}
else if(stmt instanceof IASTDeclarationStatement){
block = new MPIBlock(stmt);
addBlock(block);
}
else if(stmt instanceof IASTDefaultStatement){
block = new MPIBlock(stmt);
addBlock(block);
}
else if(stmt instanceof IASTDoStatement){
IASTDoStatement doStmt = (IASTDoStatement)stmt;
block = new MPIBlock(doStmt.getCondition(), stmt);
addBlock(block);
IBlock exitjoin = new MPIBlock(null, stmt, Block.exit_join_type);
addBlock(exitjoin);
IBlock continuejoin = new MPIBlock(null, stmt, Block.continue_join_type);
addBlock(continuejoin);
}
else if(stmt instanceof IASTExpressionStatement){
block = new MPIBlock(stmt);
addBlock(block);
}
else if(stmt instanceof IASTForStatement){
IASTForStatement forStmt = (IASTForStatement)stmt;
/* The initialization is a statement, and will be added later */
block = new MPIBlock(forStmt.getConditionExpression(), stmt);
addBlock(block);
if(forStmt.getIterationExpression() != null){
block = new MPIBlock(forStmt.getIterationExpression(), stmt);
addBlock(block);
}
IBlock continuejoin = new MPIBlock(null, stmt, Block.continue_join_type);
addBlock(continuejoin);
IBlock exitjoin = new MPIBlock(null, stmt, Block.exit_join_type);
addBlock(exitjoin);
}
else if(stmt instanceof IASTGotoStatement){
block = new MPIBlock(stmt);
addBlock(block);
}
else if(stmt instanceof IASTIfStatement){
IASTIfStatement ifStmt = (IASTIfStatement)stmt;
block = new MPIBlock(ifStmt.getConditionExpression(), stmt);
addBlock(block);
IBlock join = new MPIBlock(null, stmt, Block.exit_join_type);
addBlock(join);
}
else if(stmt instanceof IASTLabelStatement){
IASTLabelStatement labelS = (IASTLabelStatement)stmt;
block = new MPIBlock(labelS.getName(), stmt, Block.label_type);
addBlock(block);
}
else if(stmt instanceof IASTNullStatement){
block = new MPIBlock(stmt);
addBlock(block);
}
else if(stmt instanceof IASTProblemStatement){
block = new MPIBlock(stmt);
addBlock(block);
}
else if(stmt instanceof IASTReturnStatement){
IASTReturnStatement rtStmt = (IASTReturnStatement)stmt;
block = new MPIBlock(rtStmt.getReturnValue(), stmt);
addBlock(block);
}
else if(stmt instanceof IASTSwitchStatement){
IASTSwitchStatement swStmt = (IASTSwitchStatement)stmt;
block = new MPIBlock(swStmt.getControllerExpression(), stmt);
addBlock(block);
IBlock join = new MPIBlock(null, stmt, Block.exit_join_type);
addBlock(join);
}
else if(stmt instanceof IASTWhileStatement){
IASTWhileStatement whStmt = (IASTWhileStatement)stmt;
block = new MPIBlock(whStmt.getCondition(), stmt);
addBlock(block);
IBlock join = new MPIBlock(null, stmt, Block.continue_join_type);
addBlock(join);
IBlock exitjoin = new MPIBlock(null, stmt, Block.exit_join_type);
addBlock(exitjoin);
}
return PROCESS_CONTINUE;
}
}
protected void otherOPs(){
returnBlocks_ = new ArrayList<IBlock>();
PhiFlowBuilder phi = new PhiFlowBuilder();
phi.run();
BreakContinueChecker bcc = new BreakContinueChecker();
bcc.run();
}
class PhiFlowBuilder extends FlowBuilder{
public void run(){
this.shouldVisitStatements = true;
this.shouldVisitDeclarations = true;
this.shouldVisitTranslationUnit = true;
this.shouldVisitExpressions = true;
prog_.accept(this);
}
public int visit(IASTStatement stmt){
if(stmt instanceof IASTBreakStatement){
if(traceOn) System.out.println("BreakStatement");
IASTNode parent = stmt.getParent();
List<IASTIfStatement> branches = new ArrayList<IASTIfStatement>();
while(true){
if(parent instanceof IASTDoStatement ||
parent instanceof IASTForStatement ||
parent instanceof IASTWhileStatement){
MPIBlock exitjoin = (MPIBlock)getBlock(null,
(IASTStatement)parent, Block.exit_join_type);
for(Iterator<IASTIfStatement> i = branches.iterator(); i.hasNext();){
IASTIfStatement ifstmt = i.next();
MPIBlock ifcondblock = (MPIBlock)getBlock(ifstmt.getConditionExpression(), ifstmt);
PhiEdge(ifcondblock, exitjoin);
}
MPIBlock loopcondblock = null;
if(parent instanceof IASTDoStatement){
IASTDoStatement doS = (IASTDoStatement)parent;
loopcondblock = (MPIBlock)getBlock(doS.getCondition(), doS);
} else if(parent instanceof IASTForStatement){
IASTForStatement forS = (IASTForStatement)parent;
loopcondblock = (MPIBlock)getBlock(forS.getConditionExpression(), forS);
} else if(parent instanceof IASTWhileStatement){
IASTWhileStatement whileS = (IASTWhileStatement)parent;
loopcondblock = (MPIBlock)getBlock(whileS.getCondition(), whileS);
}
PhiEdge(loopcondblock, exitjoin);
break;
}
else if(parent instanceof IASTSwitchStatement){
MPIBlock exitjoin = (MPIBlock)getBlock(null, (IASTStatement)parent,
Block.exit_join_type);
IASTSwitchStatement swStmt = (IASTSwitchStatement)parent;
MPIBlock swcond = (MPIBlock)getBlock(swStmt.getControllerExpression(),
(IASTStatement)parent);
PhiEdge(swcond, exitjoin);
break;
}
else if(parent instanceof IASTIfStatement){
branches.add((IASTIfStatement)parent);
parent = parent.getParent();
}
else{
parent = parent.getParent();
}
}
}
else if(stmt instanceof IASTCaseStatement ||
stmt instanceof IASTDefaultStatement){
if(traceOn) System.out.println("CaseStatement or DefaultStatement");
IASTNode parent = stmt.getParent();
while(true){
if(parent instanceof IASTSwitchStatement) break;
else parent = parent.getParent();
}
IASTSwitchStatement swStmt = (IASTSwitchStatement)parent;
MPIBlock swblock = (MPIBlock)getBlock(swStmt.getControllerExpression(),
(IASTStatement)parent);
MPIBlock caseblock = (MPIBlock)getBlock(stmt);
if(caseblock.getPreds().size() > 1){
/* Previous case without break joins here */
PhiEdge(swblock, caseblock);
}
}
else if(stmt instanceof IASTContinueStatement){
if(traceOn) System.out.println("ContinueStatement");
IASTNode parent = stmt.getParent();
List<IASTIfStatement> branches = new ArrayList<IASTIfStatement>();
while(true){
if(parent instanceof IASTDoStatement ||
parent instanceof IASTForStatement ||
parent instanceof IASTWhileStatement){
MPIBlock continuejoin = (MPIBlock)getBlock(null,
(IASTStatement)parent, Block.continue_join_type);
for(Iterator<IASTIfStatement> i = branches.iterator(); i.hasNext();){
IASTIfStatement ifS = i.next();
MPIBlock ifcondblock = (MPIBlock)getBlock(
ifS.getConditionExpression(), ifS);
PhiEdge(ifcondblock, continuejoin);
}
break;
}
else if(parent instanceof IASTIfStatement){
branches.add((IASTIfStatement)parent);
parent = parent.getParent();
}
else{
parent = parent.getParent();
}
}
}
else if(stmt instanceof IASTDoStatement){
if(traceOn) System.out.println("DoStatement");
IASTDoStatement doStmt = (IASTDoStatement)stmt;
MPIBlock cond = (MPIBlock)getBlock(doStmt.getCondition(), stmt);
if(doStmt.getBody() != null){
MPIBlock first = (MPIBlock)firstBlock(doStmt.getBody());
PhiEdge(cond, first);
}
}
else if(stmt instanceof IASTForStatement){
if(traceOn) System.out.println("ForStatement");
IASTForStatement forStmt = (IASTForStatement)stmt;
MPIBlock cond = (MPIBlock)getBlock(forStmt.getConditionExpression(), stmt);
PhiEdge(cond, cond);
}
else if(stmt instanceof IASTIfStatement){
if(traceOn) System.out.println("IfStatement");
IASTIfStatement ifStmt = (IASTIfStatement)stmt;
MPIBlock condb = (MPIBlock)getBlock(ifStmt.getConditionExpression(), stmt);
MPIBlock join = (MPIBlock)getBlock(null, stmt, Block.exit_join_type);
PhiEdge(condb, join);
}
else if(stmt instanceof IASTReturnStatement){
if(traceOn) System.out.println("ReturnStatement");
IASTReturnStatement rtStmt = (IASTReturnStatement)stmt;
MPIBlock rv = (MPIBlock)getBlock(rtStmt.getReturnValue(), stmt);
returnBlocks_.add(rv);
}
else if(stmt instanceof IASTWhileStatement){
if(traceOn) System.out.println("WhileStatement");
IASTWhileStatement whStmt = (IASTWhileStatement)stmt;
MPIBlock cond = (MPIBlock)getBlock(whStmt.getCondition(), stmt);
PhiEdge(cond, cond);
}
return PROCESS_CONTINUE;
}
protected void PhiEdge(MPIBlock from, MPIBlock to){
if(!to.getCond().contains(from))
to.getCond().add(from);
List<IBlock> joins = from.getJoin();
if(!joins.contains(to)){
joins.add(to);
//System.out.println("Phi edge is added from " + from.getID() + " to " + to.getID());
}
}
}
class BreakContinueChecker extends ASTVisitor{
public void run(){
this.shouldVisitStatements = true;
this.shouldVisitDeclarations = true;
prog_.accept(this);
}
public int visit(IASTStatement stmt){
if(stmt instanceof IASTBreakStatement ||
stmt instanceof IASTContinueStatement){
IASTNode parent = stmt.getParent();
while(parent != prog_){
if(parent instanceof IASTIfStatement){
break;
} else {
parent = parent.getParent();
}
}
if(!(parent instanceof IASTIfStatement))
return PROCESS_CONTINUE;
IASTIfStatement ifS = (IASTIfStatement)parent;
IASTExpression cond = ifS.getConditionExpression();
MPIBlock condBlock = (MPIBlock)getBlock(cond, ifS);
if(stmt instanceof IASTBreakStatement)
condBlock.withBreak = true;
else
condBlock.withContinue = true;
}
return PROCESS_CONTINUE;
}
}
public void print(){
for(IBlock b = entry_; b != null; b = b.topNext()){
MPIBlock block = (MPIBlock)b;
block.print();
}
}
}