Change index domain for typevar_operand.

An instruction format is now seen as having two separate operand lists:
immediates and values. Change InstructionFormat.typevar_operand to be a
pure index into the value list.
This commit is contained in:
Jakob Stoklund Olesen
2017-03-10 10:38:38 -08:00
parent da693f72e2
commit cdb4cce3dc
3 changed files with 17 additions and 14 deletions

View File

@@ -39,9 +39,10 @@ class InstructionFormat(object):
:param boxed_storage: Set to `True` is this instruction format requires a :param boxed_storage: Set to `True` is this instruction format requires a
`data: Box<...>` pointer to additional storage in its `InstructionData` `data: Box<...>` pointer to additional storage in its `InstructionData`
variant. variant.
:param typevar_operand: Index of the input operand that is used to infer :param typevar_operand: Index of the value input operand that is used to
the controlling type variable. By default, this is the first `value` infer the controlling type variable. By default, this is `0`, the first
operand. `value` operand. The index is relative to the values only, ignoring
immediate operands.
""" """
# Map (multiple_results, kind, kind, ...) -> InstructionFormat # Map (multiple_results, kind, kind, ...) -> InstructionFormat
@@ -76,11 +77,12 @@ class InstructionFormat(object):
# The typevar_operand argument must point to a 'value' operand. # The typevar_operand argument must point to a 'value' operand.
self.typevar_operand = kwargs.get('typevar_operand', None) # type: int self.typevar_operand = kwargs.get('typevar_operand', None) # type: int
if self.typevar_operand is not None: if self.typevar_operand is not None:
assert self.kinds[self.typevar_operand] is VALUE, \ if not self.has_value_list:
"typevar_operand must indicate a 'value' operand" assert self.typevar_operand < self.num_value_operands, \
elif len(self.value_operands) > 0: "typevar_operand must indicate a 'value' operand"
elif self.num_value_operands != 0:
# Default to the first 'value' operand, if there is one. # Default to the first 'value' operand, if there is one.
self.typevar_operand = self.value_operands[0] self.typevar_operand = 0
# Compute a signature for the global registry. # Compute a signature for the global registry.
sig = (self.multiple_results, self.kinds) sig = (self.multiple_results, self.kinds)

View File

@@ -168,7 +168,8 @@ class Instruction(object):
typevar_error = None typevar_error = None
if self.format.typevar_operand is not None: if self.format.typevar_operand is not None:
try: try:
tv = self.ins[self.format.typevar_operand].typevar opnum = self.value_opnums[self.format.typevar_operand]
tv = self.ins[opnum].typevar
if tv is tv.free_typevar(): if tv is tv.free_typevar():
self.other_typevars = self._verify_ctrl_typevar(tv) self.other_typevars = self._verify_ctrl_typevar(tv)
self.ctrl_typevar = tv self.ctrl_typevar = tv

View File

@@ -197,7 +197,7 @@ def gen_instruction_data_impl(fmt):
fmt.line(n + ' { .. } => None,') fmt.line(n + ' { .. } => None,')
elif f.has_value_list: elif f.has_value_list:
# We keep all arguments in a value list. # We keep all arguments in a value list.
i = f.value_operands.index(f.typevar_operand) i = f.typevar_operand
fmt.line( fmt.line(
'{} {{ ref args, .. }} => ' '{} {{ ref args, .. }} => '
'args.get({}, pool),'.format(n, i)) 'args.get({}, pool),'.format(n, i))
@@ -211,9 +211,7 @@ def gen_instruction_data_impl(fmt):
else: else:
# We have multiple value operands and an array `args`. # We have multiple value operands and an array `args`.
# Which `args` index to use? # Which `args` index to use?
# Map from index into f.kinds into f.value_operands i = f.typevar_operand
# index.
i = f.value_operands.index(f.typevar_operand)
if f.boxed_storage: if f.boxed_storage:
fmt.line( fmt.line(
n + n +
@@ -280,9 +278,10 @@ def gen_opcodes(groups, fmt):
# Document polymorphism. # Document polymorphism.
if i.is_polymorphic: if i.is_polymorphic:
if i.use_typevar_operand: if i.use_typevar_operand:
opnum = i.value_opnums[i.format.typevar_operand]
fmt.doc_comment( fmt.doc_comment(
'Type inferred from {}.' 'Type inferred from {}.'
.format(i.ins[i.format.typevar_operand])) .format(i.ins[opnum]))
# Enum variant itself. # Enum variant itself.
if is_first_opcode: if is_first_opcode:
fmt.line(i.camel_name + ' = 1,') fmt.line(i.camel_name + ' = 1,')
@@ -612,9 +611,10 @@ def gen_inst_builder(inst, fmt):
args.append('types::VOID') args.append('types::VOID')
elif inst.is_polymorphic: elif inst.is_polymorphic:
# Infer the controlling type variable from the input operands. # Infer the controlling type variable from the input operands.
opnum = inst.value_opnums[inst.format.typevar_operand]
fmt.line( fmt.line(
'let ctrl_typevar = self.data_flow_graph().value_type({});' 'let ctrl_typevar = self.data_flow_graph().value_type({});'
.format(inst.ins[inst.format.typevar_operand].name)) .format(inst.ins[opnum].name))
if inst.format.multiple_results: if inst.format.multiple_results:
# The format constructor will resolve the result types from the # The format constructor will resolve the result types from the
# type var. # type var.