Python InstructionFormat refactoring.
Make some changes that will make it easier to get rid of the 'value_operands' and 'members' fields in the Python InstructionFormat class. This is necessary to be able to combine instruction formats that all use a value list representation, but with different fixed value operands. The goal is to eventually identify formats by a new signature: (multiple_results, imm_kinds, num_value_operands) Start by adding new fields: - imm_members and imm_kinds are lists describing the format operands, excluding any values and variable_args operands. - num_value_operands is the number of fixed value operands, or None in a has_value-list format. Use these new members in preference to the old ones where possible.
This commit is contained in:
@@ -57,16 +57,23 @@ class InstructionFormat(object):
|
|||||||
self.has_value_list = kwargs.get('value_list', False)
|
self.has_value_list = kwargs.get('value_list', False)
|
||||||
self.boxed_storage = kwargs.get('boxed_storage', False)
|
self.boxed_storage = kwargs.get('boxed_storage', False)
|
||||||
self.members = list() # type: List[str]
|
self.members = list() # type: List[str]
|
||||||
|
|
||||||
|
# Struct member names for the immediate operands. All other instruction
|
||||||
|
# operands are values or variable argument lists. They are all handled
|
||||||
|
# specially.
|
||||||
|
self.imm_members = list() # type: List[str]
|
||||||
|
# Operand kinds for the immediate operands.
|
||||||
|
self.imm_kinds = list() # type: List[OperandKind]
|
||||||
|
# The number of value operands stored in the format, or `None` when
|
||||||
|
# `has_value_list` is set.
|
||||||
|
self.num_value_operands = 0
|
||||||
|
|
||||||
self.kinds = tuple(self._process_member_names(kinds))
|
self.kinds = tuple(self._process_member_names(kinds))
|
||||||
|
|
||||||
# Which of self.kinds are `value`?
|
# Which of self.kinds are `value`?
|
||||||
self.value_operands = tuple(
|
self.value_operands = tuple(
|
||||||
i for i, k in enumerate(self.kinds) if k is VALUE)
|
i for i, k in enumerate(self.kinds) if k is VALUE)
|
||||||
|
|
||||||
# We require a value list for storage of variable arguments.
|
|
||||||
if VARIABLE_ARGS in self.kinds:
|
|
||||||
assert self.has_value_list, "Need a value list for variable args"
|
|
||||||
|
|
||||||
# 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:
|
||||||
@@ -102,6 +109,17 @@ class InstructionFormat(object):
|
|||||||
k = arg
|
k = arg
|
||||||
else:
|
else:
|
||||||
member, k = arg
|
member, k = arg
|
||||||
|
|
||||||
|
# We define 'immediate' as not a value or variable arguments.
|
||||||
|
if k is VALUE:
|
||||||
|
self.num_value_operands += 1
|
||||||
|
elif k is VARIABLE_ARGS:
|
||||||
|
# We require a value list for storage of variable arguments.
|
||||||
|
assert self.has_value_list, "Need a value list"
|
||||||
|
else:
|
||||||
|
self.imm_kinds.append(k)
|
||||||
|
self.imm_members.append(member)
|
||||||
|
|
||||||
self.members.append(member)
|
self.members.append(member)
|
||||||
yield k
|
yield k
|
||||||
|
|
||||||
|
|||||||
@@ -84,20 +84,11 @@ def gen_arguments_method(fmt, is_mut):
|
|||||||
.format(n, mut, mut, as_slice))
|
.format(n, mut, mut, as_slice))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
has_varargs = cdsl.operands.VARIABLE_ARGS in f.kinds
|
|
||||||
# Formats with both fixed and variable arguments delegate to
|
|
||||||
# the data struct. We need to work around borrow checker quirks
|
|
||||||
# when extracting two mutable references.
|
|
||||||
if has_varargs and len(f.value_operands) > 0:
|
|
||||||
fmt.line(
|
|
||||||
'{} {{ ref {}data, .. }} => data.{}(),'
|
|
||||||
.format(n, mut, method))
|
|
||||||
continue
|
|
||||||
# Fixed args.
|
# Fixed args.
|
||||||
if len(f.value_operands) == 0:
|
if f.num_value_operands == 0:
|
||||||
arg = '&{}[]'.format(mut)
|
arg = '&{}[]'.format(mut)
|
||||||
capture = ''
|
capture = ''
|
||||||
elif len(f.value_operands) == 1:
|
elif f.num_value_operands == 1:
|
||||||
if f.boxed_storage:
|
if f.boxed_storage:
|
||||||
capture = 'ref {}data, '.format(mut)
|
capture = 'ref {}data, '.format(mut)
|
||||||
arg = '{}(&{}data.arg)'.format(rslice, mut)
|
arg = '{}(&{}data.arg)'.format(rslice, mut)
|
||||||
@@ -111,16 +102,9 @@ def gen_arguments_method(fmt, is_mut):
|
|||||||
else:
|
else:
|
||||||
capture = 'ref {}args, '.format(mut)
|
capture = 'ref {}args, '.format(mut)
|
||||||
arg = 'args'
|
arg = 'args'
|
||||||
# Varargs.
|
|
||||||
if cdsl.operands.VARIABLE_ARGS in f.kinds:
|
|
||||||
varg = '&{}data.varargs'.format(mut)
|
|
||||||
capture = 'ref {}data, '.format(mut)
|
|
||||||
else:
|
|
||||||
varg = '&{}[]'.format(mut)
|
|
||||||
|
|
||||||
fmt.line(
|
fmt.line(
|
||||||
'{} {{ {} .. }} => [{}, {}],'
|
'{} {{ {} .. }} => [{}, &{}[]],'
|
||||||
.format(n, capture, arg, varg))
|
.format(n, capture, arg, mut))
|
||||||
|
|
||||||
|
|
||||||
def gen_instruction_data_impl(fmt):
|
def gen_instruction_data_impl(fmt):
|
||||||
@@ -219,7 +203,7 @@ def gen_instruction_data_impl(fmt):
|
|||||||
fmt.line(
|
fmt.line(
|
||||||
'{} {{ ref args, .. }} => '
|
'{} {{ ref args, .. }} => '
|
||||||
'args.get({}, pool),'.format(n, i))
|
'args.get({}, pool),'.format(n, i))
|
||||||
elif len(f.value_operands) == 1:
|
elif f.num_value_operands == 1:
|
||||||
# We have a single value operand called 'arg'.
|
# We have a single value operand called 'arg'.
|
||||||
if f.boxed_storage:
|
if f.boxed_storage:
|
||||||
fmt.line(
|
fmt.line(
|
||||||
@@ -564,9 +548,9 @@ def gen_member_inits(iform, fmt):
|
|||||||
if iform.has_value_list:
|
if iform.has_value_list:
|
||||||
# Value-list formats put *all* arguments in the list.
|
# Value-list formats put *all* arguments in the list.
|
||||||
fmt.line('args: vlist,')
|
fmt.line('args: vlist,')
|
||||||
elif len(iform.value_operands) == 1:
|
elif iform.num_value_operands == 1:
|
||||||
fmt.line('arg: op{},'.format(iform.value_operands[0]))
|
fmt.line('arg: op{},'.format(iform.value_operands[0]))
|
||||||
elif len(iform.value_operands) > 1:
|
elif iform.num_value_operands > 1:
|
||||||
fmt.line('args: [{}],'.format(
|
fmt.line('args: [{}],'.format(
|
||||||
', '.join('op{}'.format(i) for i in iform.value_operands)))
|
', '.join('op{}'.format(i) for i in iform.value_operands)))
|
||||||
|
|
||||||
|
|||||||
@@ -46,8 +46,7 @@ def unwrap_inst(iref, node, fmt):
|
|||||||
fmt.line('ref data,')
|
fmt.line('ref data,')
|
||||||
else:
|
else:
|
||||||
# Fields are encoded directly.
|
# Fields are encoded directly.
|
||||||
for m in iform.members:
|
for m in iform.imm_members:
|
||||||
if m:
|
|
||||||
fmt.line('{},'.format(m))
|
fmt.line('{},'.format(m))
|
||||||
if nvops == 1:
|
if nvops == 1:
|
||||||
fmt.line('arg,')
|
fmt.line('arg,')
|
||||||
|
|||||||
Reference in New Issue
Block a user