view python/zcc.py @ 311:ff665880a6b0

Added testcase for kernel and userspace
author Windel Bouwman
date Mon, 16 Dec 2013 12:49:24 +0100
parents b145f8e6050b
children 2c9768114877
line wrap: on
line source

#!/usr/bin/env python

import sys
import argparse
import logging

from ppci.c3 import Builder
import ppci
from ppci.codegen import CodeGenerator
import outstream
from utils import HexFile
import target
from ppci import irutils
import io


logformat='%(asctime)s|%(levelname)s|%(name)s|%(message)s'


def logLevel(s):
    numeric_level = getattr(logging, s.upper(), None)
    if not isinstance(numeric_level, int):
        raise ValueError('Invalid log level: {}'.format(s))
    return numeric_level


target_list = [target.armtarget]
targets = {t.name: t for t in target_list}
targetnames = list(targets.keys())

# Parse arguments:
parser = argparse.ArgumentParser(description='lcfos Compiler')
# Input:
parser.add_argument('source', type=argparse.FileType('r'), \
  help='the source file to build', nargs="+")
parser.add_argument('-i', '--imp', type=argparse.FileType('r'), \
  help='Possible import module', action='append', default=[])

parser.add_argument('--dumpir', action='store_true', help="Dump IR-code")
parser.add_argument('--dumpasm', action='store_true', help="Dump ASM-code")
parser.add_argument('--optimize', action='store_true', help="Optimize")
parser.add_argument('--target', help="Backend selection",
    choices=targetnames, required=True)
parser.add_argument('-o', '--output', help='Output file', metavar='filename')
parser.add_argument('--hexfile', help='Output hexfile',
    type=argparse.FileType('w'))
parser.add_argument('--log', help='Log level (INFO,DEBUG)', type=logLevel)


def zcc(srcs, imps, tg, outs, diag, dumpir=False):
    """
        Compile sources into output stream.
        Sources is an iterable of open files.
    """
    logging.info('Zcc started')
    # Front end:
    c3b = Builder(diag, tg)
    cg = CodeGenerator(tg)

    # TODO: remove this arm specifics:
    outs.getSection('code').address = 0x08000000
    outs.getSection('data').address = 0x20000000

    # Emit some custom start code:
    tg.startCode(outs)
    for ircode in c3b.build(srcs, imps):
        if not ircode:
            return
        # Optimization passes, TODO

        if dumpir:
            f = io.StringIO()
            irutils.Writer().write(ircode, f)
            print(f.getvalue())

        # Code generation:
        logging.info('Starting code generation for {}'.format(ircode))
        cg.generate(ircode, outs)
    # TODO: fixup references, do this in another way?
    outs.backpatch()
    outs.backpatch()  # Why two times?
    return c3b.ok


def main(args):
    logging.basicConfig(format=logformat, level=args.log)
    tg = targets[args.target]
    diag = ppci.DiagnosticsManager()
    outs = outstream.TextOutputStream()

    res = zcc(args.source, args.imp, tg, outs, diag, dumpir=args.dumpir)
    if not res:
        diag.printErrors()
        return 1

    if args.dumpasm:
        outs.dump()

    code_bytes = outs.sections['code'].to_bytes()
    if args.output:
        output_filename = args.output
        with open(output_filename, 'wb') as f:
            f.write(code_bytes)

    if args.hexfile:
        logging.info('Creating hexfile')
        hf = HexFile()
        hf.addRegion(0x08000000, code_bytes)
        hf.save(args.hexfile)
    return 0


if __name__ == '__main__':
    arguments = parser.parse_args()
    sys.exit(main(arguments))