diff --git a/lib/cretonne/meta/cdsl/formats.py b/lib/cretonne/meta/cdsl/formats.py index 9549eac1e0..f08d6fa119 100644 --- a/lib/cretonne/meta/cdsl/formats.py +++ b/lib/cretonne/meta/cdsl/formats.py @@ -59,17 +59,15 @@ class InstructionFormat(object): self.name = kwargs.get('name', None) # type: str self.multiple_results = kwargs.get('multiple_results', False) - # 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] # The number of value operands stored in the format, or `None` when # `has_value_list` is set. self.num_value_operands = 0 # Does this format use a value list for storing value operands? self.has_value_list = False - # Operand kinds for the immediate operands. - self.imm_kinds = tuple(self._process_member_names(kinds)) + # Operand fields for the immediate operands. All other instruction + # operands are values or variable argument lists. They are all handled + # specially. + self.imm_fields = tuple(self._process_member_names(kinds)) # The typevar_operand argument must point to a 'value' operand. self.typevar_operand = kwargs.get('typevar_operand', None) # type: int @@ -82,9 +80,9 @@ class InstructionFormat(object): self.typevar_operand = 0 # Compute a signature for the global registry. + imm_kinds = tuple(f.kind for f in self.imm_fields) sig = ( - self.multiple_results, self.imm_kinds, - self.num_value_operands, + self.multiple_results, imm_kinds, self.num_value_operands, self.has_value_list) if sig in InstructionFormat._registry: raise RuntimeError( @@ -94,7 +92,7 @@ class InstructionFormat(object): InstructionFormat.all_formats.append(self) def _process_member_names(self, kinds): - # type: (Sequence[Union[OperandKind, Tuple[str, OperandKind]]]) -> Iterable[OperandKind] # noqa + # type: (Sequence[Union[OperandKind, Tuple[str, OperandKind]]]) -> Iterable[FormatField] # noqa """ Extract names of all the immediate operands in the kinds tuple. @@ -102,10 +100,11 @@ class InstructionFormat(object): pair. The member names correspond to members in the Rust `InstructionData` data structure. - Update the fields `num_value_operands` and `imm_members`. + Updates the fields `self.num_value_operands` and `self.has_value_list`. - Yields the immediate operand kinds. + Yields the immediate operand fields. """ + inum = 0 for arg in kinds: if isinstance(arg, OperandKind): member = arg.default_member @@ -119,13 +118,13 @@ class InstructionFormat(object): elif k is VARIABLE_ARGS: self.has_value_list = True else: - self.imm_members.append(member) - yield k + yield FormatField(self, inum, k, member) + inum += 1 def __str__(self): # type: () -> str - args = ', '.join('{}: {}'.format(m, k) - for m, k in zip(self.imm_members, self.imm_kinds)) + args = ', '.join( + '{}: {}'.format(f.member, f.kind) for f in self.imm_fields) return '{}(imms=({}), vals={})'.format( self.name, args, self.num_value_operands) @@ -137,16 +136,16 @@ class InstructionFormat(object): Each non-value format member becomes a corresponding `FormatField` attribute. """ - try: - i = self.imm_members.index(attr) - except ValueError: - raise AttributeError( - '{} is neither a {} member or a ' - .format(attr, self.name) + - 'normal InstructionFormat attribute') - field = FormatField(self, i, attr) - setattr(self, attr, field) - return field + for f in self.imm_fields: + if f.member == attr: + # Cache this field attribute so we won't have to search again. + setattr(self, attr, f) + return f + + raise AttributeError( + '{} is neither a {} member or a ' + .format(attr, self.name) + + 'normal InstructionFormat attribute') @staticmethod def lookup(ins, outs): @@ -207,26 +206,28 @@ class InstructionFormat(object): class FormatField(object): """ - A field in an instruction format. + An immediate field in an instruction format. This corresponds to a single member of a variant of the `InstructionData` data type. - :param format: Parent `InstructionFormat`. - :param operand: Immediate operand number in parent. - :param name: Member name in `InstructionData` variant. + :param iformat: Parent `InstructionFormat`. + :param immnum: Immediate operand number in parent. + :param kind: Immediate Operand kind. + :param member: Member name in `InstructionData` variant. """ - def __init__(self, format, operand, name): - # type: (InstructionFormat, int, str) -> None - self.format = format - self.operand = operand - self.name = name + def __init__(self, iform, immnum, kind, member): + # type: (InstructionFormat, int, OperandKind, str) -> None + self.format = iform + self.immnum = immnum + self.kind = kind + self.member = member def __str__(self): # type: () -> str - return '{}.{}'.format(self.format.name, self.name) + return '{}.{}'.format(self.format.name, self.member) def rust_name(self): # type: () -> str - return self.name + return self.member diff --git a/lib/cretonne/meta/cdsl/predicates.py b/lib/cretonne/meta/cdsl/predicates.py index e75920d948..273f8be9a1 100644 --- a/lib/cretonne/meta/cdsl/predicates.py +++ b/lib/cretonne/meta/cdsl/predicates.py @@ -207,7 +207,7 @@ class FieldPredicate(object): def __str__(self): # type: () -> str - args = (self.field.name,) + tuple(map(str, self.args)) + args = (self.field.rust_name(),) + tuple(map(str, self.args)) return '{}({})'.format(self.function, ', '.join(args)) def predicate_context(self): diff --git a/lib/cretonne/meta/gen_encoding.py b/lib/cretonne/meta/gen_encoding.py index e78d8942dc..e4faa6410c 100644 --- a/lib/cretonne/meta/gen_encoding.py +++ b/lib/cretonne/meta/gen_encoding.py @@ -90,7 +90,7 @@ def emit_instp(instp, fmt): fnames = set() # type: Set[str] for p in leafs: assert isinstance(p, FieldPredicate) - fnames.add(p.field.name) + fnames.add(p.field.rust_name()) fields = ', '.join(sorted(fnames)) with fmt.indented('{} => {{'.format(instp.number), '}'): diff --git a/lib/cretonne/meta/gen_instr.py b/lib/cretonne/meta/gen_instr.py index dc5257ffef..9ce279dc52 100644 --- a/lib/cretonne/meta/gen_instr.py +++ b/lib/cretonne/meta/gen_instr.py @@ -515,8 +515,8 @@ def gen_format_constructor(iform, fmt): result_type = 'result_type' # Normal operand arguments. Start with the immediate operands. - for kind, name in zip(iform.imm_kinds, iform.imm_members): - args.append('{}: {}'.format(name, kind.rust_type)) + for f in iform.imm_fields: + args.append('{}: {}'.format(f.member, f.kind.rust_type)) # Then the value operands. if iform.has_value_list: # Take all value arguments as a finished value list. The value lists @@ -557,8 +557,8 @@ def gen_member_inits(iform, fmt): # Immediate operands. # We have local variables with the same names as the members. - for member in iform.imm_members: - fmt.line('{}: {},'.format(member, member)) + for f in iform.imm_fields: + fmt.line('{}: {},'.format(f.member, f.member)) # Value operands. if iform.has_value_list: diff --git a/lib/cretonne/meta/gen_legalizer.py b/lib/cretonne/meta/gen_legalizer.py index 93f2bc857c..7beda84771 100644 --- a/lib/cretonne/meta/gen_legalizer.py +++ b/lib/cretonne/meta/gen_legalizer.py @@ -43,8 +43,8 @@ def unwrap_inst(iref, node, fmt): 'let ({}) = if let InstructionData::{} {{' .format(', '.join(map(str, expr.args)), iform.name), '};'): # Fields are encoded directly. - for m in iform.imm_members: - fmt.line('{},'.format(m)) + for f in iform.imm_fields: + fmt.line('{},'.format(f.member)) if nvops == 1: fmt.line('arg,') elif iform.has_value_list or nvops > 1: @@ -58,7 +58,7 @@ def unwrap_inst(iref, node, fmt): for opnum, op in enumerate(expr.inst.ins): if op.is_immediate(): n = expr.inst.imm_opnums.index(opnum) - outs.append(iform.imm_members[n]) + outs.append(iform.imm_fields[n].member) elif op.is_value(): if nvops == 1: arg = 'arg'