Beispiel #1
0
		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
Beispiel #2
0
 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
Beispiel #3
0
		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
Beispiel #5
0
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
Beispiel #6
0
    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
Beispiel #7
0
	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
Beispiel #9
0
    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