示例#1
0
def gen_type_constraints(fmt, instrs):
    # type: (srcgen.Formatter, Sequence[Instruction]) -> None
    """
    Generate value type constraints for all instructions.

    - Emit a compact constant table of ValueTypeSet objects.
    - Emit a compact constant table of OperandConstraint objects.
    - Emit an opcode-indexed table of instruction constraints.

    """

    # Table of TypeSet instances.
    type_sets = UniqueTable()

    # Table of operand constraint sequences (as tuples). Each operand
    # constraint is represented as a string, one of:
    # - `Concrete(vt)`, where `vt` is a value type name.
    # - `Free(idx)` where `idx` isan index into `type_sets`.
    # - `Same`, `Lane`, `AsBool` for controlling typevar-derived constraints.
    operand_seqs = UniqueSeqTable()

    # Preload table with constraints for typical binops.
    operand_seqs.add(['Same'] * 3)

    fmt.comment('Table of opcode constraints.')
    with fmt.indented(
            'const OPCODE_CONSTRAINTS: [OpcodeConstraints; {}] = ['.format(
                len(instrs)), '];'):
        for i in instrs:
            # Collect constraints for the value results, not including
            # `variable_args` results which are always special cased.
            constraints = list()
            ctrl_typevar = None
            ctrl_typeset = typeset_limit
            if i.is_polymorphic:
                ctrl_typevar = i.ctrl_typevar
                ctrl_typeset = type_sets.add(ctrl_typevar.type_set)
            for idx in i.value_results:
                constraints.append(
                    get_constraint(i.outs[idx], ctrl_typevar, type_sets))
            for opnum in i.value_opnums:
                constraints.append(
                    get_constraint(i.ins[opnum], ctrl_typevar, type_sets))
            offset = operand_seqs.add(constraints)
            fixed_results = len(i.value_results)
            fixed_values = len(i.value_opnums)
            # Can the controlling type variable be inferred from the designated
            # operand?
            use_typevar_operand = i.is_polymorphic and i.use_typevar_operand
            # Can the controlling type variable be inferred from the result?
            use_result = (fixed_results > 0 and
                          i.outs[i.value_results[0]].typevar == ctrl_typevar)
            # Are we required to use the designated operand instead of the
            # result?
            requires_typevar_operand = use_typevar_operand and not use_result
            fmt.comment('{}: fixed_results={}, use_typevar_operand={}, '
                        'requires_typevar_operand={}, fixed_values={}'.format(
                            i.camel_name, fixed_results, use_typevar_operand,
                            requires_typevar_operand, fixed_values))
            fmt.comment('Constraints={}'.format(constraints))
            if i.is_polymorphic:
                fmt.comment('Polymorphic over {}'.format(
                    ctrl_typevar.type_set))
            # Compute the bit field encoding, c.f. instructions.rs.
            assert fixed_results < 8, "Bit field encoding too tight"
            flags = fixed_results
            if use_typevar_operand:
                flags |= 8
            if requires_typevar_operand:
                flags |= 0x10
            assert fixed_values < 8, "Bit field encoding too tight"
            flags |= fixed_values << 5

            with fmt.indented('OpcodeConstraints {', '},'):
                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(
            'const OPERAND_CONSTRAINTS: [OperandConstraint; {}] = ['.format(
                len(operand_seqs.table)), '];'):
        for c in operand_seqs.table:
            fmt.line('OperandConstraint::{},'.format(c))
