Example #1
0
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
Example #2
0
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
Example #3
0
 def hash_setting(s):
     # type: (Union[Setting, Preset]) -> int
     return constant_hash.simple_hash(s.name)
Example #4
0
 def hash_setting(s):
     # type: (Union[Setting, Preset]) -> int
     return constant_hash.simple_hash(s.name)
Example #5
0
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
Example #6
0
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
Example #7
0
 def hash_setting(s):
     return constant_hash.simple_hash(s.name)
Example #8
0
 def hash_setting(s):
     return constant_hash.simple_hash(s.name)
Example #9
0
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