Mercurial > codeOptimizer
changeset 4:3a56cd936c59
Cleanup some code.
Add code for breaking loops in the dependency tree.
| author | Tom Fredrik Blenning Klaussen <bfg@blenning.no> |
|---|---|
| date | Mon, 24 Sep 2012 01:16:43 +0200 |
| parents | f65c2d63ab66 |
| children | accc99f131a7 |
| files | Compilable.py Config.py DepGraph.py codeOptimizer.py |
| diffstat | 4 files changed, 124 insertions(+), 31 deletions(-) [+] |
line wrap: on
line diff
--- a/Compilable.py Sun Sep 16 21:31:41 2012 +0200 +++ b/Compilable.py Mon Sep 24 01:16:43 2012 +0200 @@ -125,3 +125,14 @@ def __repr__(self): return self.path + + + @staticmethod + def acceptsFile(name): + if name.endswith(".hpp"): + return True + if name.endswith(".h"): + return True + if name.endswith(".cpp"): + return True + return False
--- a/Config.py Sun Sep 16 21:31:41 2012 +0200 +++ b/Config.py Mon Sep 24 01:16:43 2012 +0200 @@ -27,6 +27,13 @@ def getCxxflags(self, name): value = self.getOption(self.document.childNodes[0], 'Cxxflags', name) - if not value: + if value == None: raise xml.dom.NotFoundErr() return value + + def getFiles(self): + retVal = [] + for elem in self.document.getElementsByTagName('file'): + for t in elem.childNodes: + retVal.append(t.wholeText) + return retVal
--- a/DepGraph.py Sun Sep 16 21:31:41 2012 +0200 +++ b/DepGraph.py Mon Sep 24 01:16:43 2012 +0200 @@ -1,3 +1,4 @@ +import copy, sys from types import * class DepGraph: @@ -11,14 +12,9 @@ self.values.append(value) - def addDependency(self, src, dst): - if not type(dst) is ListType: - dst = [ dst ] - + def rightSize(self): vl = len(self.values) dl = len(self.deps) - si = self.values.index(src) - if dl != vl: full = [] @@ -32,30 +28,102 @@ for i in range(0, dl): self.deps[i].append(exp[:]) - + + def addDependency(self, src, dst): + if not type(dst) is ListType: + dst = [ dst ] + + self.rightSize() + + si = self.values.index(src) for d in dst: if d in self.values: di = self.values.index(d) self.deps[si][di] = True + @staticmethod + def identifyStronglyConnectedComponents(deps): + index=0 + S=[] + vindex={} + lowlink={} + retVal=[] + for v in range(len(deps)): + if not v in vindex: + retVal.extend(DepGraph.strongconnect(deps, v, index, vindex, lowlink, S)) + return retVal + + @staticmethod + def strongconnect(deps, v, index, vindex, lowlink, S): + retVal = [] + # Set the depth index for v to the smallest unused index + vindex[v] = index + lowlink[v] = index + #print index + index += 1 + S.append(v) + + # Consider successors of v + for w in range(len(deps)): + if not deps[w][v]: + continue + if not w in vindex: + # Successor w has not yet been visited; recurse on it + res = DepGraph.strongconnect(deps, w, index, vindex, lowlink, S) + retVal.extend(res) + lowlink[v] = min(lowlink[v], lowlink[w]) + elif w in S: + # Successor w is in stack S and hence in the current SCC + lowlink[v] = min(lowlink[v], vindex[w]) + + # If v is a root node, pop the stack and generate an SCC + if lowlink[v] == vindex[v]: + #start a new strongly connected component + component = [] + w = None + while w != v: + w = S.pop() + #add w to current strongly connected component + component.append(w) + retVal.append(component) + return retVal + + @staticmethod + def dissolveStronglyConnectedComponents(deps): + dissolved = True + while dissolved: + dissolved = False + strong = DepGraph.identifyStronglyConnectedComponents(deps) + for s in strong: + if len(s) > 1: + #We remove the first dependency, and see how it goes. + v = s[0] + for w in s[1:]: + if deps[w][v]: + #print "Remove link %d -> %d" % (w, v) + deps[w][v] = False + dissolved = True + break + return deps + sys.exit(1) @staticmethod def directedGraphInternal(deps): dl = len(deps) - myVals = [] + startPoints = [] for i in range(dl): if not max(deps[i]): - myVals.append(i) + startPoints.append(i) - for i in myVals: + for i in startPoints: for j in range(dl): deps[j][i] = False - retVal = myVals + retVal = startPoints - if len(deps) != len(myVals): - subVals = self.directedGraphInternal(deps) - for val in myVals: + if len(deps) != len(startPoints): + subVals = DepGraph.directedGraphInternal(deps) + for val in startPoints: if val in subVals: ind = subVals.index(val) del subVals[ind] @@ -80,8 +148,13 @@ res += s return res - def directedGraph(self): - deps = self.deps[:][:] + def depGraphRepr(self): + return self.printableDepgraph(self.deps) + + def directedGraph(self, force = True): + deps = copy.deepcopy(self.deps) + if force: + deps = self.dissolveStronglyConnectedComponents(deps) vals = self.directedGraphInternal(deps) retVal = [] for i in vals:
--- a/codeOptimizer.py Sun Sep 16 21:31:41 2012 +0200 +++ b/codeOptimizer.py Mon Sep 24 01:16:43 2012 +0200 @@ -7,30 +7,29 @@ from Config import Config +def usage(name): + print "Usage is:\n\t%s <xml configuration file> [files for analysis]" % name -def isHppfile(name): - if name.endswith(".hpp"): - return True - if name.endswith(".h"): - return True - return False - -def isCppfile(name): - if name.endswith(".cpp"): - return True - return False +if len(sys.argv) < 2: + usage(sys.argv[0]) + sys.exit(1) try: options = Config(sys.argv[1]) except: print sys.argv[1] + ' is not a valid xml file' + sys.exit(1) + infiles = sys.argv[2:] +if not infiles: + infiles = options.getFiles() + files = {} unknown = [] for file in infiles: - if isHppfile(file) or isCppfile(file): + if Compilable.acceptsFile(file): c = Compilable(file) c.setFlags(options.getCxxflags(file)) files[file] = c @@ -47,13 +46,16 @@ depgraph.add(files[file]) for file in files: - depgraph.addDependency(files[file], files[file].dependencies()) + depgraph.addDependency(files[file], + list(files[dep] + for dep in files[file].dependencies())) files = depgraph.directedGraph() +print files for file in files: if not file.worksWithoutModifications(): - print file.path + print files[file].path raise SystemExit(file.path + " does not compile at all") for file in files:
