示例#1
0
 def run_all(self, max_passes):
     """ Optimizer main function, which runs the implemented optimizations on the codes. """
     if max_passes == 0:
         debug('optimizer disabled')
         return
     self.run_opt(self.del_unused_results)  # no need to run this one multiple times
     for count in xrange(max_passes):
         debug('------------- global optimizer pass %d (of max %d) -------------' % (
             count+1, max_passes))
         sum_counters = sum(self.opt_counters.values())
         self.run_opt(self.del_jumps_to_next, max_passes=self.INF_PASSES)
         self.run_opt(self.del_unused_labels)
         self.run_opt(self.reduce_push_pop, max_passes=self.INF_PASSES)
         self.run_opt(self.propagate_constants)
         #self.run_opt(self.clear_deleted_codes)
         if sum(self.opt_counters.values()) == sum_counters:
             debug('------------------ all optimizations returned finish -----------------')
             break
     # TODO don't assign dead vars
     # TODO free string memory
     # TODO [mov mem regA, mov regA regB]
     # TODO [mov regA memX, mov memX regB]
     if Flags.optimizer_summary:
         Status.add_note(LatteError('optimizer case counters:'))
         for name, count in self.opt_counters.iteritems():
             Status.add_note(LatteError(name + ': ' + str(count)))
示例#2
0
 def parse_args(cls, argv):
     parser = argparse.ArgumentParser(description='Latte x86 compiler',
                                      prog='latc_x86')
     parser.add_argument(
         'input_file',
         help='Latte source file (\'-\' for stdin, implies asm_output=\'-\')'
     )
     parser.add_argument('-o',
                         '--output',
                         dest='bin_file',
                         help='custom output executable file')
     parser.add_argument('-s',
                         '--asm-output',
                         dest='asm_file',
                         help="""custom output assembly
                         file ('-' for stdout, does not create executable)"""
                         )
     parser.add_argument('-d',
                         '--debug',
                         action='store_true',
                         help="""print debug messages
                         and output messages immediately (in particular, omit the requirement for
                         'OK'/'ERROR' to be in the first line)""")
     parser.add_argument(
         '-r',
         '--runtime',
         dest='runtime_file',
         default='runtime.o',
         help='path to latte runtime library (default runtime.o)')
     parser.add_argument('-C',
                         '--no-color',
                         dest='output_colors',
                         action='store_false',
                         help='disable output coloring')
     parser.add_argument('-O',
                         '--optimizer-passes',
                         type=int,
                         help='max optimizer loop iterations')
     parser.add_argument('--optimizer-summary',
                         action='store_true',
                         help='note optimization counters to output')
     parser.parse_args(
         namespace=cls)  # Saves values in this class, exits on error.
     # Set output file names, if not provided.
     if not cls.asm_file:
         (cls.asm_file, _) = splitext(cls.input_file)
         if (cls.asm_file != '-'):
             cls.asm_file += '.s'
         if cls.asm_file == cls.input_file and cls.asm_file != '-':
             Status.add_error(LatteError(
                 'assembly output cannot be the same file as the source code'
             ),
                              fatal=True)
     if (not cls.bin_file) and cls.asm_file != '-':
         (cls.bin_file, _) = splitext(cls.input_file)
         if cls.bin_file == cls.input_file:
             Status.add_error(LatteError(
                 'output binary cannot be the same file as the source code'
             ),
                              fatal=True)
示例#3
0
 def run_typechecks(cls):
     debug('--------------- TYPECHECK ---------------------')
     """ Run type and return checks. """
     cls.prog_tree.check_types()
     if Status.errors() > 0:
         Status.add_error(LatteError('compilation failed'), fatal=True)
     debug('-------------- CHECKED TREE -------------------')
     cls.prog_tree.print_tree()
示例#4
0
 def build_code(cls):
     """ Generate intermediate code from the tree. """
     debug('------------- BUILD CODE TREE -----------------')
     cls.prog_code = ProgCode(cls.prog_tree)
     debug('--------------- GEN CODES ---------------------')
     cls.prog_code.gen_code()
     cls.codes = [i for i in cls.prog_code.codes()]
     if Status.errors() > 0:
         Status.add_error(LatteError('compilation failed'), fatal=True)
示例#5
0
 def parse_code(cls):
     """ Parse the source code. """
     cls.lexer = LatteLexer(cls.filestream)
     cls.tokens = CommonTokenStream(cls.lexer)
     Status.set_token_stream(cls.tokens)
     cls.parser = LatteParser(cls.tokens)
     cls.parsed_prog = cls.parser.prog()
     if Status.errors() > 0:
         Status.add_error(LatteError('parsing failed'), fatal=True)
     debug('----------------- AST -------------------------')
     debug('Tree: ', cls.parsed_prog.tree.toStringTree())
示例#6
0
def main(argv):
    Latc.setup_args(argv)
    Latc.parse_code()
    Latc.build_code_tree()
    Latc.run_typechecks()
    Latc.build_code()
    Latc.run_optimizer()
    Latc.output_assembly()
    Latc.link_executable()
    Status.flush()
    sys.exit(Status.errors())
示例#7
0
 def output_assembly(cls):
     """ Output the assembly code. """
     debug('-------------- ASM OUTPUT ---------------------')
     try:
         asm_file = sys.stdout if Flags.output_to_stdout() else open(
             Flags.asm_file, 'w')
         for instr in Codes.gen_asm(cls.optimizer.codes):
             print(str(instr), file=asm_file)
         if not Flags.output_to_stdout():
             asm_file.close()
     except IOError as err:
         Status.add_error(err, fatal=True)
示例#8
0
 def build_code_tree(cls):
     """ Build the tree from code AST. """
     debug('-------------- BUILD TREE ---------------------')
     cls.nodes = CommonTreeNodeStream(cls.parsed_prog.tree)
     cls.nodes.setTokenStream(cls.tokens)
     Status.set_node_stream(cls.nodes)
     cls.builder = LatteTreeBuilder(cls.nodes)
     cls.prog_tree = cls.builder.prog()
     if Status.errors() > 0:
         Status.add_error(LatteError('parsing failed'), fatal=True)
     debug('---------------- TREE -------------------------')
     cls.prog_tree.print_tree()
示例#9
0
 def setup_args(cls, argv):
     """ Read arguments and open input stream. """
     Flags.parse_args(argv)  # Exits on error.
     if Flags.input_from_stdin():
         cls.filestream = ANTLRInputStream(sys.stdin)
         debug('INPUT: stdin')
     else:
         try:
             cls.filestream = ANTLRFileStream(Flags.input_file)
         except IOError as err:
             Status.add_error(err, fatal=True)
         debug('INPUT: ', Flags.input_file)
     debug('ASM OUTPUT: ', Flags.asm_file)
     debug('BIN OUTPUT: ', Flags.bin_file)
示例#10
0
 def link_executable(cls):
     """ Make the executable file from assembly and Latte runtime library. """
     if not Flags.output_to_stdout():
         # capture the output, so the possible 'ERROR' message is still in first line
         try:
             gcc_out = check_output([
                 'gcc', '-m32', Flags.runtime_file, Flags.asm_file, '-o',
                 Flags.bin_file
             ],
                                    stderr=STDOUT)
             if gcc_out:
                 Status.add_warning(
                     LatteError('linking messages:\n' + gcc_out))
         except CalledProcessError as err:
             Status.add_error(LatteError('linking failed:\n' + err.output),
                              fatal=True)