191d15aa0SMarkus Lavin# Automatically formatted with yapf (https://github.com/google/yapf) 291d15aa0SMarkus Lavin"""Utility functions for creating and manipulating LLVM 'opt' NPM pipeline objects.""" 391d15aa0SMarkus Lavin 491d15aa0SMarkus Lavin 591d15aa0SMarkus Lavindef fromStr(pipeStr): 691d15aa0SMarkus Lavin """Create pipeline object from string representation.""" 791d15aa0SMarkus Lavin stack = [] 891d15aa0SMarkus Lavin curr = [] 9*b71edfaaSTobias Hieta tok = "" 10*b71edfaaSTobias Hieta kind = "" 1191d15aa0SMarkus Lavin for c in pipeStr: 12*b71edfaaSTobias Hieta if c == ",": 13*b71edfaaSTobias Hieta if tok != "": 1491d15aa0SMarkus Lavin curr.append([None, tok]) 15*b71edfaaSTobias Hieta tok = "" 16*b71edfaaSTobias Hieta elif c == "(": 1791d15aa0SMarkus Lavin stack.append([kind, curr]) 1891d15aa0SMarkus Lavin kind = tok 1991d15aa0SMarkus Lavin curr = [] 20*b71edfaaSTobias Hieta tok = "" 21*b71edfaaSTobias Hieta elif c == ")": 22*b71edfaaSTobias Hieta if tok != "": 2391d15aa0SMarkus Lavin curr.append([None, tok]) 24*b71edfaaSTobias Hieta tok = "" 2591d15aa0SMarkus Lavin oldKind = kind 2691d15aa0SMarkus Lavin oldCurr = curr 2791d15aa0SMarkus Lavin [kind, curr] = stack.pop() 2891d15aa0SMarkus Lavin curr.append([oldKind, oldCurr]) 2991d15aa0SMarkus Lavin else: 3091d15aa0SMarkus Lavin tok += c 31*b71edfaaSTobias Hieta if tok != "": 3291d15aa0SMarkus Lavin curr.append([None, tok]) 3391d15aa0SMarkus Lavin return curr 3491d15aa0SMarkus Lavin 3591d15aa0SMarkus Lavin 3691d15aa0SMarkus Lavindef toStr(pipeObj): 3791d15aa0SMarkus Lavin """Create string representation of pipeline object.""" 38*b71edfaaSTobias Hieta res = "" 3991d15aa0SMarkus Lavin lastIdx = len(pipeObj) - 1 4091d15aa0SMarkus Lavin for i, c in enumerate(pipeObj): 4191d15aa0SMarkus Lavin if c[0]: 42*b71edfaaSTobias Hieta res += c[0] + "(" 4391d15aa0SMarkus Lavin res += toStr(c[1]) 44*b71edfaaSTobias Hieta res += ")" 4591d15aa0SMarkus Lavin else: 4691d15aa0SMarkus Lavin res += c[1] 4791d15aa0SMarkus Lavin if i != lastIdx: 48*b71edfaaSTobias Hieta res += "," 4991d15aa0SMarkus Lavin return res 5091d15aa0SMarkus Lavin 5191d15aa0SMarkus Lavin 5291d15aa0SMarkus Lavindef count(pipeObj): 5391d15aa0SMarkus Lavin """Count number of passes (pass-managers excluded) in pipeline object.""" 5491d15aa0SMarkus Lavin cnt = 0 5591d15aa0SMarkus Lavin for c in pipeObj: 5691d15aa0SMarkus Lavin if c[0]: 5791d15aa0SMarkus Lavin cnt += count(c[1]) 5891d15aa0SMarkus Lavin else: 5991d15aa0SMarkus Lavin cnt += 1 6091d15aa0SMarkus Lavin return cnt 6191d15aa0SMarkus Lavin 6291d15aa0SMarkus Lavin 6391d15aa0SMarkus Lavindef split(pipeObj, splitIndex): 6491d15aa0SMarkus Lavin """Create two new pipeline objects by splitting pipeObj in two directly after pass with index splitIndex.""" 65*b71edfaaSTobias Hieta 6691d15aa0SMarkus Lavin def splitInt(src, splitIndex, dstA, dstB, idx): 6791d15aa0SMarkus Lavin for s in src: 6891d15aa0SMarkus Lavin if s[0]: 6991d15aa0SMarkus Lavin dstA2 = [] 7091d15aa0SMarkus Lavin dstB2 = [] 7191d15aa0SMarkus Lavin idx = splitInt(s[1], splitIndex, dstA2, dstB2, idx) 7291d15aa0SMarkus Lavin dstA.append([s[0], dstA2]) 7391d15aa0SMarkus Lavin dstB.append([s[0], dstB2]) 7491d15aa0SMarkus Lavin else: 7591d15aa0SMarkus Lavin if idx <= splitIndex: 7691d15aa0SMarkus Lavin dstA.append([None, s[1]]) 7791d15aa0SMarkus Lavin else: 7891d15aa0SMarkus Lavin dstB.append([None, s[1]]) 7991d15aa0SMarkus Lavin idx += 1 8091d15aa0SMarkus Lavin return idx 8191d15aa0SMarkus Lavin 8291d15aa0SMarkus Lavin listA = [] 8391d15aa0SMarkus Lavin listB = [] 8491d15aa0SMarkus Lavin splitInt(pipeObj, splitIndex, listA, listB, 0) 8591d15aa0SMarkus Lavin return [listA, listB] 8691d15aa0SMarkus Lavin 8791d15aa0SMarkus Lavin 8891d15aa0SMarkus Lavindef remove(pipeObj, removeIndex): 8991d15aa0SMarkus Lavin """Create new pipeline object by removing pass with index removeIndex from pipeObj.""" 90*b71edfaaSTobias Hieta 9191d15aa0SMarkus Lavin def removeInt(src, removeIndex, dst, idx): 9291d15aa0SMarkus Lavin for s in src: 9391d15aa0SMarkus Lavin if s[0]: 9491d15aa0SMarkus Lavin dst2 = [] 9591d15aa0SMarkus Lavin idx = removeInt(s[1], removeIndex, dst2, idx) 9691d15aa0SMarkus Lavin dst.append([s[0], dst2]) 9791d15aa0SMarkus Lavin else: 9891d15aa0SMarkus Lavin if idx != removeIndex: 9991d15aa0SMarkus Lavin dst.append([None, s[1]]) 10091d15aa0SMarkus Lavin idx += 1 10191d15aa0SMarkus Lavin return idx 10291d15aa0SMarkus Lavin 10391d15aa0SMarkus Lavin dst = [] 10491d15aa0SMarkus Lavin removeInt(pipeObj, removeIndex, dst, 0) 10591d15aa0SMarkus Lavin return dst 10691d15aa0SMarkus Lavin 10791d15aa0SMarkus Lavin 10891d15aa0SMarkus Lavindef copy(srcPipeObj): 10991d15aa0SMarkus Lavin """Create copy of pipeline object srcPipeObj.""" 110*b71edfaaSTobias Hieta 11191d15aa0SMarkus Lavin def copyInt(dst, src): 11291d15aa0SMarkus Lavin for s in src: 11391d15aa0SMarkus Lavin if s[0]: 11491d15aa0SMarkus Lavin dst2 = [] 11591d15aa0SMarkus Lavin copyInt(dst2, s[1]) 11691d15aa0SMarkus Lavin dst.append([s[0], dst2]) 11791d15aa0SMarkus Lavin else: 11891d15aa0SMarkus Lavin dst.append([None, s[1]]) 11991d15aa0SMarkus Lavin 12091d15aa0SMarkus Lavin dstPipeObj = [] 12191d15aa0SMarkus Lavin copyInt(dstPipeObj, srcPipeObj) 12291d15aa0SMarkus Lavin return dstPipeObj 12391d15aa0SMarkus Lavin 12491d15aa0SMarkus Lavin 12591d15aa0SMarkus Lavindef prune(srcPipeObj): 12691d15aa0SMarkus Lavin """Create new pipeline object by removing empty pass-managers (those with count = 0) from srcPipeObj.""" 127*b71edfaaSTobias Hieta 12891d15aa0SMarkus Lavin def pruneInt(dst, src): 12991d15aa0SMarkus Lavin for s in src: 13091d15aa0SMarkus Lavin if s[0]: 13191d15aa0SMarkus Lavin if count(s[1]): 13291d15aa0SMarkus Lavin dst2 = [] 13391d15aa0SMarkus Lavin pruneInt(dst2, s[1]) 13491d15aa0SMarkus Lavin dst.append([s[0], dst2]) 13591d15aa0SMarkus Lavin else: 13691d15aa0SMarkus Lavin dst.append([None, s[1]]) 13791d15aa0SMarkus Lavin 13891d15aa0SMarkus Lavin dstPipeObj = [] 13991d15aa0SMarkus Lavin pruneInt(dstPipeObj, srcPipeObj) 14091d15aa0SMarkus Lavin return dstPipeObj 14191d15aa0SMarkus Lavin 14291d15aa0SMarkus Lavin 14391d15aa0SMarkus Lavinif __name__ == "__main__": 14491d15aa0SMarkus Lavin import unittest 14591d15aa0SMarkus Lavin 14691d15aa0SMarkus Lavin class Test(unittest.TestCase): 14791d15aa0SMarkus Lavin def test_0(self): 148*b71edfaaSTobias Hieta pipeStr = "a,b,A(c,B(d,e),f),g" 14991d15aa0SMarkus Lavin pipeObj = fromStr(pipeStr) 15091d15aa0SMarkus Lavin 15191d15aa0SMarkus Lavin self.assertEqual(7, count(pipeObj)) 15291d15aa0SMarkus Lavin 15391d15aa0SMarkus Lavin self.assertEqual(pipeObj, pipeObj) 15491d15aa0SMarkus Lavin self.assertEqual(pipeObj, prune(pipeObj)) 15591d15aa0SMarkus Lavin self.assertEqual(pipeObj, copy(pipeObj)) 15691d15aa0SMarkus Lavin 15791d15aa0SMarkus Lavin self.assertEqual(pipeStr, toStr(pipeObj)) 15891d15aa0SMarkus Lavin self.assertEqual(pipeStr, toStr(prune(pipeObj))) 15991d15aa0SMarkus Lavin self.assertEqual(pipeStr, toStr(copy(pipeObj))) 16091d15aa0SMarkus Lavin 16191d15aa0SMarkus Lavin [pipeObjA, pipeObjB] = split(pipeObj, 3) 162*b71edfaaSTobias Hieta self.assertEqual("a,b,A(c,B(d))", toStr(pipeObjA)) 163*b71edfaaSTobias Hieta self.assertEqual("A(B(e),f),g", toStr(pipeObjB)) 16491d15aa0SMarkus Lavin 165*b71edfaaSTobias Hieta self.assertEqual("b,A(c,B(d,e),f),g", toStr(remove(pipeObj, 0))) 166*b71edfaaSTobias Hieta self.assertEqual("a,b,A(c,B(d,e),f)", toStr(remove(pipeObj, 6))) 16791d15aa0SMarkus Lavin 16891d15aa0SMarkus Lavin pipeObjC = remove(pipeObj, 4) 169*b71edfaaSTobias Hieta self.assertEqual("a,b,A(c,B(d),f),g", toStr(pipeObjC)) 17091d15aa0SMarkus Lavin pipeObjC = remove(pipeObjC, 3) 171*b71edfaaSTobias Hieta self.assertEqual("a,b,A(c,B(),f),g", toStr(pipeObjC)) 17291d15aa0SMarkus Lavin pipeObjC = prune(pipeObjC) 173*b71edfaaSTobias Hieta self.assertEqual("a,b,A(c,f),g", toStr(pipeObjC)) 17491d15aa0SMarkus Lavin 17591d15aa0SMarkus Lavin unittest.main() 17691d15aa0SMarkus Lavin exit(0) 177