From 703762a67c527da07f90a8a567bbf29082f74428 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Thu, 9 Mar 2017 21:03:52 -0800 Subject: [PATCH] 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. --- lib/cretonne/meta/cdsl/formats.py | 26 ++++++++++++++++++++++---- lib/cretonne/meta/gen_instr.py | 30 +++++++----------------------- lib/cretonne/meta/gen_legalizer.py | 5 ++--- 3 files changed, 31 insertions(+), 30 deletions(-) diff --git a/lib/cretonne/meta/cdsl/formats.py b/lib/cretonne/meta/cdsl/formats.py index 98f6964e5c..506f0d7322 100644 --- a/lib/cretonne/meta/cdsl/formats.py +++ b/lib/cretonne/meta/cdsl/formats.py @@ -57,16 +57,23 @@ class InstructionFormat(object): self.has_value_list = kwargs.get('value_list', False) self.boxed_storage = kwargs.get('boxed_storage', False) 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)) # Which of self.kinds are `value`? self.value_operands = tuple( 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. self.typevar_operand = kwargs.get('typevar_operand', None) # type: int if self.typevar_operand is not None: @@ -102,6 +109,17 @@ class InstructionFormat(object): k = arg else: 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) yield k diff --git a/lib/cretonne/meta/gen_instr.py b/lib/cretonne/meta/gen_instr.py index b452daff2e..073891807f 100644 --- a/lib/cretonne/meta/gen_instr.py +++ b/lib/cretonne/meta/gen_instr.py @@ -84,20 +84,11 @@ def gen_arguments_method(fmt, is_mut): .format(n, mut, mut, as_slice)) 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. - if len(f.value_operands) == 0: + if f.num_value_operands == 0: arg = '&{}[]'.format(mut) capture = '' - elif len(f.value_operands) == 1: + elif f.num_value_operands == 1: if f.boxed_storage: capture = 'ref {}data, '.format(mut) arg = '{}(&{}data.arg)'.format(rslice, mut) @@ -111,16 +102,9 @@ def gen_arguments_method(fmt, is_mut): else: capture = 'ref {}args, '.format(mut) 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( - '{} {{ {} .. }} => [{}, {}],' - .format(n, capture, arg, varg)) + '{} {{ {} .. }} => [{}, &{}[]],' + .format(n, capture, arg, mut)) def gen_instruction_data_impl(fmt): @@ -219,7 +203,7 @@ def gen_instruction_data_impl(fmt): fmt.line( '{} {{ ref args, .. }} => ' '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'. if f.boxed_storage: fmt.line( @@ -564,9 +548,9 @@ def gen_member_inits(iform, fmt): if iform.has_value_list: # Value-list formats put *all* arguments in the list. 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])) - elif len(iform.value_operands) > 1: + elif iform.num_value_operands > 1: fmt.line('args: [{}],'.format( ', '.join('op{}'.format(i) for i in iform.value_operands))) diff --git a/lib/cretonne/meta/gen_legalizer.py b/lib/cretonne/meta/gen_legalizer.py index 983871ac40..3199b3741f 100644 --- a/lib/cretonne/meta/gen_legalizer.py +++ b/lib/cretonne/meta/gen_legalizer.py @@ -46,9 +46,8 @@ def unwrap_inst(iref, node, fmt): fmt.line('ref data,') else: # Fields are encoded directly. - for m in iform.members: - if m: - fmt.line('{},'.format(m)) + for m in iform.imm_members: + fmt.line('{},'.format(m)) if nvops == 1: fmt.line('arg,') elif nvops > 1: