diff --git a/lib/cretonne/meta/gen_instr.py b/lib/cretonne/meta/gen_instr.py index 4e854fe32c..21bd8bcd85 100644 --- a/lib/cretonne/meta/gen_instr.py +++ b/lib/cretonne/meta/gen_instr.py @@ -347,7 +347,7 @@ def gen_format_constructor(iform, fmt): """ # Construct method arguments. - args = ['&mut self', 'opcode: Opcode'] + args = ['self', 'opcode: Opcode'] if iform.multiple_results: args.append('ctrl_typevar: Type') @@ -361,7 +361,9 @@ def gen_format_constructor(iform, fmt): for idx, kind in enumerate(iform.kinds): args.append('op{}: {}'.format(idx, kind.rust_type)) - proto = '{}({}) -> Inst'.format(iform.name, ', '.join(args)) + proto = '{}({})'.format(iform.name, ', '.join(args)) + proto += " -> (Inst, &'f mut DataFlowGraph)" + fmt.line('#[allow(non_snake_case)]') with fmt.indented('fn {} {{'.format(proto), '}'): # Generate the instruction data. @@ -414,7 +416,7 @@ def gen_inst_builder(inst, fmt): """ # Construct method arguments. - args = ['&mut self'] + args = ['self'] # The controlling type variable will be inferred from the input values if # possible. Otherwise, it is the first method argument. @@ -481,18 +483,21 @@ def gen_inst_builder(inst, fmt): args.extend(op.name for op in inst.ins) args = ', '.join(args) - fmt.line('let inst = self.{}({});'.format(inst.format.name, args)) + # Call to the format constructor, + fcall = 'self.{}({})'.format(inst.format.name, args) if len(inst.value_results) == 0: - fmt.line('inst') - elif len(inst.value_results) == 1: - fmt.line('self.data_flow_graph().first_result(inst)') - else: - fmt.line( - 'let mut results = ' + - 'self.data_flow_graph().inst_results(inst);') - fmt.line('({})'.format(', '.join( - len(inst.value_results) * ['results.next().unwrap()']))) + fmt.line(fcall + '.0') + return + + if len(inst.value_results) == 1: + fmt.line('Value::new_direct({}.0)'.format(fcall)) + return + + fmt.line('let (inst, dfg) = {};'.format(fcall)) + fmt.line('let mut results = dfg.inst_results(inst);') + fmt.line('({})'.format(', '.join( + len(inst.value_results) * ['results.next().unwrap()']))) def gen_builder(insts, fmt): @@ -514,7 +519,8 @@ def gen_builder(insts, fmt): There is also a method per instruction format. These methods all return an `Inst`. """) - with fmt.indented("pub trait InstBuilder: InstBuilderBase {", '}'): + with fmt.indented( + "pub trait InstBuilder<'f>: InstBuilderBase<'f> {", '}'): for inst in insts: gen_inst_builder(inst, fmt) for f in cretonne.InstructionFormat.all_formats: diff --git a/lib/cretonne/src/ir/builder.rs b/lib/cretonne/src/ir/builder.rs index a360263138..6ad50d9ab8 100644 --- a/lib/cretonne/src/ir/builder.rs +++ b/lib/cretonne/src/ir/builder.rs @@ -17,7 +17,7 @@ use ir::condcodes::{IntCC, FloatCC}; /// /// Any data type that implements `InstBuilderBase` also gets all the methods of the `InstBuilder` /// trait. -pub trait InstBuilderBase { +pub trait InstBuilderBase<'f>: Sized { /// Get an immutable reference to the data flow graph that will hold the constructed /// instructions. fn data_flow_graph(&self) -> &DataFlowGraph; @@ -26,14 +26,17 @@ pub trait InstBuilderBase { /// /// A 'simple' instruction has at most one result, and the `data.ty` field must contain the /// result type or `VOID` for an instruction with no result values. - fn simple_instruction(&mut self, data: InstructionData) -> Inst; + fn simple_instruction(self, data: InstructionData) -> (Inst, &'f mut DataFlowGraph); /// Insert a simple instruction and return a reference to it. /// /// A 'complex' instruction may produce multiple results, and the result types may depend on a /// controlling type variable. For non-polymorphic instructions with multiple results, pass /// `VOID` for the `ctrl_typevar` argument. - fn complex_instruction(&mut self, data: InstructionData, ctrl_typevar: Type) -> Inst; + fn complex_instruction(self, + data: InstructionData, + ctrl_typevar: Type) + -> (Inst, &'f mut DataFlowGraph); } // Include trait code generated by `meta/gen_instr.py`. @@ -43,7 +46,7 @@ pub trait InstBuilderBase { include!(concat!(env!("OUT_DIR"), "/builder.rs")); /// Any type implementing `InstBuilderBase` gets all the `InstBuilder` methods for free. -impl InstBuilder for T {} +impl<'f, T: InstBuilderBase<'f>> InstBuilder<'f> for T {} /// Instruction builder. /// @@ -78,21 +81,24 @@ impl<'c, 'fc, 'fd> Builder<'c, 'fc, 'fd> { } } -impl<'c, 'fc, 'fd> InstBuilderBase for Builder<'c, 'fc, 'fd> { +impl<'c, 'fc, 'fd> InstBuilderBase<'fd> for Builder<'c, 'fc, 'fd> { fn data_flow_graph(&self) -> &DataFlowGraph { self.dfg } - fn simple_instruction(&mut self, data: InstructionData) -> Inst { + fn simple_instruction(self, data: InstructionData) -> (Inst, &'fd mut DataFlowGraph) { let inst = self.dfg.make_inst(data); self.pos.insert_inst(inst); - inst + (inst, self.dfg) } - fn complex_instruction(&mut self, data: InstructionData, ctrl_typevar: Type) -> Inst { + fn complex_instruction(self, + data: InstructionData, + ctrl_typevar: Type) + -> (Inst, &'fd mut DataFlowGraph) { let inst = self.dfg.make_inst(data); self.dfg.make_inst_results(inst, ctrl_typevar); self.pos.insert_inst(inst); - inst + (inst, self.dfg) } }