blob: 39c44ff73bc03101f030e1d3df61863b28126b26 [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.Iterator;
import java.util.List;
import java.util.Stack;
import org.eclipse.cdt.core.dom.ast.*;
import org.eclipse.ptp.pldt.mpi.analysis.analysis.BarrierTable.BarrierInfo;
import org.eclipse.ptp.pldt.mpi.analysis.cdt.graphs.ICallGraphNode;
import org.eclipse.ptp.pldt.mpi.analysis.cdt.graphs.impl.CallGraph;
public class MPICallGraph extends CallGraph{
/** Is the global variable pointer type? */
protected List<Boolean> gvPointer_;
protected BarrierTable btable_;
protected int count;
private static final boolean traceOn=false;
public MPICallGraph()
{
super();
btable_ = new BarrierTable();
count = 4; // 0-3 are types in BarrierExpression
gvPointer_ = new ArrayList<Boolean>();
}
public List<Boolean> getGVPointer(){return gvPointer_;}
public BarrierTable getBarrierTable(){return btable_;}
public void otherOP(){
//FunctionPointerChecker fpc = new FunctionPointerChecker();
//fpc.run();
FunctionMarker fm = new FunctionMarker();
fm.run();
checkBarrierRelatedCycles();
if(traceOn)System.out.println((btable_.commCounter + 1) + " communicators "); //$NON-NLS-1$
}
class FunctionPointerChecker extends ASTVisitor{
protected ICallGraphNode currentFunc_;
protected boolean funcPointer = false;
public boolean hasFuncPointer(){return funcPointer;}
public void run(){
this.shouldVisitDeclarations = true;
this.shouldVisitStatements = true;
this.shouldVisitExpressions = true;
for(Iterator<ICallGraphNode> i = nodes_.iterator(); i.hasNext();){
currentFunc_ = i.next();
currentFunc_.getFuncDef().accept(this);
}
}
protected Stack<String> funcCall = new Stack<String>();
public int visit(IASTExpression expr){
if(expr instanceof IASTFunctionCallExpression){
IASTFunctionCallExpression funcE = (IASTFunctionCallExpression)expr;
IASTExpression funcname = funcE.getFunctionNameExpression();
String signature = funcname.getRawSignature();
funcCall.push(signature);
}
else if(expr instanceof IASTIdExpression){
IASTIdExpression idE = (IASTIdExpression)expr;
String name = idE.getName().toString();
if(!funcCall.empty() && name.equals(funcCall.peek())){
funcCall.pop();
} else {
ICallGraphNode node = getNode(currentFunc_.getFileName(), name);
if(node != null){
funcPointer = true;
System.out.println("Function Pointer " + name + " in " + //$NON-NLS-1$ //$NON-NLS-2$
currentFunc_.getFuncName() + "(" + currentFunc_.getFileName() + ")"); //$NON-NLS-1$ //$NON-NLS-2$
}
}
}
return PROCESS_CONTINUE;
}
}
class FunctionMarker extends ASTVisitor{
protected MPICallGraphNode currentNode_ = null;
public void run()
{
this.shouldVisitExpressions = true;
this.shouldVisitStatements = true;
this.shouldVisitDeclarations = true;
for(Iterator<ICallGraphNode> i = nodes_.iterator(); i.hasNext();){
currentNode_ = (MPICallGraphNode)i.next();
//System.out.println(currentNode_.getFuncName());
currentNode_.getFuncDef().accept(this);
}
for(Iterator<ICallGraphNode> i = nodes_.iterator(); i.hasNext();){
currentNode_ = (MPICallGraphNode)i.next();
//System.out.println(currentNode_.getFuncName());
markBarrierRelated(currentNode_);
}
for(Iterator<ICallGraphNode> i = nodes_.iterator(); i.hasNext();){
currentNode_ = (MPICallGraphNode)i.next();
markMPIInit(currentNode_);
}
markFunction();
count = count -4;
}
public int visit(IASTExpression expression)
{
if (expression instanceof IASTFunctionCallExpression) {
IASTFunctionCallExpression funcExpr = (IASTFunctionCallExpression)expression;
IASTExpression funcname = funcExpr.getFunctionNameExpression();
String signature = funcname.getRawSignature();
if(signature.equals("MPI_Barrier")){ //$NON-NLS-1$
count ++;
BarrierInfo newbar = btable_.addBarrier(funcExpr, count,
currentNode_.getResource(), currentNode_.getFuncName());
currentNode_.setBarrierRelated(true);
currentNode_.getAllBarriers().add(newbar);
}
else if(signature.equals("MPI_Init")){ //$NON-NLS-1$
currentNode_.mpiInit = true;
}
}
return PROCESS_CONTINUE;
}
/* Functions that directly call barriers (MPI_Barrier()) and their
* ancestors are barrier-related
*/
protected void markBarrierRelated(MPICallGraphNode node){
if(node.barrierRelated()){
//System.out.println(node.getName());
for(Iterator<ICallGraphNode> ii = node.getCallers().iterator(); ii.hasNext();){
MPICallGraphNode caller = (MPICallGraphNode)ii.next();
if(!caller.barrierRelated()){
caller.setBarrierRelated(true);
markBarrierRelated(caller);
}
}
}
}
protected void markMPIInit(MPICallGraphNode node){
if(node.mpiInit){
for(Iterator<ICallGraphNode> ii = node.getCallers().iterator(); ii.hasNext();){
MPICallGraphNode caller = (MPICallGraphNode)ii.next();
if(!caller.mpiInit){
caller.mpiInit = true;
markMPIInit(caller);
}
}
}
}
/** A function is marked if:<br>
* (1) It is a barrier-related function<br>
* (2) It is called by (1)<br>
* (3) It is an MPI Initialization function (call MPI_Init)<br>
* (4) It is an ancestor of (3)<br>
* (5) It is called by (4)
*/
protected void markFunction(){
int total = nodes_.size();
int marked = 0;
for(ICallGraphNode node = topEntry_; node != null; node = node.topNext()){
currentNode_ = (MPICallGraphNode)node;
if(currentNode_.barrierRelated() || currentNode_.mpiInit){
currentNode_.marked = true;
marked ++;
}
}
boolean changed = true;
while(changed){
changed = false;
for(ICallGraphNode node = topEntry_; node != null; node = node.topNext()){
currentNode_ = (MPICallGraphNode)node;
if(currentNode_.marked){
for(Iterator<ICallGraphNode> i = currentNode_.getCallees().iterator(); i.hasNext();){
MPICallGraphNode callee = (MPICallGraphNode)i.next();
if(!callee.marked){
callee.marked = true;
marked ++;
changed = true;
}
}
}
}
}
if(traceOn)System.out.println(marked + " out of " + total + " functions are marked"); //$NON-NLS-1$ //$NON-NLS-2$
}
}
protected void checkBarrierRelatedCycles(){
for(Iterator<List<ICallGraphNode>> i=cycles_.iterator(); i.hasNext();){
List<ICallGraphNode> cycle = i.next();
boolean barrierRelated = false;
for(Iterator<ICallGraphNode> ii = cycle.iterator(); ii.hasNext();){
MPICallGraphNode node = (MPICallGraphNode)ii.next();
if(node.barrierRelated){
barrierRelated = true;
break;
}
}
if(!barrierRelated) continue;
String errorMsg = new String("Barrier related recursive function calls on: "); //$NON-NLS-1$
for(Iterator<ICallGraphNode> ii = cycle.iterator(); ii.hasNext();){
ICallGraphNode func = ii.next();
errorMsg = errorMsg + func.getFuncName() + "(" + func.getFileName() + "), "; //$NON-NLS-1$ //$NON-NLS-2$
}
System.out.println(errorMsg);
}
}
}