def gen_opcodes(groups, fmt): """ Generate opcode enumerations. 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.line('#[derive(Copy, Clone, PartialEq, Eq, Debug)]') instrs = [] with fmt.indented('pub enum Opcode {', '}'): fmt.doc_comment('An invalid opcode.') fmt.line('NotAnOpcode,') for g in groups: for i in g.instructions: instrs.append(i) i.number = len(instrs) fmt.doc_comment('`{}`. ({})'.format(i, i.format.name)) # Document polymorphism. if i.is_polymorphic: if i.use_typevar_operand: fmt.doc_comment('Type inferred from {}.'.format( i.ins[i.format.typevar_operand])) # Enum variant itself. fmt.line(i.camel_name + ',') fmt.line() # Generate a private opcode_format table. with fmt.indented( 'const OPCODE_FORMAT: [InstructionFormat; {}] = ['.format( len(instrs)), '];'): for i in instrs: fmt.format('InstructionFormat::{}, // {}', i.format.name, i.name) fmt.line() # Generate a private opcode_name function. with fmt.indented('fn opcode_name(opc: Opcode) -> &\'static str {', '}'): with fmt.indented('match opc {', '}'): fmt.line('Opcode::NotAnOpcode => "<not an opcode>",') for i in instrs: fmt.format('Opcode::{} => "{}",', i.camel_name, i.name) fmt.line() # Generate an opcode hash table for looking up opcodes by name. hash_table = constant_hash.compute_quadratic( instrs, lambda i: constant_hash.simple_hash(i.name)) with fmt.indented( 'const OPCODE_HASH_TABLE: [Opcode; {}] = ['.format( len(hash_table)), '];'): for i in hash_table: if i is None: fmt.line('Opcode::NotAnOpcode,') else: fmt.format('Opcode::{},', i.camel_name) fmt.line() return instrs
def gen_opcodes(groups, fmt): # type: (Sequence[InstructionGroup], srcgen.Formatter) -> Sequence[Instruction] # noqa """ Generate opcode enumerations. Return a list of all instructions. """ fmt.doc_comment(''' An instruction opcode. All instructions from all supported ISAs are present. ''') fmt.line('#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]') instrs = [] # We explicitly set the discriminant of the first variant to 1, which # allows us to take advantage of the NonZero optimization, meaning that # wrapping enums can use the 0 discriminant instead of increasing the size # if the whole type, and so SIZEOF(Option<Opcode>>) == SIZEOF(Opcode) is_first_opcode = True with fmt.indented('pub enum Opcode {', '}'): for g in groups: for i in g.instructions: instrs.append(i) i.number = len(instrs) fmt.doc_comment('`{}`. ({})'.format(i, i.format.name)) # Document polymorphism. if i.is_polymorphic: if i.use_typevar_operand: opnum = i.value_opnums[i.format.typevar_operand] fmt.doc_comment('Type inferred from {}.'.format( i.ins[opnum])) # Enum variant itself. if is_first_opcode: fmt.line(i.camel_name + ' = 1,') is_first_opcode = False else: fmt.line(i.camel_name + ',') fmt.line() with fmt.indented('impl Opcode {', '}'): for attr in sorted(Instruction.ATTRIBS.keys()): fmt.doc_comment(Instruction.ATTRIBS[attr]) with fmt.indented('pub fn {}(self) -> bool {{'.format(attr), '}'): m = srcgen.Match('self') for i in instrs: if getattr(i, attr): m.arm('Opcode::' + i.camel_name, [], 'true') m.arm('_', [], 'false') fmt.match(m) fmt.line() fmt.line() # Generate a private opcode_format table. with fmt.indented( 'const OPCODE_FORMAT: [InstructionFormat; {}] = ['.format( len(instrs)), '];'): for i in instrs: fmt.format('InstructionFormat::{}, // {}', i.format.name, i.name) fmt.line() # Generate a private opcode_name function. with fmt.indented('fn opcode_name(opc: Opcode) -> &\'static str {', '}'): m = srcgen.Match('opc') for i in instrs: m.arm('Opcode::' + i.camel_name, [], '"{}"'.format(i.name)) fmt.match(m) fmt.line() # Generate an opcode hash table for looking up opcodes by name. hash_table = constant_hash.compute_quadratic( instrs, lambda i: constant_hash.simple_hash(i.name)) with fmt.indented( 'const OPCODE_HASH_TABLE: [Option<Opcode>; {}] = ['.format( len(hash_table)), '];'): for i in hash_table: if i is None: fmt.line('None,') else: fmt.format('Some(Opcode::{}),', i.camel_name) fmt.line() return instrs
def hash_setting(s): # type: (Union[Setting, Preset]) -> int return constant_hash.simple_hash(s.name)
def gen_opcodes(groups, fmt): # type: (Sequence[InstructionGroup], srcgen.Formatter) -> Sequence[Instruction] # noqa """ Generate opcode enumerations. Return a list of all instructions. """ fmt.doc_comment(''' An instruction opcode. All instructions from all supported ISAs are present. ''') fmt.line('#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]') instrs = [] # We explicitly set the discriminant of the first variant to 1, which # allows us to take advantage of the NonZero optimization, meaning that # wrapping enums can use the 0 discriminant instead of increasing the size # if the whole type, and so SIZEOF(Option<Opcode>>) == SIZEOF(Opcode) is_first_opcode = True with fmt.indented('pub enum Opcode {', '}'): for g in groups: for i in g.instructions: instrs.append(i) i.number = len(instrs) fmt.doc_comment('`{}`. ({})'.format(i, i.format.name)) # Document polymorphism. if i.is_polymorphic: if i.use_typevar_operand: opnum = i.value_opnums[i.format.typevar_operand] fmt.doc_comment( 'Type inferred from {}.' .format(i.ins[opnum])) # Enum variant itself. if is_first_opcode: fmt.line(i.camel_name + ' = 1,') is_first_opcode = False else: fmt.line(i.camel_name + ',') fmt.line() with fmt.indented('impl Opcode {', '}'): for attr in sorted(Instruction.ATTRIBS.keys()): fmt.doc_comment(Instruction.ATTRIBS[attr]) with fmt.indented('pub fn {}(self) -> bool {{' .format(attr), '}'): with fmt.indented('match self {', '}'): for i in instrs: if getattr(i, attr): fmt.format( 'Opcode::{} => true,', i.camel_name, i.name) fmt.line('_ => false,') fmt.line() fmt.line() # Generate a private opcode_format table. with fmt.indented( 'const OPCODE_FORMAT: [InstructionFormat; {}] = [' .format(len(instrs)), '];'): for i in instrs: fmt.format( 'InstructionFormat::{}, // {}', i.format.name, i.name) fmt.line() # Generate a private opcode_name function. with fmt.indented('fn opcode_name(opc: Opcode) -> &\'static str {', '}'): with fmt.indented('match opc {', '}'): for i in instrs: fmt.format('Opcode::{} => "{}",', i.camel_name, i.name) fmt.line() # Generate an opcode hash table for looking up opcodes by name. hash_table = constant_hash.compute_quadratic( instrs, lambda i: constant_hash.simple_hash(i.name)) with fmt.indented( 'const OPCODE_HASH_TABLE: [Option<Opcode>; {}] = [' .format(len(hash_table)), '];'): for i in hash_table: if i is None: fmt.line('None,') else: fmt.format('Some(Opcode::{}),', i.camel_name) fmt.line() return instrs
def gen_opcodes(groups, fmt): """ Generate opcode enumerations. 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.line('#[derive(Copy, Clone, PartialEq, Eq, Debug)]') instrs = [] # We explicitly set the discriminant of the first variant to 1, which # allows us to take advantage of the NonZero optimization, meaning that # wrapping enums can use the 0 discriminant instead of increasing the size # if the whole type, and so SIZEOF(Option<Opcode>>) == SIZEOF(Opcode) is_first_opcode = True with fmt.indented('pub enum Opcode {', '}'): for g in groups: for i in g.instructions: instrs.append(i) i.number = len(instrs) fmt.doc_comment('`{}`. ({})'.format(i, i.format.name)) # Document polymorphism. if i.is_polymorphic: if i.use_typevar_operand: fmt.doc_comment('Type inferred from {}.'.format( i.ins[i.format.typevar_operand])) # Enum variant itself. if is_first_opcode: fmt.line(i.camel_name + ' = 1,') is_first_opcode = False else: fmt.line(i.camel_name + ',') fmt.line() with fmt.indented('impl Opcode {', '}'): attrs = [{ 'name': 'is_branch', 'comment': 'True for all branch instructions.' }, { 'name': 'is_terminator', 'comment': 'True for instructions that terminate EBB.' }, { 'name': 'can_trap', 'comment': 'True if instruction could trap.' }] for attr in attrs: if attr != attrs[0]: fmt.line() fmt.doc_comment(attr['comment']) with fmt.indented( 'pub fn {}(self) -> bool {{'.format(attr['name']), '}'): with fmt.indented('match self {', '}'): for i in instrs: if getattr(i, attr['name']): fmt.format('Opcode::{} => true,', i.camel_name, i.name) fmt.line('_ => false') # Generate a private opcode_format table. with fmt.indented( 'const OPCODE_FORMAT: [InstructionFormat; {}] = ['.format( len(instrs)), '];'): for i in instrs: fmt.format('InstructionFormat::{}, // {}', i.format.name, i.name) fmt.line() # Generate a private opcode_name function. with fmt.indented('fn opcode_name(opc: Opcode) -> &\'static str {', '}'): with fmt.indented('match opc {', '}'): for i in instrs: fmt.format('Opcode::{} => "{}",', i.camel_name, i.name) fmt.line() # Generate an opcode hash table for looking up opcodes by name. hash_table = constant_hash.compute_quadratic( instrs, lambda i: constant_hash.simple_hash(i.name)) with fmt.indented( 'const OPCODE_HASH_TABLE: [Option<Opcode>; {}] = ['.format( len(hash_table)), '];'): for i in hash_table: if i is None: fmt.line('None,') else: fmt.format('Some(Opcode::{}),', i.camel_name) fmt.line() return instrs
def hash_setting(s): return constant_hash.simple_hash(s.name)
def gen_opcodes(groups, fmt): """ Generate opcode enumerations. 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.line('#[derive(Copy, Clone, PartialEq, Eq, Debug)]') instrs = [] with fmt.indented('pub enum Opcode {', '}'): fmt.doc_comment('An invalid opcode.') fmt.line('NotAnOpcode,') for g in groups: for i in g.instructions: instrs.append(i) i.number = len(instrs) fmt.doc_comment('`{}`. ({})'.format(i, i.format.name)) # Document polymorphism. if i.is_polymorphic: if i.use_typevar_operand: fmt.doc_comment( 'Type inferred from {}.' .format(i.ins[i.format.typevar_operand])) # Enum variant itself. fmt.line(i.camel_name + ',') fmt.line() # Generate a private opcode_format table. with fmt.indented( 'const OPCODE_FORMAT: [InstructionFormat; {}] = [' .format(len(instrs)), '];'): for i in instrs: fmt.format( 'InstructionFormat::{}, // {}', i.format.name, i.name) fmt.line() # Generate a private opcode_name function. with fmt.indented('fn opcode_name(opc: Opcode) -> &\'static str {', '}'): with fmt.indented('match opc {', '}'): fmt.line('Opcode::NotAnOpcode => "<not an opcode>",') for i in instrs: fmt.format('Opcode::{} => "{}",', i.camel_name, i.name) fmt.line() # Generate an opcode hash table for looking up opcodes by name. hash_table = constant_hash.compute_quadratic( instrs, lambda i: constant_hash.simple_hash(i.name)) with fmt.indented( 'const OPCODE_HASH_TABLE: [Opcode; {}] = [' .format(len(hash_table)), '];'): for i in hash_table: if i is None: fmt.line('Opcode::NotAnOpcode,') else: fmt.format('Opcode::{},', i.camel_name) fmt.line() return instrs