def getAdditionalImportsAndDeclarationsForParentScope(parentNode, argumentSymbolNames): additionalImports = [] additionalDeclarations = [] additionalDummies = [] dependantTemplatesAndEntries = getDomainDependantTemplatesAndEntries(cgDoc, parentNode) for template, entry in dependantTemplatesAndEntries: dependantName = entry.firstChild.nodeValue if dependantName in argumentSymbolNames: continue #in case user is working with slices and passing them to different symbols inside the kernel, he has to manage that stuff manually symbol = currSymbolsByName.get(dependantName) if symbol == None: logging.debug("while analyzing additional kernel parameters: symbol %s was not available yet for parent %s, so it was loaded freshly" %( dependantName, parentNode.getAttribute('name') )) symbol = Symbol( dependantName, template, symbolEntry=entry, scopeNode=parentNode, analysis=getAnalysisForSymbol(symbolAnalysisByRoutineNameAndSymbolName, parentNode.getAttribute('name'), dependantName), parallelRegionTemplates=parallelRegionTemplates ) symbol.loadRoutineNodeAttributes(parentNode, parallelRegionTemplates) if symbol.isDummySymbolForRoutine(routineName=parentNode.getAttribute('name')): continue #already passed manually if symbol.declarationType == DeclarationType.LOCAL_MODULE_SCALAR \ and routineNode.getAttribute('module') == moduleNode.getAttribute('name'): additionalDeclarations.append(symbol) elif (symbol.analysis and symbol.analysis.isModuleSymbol) or symbol.declarationType == DeclarationType.FOREIGN_MODULE_SCALAR: additionalImports.append(symbol) elif symbol.declarationType == DeclarationType.LOCAL_ARRAY: additionalDummies.append(symbol) return additionalImports, additionalDeclarations, additionalDummies
def isModuleStillValid(module, inputModules, inputModuleSymbolIndex, referenceXML): moduleName = module.getAttribute('name') if moduleName in ["", None]: raise Exception("invalid module definition: %s" % (module.toxml())) if not moduleName in inputModules: return True #module is not found anymore - we don't have to care about this case, should be handled by GNU Make templatesAndEntries = getDomainDependantTemplatesAndEntries( referenceXML, module) for template, entry in templatesAndEntries: symbolName = entry.firstChild.nodeValue if symbolName in ["", None]: raise Exception("invalid entry: %s" % (entry.toxml())) inputTemplateAndEntry = inputModuleSymbolIndex.get( (moduleName, symbolName)) if inputTemplateAndEntry == None: logging.debug("symbol %s has been deleted from %s" % (symbolName, moduleName)) return False #symbol has been deleted inputTemplate, inputEntry = inputModuleSymbolIndex[(moduleName, symbolName)] if not isEqualElement(entry, inputEntry, ["id"]) or not isEqualElement( template, inputTemplate, ["id"]): logging.debug("symbol %s in %s has been changed" % (symbolName, moduleName)) return False return True
def getAdditionalImportsAndDeclarationsForParentScope(parentNode, argumentSymbolNames): additionalImports = [] additionalDeclarations = [] additionalDummies = [] dependantTemplatesAndEntries = getDomainDependantTemplatesAndEntries(parentNode.ownerDocument, parentNode) for template, entry in dependantTemplatesAndEntries: dependantName = entry.firstChild.nodeValue if dependantName in argumentSymbolNames: continue #in case user is working with slices and passing them to different symbols inside the kernel, he has to manage that stuff manually symbol = currRoutine.symbolsByName.get(uniqueIdentifier(dependantName, currRoutine.name)) if not symbol: symbol = currRoutine.symbolsByName.get(uniqueIdentifier(dependantName, currRoutine._parentModule().name)) if not symbol: symbol = currRoutine.symbolsByName.get(dependantName) if not symbol: logging.debug("while analyzing additional kernel parameters: symbol %s was not available yet for parent %s, so it was loaded freshly;\nCurrent symbols:%s\n" %( dependantName, parentNode.getAttribute('name'), currRoutine.symbolsByName.keys() )) symbol = Symbol( dependantName, template, symbolEntry=entry, scopeNode=parentNode, analysis=getAnalysisForSymbol(symbolAnalysisByRoutineNameAndSymbolName, parentNode.getAttribute('name'), dependantName), parallelRegionTemplates=callee.parallelRegionTemplates ) symbol.loadRoutineNodeAttributes(parentNode, callee.parallelRegionTemplates) updateTypeParameterProperties(symbol, currRoutine.symbolsByName.values()) if symbol.isTypeParameter: continue if symbol.isDummySymbolForRoutine(routineName=parentNode.getAttribute('name')): continue #already passed manually isModuleSymbol = symbol.declarationType in [ DeclarationType.LOCAL_MODULE_SCALAR, DeclarationType.MODULE_ARRAY, DeclarationType.MODULE_ARRAY_PASSED_IN_AS_ARGUMENT ] if isModuleSymbol and currRoutine.node.getAttribute('module') == symbol.sourceModule: logging.debug("decl added for %s" %(symbol)) additionalDeclarations.append(symbol) elif (symbol.analysis and symbol.analysis.isModuleSymbol) \ or (isModuleSymbol and currRoutine.node.getAttribute('module') != symbol.sourceModule) \ or symbol.declarationType == DeclarationType.FOREIGN_MODULE_SCALAR: if symbol.sourceModule != callee.parentModule.node.getAttribute('name'): foreignModuleNode = moduleNodesByName[symbol.sourceModule] symbol.loadImportInformation(parentNode.ownerDocument, foreignModuleNode) logging.debug("import added for %s" %(symbol)) additionalImports.append(symbol) elif symbol.declarationType in [ DeclarationType.LOCAL_ARRAY, DeclarationType.LOCAL_SCALAR, DeclarationType.OTHER_SCALAR ]: logging.debug("dummy added for %s" %(symbol)) additionalDummies.append(symbol) return additionalImports, additionalDeclarations, additionalDummies
def getDomainDependantTemplatesAndEntriesByModuleNameAndSymbolName(xmlData): result = {} for module in xmlData.getElementsByTagName('module'): moduleName = module.getAttribute('name') templatesAndEntries = getDomainDependantTemplatesAndEntries(xmlData, module) for template, entry in templatesAndEntries: symbolName = entry.firstChild.nodeValue result[(moduleName,symbolName)] = (template, entry) return result
def getDomainDependantTemplatesAndEntriesByModuleNameAndSymbolName(xmlData): result = {} for module in xmlData.getElementsByTagName('module'): moduleName = module.getAttribute('name') templatesAndEntries = getDomainDependantTemplatesAndEntries( xmlData, module) for template, entry in templatesAndEntries: symbolName = entry.firstChild.nodeValue result[(moduleName, symbolName)] = (template, entry) return result
def makeDummySymbol(self, cgDoc, module, routine): from models.symbol import Symbol from tools.metadata import getDomainDependantTemplatesAndEntries routineNode = routine.node self.assertEqual(routineNode.tagName, "routine") templatesAndEntries = getDomainDependantTemplatesAndEntries( cgDoc, routineNode) self.assertEqual(len(templatesAndEntries), 1) template, entry = templatesAndEntries[0] symbol = Symbol("testSymbol", template, symbolEntry=entry, scopeNode=routineNode, analysis=None, parallelRegionTemplates=[], globalParallelDomainNames={}) routine.loadSymbolsByName({"testSymbol": symbol}) return symbol
def makeDummySymbol(self, cgDoc, module, routine): from models.symbol import Symbol from tools.metadata import getDomainDependantTemplatesAndEntries routineNode = routine.node self.assertEqual(routineNode.tagName, "routine") templatesAndEntries = getDomainDependantTemplatesAndEntries(cgDoc, routineNode) self.assertEqual(len(templatesAndEntries), 1) template, entry = templatesAndEntries[0] symbol = Symbol( "testSymbol", template, symbolEntry=entry, scopeNode=routineNode, analysis=None, parallelRegionTemplates=[], globalParallelDomainNames={} ) routine.loadSymbolsByName({"testSymbol":symbol}) return symbol
def isModuleStillValid(module,inputModules,inputModuleSymbolIndex,referenceXML): moduleName = module.getAttribute('name') if moduleName in ["", None]: raise Exception("invalid module definition: %s" %(module.toxml())) if not moduleName in inputModules: return True #module is not found anymore - we don't have to care about this case, should be handled by GNU Make templatesAndEntries = getDomainDependantTemplatesAndEntries(referenceXML, module) for template, entry in templatesAndEntries: symbolName = entry.firstChild.nodeValue if symbolName in ["", None]: raise Exception("invalid entry: %s" %(entry.toxml())) inputTemplateAndEntry = inputModuleSymbolIndex.get((moduleName, symbolName)) if inputTemplateAndEntry == None: logging.debug("symbol %s has been deleted from %s" %( symbolName, moduleName )) return False #symbol has been deleted inputTemplate,inputEntry = inputModuleSymbolIndex[(moduleName, symbolName)] if not isEqualElement(entry, inputEntry, ["id"]) or not isEqualElement(template, inputTemplate, ["id"]): logging.debug("symbol %s in %s has been changed" %( symbolName, moduleName )) return False return True
def getSymbolAnalysisFor(self, routineName, symbolAnalysis=None, symbolAnalysisByNameAndSource=None, call=None, analysisWarningsByCalleeName=None): if symbolAnalysis == None: symbolAnalysis = {} if symbolAnalysisByNameAndSource == None: symbolAnalysisByNameAndSource = {} if analysisWarningsByCalleeName == None: analysisWarningsByCalleeName = {} routine = self.routinesByName.get(routineName) if not routine: return symbolAnalysis, symbolAnalysisByNameAndSource routineArguments = getArguments(routine) callArguments = [] if call != None: callArguments = getArguments(call) if call.getAttribute("callee") != routineName: raise Exception( "call passed to analysis of %s is not a call to this routine: %s" % (routineName, prettyprint(call))) if len(callArguments) != len(routineArguments): warnings = analysisWarningsByCalleeName.get(routineName, []) warnings.append( (call.getAttribute("caller"), len(callArguments), len(routineArguments), str(callArguments))) analysisWarningsByCalleeName[routineName] = warnings return symbolAnalysis, symbolAnalysisByNameAndSource templates_and_entries = getDomainDependantTemplatesAndEntries( self.doc, routine) analysisToAdd = {} #check arguments to this routine - temporarily remove previous calls from the analysis. #we don't want to overwrite information from previous calls. temporarilyStoredAnalysisByArgumentName = {} for argIndex, _ in enumerate(callArguments): localArgumentName = routineArguments[argIndex] if not (routineName, localArgumentName) in symbolAnalysis: continue temporarilyStoredAnalysisByArgumentName[ localArgumentName] = symbolAnalysis[(routineName, localArgumentName)] del symbolAnalysis[(routineName, localArgumentName)] #Symbol Analysis based on local information for (_, entry) in templates_and_entries: analysis = SymbolAnalysis() analysis.name = entry.firstChild.nodeValue analysis.sourceModule = entry.getAttribute("sourceModule") analysis.sourceSymbol = entry.getAttribute("sourceSymbol") analysis.aliasNamesByRoutineName[routineName] = analysis.name argIndex = -1 try: argIndex = routineArguments.index(analysis.name) except Exception: pass if argIndex > -1: analysis.argumentIndexByRoutineName[routineName] = argIndex if argIndex > -1: analysis.symbolType = SymbolType.ARGUMENT_WITH_DOMAIN_DEPENDANT_SPEC elif type(analysis.sourceModule) in [ unicode, str ] and analysis.sourceModule != "": analysis.symbolType = SymbolType.MODULE_DATA_WITH_DOMAIN_DEPENDANT_SPEC else: analysis.symbolType = SymbolType.DOMAIN_DEPENDANT analysisToAdd[analysis.name] = analysis for argIndex, argument in enumerate(routineArguments): if argument in analysisToAdd: continue analysis = SymbolAnalysis() analysis.name = argument analysis.symbolType = SymbolType.ARGUMENT analysis.argumentIndexByRoutineName[routineName] = argIndex analysisToAdd[analysis.name] = analysis #Symbol Analysis based on caller #--> check whether an analysis has already been done, update that and add it under the current routine, symbolName tuple for symbolName in analysisToAdd.keys(): currentAnalysis = analysisToAdd[symbolName] argIndex = currentAnalysis.argumentIndexByRoutineName.get( routineName, -1) existingSymbolAnalysis = None if argIndex > -1 and len(callArguments) > 0: symbolNameInCaller = callArguments[argIndex] callerName = call.getAttribute("caller") existingSymbolAnalysis = symbolAnalysis.get( (callerName, symbolNameInCaller), []) elif currentAnalysis.isModuleSymbol: existingModuleSymbolAnalysis = symbolAnalysisByNameAndSource.get( (currentAnalysis.sourceSymbol, currentAnalysis.sourceModule)) if existingModuleSymbolAnalysis: existingSymbolAnalysis = [existingModuleSymbolAnalysis] else: existingSymbolAnalysis = [] else: existingSymbolAnalysis = [currentAnalysis] for analysis in existingSymbolAnalysis: if not isinstance(analysis, SymbolAnalysis): raise Exception( "unexpected error in routine %s: current analysis list contains unexpected objects: %s" % (routineName, str(existingSymbolAnalysis))) if len(existingSymbolAnalysis) == 0 or ( len(existingSymbolAnalysis) == 1 and existingSymbolAnalysis[0] == currentAnalysis): symbolAnalysis[(routineName, symbolName)] = [currentAnalysis] if currentAnalysis.isModuleSymbol: symbolAnalysisByNameAndSource[( currentAnalysis.sourceSymbol, currentAnalysis.sourceModule)] = currentAnalysis else: for analysis in existingSymbolAnalysis: analysis.updateWith(currentAnalysis, routineName) symbolAnalysis[(routineName, symbolName)] = existingSymbolAnalysis #Analyse callgraph downstream from here for call in self.callsByCallerName.get(routineName, []): if call.getAttribute("caller") != routineName: raise Exception( "unexpected error when constructing callgraph for symbol aliases" ) calleeName = call.getAttribute("callee") symbolAnalysis, symbolAnalysisByNameAndSource = self.getSymbolAnalysisFor( calleeName, symbolAnalysis=symbolAnalysis, symbolAnalysisByNameAndSource=symbolAnalysisByNameAndSource, call=call, analysisWarningsByCalleeName=analysisWarningsByCalleeName) for argumentName in temporarilyStoredAnalysisByArgumentName.keys(): symbolAnalysis[( routineName, argumentName)] = temporarilyStoredAnalysisByArgumentName[ argumentName] + symbolAnalysis.get( (routineName, argumentName), []) return symbolAnalysis, symbolAnalysisByNameAndSource
def getSymbolAnalysisFor(self, routineName, symbolAnalysis=None, symbolAnalysisByNameAndSource=None, call=None, analysisWarningsByCalleeName=None): if symbolAnalysis == None: symbolAnalysis = {} if symbolAnalysisByNameAndSource == None: symbolAnalysisByNameAndSource = {} if analysisWarningsByCalleeName == None: analysisWarningsByCalleeName = {} routine = self.routinesByName.get(routineName) if not routine: return symbolAnalysis, symbolAnalysisByNameAndSource routineArguments = getArguments(routine) callArguments = [] if call != None: callArguments = getArguments(call) if call.getAttribute("callee") != routineName: raise Exception("call passed to analysis of %s is not a call to this routine: %s" %( routineName, prettyprint(call) )) if len(callArguments) != len(routineArguments): warnings = analysisWarningsByCalleeName.get(routineName, []) warnings.append((call.getAttribute("caller"), len(callArguments), len(routineArguments), str(callArguments))) analysisWarningsByCalleeName[routineName] = warnings return symbolAnalysis, symbolAnalysisByNameAndSource templates_and_entries = getDomainDependantTemplatesAndEntries( self.doc, routine ) analysisToAdd = {} #check arguments to this routine - temporarily remove previous calls from the analysis. #we don't want to overwrite information from previous calls. temporarilyStoredAnalysisByArgumentName = {} for argIndex, _ in enumerate(callArguments): localArgumentName = routineArguments[argIndex] if not (routineName, localArgumentName) in symbolAnalysis: continue temporarilyStoredAnalysisByArgumentName[localArgumentName] = symbolAnalysis[(routineName, localArgumentName)] del symbolAnalysis[(routineName, localArgumentName)] #Symbol Analysis based on local information for (_, entry) in templates_and_entries: analysis = SymbolAnalysis() analysis.name = entry.firstChild.nodeValue analysis.sourceModule = entry.getAttribute("sourceModule") analysis.sourceSymbol = entry.getAttribute("sourceSymbol") analysis.aliasNamesByRoutineName[routineName] = analysis.name argIndex = -1 try: argIndex = routineArguments.index(analysis.name) except Exception: pass if argIndex > -1: analysis.argumentIndexByRoutineName[routineName] = argIndex if argIndex > -1: analysis.symbolType = SymbolType.ARGUMENT_WITH_DOMAIN_DEPENDANT_SPEC elif type(analysis.sourceModule) in [unicode, str] and analysis.sourceModule != "": analysis.symbolType = SymbolType.MODULE_DATA_WITH_DOMAIN_DEPENDANT_SPEC else: analysis.symbolType = SymbolType.DOMAIN_DEPENDANT analysisToAdd[analysis.name] = analysis for argIndex, argument in enumerate(routineArguments): if argument in analysisToAdd: continue analysis = SymbolAnalysis() analysis.name = argument analysis.symbolType = SymbolType.ARGUMENT analysis.argumentIndexByRoutineName[routineName] = argIndex analysisToAdd[analysis.name] = analysis #Symbol Analysis based on caller #--> check whether an analysis has already been done, update that and add it under the current routine, symbolName tuple for symbolName in analysisToAdd.keys(): currentAnalysis = analysisToAdd[symbolName] argIndex = currentAnalysis.argumentIndexByRoutineName.get(routineName, -1) existingSymbolAnalysis = None if argIndex > -1 and len(callArguments) > 0: symbolNameInCaller = callArguments[argIndex] callerName = call.getAttribute("caller") existingSymbolAnalysis = symbolAnalysis.get((callerName, symbolNameInCaller), []) elif currentAnalysis.isModuleSymbol: existingModuleSymbolAnalysis = symbolAnalysisByNameAndSource.get((currentAnalysis.sourceSymbol, currentAnalysis.sourceModule)) if existingModuleSymbolAnalysis: existingSymbolAnalysis = [existingModuleSymbolAnalysis] else: existingSymbolAnalysis = [] else: existingSymbolAnalysis = [currentAnalysis] for analysis in existingSymbolAnalysis: if not isinstance(analysis, SymbolAnalysis): raise Exception("unexpected error in routine %s: current analysis list contains unexpected objects: %s" %( routineName, str(existingSymbolAnalysis) )) if len(existingSymbolAnalysis) == 0 or (len(existingSymbolAnalysis) == 1 and existingSymbolAnalysis[0] == currentAnalysis): symbolAnalysis[(routineName, symbolName)] = [currentAnalysis] if currentAnalysis.isModuleSymbol: symbolAnalysisByNameAndSource[(currentAnalysis.sourceSymbol, currentAnalysis.sourceModule)] = currentAnalysis else: for analysis in existingSymbolAnalysis: analysis.updateWith(currentAnalysis, routineName) symbolAnalysis[(routineName, symbolName)] = existingSymbolAnalysis #Analyse callgraph downstream from here for call in self.callsByCallerName.get(routineName, []): if call.getAttribute("caller") != routineName: raise Exception( "unexpected error when constructing callgraph for symbol aliases" ) calleeName = call.getAttribute("callee") symbolAnalysis, symbolAnalysisByNameAndSource = self.getSymbolAnalysisFor( calleeName, symbolAnalysis=symbolAnalysis, symbolAnalysisByNameAndSource=symbolAnalysisByNameAndSource, call=call, analysisWarningsByCalleeName=analysisWarningsByCalleeName ) for argumentName in temporarilyStoredAnalysisByArgumentName.keys(): symbolAnalysis[(routineName, argumentName)] = temporarilyStoredAnalysisByArgumentName[argumentName] + symbolAnalysis.get((routineName, argumentName), []) return symbolAnalysis, symbolAnalysisByNameAndSource