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:
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
Reference in New Issue
Block a user