Source code for ducky.tools.cc

import sys
import argparse

from six import iterkeys

from . import parse_options
from ..cc import CompilerError
from ..cc.passes import AST_PASSES, BT_PASSES

from itertools import chain
from pycparser import parse_file

[docs]def compile_file(logger, options, file_in, file_out): ast = parse_file(file_in, use_cpp = True, cpp_path = 'gcc', cpp_args = ['-E', r'-Ilibc/include']) # ast.show() options.passes = list(set(options.passes)) def __apply_opt_passes(passes, tree): tree_modified = True while tree_modified is True: tree_modified = False for opt_pass in iterkeys(passes): if opt_pass not in options.passes or ('no-' + opt_pass) in options.passes: logger.debug('Pass %s is disabled', opt_pass) continue logger.debug('Pass %s is enabled, running', opt_pass) v = passes[opt_pass](logger) v.DOWN() v.tree_modified = True while v.tree_modified is True: v.tree_modified = False v.visit(tree) if v.tree_modified is True: tree_modified = True v.UP() __apply_opt_passes(AST_PASSES, ast) cv = AST_PASSES['ast-codegen'](logger) try: cv.visit(ast) except Exception: logger.exception('Exception raised during compilation') raise SystemExit(1) __apply_opt_passes(BT_PASSES, cv) with open(file_out, 'w') as f_out: f_out.write(cv.materialize())
[docs]def main(): parser = argparse.ArgumentParser() group = parser.add_argument_group('Tool verbosity') group.add_argument('-d', '--debug', dest = 'debug', action = 'store_true', default = False, help = 'Debug mode') group.add_argument('-q', '--quiet', dest = 'quiet', action = 'count', default = 0, help = 'Decrease verbosity. This option can be used multiple times') group.add_argument('-v', '--verbose', dest = 'verbose', action = 'count', default = 0, help = 'Increase verbosity. This option can be used multiple times') group = parser.add_argument_group('File options') group.add_argument('-i', dest = 'file_in', action = 'append', default = [], help = 'Input file') group.add_argument('-o', dest = 'file_out', action = 'append', default = [], help = 'Output file') group.add_argument('-f', dest = 'force', action = 'store_true', default = False, help = 'Force overwrite of the output file') group = parser.add_argument_group('Passes') group.add_argument('-O', dest = 'opt_level', action = 'store', default = 1, nargs = 1, type = int, help = 'Set requested optimization level', metavar = 'LEVEL') group.add_argument('-p', dest = 'passes', action = 'append', default = [], nargs = 1, help = 'Enable or disable optimization pass', metavar = 'PASS') options, logger = parse_options(parser) from ..cc.passes import load as load_passes load_passes(logger) options.passes = list(chain.from_iterable(options.passes)) if options.opt_level == [0]: for p in iterkeys(AST_PASSES): options.passes.append('no-%s' % p) for p in iterkeys(BT_PASSES): options.passes.append('no-%s' % p) elif options.opt_level == [1]: options.passes += ['ast-const-prop', 'ast-dce', 'bt-peephole', 'bt-simplify'] else: pass if not options.file_in: parser.print_help() sys.exit(1) try: for filepath in options.file_in: compile_file(logger, options, filepath, options.file_out.pop(0)) except CompilerError as e: logger.error(e.message)