From d9c61373e2eb8d351882b727943cc102df72d7e4 Mon Sep 17 00:00:00 2001 From: Jakob Stoklund Olesen Date: Fri, 10 Mar 2017 09:05:53 -0800 Subject: [PATCH] Change InstBuilder low-level format constructor signatures. The per-instruction format low-level constructors in InstBuilder should be independent of the relative ordering of value and immediate operands in order to prepare for the future instruction format merger. Reorder their arguments such that all the immediate operands are placed before the value operands. For instruction formats that use a value list representation, just take a single ValueList argument. The value lists are created by the individual instruction constructors. This means that the format constructor doesn't care how many of the instructions operands are 'fixed' and how many are 'variable' arguments. --- lib/cretonne/meta/cdsl/operands.py | 7 +++ lib/cretonne/meta/gen_instr.py | 94 +++++++++++++++++------------- 2 files changed, 62 insertions(+), 39 deletions(-) diff --git a/lib/cretonne/meta/cdsl/operands.py b/lib/cretonne/meta/cdsl/operands.py index dafa18de35..49e3e588af 100644 --- a/lib/cretonne/meta/cdsl/operands.py +++ b/lib/cretonne/meta/cdsl/operands.py @@ -158,6 +158,13 @@ class Operand(object): """ return self.kind is VALUE + def is_varargs(self): + # type: () -> bool + """ + Is this a VARIABLE_ARGS operand? + """ + return self.kind is VARIABLE_ARGS + def is_immediate(self): # type: () -> bool """ diff --git a/lib/cretonne/meta/gen_instr.py b/lib/cretonne/meta/gen_instr.py index 23f28efeb7..b9e46172d7 100644 --- a/lib/cretonne/meta/gen_instr.py +++ b/lib/cretonne/meta/gen_instr.py @@ -7,7 +7,6 @@ import constant_hash from unique_table import UniqueTable, UniqueSeqTable from cdsl import camel_case from cdsl.operands import ImmediateKind -import cdsl.types from cdsl.formats import InstructionFormat from cdsl.instructions import Instruction # noqa @@ -477,11 +476,7 @@ def gen_format_constructor(iform, fmt): """ # Construct method arguments. - if iform.has_value_list: - args = ['mut self'] - else: - args = ['self'] - args.append('opcode: Opcode') + args = ['self', 'opcode: Opcode'] if iform.multiple_results: args.append('ctrl_typevar: Type') @@ -491,9 +486,18 @@ def gen_format_constructor(iform, fmt): args.append('result_type: Type') result_type = 'result_type' - # Normal operand arguments. - for idx, kind in enumerate(iform.kinds): - args.append('op{}: {}'.format(idx, kind.rust_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)) + # Then the value operands. + if iform.has_value_list: + # Take all value arguments as a finished value list. The value lists + # are created by the individual instruction constructors. + args.append('args: ValueList') + else: + # Take a fixed number of value operands. + for i in range(iform.num_value_operands): + args.append('arg{}: Value'.format(i)) proto = '{}({})'.format(iform.name, ', '.join(args)) proto += " -> (Inst, &'f mut DataFlowGraph)" @@ -501,21 +505,6 @@ def gen_format_constructor(iform, fmt): fmt.doc_comment(str(iform)) fmt.line('#[allow(non_snake_case)]') with fmt.indented('fn {} {{'.format(proto), '}'): - # Start by constructing a value list with *all* the arguments. - if iform.has_value_list: - fmt.line('let mut vlist = ValueList::default();') - with fmt.indented('{', '}'): - fmt.line( - 'let pool = ' - '&mut self.data_flow_graph_mut().value_lists;') - for idx, kind in enumerate(iform.kinds): - if kind is cdsl.operands.VALUE: - fmt.line('vlist.push(op{}, pool);'.format(idx)) - elif kind is cdsl.operands.VARIABLE_ARGS: - fmt.line( - 'vlist.extend(op{}.iter().cloned(), pool);' - .format(idx)) - # Generate the instruction data. with fmt.indented( 'let data = InstructionData::{} {{'.format(iform.name), '};'): @@ -543,20 +532,19 @@ def gen_member_inits(iform, fmt): Emit member initializers for an `iform` instruction. """ - # Values first. - if iform.has_value_list: - # Value-list formats put *all* arguments in the list. - fmt.line('args: vlist,') - elif iform.num_value_operands == 1: - fmt.line('arg: op{},'.format(iform.value_operands[0])) - elif iform.num_value_operands > 1: - fmt.line('args: [{}],'.format( - ', '.join('op{}'.format(i) for i in iform.value_operands))) + # Immediate operands. + # We have local variables with the same names as the members. + for member in iform.imm_members: + fmt.line('{}: {},'.format(member, member)) - # Immediates and entity references. - for idx, member in enumerate(iform.members): - if member: - fmt.line('{}: op{},'.format(member, idx)) + # Value operands. + if iform.has_value_list: + fmt.line('args: args,') + elif iform.num_value_operands == 1: + fmt.line('arg: arg0,') + elif iform.num_value_operands > 1: + args = ('arg{}'.format(i) for i in range(iform.num_value_operands)) + fmt.line('args: [{}],'.format(', '.join(args))) def gen_inst_builder(inst, fmt): @@ -570,7 +558,10 @@ def gen_inst_builder(inst, fmt): """ # Construct method arguments. - args = ['self'] + if inst.format.has_value_list: + args = ['mut self'] + else: + args = ['self'] # The controlling type variable will be inferred from the input values if # possible. Otherwise, it is the first method argument. @@ -645,7 +636,32 @@ def gen_inst_builder(inst, fmt): inst.outs[inst.value_results[0]] .typevar.singleton_type.rust_name()) - args.extend(op.name for op in inst.ins) + # Now add all of the immediate operands to the constructor arguments. + for opnum in inst.imm_opnums: + args.append(inst.ins[opnum].name) + + # Finally, the value operands. + if inst.format.has_value_list: + # We need to build a value list with all the arguments. + fmt.line('let mut vlist = ValueList::default();') + args.append('vlist') + with fmt.indented('{', '}'): + fmt.line( + 'let pool = ' + '&mut self.data_flow_graph_mut().value_lists;') + for op in inst.ins: + if op.is_value(): + fmt.line('vlist.push({}, pool);'.format(op.name)) + elif op.is_varargs(): + fmt.line( + 'vlist.extend({}.iter().cloned(), pool);' + .format(op.name)) + else: + # With no value list, we're guaranteed to just have a set of fixed + # value operands. + for opnum in inst.value_opnums: + args.append(inst.ins[opnum].name) + # Call to the format constructor, fcall = 'self.{}({})'.format(inst.format.name, ', '.join(args))