| /********************************************************************** |
| * 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); |
| } |
| } |
| } |