if (not options.sourceDir): logging.error( "sourceDirectory option is mandatory. Use '--help' for informations on how to use this module" ) sys.exit(1) #prepare xml output doc = Document() callGraphRoot = doc.createElement("callGraph") doc.appendChild(callGraphRoot) filesInDir = dirEntries(str(options.sourceDir), True, 'h90') #first pass: loop through all h90 files (hybrid fortran 90) in the current directory # and build the basic callgraph based on subprocedures and calls. Also parse @-directives for annotations. progressIndicatorReset(sys.stderr) for fileNum, fileInDir in enumerate(filesInDir): parser = H90XMLCallGraphGenerator(doc) parser.processFile(fileInDir) logging.debug("Callgraph generated for " + fileInDir + "") printProgressIndicator(sys.stderr, fileInDir, fileNum + 1, len(filesInDir), "Callgraph parsing") #second pass: moved to generateP90Codebase.py since we need symbol analysis already if (options.pretty): sys.stdout.write(doc.toprettyxml()) else: sys.stdout.write(doc.toxml()) sys.stdout.flush()
help="make xml output pretty") (options, args) = parser.parse_args() setupDeferredLogging('preprocessor.log', logging.DEBUG if options.debug else logging.INFO) if (not options.sourceDir): logging.error("sourceDirectory option is mandatory. Use '--help' for informations on how to use this module") sys.exit(1) #prepare xml output doc = Document() callGraphRoot = doc.createElement("callGraph") doc.appendChild(callGraphRoot) filesInDir = dirEntries(str(options.sourceDir), True, 'h90') #first pass: loop through all h90 files (hybrid fortran 90) in the current directory # and build the basic callgraph based on subprocedures and calls. Also parse @-directives for annotations. progressIndicatorReset(sys.stderr) for fileNum, fileInDir in enumerate(filesInDir): parser = H90XMLCallGraphGenerator(doc) parser.processFile(fileInDir) logging.debug("Callgraph generated for " + fileInDir + "") printProgressIndicator(sys.stderr, fileInDir, fileNum + 1, len(filesInDir), "Callgraph parsing") #second pass: moved to generateP90Codebase.py since we need symbol analysis already if (options.pretty): sys.stdout.write(doc.toprettyxml()) else: sys.stdout.write(doc.toxml())
def analyseParallelRegions(doc, appliesTo): callNodes = doc.getElementsByTagName("call") routineNodes = doc.getElementsByTagName("routine") templates = doc.getElementsByTagName("parallelRegionTemplate") for routineNum, routineNode in enumerate(routineNodes): filterParallelRegionNodes(doc, routineNode, appliesTo, templates) printProgressIndicator( sys.stderr, "", routineNum + 1, len(routineNodes), "Filtering parallel regions for %s" %(appliesTo) if appliesTo != "" else "Filtering parallel regions" ) progressIndicatorReset(sys.stderr) callNodesByCallerName = getCalleesByCallerName(callNodes) callNodesByCalleeName = getCallersByCalleeName(callNodes) parallelRegionNodes = doc.getElementsByTagName("parallelRegions") parallelRegionNodesByRoutineName = {} sys.stderr.write("Populating parallel region cache\n") for regionNum, parallelRegionNode in enumerate(parallelRegionNodes): routine = parallelRegionNode.parentNode routineName = routine.getAttribute("name") if appliesTo == "GPU" and parallelRegionNodesByRoutineName.get(routineName) != None: raise Exception("Multiple GPU parallel regions in subroutine %s" %(routineName)) parallelRegionNodesByRoutineName[routineName] = parallelRegionNode kernelCallerProblemFound = False messagesPresentedFor = [] sys.stderr.write("Parallel region analysis\n") for regionNum, parallelRegionNode in enumerate(parallelRegionNodes): if not parallelRegionNode.parentNode.tagName == "routine": raise Exception("Parallel region not within routine.") parallelRegionNode.parentNode.setAttribute("parallelRegionPosition", "within") routine = parallelRegionNode.parentNode routineName = routine.getAttribute("name") if routineName == None: raise Exception("Kernel routine without name") addAttributeToAllCallGraphAncestors(routineNodes, callNodesByCalleeName, routine, "parallelRegionPosition", "inside") addAttributeToAllCallGraphHeirs(routineNodes, callNodesByCallerName, routine, "parallelRegionPosition", "outside") #rename this parallelRegion node to 'activeParallelRegion' children = parallelRegionNode.childNodes existingActiveParallelRegions = routine.getElementsByTagName("activeParallelRegions") newRegionNode = None newRegionNodeNeedsAppending = False if len(existingActiveParallelRegions) > 0: newRegionNode = existingActiveParallelRegions[0] else: newRegionNode = doc.createElement("activeParallelRegions") newRegionNodeNeedsAppending = True for child in children: newRegionNode.appendChild(child.cloneNode(deep=True)) routine.removeChild(parallelRegionNode) if newRegionNodeNeedsAppending: routine.appendChild(newRegionNode) if appliesTo != "GPU": continue #check our kernel callers. Rule: Their direct callees should not be a kernel caller themselves. kernelCallers = callNodesByCalleeName.get(routineName) if not kernelCallers: continue for kernelCaller in kernelCallers: kernelCallerName = kernelCaller.getAttribute("caller") kernelWrapperCall = getFirstKernelCallerInCalleesOf(kernelCallerName, callNodesByCallerName, parallelRegionNodesByRoutineName) if kernelWrapperCall != None: kernelWrapperName = kernelWrapperCall.getAttribute("callee") if not kernelCallerProblemFound: logging.warning("Subroutine %s calls at least one kernel (%s) and at least one kernel wrapper (%s). \ This may cause device attribute mismatch compiler errors. In this case please wrap all kernels called by %s, such that it does not call a mix of kernel wrappers and kernels.\n" %(kernelCallerName, routineName, kernelWrapperName, kernelCallerName) ) kernelCallerProblemFound = True messagesPresentedFor.append(kernelCallerName) elif kernelCallerName not in messagesPresentedFor: messagesPresentedFor.append(kernelCallerName) logging.warning("...same for %s: calls kernel %s, kernel wrapper %s" %(kernelCallerName, routineName, kernelWrapperName))
getattr(implementations.fortran, implementationNamesByTemplateName[templateName])(optionFlags)) for templateName in implementationNamesByTemplateName.keys()) # parse the @domainDependant symbol declarations flags in all h90 files # -> update the callgraph document with this information. # note: We do this, since for simplicity reasons, the declaration parser relies on the symbol names that # have been declared in @domainDependant directives. Since these directives come *after* the declaration, # we need this pass # cgDoc = getClonedDocument(cgDoc) for fileNum, fileInDir in enumerate(filesInDir): parser = H90XMLSymbolDeclarationExtractor( cgDoc, implementationsByTemplateName=implementationsByTemplateName) parser.processFile(fileInDir) logging.debug("Symbol declarations extracted for " + fileInDir + "") printProgressIndicator(sys.stderr, fileInDir, fileNum + 1, len(filesInDir), "Symbol parsing, excluding imports") progressIndicatorReset(sys.stderr) # build up symbol table indexed by module name moduleNodesByNameWithoutImplicitImports = getModuleNodesByName(cgDoc) symbolAnalyzer = SymbolDependencyAnalyzer(cgDoc) symbolAnalysisByRoutineNameAndSymbolNameWithoutImplicitImports = symbolAnalyzer.getSymbolAnalysisByRoutine( ) symbolsByModuleNameAndSymbolNameWithoutImplicitImports = getSymbolsByModuleNameAndSymbolName( ImmutableDOMDocument(cgDoc), moduleNodesByNameWithoutImplicitImports, symbolAnalysisByRoutineNameAndSymbolName= symbolAnalysisByRoutineNameAndSymbolNameWithoutImplicitImports) # parse the symbols again, this time know about all informations in the sourced modules in import # -> update the callgraph document with this information.
implementationsByTemplateName = { templateName:getattr(implementations.fortran, implementationNamesByTemplateName[templateName])(optionFlags) for templateName in implementationNamesByTemplateName.keys() } # parse the @domainDependant symbol declarations flags in all h90 files # -> update the callgraph document with this information. # note: We do this, since for simplicity reasons, the declaration parser relies on the symbol names that # have been declared in @domainDependant directives. Since these directives come *after* the declaration, # we need this pass # cgDoc = getClonedDocument(cgDoc) for fileNum, fileInDir in enumerate(filesInDir): parser = H90XMLSymbolDeclarationExtractor(cgDoc, implementationsByTemplateName=implementationsByTemplateName) parser.processFile(fileInDir) logging.debug("Symbol declarations extracted for " + fileInDir + "") printProgressIndicator(sys.stderr, fileInDir, fileNum + 1, len(filesInDir), "Symbol parsing, excluding imports") progressIndicatorReset(sys.stderr) # build up symbol table indexed by module name moduleNodesByNameWithoutImplicitImports = getModuleNodesByName(cgDoc) symbolAnalyzer = SymbolDependencyAnalyzer(cgDoc) symbolAnalysisByRoutineNameAndSymbolNameWithoutImplicitImports = symbolAnalyzer.getSymbolAnalysisByRoutine() symbolsByModuleNameAndSymbolNameWithoutImplicitImports = getSymbolsByModuleNameAndSymbolName( ImmutableDOMDocument(cgDoc), moduleNodesByNameWithoutImplicitImports, symbolAnalysisByRoutineNameAndSymbolName=symbolAnalysisByRoutineNameAndSymbolNameWithoutImplicitImports ) # parse the symbols again, this time know about all informations in the sourced modules in import # -> update the callgraph document with this information. for fileNum, fileInDir in enumerate(filesInDir):