Switch InstrBuilder to the one-shot builder pattern.
All the InstrBuilder methods now consume the builder, and the non-leaf methods return the dfg mutable reference they were holding. This makes it possible to construct instruction builders that are only safe to use once because they are doing more advanced value rewriting.
This commit is contained in:
@@ -347,7 +347,7 @@ def gen_format_constructor(iform, fmt):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
# Construct method arguments.
|
# Construct method arguments.
|
||||||
args = ['&mut self', 'opcode: Opcode']
|
args = ['self', 'opcode: Opcode']
|
||||||
|
|
||||||
if iform.multiple_results:
|
if iform.multiple_results:
|
||||||
args.append('ctrl_typevar: Type')
|
args.append('ctrl_typevar: Type')
|
||||||
@@ -361,7 +361,9 @@ def gen_format_constructor(iform, fmt):
|
|||||||
for idx, kind in enumerate(iform.kinds):
|
for idx, kind in enumerate(iform.kinds):
|
||||||
args.append('op{}: {}'.format(idx, kind.rust_type))
|
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)]')
|
fmt.line('#[allow(non_snake_case)]')
|
||||||
with fmt.indented('fn {} {{'.format(proto), '}'):
|
with fmt.indented('fn {} {{'.format(proto), '}'):
|
||||||
# Generate the instruction data.
|
# Generate the instruction data.
|
||||||
@@ -414,7 +416,7 @@ def gen_inst_builder(inst, fmt):
|
|||||||
"""
|
"""
|
||||||
|
|
||||||
# Construct method arguments.
|
# Construct method arguments.
|
||||||
args = ['&mut self']
|
args = ['self']
|
||||||
|
|
||||||
# The controlling type variable will be inferred from the input values if
|
# The controlling type variable will be inferred from the input values if
|
||||||
# possible. Otherwise, it is the first method argument.
|
# 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.extend(op.name for op in inst.ins)
|
||||||
args = ', '.join(args)
|
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:
|
if len(inst.value_results) == 0:
|
||||||
fmt.line('inst')
|
fmt.line(fcall + '.0')
|
||||||
elif len(inst.value_results) == 1:
|
return
|
||||||
fmt.line('self.data_flow_graph().first_result(inst)')
|
|
||||||
else:
|
if len(inst.value_results) == 1:
|
||||||
fmt.line(
|
fmt.line('Value::new_direct({}.0)'.format(fcall))
|
||||||
'let mut results = ' +
|
return
|
||||||
'self.data_flow_graph().inst_results(inst);')
|
|
||||||
fmt.line('({})'.format(', '.join(
|
fmt.line('let (inst, dfg) = {};'.format(fcall))
|
||||||
len(inst.value_results) * ['results.next().unwrap()'])))
|
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):
|
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
|
There is also a method per instruction format. These methods all
|
||||||
return an `Inst`.
|
return an `Inst`.
|
||||||
""")
|
""")
|
||||||
with fmt.indented("pub trait InstBuilder: InstBuilderBase {", '}'):
|
with fmt.indented(
|
||||||
|
"pub trait InstBuilder<'f>: InstBuilderBase<'f> {", '}'):
|
||||||
for inst in insts:
|
for inst in insts:
|
||||||
gen_inst_builder(inst, fmt)
|
gen_inst_builder(inst, fmt)
|
||||||
for f in cretonne.InstructionFormat.all_formats:
|
for f in cretonne.InstructionFormat.all_formats:
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ use ir::condcodes::{IntCC, FloatCC};
|
|||||||
///
|
///
|
||||||
/// Any data type that implements `InstBuilderBase` also gets all the methods of the `InstBuilder`
|
/// Any data type that implements `InstBuilderBase` also gets all the methods of the `InstBuilder`
|
||||||
/// trait.
|
/// trait.
|
||||||
pub trait InstBuilderBase {
|
pub trait InstBuilderBase<'f>: Sized {
|
||||||
/// Get an immutable reference to the data flow graph that will hold the constructed
|
/// Get an immutable reference to the data flow graph that will hold the constructed
|
||||||
/// instructions.
|
/// instructions.
|
||||||
fn data_flow_graph(&self) -> &DataFlowGraph;
|
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
|
/// 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.
|
/// 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.
|
/// 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
|
/// 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
|
/// controlling type variable. For non-polymorphic instructions with multiple results, pass
|
||||||
/// `VOID` for the `ctrl_typevar` argument.
|
/// `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`.
|
// Include trait code generated by `meta/gen_instr.py`.
|
||||||
@@ -43,7 +46,7 @@ pub trait InstBuilderBase {
|
|||||||
include!(concat!(env!("OUT_DIR"), "/builder.rs"));
|
include!(concat!(env!("OUT_DIR"), "/builder.rs"));
|
||||||
|
|
||||||
/// Any type implementing `InstBuilderBase` gets all the `InstBuilder` methods for free.
|
/// Any type implementing `InstBuilderBase` gets all the `InstBuilder` methods for free.
|
||||||
impl<T: InstBuilderBase> InstBuilder for T {}
|
impl<'f, T: InstBuilderBase<'f>> InstBuilder<'f> for T {}
|
||||||
|
|
||||||
/// Instruction builder.
|
/// 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 {
|
fn data_flow_graph(&self) -> &DataFlowGraph {
|
||||||
self.dfg
|
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);
|
let inst = self.dfg.make_inst(data);
|
||||||
self.pos.insert_inst(inst);
|
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);
|
let inst = self.dfg.make_inst(data);
|
||||||
self.dfg.make_inst_results(inst, ctrl_typevar);
|
self.dfg.make_inst_results(inst, ctrl_typevar);
|
||||||
self.pos.insert_inst(inst);
|
self.pos.insert_inst(inst);
|
||||||
inst
|
(inst, self.dfg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user