def addCallees(symbolName, routineName): for call in self.callsByCallerName.get(routineName, []): if call.getAttribute("caller") != routineName: raise Exception( "unexpected error when constructing callgraph for symbol aliases" ) argumentsInCall = [ argument.getAttribute("symbolName") for argument in call.getElementsByTagName("argument") ] argIndex = -1 try: argIndex = argumentsInCall.index(symbolName) except Exception: pass if argIndex < 0: continue calleeName = call.getAttribute("callee") if calleeName in aliasNamesByRoutineName: raise Exception( "unsupported case: symbol %s is passed into routine %s in multiple paths in the callgraph" % (symbolName, calleeName)) calleeRoutine = self.routinesByName[calleeName] argumentsInCallee = [ argument.getAttribute("symbolName") for argument in calleeRoutine.getElementsByTagName("argument") ] if len(argumentsInCall) != len(argumentsInCallee): raise Exception( "call to %s in %s doesn't have the expected number of arguments" % (calleeName, routineName)) aliasName = argumentsInCallee[argIndex] aliasNamesByRoutineName[calleeName] = aliasName addCallees(aliasName, calleeName)
def __init__(self, doc): def getCallIndexByAttribute(attributeName): index = {} for call in doc.getElementsByTagName("call"): identifier = call.getAttribute(attributeName) callList = index.get(identifier, []) callList.append(call) index[identifier] = callList return index routinesByName = {} for routine in doc.getElementsByTagName("routine"): routineName = routine.getAttribute("name") if routineName in routinesByName: raise UsageError( "Duplicate subroutines found with name %s. Subroutines need to have unique names in Hybrid Fortran." % (routineName)) routinesByName[routineName] = routine callsByCalleeName = getCallIndexByAttribute("callee") callsByCallerName = getCallIndexByAttribute("caller") callGraphEdgesByCallerName = {} callGraphEdgesByCalleeName = {} def addCallees(routineName): for call in callsByCallerName.get(routineName, []): callerName = call.getAttribute("caller") if callerName != routineName: raise Exception( "unexpected error when constructing callgraph") calleeName = call.getAttribute("callee") edgeList = callGraphEdgesByCallerName.get(routineName, []) edgeList.append((callerName, calleeName)) callGraphEdgesByCallerName[routineName] = edgeList edgeList = callGraphEdgesByCalleeName.get(calleeName, []) edgeList.append((callerName, calleeName)) callGraphEdgesByCalleeName[calleeName] = edgeList addCallees(calleeName) callGraphRootRoutineNames = [ routineName for routineName in routinesByName.keys() if len(callsByCalleeName.get(routineName, [])) == 0 ] for routineName in callGraphRootRoutineNames: addCallees(routineName) #at this point we should have the complete callgraph self.callGraphEdgesByCallerName = callGraphEdgesByCallerName self.routinesByName = routinesByName self.callsByCalleeName = callsByCalleeName self.callsByCallerName = callsByCallerName self.doc = doc self.symbolsNode = createOrGetFirstNodeWithName('symbols', doc)
def addCallees(routineName): for call in callsByCallerName.get(routineName, []): callerName = call.getAttribute("caller") if callerName != routineName: raise Exception("unexpected error when constructing callgraph") calleeName = call.getAttribute("callee") edgeList = callGraphEdgesByCallerName.get(routineName, []) edgeList.append((callerName, calleeName)) callGraphEdgesByCallerName[routineName] = edgeList edgeList = callGraphEdgesByCalleeName.get(calleeName, []) edgeList.append((callerName, calleeName)) callGraphEdgesByCalleeName[calleeName] = edgeList addCallees(calleeName)
def __init__(self, doc): def getCallIndexByAttribute(attributeName): index = {} for call in doc.getElementsByTagName("call"): identifier = call.getAttribute(attributeName) callList = index.get(identifier, []) callList.append(call) index[identifier] = callList return index routinesByName = {} for routine in doc.getElementsByTagName("routine"): routineName = routine.getAttribute("name") if routineName in routinesByName: raise UsageError("Duplicate subroutines found with name %s. Subroutines need to have unique names in Hybrid Fortran." %(routineName)) routinesByName[routineName] = routine callsByCalleeName = getCallIndexByAttribute("callee") callsByCallerName = getCallIndexByAttribute("caller") callGraphEdgesByCallerName = {} callGraphEdgesByCalleeName = {} def addCallees(routineName): for call in callsByCallerName.get(routineName, []): callerName = call.getAttribute("caller") if callerName != routineName: raise Exception("unexpected error when constructing callgraph") calleeName = call.getAttribute("callee") edgeList = callGraphEdgesByCallerName.get(routineName, []) edgeList.append((callerName, calleeName)) callGraphEdgesByCallerName[routineName] = edgeList edgeList = callGraphEdgesByCalleeName.get(calleeName, []) edgeList.append((callerName, calleeName)) callGraphEdgesByCalleeName[calleeName] = edgeList addCallees(calleeName) callGraphRootRoutineNames = [ routineName for routineName in routinesByName.keys() if len(callsByCalleeName.get(routineName, [])) == 0 ] for routineName in callGraphRootRoutineNames: addCallees(routineName) #at this point we should have the complete callgraph self.callGraphEdgesByCallerName = callGraphEdgesByCallerName self.routinesByName = routinesByName self.callsByCalleeName = callsByCalleeName self.callsByCallerName = callsByCallerName self.doc = doc self.symbolsNode = createOrGetFirstNodeWithName('symbols', doc)
def addCallees(routineName): for call in callsByCallerName.get(routineName, []): callerName = call.getAttribute("caller") if callerName != routineName: raise Exception( "unexpected error when constructing callgraph") calleeName = call.getAttribute("callee") edgeList = callGraphEdgesByCallerName.get(routineName, []) edgeList.append((callerName, calleeName)) callGraphEdgesByCallerName[routineName] = edgeList edgeList = callGraphEdgesByCalleeName.get(calleeName, []) edgeList.append((callerName, calleeName)) callGraphEdgesByCalleeName[calleeName] = edgeList addCallees(calleeName)
def addCallees(symbolName, routineName): for call in self.callsByCallerName.get(routineName, []): if call.getAttribute("caller") != routineName: raise Exception( "unexpected error when constructing callgraph for symbol aliases" ) argumentsInCall = [ argument.getAttribute("symbolName") for argument in call.getElementsByTagName("argument") ] argIndex = -1 try: argIndex = argumentsInCall.index(symbolName) except Exception: pass if argIndex < 0: continue calleeName = call.getAttribute("callee") if calleeName in aliasNamesByRoutineName: raise Exception( "unsupported case: symbol %s is passed into routine %s in multiple paths in the callgraph" %( symbolName, calleeName ) ) calleeRoutine = self.routinesByName[calleeName] argumentsInCallee = [ argument.getAttribute("symbolName") for argument in calleeRoutine.getElementsByTagName("argument") ] if len(argumentsInCall) != len(argumentsInCallee): raise Exception( "call to %s in %s doesn't have the expected number of arguments" %( calleeName, routineName ) ) aliasName = argumentsInCallee[argIndex] aliasNamesByRoutineName[calleeName] = aliasName addCallees(aliasName, calleeName)