| /********************************************************************** |
| * Copyright (c) 2006, 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.openmp.analysis.PAST; |
| |
| import java.util.Iterator; |
| import java.util.LinkedList; |
| |
| import org.eclipse.cdt.core.dom.ast.ASTVisitor; |
| import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement; |
| import org.eclipse.cdt.core.dom.ast.IASTFileLocation; |
| import org.eclipse.cdt.core.dom.ast.IASTForStatement; |
| import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; |
| import org.eclipse.cdt.core.dom.ast.IASTNode; |
| import org.eclipse.cdt.core.dom.ast.IASTStatement; |
| import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; |
| import org.eclipse.cdt.core.dom.ast.IScope; |
| import org.eclipse.cdt.core.parser.IToken; |
| import org.eclipse.cdt.internal.core.dom.parser.ASTInternal; |
| import org.eclipse.cdt.internal.core.dom.parser.ASTNode; |
| import org.eclipse.cdt.internal.core.dom.parser.c.CScope; |
| import org.eclipse.cdt.internal.core.dom.parser.cpp.CPPScope; |
| import org.eclipse.jface.text.IDocument; |
| import org.eclipse.ptp.pldt.common.util.Utility; |
| import org.eclipse.ptp.pldt.openmp.analysis.OpenMPError; |
| import org.eclipse.ptp.pldt.openmp.analysis.OpenMPErrorManager; |
| import org.eclipse.ptp.pldt.openmp.analysis.dictionary.Dictionary; |
| import org.eclipse.ptp.pldt.openmp.analysis.dictionary.Symbol; |
| import org.eclipse.ptp.pldt.openmp.analysis.parser.OpenMPScanner; |
| import org.eclipse.ptp.pldt.openmp.analysis.parser.OpenMPToken; |
| |
| /** |
| * Factory to convert PASTPragma-->PASTOMPPragma |
| * @author pazel |
| * |
| */ |
| public class PASTOMPFactory |
| { |
| protected PASTPragma pragma_ = null; |
| protected PASTOMPPragma ompPragma_ = null; |
| protected IASTTranslationUnit ast_ = null; |
| protected Dictionary dictionary_ = null; |
| |
| protected static boolean traceOn_ = false; |
| private static final boolean traceOn=false; |
| |
| protected OpenMPScanner scanner_ = null; |
| protected OpenMPToken token_ = null; |
| |
| //protected ScannerCallbackManager callbackManager_ = null; |
| |
| /** |
| * Factory used only by this class |
| * @param pragma - PASTPragma |
| */ |
| protected PASTOMPFactory(PASTPragma pragma, |
| IASTTranslationUnit ast, |
| Dictionary dictionary) |
| { |
| pragma_ = pragma; |
| scanner_ = new OpenMPScanner(pragma_.getContent()); |
| ast_ = ast; |
| dictionary_ = dictionary; |
| |
| //experiment(); |
| |
| if (traceOn_) |
| readTokens(); |
| |
| //otherinit(null); |
| } |
| |
| private void experiment() |
| { |
| IASTFileLocation loc = pragma_.getFileLocation(); |
| if (loc!=null) { |
| IDocument document = Utility.getDocument(loc.getFileName()); |
| if (document != null) { |
| try { |
| String txt = document.get(pragma_.getLocalOffset(), pragma_.getLength()); |
| System.out.println(txt); |
| } |
| catch(Exception e) {} |
| } |
| } |
| } |
| |
| |
| /** |
| * Return either omp or non-omp pragma |
| * @return |
| */ |
| protected PASTPragma retrievePragma() |
| { |
| return (ompPragma_!=null ? ompPragma_ : pragma_); |
| } |
| |
| /** |
| * Factory for making the PASTOMPPragma structure |
| * if possible |
| * @param pragma : PASTPragma |
| * @param ast : IASTTranslationUnit |
| * @param dictionary : Dictionary |
| * @return: PASTPragma (or PASTOMPPragma if do-able) |
| */ |
| public static PASTPragma makePASTOMP(PASTPragma pragma, |
| IASTTranslationUnit ast, |
| Dictionary dictionary) |
| { |
| PASTOMPFactory factory = new PASTOMPFactory(pragma, ast, dictionary); |
| factory.parse(); |
| factory.locateRegion(); |
| return factory.retrievePragma(); |
| } |
| |
| /** |
| * Parse the pragma context for OMP |
| * @return boolean |
| */ |
| protected boolean parse() |
| { |
| // The first two tokens should be # and pragma |
| OpenMPToken tok=nextToken(); |
| if(tok==null){ |
| if(traceOn)System.out.println("PASTOMPFactory.parser()..null token, ignored."); |
| return false; //robustly handle empty tokens |
| } |
| if (tok.getType()!=OpenMPScanner.mpPound) return false; |
| tok=nextToken(); |
| if (tok.getType()!=OpenMPScanner.mpPragma) return false; |
| |
| // if next is not omp - this is not an openmp directive |
| if (nextToken().getType()!=OpenMPScanner.mpOmp) |
| return false; |
| |
| // Construct the OpenMP pragma |
| ompPragma_ = new PASTOMPPragma(pragma_); |
| |
| // The next token sets the type |
| nextToken(); |
| OpenMPToken typeToken = token_; // determines type, used for error message |
| if (token_==null) return false; |
| ompPragma_.setOMPType(setOMPType(token_.getType())); |
| |
| if (token_==null) return false; |
| |
| switch(ompPragma_.getOMPType()) { |
| case PASTOMPPragma.OmpParallel: |
| completeParallel(); |
| break; |
| case PASTOMPPragma.OmpFor: |
| completeFor(); |
| break; |
| case PASTOMPPragma.OmpParallelFor: |
| completeParallelFor(); |
| break; |
| case PASTOMPPragma.OmpSections: |
| completeSections(); |
| break; |
| case PASTOMPPragma.OmpParallelSections: |
| completeParallelSections(); |
| break; |
| case PASTOMPPragma.OmpSingle: |
| completeSingle(); |
| break; |
| case PASTOMPPragma.OmpMaster: |
| break; |
| case PASTOMPPragma.OmpCritical: |
| break; |
| case PASTOMPPragma.OmpBarrier: |
| break; |
| case PASTOMPPragma.OmpAtomic: |
| break; |
| case PASTOMPPragma.OmpSection: |
| break; |
| case PASTOMPPragma.OmpFlush: |
| completeFlush(); |
| break; |
| case PASTOMPPragma.OmpOrdered: |
| break; |
| case PASTOMPPragma.OmpThreadPrivate: |
| completeThreadPrivate(); |
| break; |
| case PASTOMPPragma.OmpUnknown: |
| String typeString = (typeToken!=null ? typeToken.getImage(): ""); |
| handleProblem("Unexpected token '"+typeString+"'", OpenMPError.ERROR); |
| break; |
| } |
| |
| // all remaining tokens are bogus |
| while(token_!=null) { |
| handleProblem("Unexpected token '"+token_.getImage()+"'", OpenMPError.ERROR); |
| nextToken(); |
| } |
| |
| return true; |
| } |
| |
| /** |
| * Set the type of OpenMP statement based on keyword |
| * @param t |
| * @return |
| * Note: always exit with the current token being the next to process, i.e. |
| * call nextToken() |
| */ |
| protected int setOMPType(int t) |
| { |
| nextToken(); // advance to next token |
| switch(t) { |
| case OpenMPScanner.mpParallel: |
| if (token_==null) return PASTOMPPragma.OmpParallel; |
| if (token_.getType()==OpenMPScanner.mpFor) { |
| nextToken(); return PASTOMPPragma.OmpParallelFor; |
| } |
| else if (token_.getType()==OpenMPScanner.mpSections) { |
| nextToken(); return PASTOMPPragma.OmpParallelSections; |
| } |
| return PASTOMPPragma.OmpParallel; |
| case OpenMPScanner.mpFor: |
| return PASTOMPPragma.OmpFor; |
| case OpenMPScanner.mpSections: |
| return PASTOMPPragma.OmpSections; |
| case OpenMPScanner.mpSection: |
| return PASTOMPPragma.OmpSection; |
| case OpenMPScanner.mpSingle: |
| return PASTOMPPragma.OmpSingle; |
| case OpenMPScanner.mpMaster: |
| return PASTOMPPragma.OmpMaster; |
| case OpenMPScanner.mpCritical: |
| return PASTOMPPragma.OmpCritical; |
| case OpenMPScanner.mpBarrier: |
| return PASTOMPPragma.OmpBarrier; |
| case OpenMPScanner.mpAtomic: |
| return PASTOMPPragma.OmpAtomic; |
| case OpenMPScanner.mpFlush: |
| return PASTOMPPragma.OmpFlush; |
| case OpenMPScanner.mpOrdered: |
| return PASTOMPPragma.OmpOrdered; |
| case OpenMPScanner.mpThreadPrivate: |
| return PASTOMPPragma.OmpThreadPrivate; |
| } |
| return PASTOMPPragma.OmpUnknown; |
| } |
| |
| /** |
| * Parse a list of identifiers, e.g. as from shared(...) |
| * @return OpenMPToken [] |
| */ |
| protected OpenMPToken [] getIdentifierList() |
| { |
| LinkedList l = new LinkedList(); |
| |
| if (token_==null) return null; |
| //if (token_.getType()!=IToken.tLPAREN) return null; |
| |
| // look for lists like a,b,c |
| boolean commaNext = false; |
| nextToken(); |
| while(token_!=null) { |
| if (commaNext) { |
| if (token_.getType()!=IToken.tCOMMA) break; |
| else { commaNext=false; nextToken(); continue; } |
| } |
| // whatever it is, add to the list |
| l.add(token_); |
| commaNext=true; |
| nextToken(); |
| } |
| |
| // build the list |
| OpenMPToken [] ompl = new OpenMPToken[l.size()]; |
| int count=0; |
| for(Iterator i = l.iterator(); i.hasNext();) { |
| ompl[count++] = (OpenMPToken)i.next(); |
| // check to see if in dictionary |
| Symbol [] symbols = dictionary_.getSymbolsFor(ompl[count-1].getImage()); |
| if (symbols.length==0) { |
| handleProblem("Undefined symbol '"+ompl[count-1].getImage()+"'", OpenMPError.ERROR); |
| } |
| else { |
| // try to find at least one (non-global that is in same scope as pragma |
| boolean found=false; |
| for(int j=0; j<symbols.length; j++) { |
| IASTNode fctn = symbols[j].getDefiningFunction(); |
| if (fctn==null || !(fctn instanceof IASTFunctionDefinition)) continue; |
| if (isSymbolRelevant(symbols[j])) { found=true; break; } |
| } |
| if (!found) |
| handleProblem("Symbol out of scope: '"+ompl[count-1].getImage()+"'", OpenMPError.ERROR); |
| } |
| } |
| |
| // rule: always leave one ahead |
| nextToken(); |
| |
| return ompl; |
| } |
| |
| /** |
| * See if symbol is a local variable in scope to pragma |
| * @param symbol - Symbol |
| * @return boolean |
| */ |
| protected boolean isSymbolRelevant(Symbol symbol) |
| { |
| if(traceOn)System.out.println("Symbol: "+symbol.getName()+" PASTOMPFactory.isSymbolRelevant()"); |
| IASTNode node = null; |
| IASTNode parent,gp=null; |
| try { |
| // node=symbol.getScope().getPhysicalNode(); // no longer in CDT 4.0 |
| // BRT replacement for getPhysicalNode() for CDT 4.0 |
| // The following probably isn't an ideal solution (using Discouraged access methods) |
| // but seems to work for now. |
| // alternatively I tried implementing: symbol.getPhysicalNode() but could not get the same answer from there. |
| |
| IScope scope=symbol.getScope(); |
| // see: http://dev.eclipse.org/mhonarc/lists/cdt-dev/msg08653.html |
| // Another alternative would be to cast to CScope and do cScope.getPhysicalNode() from there. |
| node = ASTInternal.getPhysicalNodeOfScope(scope); |
| |
| } catch (Exception e) { |
| return false; |
| } |
| |
| Utility.Location l = Utility.getLocation(node); |
| int nodeOffset = (l!=null ? l.getLow() : 0); //728 |
| int nodeEndset = (l!=null ? l.getHigh() : 0); //745 |
| if(traceOn)System.out.println("node: "+node.getRawSignature()+" nodeOffset: "+nodeOffset+" nodeEndset= "+nodeEndset); |
| |
| int pOffset = pragma_.getLocalOffset(); //822 |
| int pEndset = pOffset+pragma_.getLength()-1; //864 |
| if(traceOn)System.out.println(("pragma pOffset= "+pOffset+" pEndset= "+pEndset)); |
| |
| boolean tf = ((nodeEndset<pOffset || pEndset<nodeOffset) ? false : true); //false |
| if (!tf) return tf; |
| |
| // See if the declaration succeeds the pragma |
| Utility.Location dl = Utility.getLocation(symbol.getDeclarator()); |
| if (dl==null) return false; |
| if(traceOn)System.out.println("dl.getLow()="+dl.getLow()+" pOffset="+pOffset+ |
| " > is: "+(dl.getLow()>pOffset)); |
| |
| return (dl.getLow()>pOffset ? false : true); |
| } |
| |
| /** |
| * Acquire the next token |
| * @return OpenMPToken |
| */ |
| protected OpenMPToken nextToken() |
| { |
| // Following in case of backup |
| if (token_!=null && token_.getNext()!=null) { |
| token_ = token_.getNext(); |
| return token_; |
| } |
| |
| // chain to last one and move on |
| OpenMPToken token = scanner_.nextToken(); |
| if (token_!=null) |
| token_.setNext(token); |
| token_ = token; |
| return token_; |
| } |
| |
| /** |
| * Get current token so as to mark (in code) where we were |
| * @return OpenMPToken |
| */ |
| protected OpenMPToken mark() |
| { |
| if (token_==null) |
| token_ = nextToken(); |
| return token_; |
| } |
| |
| /** |
| * Reset token queue (nextToken() get one after this one) |
| * @param token |
| */ |
| protected void backupTo(OpenMPToken token) |
| { |
| token_ = token; |
| } |
| |
| /** |
| * Test the parser |
| * |
| */ |
| private void readTokens() |
| { |
| OpenMPScanner scanner = new OpenMPScanner(pragma_.getContent()); |
| |
| OpenMPToken token = null; |
| do { |
| token = scanner.nextToken(); |
| if (token!=null) |
| System.out.println("Token:"+token.getImage()+" type="+token.getType()); |
| } while(token!=null); |
| } |
| |
| /** |
| * Complete the parsing of #pragma omp parallel |
| * |
| */ |
| private void completeParallel() |
| { |
| boolean bShared = false; |
| boolean bPrivate = false; |
| boolean bFirstPrivate = false; |
| boolean bDefault = false; |
| boolean bReduction = false; |
| boolean bCopyin = false; |
| boolean bIf = false; |
| boolean bNumthreads = false; |
| |
| while(token_!=null) { |
| switch(token_.getType()){ |
| case OpenMPScanner.mpShared: |
| if (!bShared) |
| bShared = setShared(); |
| break; |
| case OpenMPScanner.mpPrivate: |
| if (!bPrivate) |
| bPrivate = setPrivate(); |
| break; |
| case OpenMPScanner.mpFirstprivate: |
| if (!bFirstPrivate) |
| bFirstPrivate = setFirstPrivate(); |
| break; |
| case OpenMPScanner.mpDefault: |
| if (!bDefault) |
| bDefault = setDefault(); |
| break; |
| case OpenMPScanner.mpReduction: |
| if (!bReduction) |
| bReduction = setReduction(); |
| break; |
| case OpenMPScanner.mpCopyin: |
| if (!bCopyin) |
| bCopyin = setCopyin(); |
| break; |
| case OpenMPScanner.mpIf: |
| if (!bIf) |
| bIf = setIf(); |
| break; |
| case OpenMPScanner.mpNumthreads: |
| if (!bNumthreads) |
| bNumthreads = setNumThreads(); |
| break; |
| default: |
| handleProblem("Unexpected token "+token_.getImage(), OpenMPError.ERROR); |
| nextToken(); |
| break; |
| } |
| } |
| } |
| |
| /** |
| * Complete parsing #paragma omp for |
| * |
| */ |
| private void completeFor() |
| { |
| boolean bPrivate = false; |
| boolean bFirstPrivate = false; |
| boolean bLastPrivate = false; |
| boolean bReduction = false; |
| boolean bOrdered = false; |
| boolean bSchedule = false; |
| boolean bNowait = false; |
| |
| while(token_!=null) { |
| switch(token_.getType()){ |
| case OpenMPScanner.mpPrivate: |
| if (!bPrivate) |
| bPrivate = setPrivate(); |
| break; |
| case OpenMPScanner.mpFirstprivate: |
| if (!bFirstPrivate) |
| bFirstPrivate = setFirstPrivate(); |
| break; |
| case OpenMPScanner.mpLastprivate: |
| if (!bLastPrivate) |
| bLastPrivate = setLastPrivate(); |
| break; |
| case OpenMPScanner.mpReduction: |
| if (!bReduction) |
| bReduction = setReduction(); |
| break; |
| case OpenMPScanner.mpOrdered: |
| if (!bOrdered) { |
| ompPragma_.setOrdered(true); bOrdered=true; } |
| nextToken(); |
| break; |
| case OpenMPScanner.mpSchedule: |
| if (!bSchedule) |
| bSchedule = setSchedule(); |
| break; |
| case OpenMPScanner.mpNowait: |
| if (!bNowait) { |
| ompPragma_.setNoWait(true); bNowait=true; } |
| nextToken(); |
| break; |
| default: |
| handleProblem("Unexpected token "+token_.getImage(), OpenMPError.ERROR); |
| nextToken(); |
| break; |
| } |
| } |
| } |
| |
| |
| /** |
| * Complete parsing #paragma omp parallel for |
| * |
| */ |
| private void completeParallelFor() |
| { |
| boolean bShared = false; |
| boolean bPrivate = false; |
| boolean bFirstPrivate = false; |
| boolean bLastPrivate = false; |
| boolean bDefault = false; |
| boolean bReduction = false; |
| boolean bCopyin = false; |
| boolean bIf = false; |
| boolean bOrdered = false; |
| boolean bSchedule = false; |
| |
| while(token_!=null) { |
| switch(token_.getType()){ |
| case OpenMPScanner.mpShared: |
| if (!bShared) |
| bShared = setShared(); |
| break; |
| case OpenMPScanner.mpPrivate: |
| if (!bPrivate) |
| bPrivate = setPrivate(); |
| break; |
| case OpenMPScanner.mpFirstprivate: |
| if (!bFirstPrivate) |
| bFirstPrivate = setFirstPrivate(); |
| break; |
| case OpenMPScanner.mpLastprivate: |
| if (!bLastPrivate) |
| bLastPrivate = setLastPrivate(); |
| break; |
| case OpenMPScanner.mpDefault: |
| if (!bDefault) |
| bDefault = setDefault(); |
| break; |
| case OpenMPScanner.mpReduction: |
| if (!bReduction) |
| bReduction = setReduction(); |
| break; |
| case OpenMPScanner.mpCopyin: |
| if (!bCopyin) |
| bCopyin = setCopyin(); |
| break; |
| case OpenMPScanner.mpIf: |
| if (!bIf) |
| bIf = setIf(); |
| break; |
| case OpenMPScanner.mpOrdered: |
| if (!bOrdered) { |
| ompPragma_.setOrdered(true); bOrdered=true; } |
| nextToken(); |
| break; |
| case OpenMPScanner.mpSchedule: |
| if (!bSchedule) |
| bSchedule = setSchedule(); |
| break; |
| default: |
| handleProblem("Unexpected token "+token_.getImage(), OpenMPError.ERROR); |
| nextToken(); |
| break; |
| } |
| } |
| } |
| |
| |
| /** |
| * Complete parsing #pragma omp parallel sections |
| * |
| */ |
| private void completeParallelSections() |
| { |
| boolean bShared = false; |
| boolean bPrivate = false; |
| boolean bFirstPrivate = false; |
| boolean bLastPrivate = false; |
| boolean bDefault = false; |
| boolean bReduction = false; |
| boolean bCopyin = false; |
| boolean bIf = false; |
| |
| while(token_!=null) { |
| switch(token_.getType()){ |
| case OpenMPScanner.mpShared: |
| if (!bShared) |
| bShared = setShared(); |
| break; |
| case OpenMPScanner.mpPrivate: |
| if (!bPrivate) |
| bPrivate = setPrivate(); |
| break; |
| case OpenMPScanner.mpFirstprivate: |
| if (!bFirstPrivate) |
| bFirstPrivate = setFirstPrivate(); |
| break; |
| case OpenMPScanner.mpLastprivate: |
| if (!bLastPrivate) |
| bLastPrivate = setLastPrivate(); |
| break; |
| case OpenMPScanner.mpDefault: |
| if (!bDefault) |
| bDefault = setDefault(); |
| break; |
| case OpenMPScanner.mpReduction: |
| if (!bReduction) |
| bReduction = setReduction(); |
| break; |
| case OpenMPScanner.mpCopyin: |
| if (!bCopyin) |
| bCopyin = setCopyin(); |
| break; |
| case OpenMPScanner.mpIf: |
| if (!bIf) |
| bIf = setIf(); |
| break; |
| default: |
| handleProblem("Unexpected token "+token_.getImage(), OpenMPError.ERROR); |
| nextToken(); |
| break; |
| } |
| } |
| } |
| |
| |
| /** |
| * Complete parse of #pragma omp sections |
| * |
| */ |
| private void completeSections() |
| { |
| boolean bPrivate = false; |
| boolean bFirstPrivate = false; |
| boolean bLastPrivate = false; |
| boolean bReduction = false; |
| boolean bNowait = false; |
| |
| while(token_!=null) { |
| switch(token_.getType()){ |
| case OpenMPScanner.mpPrivate: |
| if (!bPrivate) |
| bPrivate = setPrivate(); |
| break; |
| case OpenMPScanner.mpFirstprivate: |
| if (!bFirstPrivate) |
| bFirstPrivate = setFirstPrivate(); |
| break; |
| case OpenMPScanner.mpLastprivate: |
| if (!bLastPrivate) |
| bLastPrivate = setLastPrivate(); |
| break; |
| case OpenMPScanner.mpReduction: |
| if (!bReduction) |
| bReduction = setReduction(); |
| break; |
| case OpenMPScanner.mpNowait: |
| if (!bNowait) { |
| ompPragma_.setNoWait(true); bNowait=true; } |
| nextToken(); |
| break; |
| default: |
| handleProblem("Unexpected token "+token_.getImage(), OpenMPError.ERROR); |
| nextToken(); |
| break; |
| } |
| } |
| |
| } |
| |
| /** |
| * Complete options for the #pragma omp single |
| * |
| */ |
| private void completeSingle() |
| { |
| boolean bPrivate = false; |
| boolean bFirstPrivate = false; |
| boolean bCopyPrivate = false; |
| boolean bNowait = false; |
| |
| while(token_!=null) { |
| switch(token_.getType()){ |
| case OpenMPScanner.mpPrivate: |
| if (!bPrivate) |
| bPrivate = setPrivate(); |
| break; |
| case OpenMPScanner.mpFirstprivate: |
| if (!bFirstPrivate) |
| bFirstPrivate = setFirstPrivate(); |
| break; |
| case OpenMPScanner.mpCopyprivate: |
| if (!bCopyPrivate) |
| bCopyPrivate = setCopyPrivate(); |
| break; |
| case OpenMPScanner.mpNowait: |
| if (!bNowait) { |
| ompPragma_.setNoWait(true); bNowait=true; } |
| nextToken(); |
| break; |
| default: |
| handleProblem("Unexpected token "+token_.getImage(), OpenMPError.ERROR); |
| nextToken(); |
| break; |
| } |
| } |
| |
| } |
| |
| /** |
| * Complete the options for the #pragma omp flush |
| * |
| */ |
| private void completeFlush() |
| { |
| if (token_==null || token_.getType()!=IToken.tLPAREN) return; |
| |
| OpenMPToken [] list = getIdentifierList(); |
| |
| ompPragma_.setPrivateList(list); |
| } |
| |
| |
| /** |
| * Complete the options for the #pragma omp threadprivate |
| * |
| */ |
| private void completeThreadPrivate() |
| { |
| if (token_==null || token_.getType()!=IToken.tLPAREN) return; |
| |
| OpenMPToken [] list = getIdentifierList(); |
| |
| ompPragma_.setThreadPrivateList(list); |
| } |
| |
| /** |
| * Translate the type of reduction operato |
| * @return int (that PASTOMPPragma understands) |
| */ |
| private int getReductionOperator() |
| { |
| switch(token_.getType()) { |
| case IToken.tPLUS: |
| return PASTOMPPragma.OmpOpPlus; |
| case IToken.tSTAR: |
| return PASTOMPPragma.OmpOpMult; |
| case IToken.tMINUS: |
| return PASTOMPPragma.OmpOpMinus; |
| case IToken.tAMPER: |
| return PASTOMPPragma.OmpOpBAnd; |
| case IToken.tXOR: |
| return PASTOMPPragma.OmpOpBXor; |
| case IToken.tBITOR: |
| return PASTOMPPragma.OmpOpBOr; |
| case IToken.tAND: |
| return PASTOMPPragma.OmpOpLAnd; |
| case IToken.tOR: |
| return PASTOMPPragma.OmpOpLOr; |
| default: |
| return PASTOMPPragma.OmpOpUnknown; |
| } |
| } |
| |
| /** |
| * Translate the kind of schedule |
| * @return int (that PASTOMPPragma understands) |
| */ |
| private int getScheduleKind() |
| { |
| switch(token_.getType()) { |
| case OpenMPScanner.mpStatic: |
| return PASTOMPPragma.OmpSKStatic; |
| case OpenMPScanner.mpDynamic: |
| return PASTOMPPragma.OmpSKDynamic; |
| case OpenMPScanner.mpGuided: |
| return PASTOMPPragma.OmpSKGuided; |
| case OpenMPScanner.mpRuntime: |
| return PASTOMPPragma.OmpSKRuntime; |
| default: |
| return PASTOMPPragma.OmpSKUnknown; |
| } |
| } |
| |
| /** |
| * Get the schedule expression |
| * @return OpenMPToken [] |
| */ |
| private OpenMPToken [] getExpression() |
| { |
| LinkedList l = new LinkedList(); |
| int parenCt=1; |
| |
| nextToken(); |
| while(token_!=null) { |
| if (token_.getType()==IToken.tRPAREN){ |
| parenCt--; if (parenCt==0) break; |
| else {l.add(token_); } // end of schedule clause |
| } |
| else if (token_.getType()==IToken.tCOMMA) { |
| if (parenCt==1) break; else l.add(token_); // another way to exit |
| } |
| else if (token_.getType()==IToken.tLPAREN) |
| { parenCt++; l.add(token_); } |
| else |
| l.add(token_); |
| nextToken(); |
| } |
| |
| OpenMPToken [] list = new OpenMPToken[l.size()]; |
| for(int i=0; i<l.size(); i++) |
| list[i] = (OpenMPToken)l.get(i); |
| |
| nextToken(); // move ahead |
| return list; |
| } |
| |
| private boolean setIf() |
| { |
| nextToken(); |
| OpenMPToken [] list = getExpression(); |
| ompPragma_.setIfExpression(list); |
| return true; |
| } |
| |
| |
| private boolean setPrivate() |
| { |
| nextToken(); |
| OpenMPToken [] list = getIdentifierList(); |
| ompPragma_.setPrivateList(list); |
| return true; |
| } |
| |
| private boolean setFirstPrivate() |
| { |
| nextToken(); |
| OpenMPToken [] list = getIdentifierList(); |
| ompPragma_.setFirstPrivateList(list); |
| return true; |
| } |
| |
| private boolean setLastPrivate() |
| { |
| nextToken(); |
| OpenMPToken [] list = getIdentifierList(); |
| ompPragma_.setLastPrivateList(list); |
| return true; |
| } |
| |
| private boolean setShared() |
| { |
| nextToken(); |
| OpenMPToken [] list = getIdentifierList(); |
| ompPragma_.setSharedList(list); |
| return true; |
| } |
| |
| private boolean setCopyin() |
| { |
| nextToken(); |
| OpenMPToken [] list = getIdentifierList(); |
| ompPragma_.setCopyinList(list); |
| return true; |
| } |
| |
| |
| private boolean setCopyPrivate() |
| { |
| nextToken(); |
| OpenMPToken [] list = getIdentifierList(); |
| ompPragma_.setCopyPrivateList(list); |
| return true; |
| } |
| |
| |
| private boolean setDefault() |
| { |
| boolean shared = false; |
| nextToken(); |
| if (token_.getType()==IToken.tLPAREN) { |
| nextToken(); |
| if (token_.getType()==OpenMPScanner.mpShared) shared=true; |
| else if (token_.getType()==OpenMPScanner.mpNone) shared=false; |
| else return false; |
| nextToken(); // get the paren |
| if (token_==null || token_.getType()!=IToken.tRPAREN) return false; |
| ompPragma_.setDefault(shared ? PASTOMPPragma.OmpShared : |
| PASTOMPPragma.OmpNone); |
| nextToken(); |
| return true; |
| } |
| return false; |
| } |
| |
| private boolean setReduction() |
| { |
| nextToken(); |
| if (token_.getType()==IToken.tLPAREN) { |
| nextToken(); |
| int ro = getReductionOperator(); |
| nextToken(); |
| if (token_!=null && token_.getType()==IToken.tCOLON) { |
| OpenMPToken [] rlist = getIdentifierList(); |
| ompPragma_.setReductionOperator(ro); |
| ompPragma_.setReductionList(rlist); |
| return true; |
| } |
| return false; |
| } |
| return false; |
| } |
| |
| private boolean setNumThreads() |
| { |
| nextToken(); |
| if (token_.getType()==IToken.tLPAREN) { |
| OpenMPToken [] expr = getExpression(); |
| if (token_==null || token_.getType()!=IToken.tRPAREN) return false; |
| ompPragma_.setNumThreadsExpr(expr); |
| return true; |
| } |
| return false; |
| } |
| |
| private boolean setSchedule() |
| { |
| nextToken(); |
| if (token_.getType()==IToken.tLPAREN) { |
| nextToken(); |
| int kind = getScheduleKind(); |
| nextToken(); |
| if (token_!=null && token_.getType()==IToken.tCOMMA) { |
| OpenMPToken [] expr = getExpression(); |
| ompPragma_.setScheduleKind(kind); |
| ompPragma_.setChunkExpression(expr); |
| return true; |
| } |
| return false; |
| } |
| return false; |
| } |
| |
| |
| // We are presently unsure of what to do with all the following stuff: |
| // protected static final ScannerProblemFactory spf = new ScannerProblemFactory(); |
| // protected ScannerCallbackManager callbackManager; |
| // protected static char[] EMPTY_CHAR_ARRAY = new char[0]; |
| // |
| // protected void otherinit(ISourceElementRequestor requestor) |
| // { |
| // callbackManager = new ScannerCallbackManager(new NullSourceElementRequestor()); |
| // } |
| |
| /** |
| * handleProblem |
| * @param description - String |
| * @param severity - int |
| */ |
| protected void handleProblem(String description, int severity) |
| { |
| OpenMPError error = new OpenMPError(description, |
| pragma_.getContainingFilename(), |
| pragma_.getStartingLine(), |
| severity); |
| OpenMPErrorManager.getCurrentErrorManager().addError(error); |
| ompPragma_.addProblem(error); // we really don't need this, but may be useful later |
| } |
| |
| /** |
| * lFind the associated region to the current pragma |
| * |
| */ |
| private void locateRegion() |
| { |
| if (ompPragma_==null) return; |
| |
| switch (ompPragma_.getOMPType()) { |
| // followed by structured region |
| case PASTOMPPragma.OmpParallel: |
| case PASTOMPPragma.OmpSections: |
| case PASTOMPPragma.OmpSection: |
| case PASTOMPPragma.OmpParallelSections: |
| case PASTOMPPragma.OmpSingle: |
| case PASTOMPPragma.OmpMaster: |
| case PASTOMPPragma.OmpCritical: |
| case PASTOMPPragma.OmpOrdered: |
| determineRegion(STRUCTURED_BLOCK, ompPragma_); |
| break; |
| |
| // Must be followed by FOR |
| case PASTOMPPragma.OmpFor: |
| case PASTOMPPragma.OmpParallelFor: |
| determineRegion(FOR_BLOCK, ompPragma_); |
| break; |
| |
| // Stands alone |
| case PASTOMPPragma.OmpBarrier: |
| case PASTOMPPragma.OmpFlush: |
| case PASTOMPPragma.OmpThreadPrivate: |
| determineRegion(LOCATION_ONLY, ompPragma_); |
| break; |
| |
| // Followed by expression |
| case PASTOMPPragma.OmpAtomic: |
| determineRegion(EXPRESSION_BLOCK, ompPragma_); |
| break; |
| case PASTOMPPragma.OmpUnknown: |
| break; |
| } |
| } |
| |
| public static final int STRUCTURED_BLOCK = RegionDeterminationVisitor.STRUCTURED_BLOCK; |
| public static final int FOR_BLOCK = RegionDeterminationVisitor.FOR_BLOCK; |
| public static final int EXPRESSION_BLOCK = RegionDeterminationVisitor.EXPRESSION_BLOCK; |
| public static final int LOCATION_ONLY = RegionDeterminationVisitor.LOCATION_ONLY; |
| |
| /** |
| * Determine that code region affilated with a pragma & the peer node |
| * @param type - int (see constatns above) |
| * @param ompPragma - PASTOMPPragma |
| */ |
| protected void determineRegion(int type, PASTOMPPragma ompPragma) |
| { |
| RegionDeterminationVisitor rdv = new RegionDeterminationVisitor(type, ompPragma); |
| ast_.accept(rdv); |
| |
| // Ensure that region for structured block is a compound statement |
| if (type==STRUCTURED_BLOCK) { |
| IASTNode region = ompPragma.getRegion(); |
| if (region==null || !(region instanceof IASTCompoundStatement)) |
| handleProblem("Pragma expects structured block to follow it", OpenMPError.ERROR); |
| } |
| else if (type==FOR_BLOCK) { |
| IASTNode region = ompPragma.getRegion(); |
| if (region==null || !(region instanceof IASTForStatement)) |
| handleProblem("Pragma expects for loop to follow it", OpenMPError.ERROR); |
| } |
| } |
| |
| |
| /** |
| * RegionDeterminationVisitor is used to traverse AST to find region |
| */ |
| protected class RegionDeterminationVisitor extends ASTVisitor |
| { |
| protected int searchType_ = STRUCTURED_BLOCK; |
| protected PASTOMPPragma oPragma_ = null; |
| protected int pragmaLine_ = 0; |
| protected int pragmaLocation_ = 0; |
| protected int pragmaLength_ = 0; |
| |
| protected int closeness_ = -1; |
| |
| // for statement location |
| //protected IASTStatement lastStatement_ = null; |
| |
| public final static int STRUCTURED_BLOCK = 0; |
| public final static int FOR_BLOCK = 1; |
| public final static int EXPRESSION_BLOCK = 2; |
| public final static int LOCATION_ONLY = 3; // tell me what immediately precedes |
| |
| public RegionDeterminationVisitor(int type, PASTOMPPragma ompPragma) |
| { |
| searchType_ = type; |
| switch(searchType_) { |
| case STRUCTURED_BLOCK: |
| shouldVisitStatements = true; |
| break; |
| case FOR_BLOCK: |
| shouldVisitStatements = true; |
| break; |
| case EXPRESSION_BLOCK: |
| shouldVisitStatements = true; // we want an expression statement |
| break; |
| case LOCATION_ONLY: |
| shouldVisitStatements = true; |
| break; |
| } |
| |
| oPragma_ = ompPragma; |
| pragmaLine_ = oPragma_.getStartingLine(); |
| pragmaLocation_ = oPragma_.getOffset(); //oPragma_.getStartLocation(); |
| pragmaLength_ = oPragma_.getLength(); |
| } |
| |
| /** |
| * override function to visit statements implementation |
| * NOTE: Region is first statement following pragma |
| * |
| * @param statement - IASTStatement |
| * @return int |
| */ |
| public int visit(IASTStatement statement) { |
| ASTNode node = (statement instanceof ASTNode ? (ASTNode)statement : null); |
| if (node==null) return PROCESS_CONTINUE; |
| |
| // ensure the node is in the same file as the pragma |
| if (node.getContainingFilename().equals(oPragma_.getFileLocation().getFileName())) { |
| int totalOffset = node.getOffset(); |
| Utility.Location loc = Utility.getLocation(node); |
| assert(loc!=null); |
| int localOffset = loc.getLow(); // this is the offset local to the file |
| int length = loc.getHigh()-loc.getLow()+1; |
| |
| // We look at all nodes that occur before the pragma - 2 cases |
| // 1) if the node scope encompases the pragam, pragma is a child of node |
| // 2) otherwise we call it a peer (even when it isn't) |
| // Corrections occur by continuing for the tightest fit |
| if (totalOffset<pragmaLocation_) { |
| if (pragmaLocation_+pragmaLength_<totalOffset+length) { // encompassing |
| oPragma_.setLocation(statement, PASTOMPPragma.ChildProximity); |
| } |
| else { |
| if (totalOffset+length<pragmaLocation_) { |
| int closeness = pragmaLocation_-(totalOffset+length); |
| if (closeness_==-1 || closeness<closeness_) { // get closest statement |
| oPragma_.setLocation(statement, PASTOMPPragma.NeighborProximity); |
| closeness_ = closeness; |
| } |
| } |
| } |
| // keep going to find tightest fit |
| } |
| |
| // Check if this is the first node after the pragma - if so, could be our region |
| if (totalOffset>pragmaLocation_) { |
| if (searchType_!=LOCATION_ONLY) { |
| // With this we got to the next stmt: |
| if (searchType_==FOR_BLOCK && !(statement instanceof IASTForStatement)) |
| return PROCESS_ABORT; // error handled in determineRegion |
| // Set region information (ref. OpenMPArtifactView to see how used) |
| oPragma_.setRegionFilename(node.getContainingFilename()); |
| oPragma_.setRegionLength(length); |
| oPragma_.setRegionOffset(localOffset); |
| oPragma_.setRegion(statement); |
| if (traceOn_) |
| System.out.println((searchType_==FOR_BLOCK ? "(for)" : "(region)") + "pragma at "+ pragmaLocation_+ |
| " has statement at "+ localOffset); |
| } |
| return PROCESS_ABORT; |
| } |
| } |
| return PROCESS_CONTINUE; |
| } |
| |
| } |
| |
| |
| } |