view python/ppci/irutils.py @ 307:e609d5296ee9

Massive rewrite of codegenerator
author Windel Bouwman
date Thu, 12 Dec 2013 20:42:56 +0100
parents
children 68b01c8abf8a
line wrap: on
line source


"""
    Some utilities for ir-code.
"""
from .ir import Temp, Block, Function, Statement

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

        print('"{}" -> "{}" [label="entry"]'
              .format(id(f), id(f.entry)), file=outf)
    print('}', file=outf)


# Constructing IR:

class NamedClassGenerator:
    def __init__(self, prefix, cls):
        self.prefix = prefix
        self.cls = cls

        def NumGen():
            a = 0
            while True:
                yield a
                a = a + 1
        self.nums = NumGen()

    def gen(self, prefix=None):
        if not prefix:
            prefix = self.prefix
        return self.cls('{0}{1}'.format(prefix, self.nums.__next__()))


class Builder:
    """ Base class for ir code generators """
    def __init__(self):
        self.prepare()

    def prepare(self):
        self.newTemp = NamedClassGenerator('reg', Temp).gen
        self.newBlock2 = NamedClassGenerator('block', Block).gen
        self.bb = None
        self.m = None
        self.fn = None
        self.loc = None

    # Helpers:
    def setModule(self, m):
        self.m = m

    def newFunction(self, name):
        f = Function(name)
        self.m.addFunc(f)
        return f

    def newBlock(self):
        assert self.fn
        b = self.newBlock2()
        b.function = self.fn
        return b

    def setFunction(self, f):
        self.fn = f
        self.bb = f.entry if f else None

    def setBlock(self, b):
        self.bb = b

    def setLoc(self, l):
        self.loc = l

    def emit(self, i):
        assert isinstance(i, Statement)
        i.debugLoc = self.loc
        if not self.bb:
            raise Exception('No basic block')
        self.bb.addInstruction(i)