view python/ppci/codegen/codegen.py @ 364:c49459768aaa

Work on globals
author Windel Bouwman
date Wed, 19 Mar 2014 20:24:03 +0100
parents c2ddc8a36f5e
children 39bf68bf1891
line wrap: on
line source

from .. import ir
from ..irutils import Verifier
from ..transform import RemoveAddZero
from ..target import Target
from .. import CompilerError
from .canon import make as canonicalize
from .registerallocator import RegisterAllocator
import logging


class CodeGenerator:
    """ Generic code generator """
    def __init__(self, target):
        # TODO: schedule traces in better order.
        # This is optional!
        assert isinstance(target, Target), target
        self.logger = logging.getLogger('codegen')
        self.target = target
        self.ins_sel = target.ins_sel
        self.ra = RegisterAllocator()
        self.verifier = Verifier()

    def generateFunc(self, irfunc, outs):
        """ Generate code for one function into a frame """
        self.logger.debug('Generating code for {}'.format(irfunc.name))
        # Create a frame for this function:
        frame = self.target.FrameClass(ir.label_name(irfunc))

        # Canonicalize the intermediate language:
        canonicalize(irfunc, frame)
        RemoveAddZero().run(irfunc)
        self.logger.debug('after canonicalize', extra={'irfunc': irfunc})
        self.verifier.verify_function(irfunc)
        self.ins_sel.munchFunction(irfunc, frame)
        self.logger.debug('Selected instructions', extra={'ppci_frame': frame})

        # Do register allocation:
        self.ra.allocFrame(frame)
        self.logger.debug('Registers allocated, now adding final glue')
        # TODO: Peep-hole here?

        # Add label and return and stack adjustment:
        frame.EntryExitGlue3()

        # Materialize the register allocated instructions into a stream of
        # real instructions.
        self.target.lower_frame_to_stream(frame, outs)
        self.logger.debug('Instructions materialized')
        return frame

    def generate(self, ircode, outs):
        """ Generate code into output stream """
        assert isinstance(ircode, ir.Module)
        outs.select_section('data')
        for global_variable in ircode.Variables:
            print(global_variable)
            self.target.emit_global(outs, ir.label_name(global_variable))
        outs.select_section('code')

        # Munch program into a bunch of frames. One frame per function.
        # Each frame has a flat list of abstract instructions.
        # Generate code for all functions:
        self.frames = [self.generateFunc(f, outs) for f in ircode.Functions]
        return self.frames