view python/ppci/buildtasks.py @ 336:d1ecc493384e

Added spiffy armtoken class for bit fiddeling. Added cool test that checks for build repeatability
author Windel Bouwman
date Wed, 19 Feb 2014 22:32:15 +0100
parents 582a1aaa3983
children b00219172a42
line wrap: on
line source


"""
Defines task classes that can compile, link etc..
Task can depend upon one another.
"""

import logging

from .c3 import Builder
from .irutils import Verifier
from .codegen import CodeGenerator
from .transform import CleanPass, RemoveAddZero
from .tasks import Task
from . import DiagnosticsManager
from .assembler import Assembler
from .objectfile import ObjectFile
from .linker import Linker
import outstream


class BuildTask(Task):
    """ Base task for all kind of weird build tasks """
    def __init__(self, name):
        super().__init__(name)
        self.logger = logging.getLogger('buildtask')


class Assemble(BuildTask):
    """ Task that can runs the assembler over the source and enters the 
        output into an object file """
    def __init__(self, source, target, output_object):
        super().__init__('Assemble')
        self.source = source
        self.output = output_object
        self.ostream = outstream.BinaryOutputStream(self.output)
        self.assembler = Assembler(target, self.ostream)

    def run(self):
        self.ostream.selectSection('code')
        self.assembler.assemble(self.source)


class Compile(BuildTask):
    """ Task that compiles C3 source for some target into an object file """
    def __init__(self, sources, includes, target, output_object):
        super().__init__('Compile')
        self.sources = sources
        self.includes = includes
        self.target = target
        self.output = output_object

    def run(self):
        self.logger.debug('Compile started')
        diag = DiagnosticsManager()
        c3b = Builder(diag, self.target)
        cg = CodeGenerator(self.target)

        for ircode in c3b.build(self.sources, self.includes):
            if not ircode:
                return

            d = {'ircode':ircode}
            self.logger.debug('Verifying code {}'.format(ircode), extra=d)
            Verifier().verify(ircode)

            # Optimization passes:
            CleanPass().run(ircode)
            Verifier().verify(ircode)
            RemoveAddZero().run(ircode)
            Verifier().verify(ircode)
            CleanPass().run(ircode)
            Verifier().verify(ircode)

            # Code generation:
            d = {'ircode':ircode}
            self.logger.debug('Starting code generation for {}'.format(ircode), extra=d)
            o = outstream.BinaryOutputStream(self.output)
            cg.generate(ircode, o)

        if not c3b.ok:
            diag.printErrors()
            raise TaskError('Compile errors')


class Link(BuildTask):
    """ Link together a collection of object files """
    def __init__(self, objects, layout, output_file):
        super().__init__('Link')
        self.objects = objects
        self.linker = Linker()
        self.duration = 0.1337
        self.layout = layout
        self.output_file = output_file

    def run(self):
        output_obj = self.linker.link(self.objects, self.layout)
        code = output_obj.get_section('code').data
        with open(self.output_file, 'wb') as f:
            f.write(code)


class ObjCopy(BuildTask):
    def __init__(self, objects, output_file):
        super().__init__('ObjCopy')