173 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Python
		
	
	
	
			
		
		
	
	
			173 lines
		
	
	
		
			4.9 KiB
		
	
	
	
		
			Python
		
	
	
	
| # Automatically formatted with yapf (https://github.com/google/yapf)
 | |
| """Utility functions for creating and manipulating LLVM 'opt' NPM pipeline objects."""
 | |
| 
 | |
| 
 | |
| def fromStr(pipeStr):
 | |
|     """Create pipeline object from string representation."""
 | |
|     stack = []
 | |
|     curr = []
 | |
|     tok = ''
 | |
|     kind = ''
 | |
|     for c in pipeStr:
 | |
|         if c == ',':
 | |
|             if tok != '':
 | |
|                 curr.append([None, tok])
 | |
|             tok = ''
 | |
|         elif c == '(':
 | |
|             stack.append([kind, curr])
 | |
|             kind = tok
 | |
|             curr = []
 | |
|             tok = ''
 | |
|         elif c == ')':
 | |
|             if tok != '':
 | |
|                 curr.append([None, tok])
 | |
|             tok = ''
 | |
|             oldKind = kind
 | |
|             oldCurr = curr
 | |
|             [kind, curr] = stack.pop()
 | |
|             curr.append([oldKind, oldCurr])
 | |
|         else:
 | |
|             tok += c
 | |
|     if tok != '':
 | |
|         curr.append([None, tok])
 | |
|     return curr
 | |
| 
 | |
| 
 | |
| def toStr(pipeObj):
 | |
|     """Create string representation of pipeline object."""
 | |
|     res = ''
 | |
|     lastIdx = len(pipeObj) - 1
 | |
|     for i, c in enumerate(pipeObj):
 | |
|         if c[0]:
 | |
|             res += c[0] + '('
 | |
|             res += toStr(c[1])
 | |
|             res += ')'
 | |
|         else:
 | |
|             res += c[1]
 | |
|         if i != lastIdx:
 | |
|             res += ','
 | |
|     return res
 | |
| 
 | |
| 
 | |
| def count(pipeObj):
 | |
|     """Count number of passes (pass-managers excluded) in pipeline object."""
 | |
|     cnt = 0
 | |
|     for c in pipeObj:
 | |
|         if c[0]:
 | |
|             cnt += count(c[1])
 | |
|         else:
 | |
|             cnt += 1
 | |
|     return cnt
 | |
| 
 | |
| 
 | |
| def split(pipeObj, splitIndex):
 | |
|     """Create two new pipeline objects by splitting pipeObj in two directly after pass with index splitIndex."""
 | |
|     def splitInt(src, splitIndex, dstA, dstB, idx):
 | |
|         for s in src:
 | |
|             if s[0]:
 | |
|                 dstA2 = []
 | |
|                 dstB2 = []
 | |
|                 idx = splitInt(s[1], splitIndex, dstA2, dstB2, idx)
 | |
|                 dstA.append([s[0], dstA2])
 | |
|                 dstB.append([s[0], dstB2])
 | |
|             else:
 | |
|                 if idx <= splitIndex:
 | |
|                     dstA.append([None, s[1]])
 | |
|                 else:
 | |
|                     dstB.append([None, s[1]])
 | |
|                 idx += 1
 | |
|         return idx
 | |
| 
 | |
|     listA = []
 | |
|     listB = []
 | |
|     splitInt(pipeObj, splitIndex, listA, listB, 0)
 | |
|     return [listA, listB]
 | |
| 
 | |
| 
 | |
| def remove(pipeObj, removeIndex):
 | |
|     """Create new pipeline object by removing pass with index removeIndex from pipeObj."""
 | |
|     def removeInt(src, removeIndex, dst, idx):
 | |
|         for s in src:
 | |
|             if s[0]:
 | |
|                 dst2 = []
 | |
|                 idx = removeInt(s[1], removeIndex, dst2, idx)
 | |
|                 dst.append([s[0], dst2])
 | |
|             else:
 | |
|                 if idx != removeIndex:
 | |
|                     dst.append([None, s[1]])
 | |
|                 idx += 1
 | |
|         return idx
 | |
| 
 | |
|     dst = []
 | |
|     removeInt(pipeObj, removeIndex, dst, 0)
 | |
|     return dst
 | |
| 
 | |
| 
 | |
| def copy(srcPipeObj):
 | |
|     """Create copy of pipeline object srcPipeObj."""
 | |
|     def copyInt(dst, src):
 | |
|         for s in src:
 | |
|             if s[0]:
 | |
|                 dst2 = []
 | |
|                 copyInt(dst2, s[1])
 | |
|                 dst.append([s[0], dst2])
 | |
|             else:
 | |
|                 dst.append([None, s[1]])
 | |
| 
 | |
|     dstPipeObj = []
 | |
|     copyInt(dstPipeObj, srcPipeObj)
 | |
|     return dstPipeObj
 | |
| 
 | |
| 
 | |
| def prune(srcPipeObj):
 | |
|     """Create new pipeline object by removing empty pass-managers (those with count = 0) from srcPipeObj."""
 | |
|     def pruneInt(dst, src):
 | |
|         for s in src:
 | |
|             if s[0]:
 | |
|                 if count(s[1]):
 | |
|                     dst2 = []
 | |
|                     pruneInt(dst2, s[1])
 | |
|                     dst.append([s[0], dst2])
 | |
|             else:
 | |
|                 dst.append([None, s[1]])
 | |
| 
 | |
|     dstPipeObj = []
 | |
|     pruneInt(dstPipeObj, srcPipeObj)
 | |
|     return dstPipeObj
 | |
| 
 | |
| 
 | |
| if __name__ == "__main__":
 | |
|     import unittest
 | |
| 
 | |
|     class Test(unittest.TestCase):
 | |
|         def test_0(self):
 | |
|             pipeStr = 'a,b,A(c,B(d,e),f),g'
 | |
|             pipeObj = fromStr(pipeStr)
 | |
| 
 | |
|             self.assertEqual(7, count(pipeObj))
 | |
| 
 | |
|             self.assertEqual(pipeObj, pipeObj)
 | |
|             self.assertEqual(pipeObj, prune(pipeObj))
 | |
|             self.assertEqual(pipeObj, copy(pipeObj))
 | |
| 
 | |
|             self.assertEqual(pipeStr, toStr(pipeObj))
 | |
|             self.assertEqual(pipeStr, toStr(prune(pipeObj)))
 | |
|             self.assertEqual(pipeStr, toStr(copy(pipeObj)))
 | |
| 
 | |
|             [pipeObjA, pipeObjB] = split(pipeObj, 3)
 | |
|             self.assertEqual('a,b,A(c,B(d))', toStr(pipeObjA))
 | |
|             self.assertEqual('A(B(e),f),g', toStr(pipeObjB))
 | |
| 
 | |
|             self.assertEqual('b,A(c,B(d,e),f),g', toStr(remove(pipeObj, 0)))
 | |
|             self.assertEqual('a,b,A(c,B(d,e),f)', toStr(remove(pipeObj, 6)))
 | |
| 
 | |
|             pipeObjC = remove(pipeObj, 4)
 | |
|             self.assertEqual('a,b,A(c,B(d),f),g', toStr(pipeObjC))
 | |
|             pipeObjC = remove(pipeObjC, 3)
 | |
|             self.assertEqual('a,b,A(c,B(),f),g', toStr(pipeObjC))
 | |
|             pipeObjC = prune(pipeObjC)
 | |
|             self.assertEqual('a,b,A(c,f),g', toStr(pipeObjC))
 | |
| 
 | |
|     unittest.main()
 | |
|     exit(0)
 |