Mercurial > lcfOS
view python/zcc.py @ 327:61c9df5bffce
Changed emulated board to cortex a8 board
author | Windel Bouwman |
---|---|
date | Sat, 01 Feb 2014 17:21:21 +0100 |
parents | e9fe6988497c |
children | 8f6f3ace4e78 |
line wrap: on
line source
#!/usr/bin/env python import sys import argparse import logging from ppci.c3 import Builder, AstPrinter import ppci from ppci.irutils import Verifier, Writer from ppci.codegen import CodeGenerator import outstream from utils import HexFile import target from target.target_list import target_list from ppci import irutils import io from ppci.transform import CleanPass, RemoveAddZero logformat='%(asctime)s|%(levelname)s|%(name)s|%(message)s' def logLevel(s): """ Converts a string to a valid logging level """ numeric_level = getattr(logging, s.upper(), None) if not isinstance(numeric_level, int): raise ValueError('Invalid log level: {}'.format(s)) return numeric_level class RstFormatter(logging.Formatter): """ Formatter that tries to create an rst document """ def __init__(self): super().__init__(fmt=logformat) def format(self, record): s = super().format(record) s += '\n' if hasattr(record, 'c3_ast'): f = io.StringIO() print('', file=f) print('', file=f) print('.. code::', file=f) print('', file=f) AstPrinter().printAst(record.c3_ast, f) print('', file=f) s += '\n' + f.getvalue() if hasattr(record, 'ircode'): f = io.StringIO() print('', file=f) print('', file=f) print('.. code::', file=f) print('', file=f) Writer(' ').write(record.ircode, f) print('', file=f) s += '\n' + f.getvalue() if hasattr(record, 'irfunc'): f = io.StringIO() print('', file=f) print('', file=f) print('.. code::', file=f) print('', file=f) Writer(' ').write_function(record.irfunc, f) print('', file=f) s += '\n' + f.getvalue() if hasattr(record, 'ppci_frame'): f = io.StringIO() frame = record.ppci_frame print('', file=f) print('.. code::', file=f) print('', file=f) print(' {}'.format(frame.name), file=f) for i in frame.instructions: print(' {}'.format(i),file=f) print('', file=f) s += '\n' + f.getvalue() if hasattr(record, 'ra_cfg'): f = io.StringIO() print('', file=f) print('', file=f) print('.. graphviz::', file=f) print('', file=f) print(' digraph G {', file=f) print(' size="8,80";', file=f) cfg = record.ra_cfg cfg.to_dot(f) print(' }', file=f) print('', file=f) s += '\n' + f.getvalue() if hasattr(record, 'ra_ig'): f = io.StringIO() print('', file=f) print('', file=f) print('.. graphviz::', file=f) print('', file=f) print(' digraph G {', file=f) print(' ratio="compress";', file=f) print(' size="8,80";', file=f) ig = record.ra_ig ig.to_dot(f) print(' }', file=f) print('', file=f) s += '\n' + f.getvalue() if hasattr(record, 'zcc_outs'): f = io.StringIO() print('', file=f) print('', file=f) print('.. code::', file=f) print('', file=f) outstream.OutputStreamWriter(' ').dump(record.zcc_outs, f) print('', file=f) s += '\n' + f.getvalue() return s targets = {t.name: t for t in target_list} targetnames = list(targets.keys()) # Parse arguments: parser = argparse.ArgumentParser(description='lcfos Compiler') 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('--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,[WARN])', type=logLevel, default='WARN') parser.add_argument('--report', help='Specify a file to write the compile report to', type=argparse.FileType('w')) def zcc(srcs, imps, tg, outs, diag): """ Compiler driver Compile sources into output stream. Sources is an iterable of open files. """ logger = logging.getLogger('zcc') logger.info('Zcc started {}'.format(srcs)) # 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 d = {'ircode':ircode} logger.info('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} logger.info('Starting code generation for {}'.format(ircode), extra=d) 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): # Configure some logging: logging.getLogger().setLevel(logging.DEBUG) ch = logging.StreamHandler() ch.setFormatter(logging.Formatter(logformat)) ch.setLevel(args.log) logging.getLogger().addHandler(ch) if args.report: fh = logging.StreamHandler(stream=args.report) fh.setFormatter(RstFormatter()) logging.getLogger().addHandler(fh) tg = targets[args.target] diag = ppci.DiagnosticsManager() outs = outstream.TextOutputStream() res = zcc(args.source, args.imp, tg, outs, diag) if not res: diag.printErrors() return 1 logging.info('Assembly created', extra={'zcc_outs':outs}) 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) if args.report: logging.getLogger().removeHandler(fh) logging.getLogger().removeHandler(ch) return 0 if __name__ == '__main__': arguments = parser.parse_args() sys.exit(main(arguments))