view python/zcc.py @ 301:6753763d3bec

merge codegen into ppci package
author Windel Bouwman
date Thu, 05 Dec 2013 17:02:38 +0100
parents 158068af716c
children 0615b5308710
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


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:
            ircode.dump()

        # Code generation:
        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))