示例#2
0
def gen_type_constraints(fmt, instrs):
    """
    Generate value type constraints for all instructions.

    - Emit a compact constant table of ValueTypeSet objects.
    - Emit a compact constant table of OperandConstraint objects.
    - Emit an opcode-indexed table of instruction constraints.

    """

    # Table of TypeSet instances.
    type_sets = UniqueTable()

    # Table of operand constraint sequences (as tuples). Each operand
    # constraint is represented as a string, one of:
    # - `Concrete(vt)`, where `vt` is a value type name.
    # - `Free(idx)` where `idx` isan index into `type_sets`.
    # - `Same`, `Lane`, `AsBool` for controlling typevar-derived constraints.
    operand_seqs = UniqueSeqTable()

    # Preload table with constraints for typical binops.
    operand_seqs.add(['Same'] * 3)

    # TypeSet indexes are encoded in 8 bits, with `0xff` reserved.
    typeset_limit = 0xff

    fmt.comment('Table of opcode constraints.')
    with fmt.indented(
            'const OPCODE_CONSTRAINTS : [OpcodeConstraints; {}] = ['
            .format(len(instrs)), '];'):
        for i in instrs:
            # Collect constraints for the value results, not including
            # `variable_args` results which are always special cased.
            constraints = list()
            ctrl_typevar = None
            ctrl_typeset = typeset_limit
            if i.is_polymorphic:
                ctrl_typevar = i.ctrl_typevar
                ctrl_typeset = type_sets.add(ctrl_typevar.type_set)
            for idx in i.value_results:
                constraints.append(
                        get_constraint(i.outs[idx], ctrl_typevar, type_sets))
            for idx in i.format.value_operands:
                constraints.append(
                        get_constraint(i.ins[idx], ctrl_typevar, type_sets))
            offset = operand_seqs.add(constraints)
            fixed_results = len(i.value_results)
            use_typevar_operand = i.is_polymorphic and i.use_typevar_operand
            fmt.comment(
                    '{}: fixed_results={}, use_typevar_operand={}'
                    .format(i.camel_name, fixed_results, use_typevar_operand))
            fmt.comment('Constraints={}'.format(constraints))
            if i.is_polymorphic:
                fmt.comment(
                        'Polymorphic over {}'.format(ctrl_typevar.type_set))
            # Compute the bit field encoding, c.f. instructions.rs.
            assert fixed_results < 8, "Bit field encoding too tight"
            flags = fixed_results
            if use_typevar_operand:
                flags |= 8

            with fmt.indented('OpcodeConstraints {', '},'):
                fmt.line('flags: {:#04x},'.format(flags))
                fmt.line('typeset_offset: {},'.format(ctrl_typeset))
                fmt.line('constraint_offset: {},'.format(offset))

    fmt.comment('Table of value type sets.')
    assert len(type_sets.table) <= typeset_limit, "Too many type sets"
    with fmt.indented(
            'const TYPE_SETS : [ValueTypeSet; {}] = ['
            .format(len(type_sets.table)), '];'):
        for ts in type_sets.table:
            with fmt.indented('ValueTypeSet {', '},'):
                ts.emit_fields(fmt)

    fmt.comment('Table of operand constraint sequences.')
    with fmt.indented(
            'const OPERAND_CONSTRAINTS : [OperandConstraint; {}] = ['
            .format(len(operand_seqs.table)), '];'):
        for c in operand_seqs.table:
            fmt.line('OperandConstraint::{},'.format(c))
示例#3
0
def gen_type_constraints(fmt, instrs):
    # type: (srcgen.Formatter, Sequence[Instruction]) -> None
    """
    Generate value type constraints for all instructions.

    - Emit a compact constant table of ValueTypeSet objects.
    - Emit a compact constant table of OperandConstraint objects.
    - Emit an opcode-indexed table of instruction constraints.

    """

    # Table of TypeSet instances.
    type_sets = UniqueTable()

    # Table of operand constraint sequences (as tuples). Each operand
    # constraint is represented as a string, one of:
    # - `Concrete(vt)`, where `vt` is a value type name.
    # - `Free(idx)` where `idx` isan index into `type_sets`.
    # - `Same`, `Lane`, `AsBool` for controlling typevar-derived constraints.
    operand_seqs = UniqueSeqTable()

    # Preload table with constraints for typical binops.
    operand_seqs.add(['Same'] * 3)

    fmt.comment('Table of opcode constraints.')
    with fmt.indented(
            'const OPCODE_CONSTRAINTS: [OpcodeConstraints; {}] = ['
            .format(len(instrs)), '];'):
        for i in instrs:
            # Collect constraints for the value results, not including
            # `variable_args` results which are always special cased.
            constraints = list()
            ctrl_typevar = None
            ctrl_typeset = typeset_limit
            if i.is_polymorphic:
                ctrl_typevar = i.ctrl_typevar
                ctrl_typeset = type_sets.add(ctrl_typevar.type_set)
            for idx in i.value_results:
                constraints.append(
                        get_constraint(i.outs[idx], ctrl_typevar, type_sets))
            for opnum in i.value_opnums:
                constraints.append(
                        get_constraint(i.ins[opnum], ctrl_typevar, type_sets))
            offset = operand_seqs.add(constraints)
            fixed_results = len(i.value_results)
            fixed_values = len(i.value_opnums)
            # Can the controlling type variable be inferred from the designated
            # operand?
            use_typevar_operand = i.is_polymorphic and i.use_typevar_operand
            # Can the controlling type variable be inferred from the result?
            use_result = (fixed_results > 0 and
                          i.outs[i.value_results[0]].typevar == ctrl_typevar)
            # Are we required to use the designated operand instead of the
            # result?
            requires_typevar_operand = use_typevar_operand and not use_result
            fmt.comment(
                    '{}: fixed_results={}, use_typevar_operand={}, '
                    'requires_typevar_operand={}, fixed_values={}'
                    .format(i.camel_name, fixed_results, use_typevar_operand,
                            requires_typevar_operand, fixed_values))
            fmt.comment('Constraints={}'.format(constraints))
            if i.is_polymorphic:
                fmt.comment(
                        'Polymorphic over {}'.format(ctrl_typevar.type_set))
            # Compute the bit field encoding, c.f. instructions.rs.
            assert fixed_results < 8, "Bit field encoding too tight"
            flags = fixed_results
            if use_typevar_operand:
                flags |= 8
            if requires_typevar_operand:
                flags |= 0x10
            assert fixed_values < 8, "Bit field encoding too tight"
            flags |= fixed_values << 5

            with fmt.indented('OpcodeConstraints {', '},'):
                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(
            'const OPERAND_CONSTRAINTS: [OperandConstraint; {}] = ['
            .format(len(operand_seqs.table)), '];'):
        for c in operand_seqs.table:
            fmt.line('OperandConstraint::{},'.format(c))
