diff --git a/lib/cretonne/meta/gen_instr.py b/lib/cretonne/meta/gen_instr.py index 4c537acf12..2bd34a926c 100644 --- a/lib/cretonne/meta/gen_instr.py +++ b/lib/cretonne/meta/gen_instr.py @@ -28,11 +28,13 @@ def gen_formats(fmt): # type: (srcgen.Formatter) -> None """Generate an instruction format enumeration""" - fmt.doc_comment('An instruction format') - fmt.doc_comment('') - fmt.doc_comment('Every opcode has a corresponding instruction format') - fmt.doc_comment('which is represented by both the `InstructionFormat`') - fmt.doc_comment('and the `InstructionData` enums.') + fmt.doc_comment(''' + An instruction format + + Every opcode has a corresponding instruction format + which is represented by both the `InstructionFormat` + and the `InstructionData` enums. + ''') fmt.line('#[derive(Copy, Clone, PartialEq, Eq, Debug)]') with fmt.indented('pub enum InstructionFormat {', '}'): for f in InstructionFormat.all_formats: @@ -126,6 +128,7 @@ def gen_instruction_data_impl(fmt): fmt.line( 'InstructionData::{} {{ opcode, .. }} => opcode,' .format(f.name)) + fmt.line() fmt.doc_comment('Get the controlling type variable operand.') with fmt.indented( @@ -153,18 +156,22 @@ def gen_instruction_data_impl(fmt): n + ' {{ ref args, .. }} => Some(args[{}]),' .format(i)) + fmt.line() fmt.doc_comment( """ Get the value arguments to this instruction. """) gen_arguments_method(fmt, False) + fmt.line() + fmt.doc_comment( """ Get mutable references to the value arguments to this instruction. """) gen_arguments_method(fmt, True) + fmt.line() fmt.doc_comment( """ @@ -184,6 +191,7 @@ def gen_instruction_data_impl(fmt): fmt.line( n + ' { ref mut args, .. } => Some(args.take()),') fmt.line('_ => None,') + fmt.line() fmt.doc_comment( """ @@ -227,9 +235,11 @@ def gen_opcodes(groups, fmt): Return a list of all instructions. """ - fmt.doc_comment('An instruction opcode.') - fmt.doc_comment('') - fmt.doc_comment('All instructions from all supported ISAs are present.') + fmt.doc_comment(''' + An instruction opcode. + + All instructions from all supported ISAs are present. + ''') fmt.line('#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]') instrs = [] @@ -272,6 +282,8 @@ def gen_opcodes(groups, fmt): i.camel_name, i.name) fmt.line('_ => false,') + fmt.line() + fmt.line() # Generate a private opcode_format table. with fmt.indented( @@ -437,8 +449,10 @@ def gen_type_constraints(fmt, instrs): fmt.line('flags: {:#04x},'.format(flags)) fmt.line('typeset_offset: {},'.format(ctrl_typeset)) fmt.line('constraint_offset: {},'.format(offset)) + fmt.line() gen_typesets_table(fmt, type_sets) + fmt.line() fmt.comment('Table of operand constraint sequences.') with fmt.indented( @@ -668,6 +682,7 @@ def generate(isas, out_dir): fmt = srcgen.Formatter() gen_formats(fmt) gen_instruction_data_impl(fmt) + fmt.line() instrs = gen_opcodes(groups, fmt) gen_type_constraints(fmt, instrs) fmt.update_file('opcodes.rs', out_dir) diff --git a/lib/cretonne/meta/gen_types.py b/lib/cretonne/meta/gen_types.py index c5e36758ba..bc912e78f7 100644 --- a/lib/cretonne/meta/gen_types.py +++ b/lib/cretonne/meta/gen_types.py @@ -28,6 +28,7 @@ def emit_type(ty, fmt): fmt.line( 'pub const {}: Type = Type({:#x});' .format(name, ty.number)) + fmt.line() def emit_vectors(bits, fmt): diff --git a/lib/cretonne/meta/srcgen.py b/lib/cretonne/meta/srcgen.py index f0f7931ea1..9761160487 100644 --- a/lib/cretonne/meta/srcgen.py +++ b/lib/cretonne/meta/srcgen.py @@ -168,12 +168,30 @@ def parse_multiline(s): # type: (str) -> List[str] """ Given a multi-line string, split it into a sequence of lines after - stripping a common indentation. This is useful for strings defined with doc - strings: + stripping a common indentation, as described in the "trim" function + from PEP 257. This is useful for strings defined with doc strings: >>> parse_multiline('\\n hello\\n world\\n') - [None, 'hello', 'world'] + ['hello', 'world'] """ - lines = s.splitlines() - indents = list(i for i in (_indent(l) for l in lines) if i) - indent = min(indents) if indents else 0 - return list(l[indent:] if len(l) > indent else None for l in lines) + if not s: + return [] + # Convert tabs to spaces (following the normal Python rules) + # and split into a list of lines: + lines = s.expandtabs().splitlines() + # Determine minimum indentation (first line doesn't count): + indent = sys.maxsize + for line in lines[1:]: + stripped = line.lstrip() + if stripped: + indent = min(indent, len(line) - len(stripped)) + # Remove indentation (first line is special): + trimmed = [lines[0].strip()] + if indent < sys.maxsize: + for line in lines[1:]: + trimmed.append(line[indent:].rstrip()) + # Strip off trailing and leading blank lines: + while trimmed and not trimmed[-1]: + trimmed.pop() + while trimmed and not trimmed[0]: + trimmed.pop(0) + return trimmed