blob: 65fdcf00fd5581168c63d5fc48cd32694a476cc6 [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);
}
}
}