view python/ir/module.py @ 272:e64bae57cda8

refactor ir
author Windel Bouwman
date Sat, 31 Aug 2013 17:58:54 +0200
parents cf7d5fb7d9c8
children ea93e0a7a31e
line wrap: on
line source

# IR-Structures:


class Module:
    """ Main container for a piece of code. """
    def __init__(self, name):
      self.name = name
      self.funcs = []
      self.variables = []

    def __repr__(self):
        return 'IR-module [{0}]'.format(self.name)

    def addFunc(self, f):
        self.funcs.append(f)

    addFunction = addFunc

    def addVariable(self, v):
        self.variables.append(v)

    def getVariables(self):
        return self.variables

    Variables = property(getVariables)

    def getFunctions(self):
        return self.funcs

    Functions = property(getFunctions)

    def findFunction(self, name):
        for f in self.funcs:
            if f.name == name:
                return f
        raise KeyError(name)

    getFunction = findFunction

    def dump(self):
      print(self)
      for v in self.Variables:
            print('   ', v)
      for fn in self.Functions:
         print(fn)
         for bb in fn.BasicBlocks:
            print('   ', bb)
            for ins in bb.Instructions:
               print('      ', ins)

    def dumpgv(self, outf):
      outf.write('digraph G \n{\n')
      for f in self.Functions:
         outf.write('{0} [label="{1}" shape=box3d]\n'.format(id(f), f))
         for bb in f.BasicBlocks:
            contents = str(bb) + '\n'
            contents += '\n'.join([str(i) for i in bb.Instructions])
            outf.write('{0} [shape=note label="{1}"];\n'.format(id(bb), contents))
            for successor in bb.Successors:
               outf.write('"{0}" -> "{1}"\n'.format(id(bb), id(successor)))

         outf.write('"{0}" -> "{1}" [label="entry"]\n'.format(id(f), id(f.entry)))
      outf.write('}\n')

    # Analysis functions:
    def check(self):
        """ Perform sanity check on module """
        for f in self.Functions:
            f.check()


class Function:
    def __init__(self, name):
        self.name = name
        self.entry = Block('{}_entry'.format(name))
        self.epiloog = Block('{}_epilog'.format(name))
        self.arguments = []

    def __repr__(self):
        return 'Function {0}'.format(self.name)

    def addBB(self, bb):
        self.bbs.append(bb)
        bb.parent = self
    addBasicBlock = addBB

    def removeBasicBlock(self, bb):
        self.bbs.remove(bb)
        bb.parent = None

    def getBBs(self):
        bbs = [self.entry]
        worklist = [self.entry]
        while worklist:
            b = worklist.pop()
            for sb in b.Successors:
                if sb not in bbs:
                    bbs.append(sb)
                    worklist.append(sb)
        bbs.remove(self.entry)
        if self.epiloog in bbs:
            bbs.remove(self.epiloog)
        bbs.insert(0, self.entry)
        bbs.append(self.epiloog)
        return bbs

    def findBasicBlock(self, name):
        for bb in self.bbs:
            if bb.name == name:
                return bb
        raise KeyError(name)

    BasicBlocks = property(getBBs)

    @property
    def Entry(self):
        return self.entry

    def check(self):
        pass

    def call(self, *args):
        varmap = {}
        bb = self.Entry
        ip = 0
        while True:
            i = bb.Instructions[ip]
            ip += 1
            return


class Block:
    """ 
        Uninterrupted sequence of instructions with a label at the start.
    """
    def __init__(self, name):
        self.name = name
        self.instructions = []

    def __repr__(self):
        return 'Block {0}'.format(self.name)

    def addInstruction(self, i):
        i.parent = self
        self.instructions.append(i)

    def replaceInstruction(self, i1, i2):
        idx = self.instructions.index(i1)
        i1.parent = None
        i1.delete()
        i2.parent = self
        self.instructions[idx] = i2

    def removeInstruction(self, i):
        i.parent = None
        i.delete()
        self.instructions.remove(i)

    def getInstructions(self):
        return self.instructions
    Instructions = property(getInstructions)

    def getLastIns(self):
        return self.instructions[-1]
    LastInstruction = property(getLastIns)

    @property
    def Empty(self):
        return len(self.instructions) == 0

    @property
    def FirstInstruction(self):
        return self.instructions[0]

    def getSuccessors(self):
        if not self.Empty:
            return self.LastInstruction.Targets
        return []
    Successors = property(getSuccessors)

    def getPredecessors(self):
        preds = []
        for bb in self.parent.BasicBlocks:
            if self in bb.Successors:
                preds.append(bb)
        return preds
    Predecessors = property(getPredecessors)

    def precedes(self, other):
        raise NotImplementedError()

    def check(self):
        pass