示例#4
0
def gen_type_constraints(fmt, instrs):
    """
    Generate value type constraints for all instructions.

    - Emit a compact constant table of ValueTypeSet objects.
    - Emit a compact constant table of OperandConstraint objects.
    - Emit an opcode-indexed table of instruction constraints.

    """

    # Table of TypeSet instances.
    type_sets = UniqueTable()

    # Table of operand constraint sequences (as tuples). Each operand
    # constraint is represented as a string, one of:
    # - `Concrete(vt)`, where `vt` is a value type name.
    # - `Free(idx)` where `idx` isan index into `type_sets`.
    # - `Same`, `Lane`, `AsBool` for controlling typevar-derived constraints.
    operand_seqs = UniqueSeqTable()

    # Preload table with constraints for typical binops.
    operand_seqs.add(['Same'] * 3)

    # TypeSet indexes are encoded in 8 bits, with `0xff` reserved.
    typeset_limit = 0xff

    fmt.comment('Table of opcode constraints.')
    with fmt.indented(
            'const OPCODE_CONSTRAINTS : [OpcodeConstraints; {}] = ['.format(
                len(instrs)), '];'):
        for i in instrs:
            # Collect constraints for the value results, not including
            # `variable_args` results which are always special cased.
            constraints = list()
            ctrl_typevar = None
            ctrl_typeset = typeset_limit
            if i.is_polymorphic:
                ctrl_typevar = i.ctrl_typevar
                ctrl_typeset = type_sets.add(ctrl_typevar.type_set)
            for idx in i.value_results:
                constraints.append(
                    get_constraint(i.outs[idx], ctrl_typevar, type_sets))
            for idx in i.format.value_operands:
                constraints.append(
                    get_constraint(i.ins[idx], ctrl_typevar, type_sets))
            offset = operand_seqs.add(constraints)
            fixed_results = len(i.value_results)
            use_typevar_operand = i.is_polymorphic and i.use_typevar_operand
            fmt.comment('{}: fixed_results={}, use_typevar_operand={}'.format(
                i.camel_name, fixed_results, use_typevar_operand))
            fmt.comment('Constraints={}'.format(constraints))
            if i.is_polymorphic:
                fmt.comment('Polymorphic over {}'.format(
                    ctrl_typevar.type_set))
            # Compute the bit field encoding, c.f. instructions.rs.
            assert fixed_results < 8, "Bit field encoding too tight"
            flags = fixed_results
            if use_typevar_operand:
                flags |= 8

            with fmt.indented('OpcodeConstraints {', '},'):
                fmt.line('flags: {:#04x},'.format(flags))
                fmt.line('typeset_offset: {},'.format(ctrl_typeset))
                fmt.line('constraint_offset: {},'.format(offset))

    fmt.comment('Table of value type sets.')
    assert len(type_sets.table) <= typeset_limit, "Too many type sets"
    with fmt.indented(
            'const TYPE_SETS : [ValueTypeSet; {}] = ['.format(
                len(type_sets.table)), '];'):
        for ts in type_sets.table:
            with fmt.indented('ValueTypeSet {', '},'):
                ts.emit_fields(fmt)

    fmt.comment('Table of operand constraint sequences.')
    with fmt.indented(
            'const OPERAND_CONSTRAINTS : [OperandConstraint; {}] = ['.format(
                len(operand_seqs.table)), '];'):
        for c in operand_seqs.table:
            fmt.line('OperandConstraint::{},'.format(c))