From eba396546a76ee720d948ac74172798308da363b Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Wed, 6 Apr 2016 10:45:06 -0700 Subject: [PATCH] Begin source generation. Start out easy by emiting an opcodes.rs file containing an opcode enumeration. --- meta/build.py | 6 ++++ meta/gen_instr.py | 31 ++++++++++++++++++++ meta/srcgen.py | 73 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 110 insertions(+) create mode 100644 meta/gen_instr.py create mode 100644 meta/srcgen.py diff --git a/meta/build.py b/meta/build.py index 2cdda53403..76673fa62b 100644 --- a/meta/build.py +++ b/meta/build.py @@ -3,9 +3,15 @@ # This script is run from src/libcretonne/build.rs to generate Rust files. import argparse +import target +import gen_instr parser = argparse.ArgumentParser(description='Generate sources for Cretonne.') parser.add_argument('--out-dir', help='set output directory') args = parser.parse_args() out_dir = args.out_dir + +targets = target.all_targets() + +gen_instr.generate(targets, out_dir) diff --git a/meta/gen_instr.py b/meta/gen_instr.py new file mode 100644 index 0000000000..a92609c861 --- /dev/null +++ b/meta/gen_instr.py @@ -0,0 +1,31 @@ +""" +Generate sources with instruction info. +""" + +import srcgen + +def collect_instr_groups(targets): + seen = set() + groups = [] + for t in targets: + for g in t.instruction_groups: + if g not in seen: + groups.append(g) + seen.add(g) + return groups + +def gen_opcodes(groups, out_dir): + """Generate opcode enumerations.""" + fmt = srcgen.Formatter() + fmt.line('enum Opcode {') + fmt.indent_push() + for g in groups: + for i in g.instructions: + fmt.line(i.camel_name + ',') + fmt.indent_pop() + fmt.line('}') + fmt.update_file('opcodes.rs', out_dir) + +def generate(targets, out_dir): + groups = collect_instr_groups(targets) + gen_opcodes(groups, out_dir) diff --git a/meta/srcgen.py b/meta/srcgen.py new file mode 100644 index 0000000000..9778e2c518 --- /dev/null +++ b/meta/srcgen.py @@ -0,0 +1,73 @@ +""" +Source code generator. + +The `srcgen` module contains generic helper routines and classes for generating +source code. + +""" + +import sys +import os + +class Formatter(object): + """ + Source code formatter class. + + - Collect source code to be written to a file. + - Keep track of indentation. + + Indentation example: + + >>> f = Formatter() + >>> f.line('Hello line 1') + >>> f.writelines() + Hello line 1 + >>> f.indent_push() + >>> f.comment('Nested comment') + >>> f.indent_pop() + >>> f.line('Back again') + >>> f.writelines() + Hello line 1 + // Nested comment + Back again + + """ + + shiftwidth = 2 + + def __init__(self): + self.indent = '' + self.lines = [] + + def indent_push(self): + """Increase current indentation level by one.""" + self.indent += ' ' * self.shiftwidth + + def indent_pop(self): + """Decrease indentation by one level.""" + assert self.indent != '', 'Already at top level indentation' + self.indent = self.indent[0:-self.shiftwidth] + + def line(self, s): + """And an indented line.""" + self.lines.append('{}{}\n'.format(self.indent, s)) + + def writelines(self, f=None): + """Write all lines to `f`.""" + if not f: + f = sys.stdout + f.writelines(self.lines) + + def update_file(self, filename, directory): + if directory is not None: + filename = os.path.join(directory, filename) + with open(filename, 'w') as f: + self.writelines(f) + + def comment(self, s): + """Add a comment line.""" + self.line('// ' + s) + +if __name__ == "__main__": + import doctest + doctest.testmod()