peepmatic: Be generic over the operator type
This lets us avoid the cost of `cranelift_codegen::ir::Opcode` to `peepmatic_runtime::Operator` conversion overhead, and paves the way for allowing Peepmatic to support non-clif optimizations (e.g. vcode optimizations). Rather than defining our own `peepmatic::Operator` type like we used to, now the whole `peepmatic` crate is effectively generic over a `TOperator` type parameter. For the Cranelift integration, we use `cranelift_codegen::ir::Opcode` as the concrete type for our `TOperator` type parameter. For testing, we also define a `TestOperator` type, so that we can test Peepmatic code without building all of Cranelift, and we can keep them somewhat isolated from each other. The methods that `peepmatic::Operator` had are now translated into trait bounds on the `TOperator` type. These traits need to be shared between all of `peepmatic`, `peepmatic-runtime`, and `cranelift-codegen`'s Peepmatic integration. Therefore, these new traits live in a new crate: `peepmatic-traits`. This crate acts as a header file of sorts for shared trait/type/macro definitions. Additionally, the `peepmatic-runtime` crate no longer depends on the `peepmatic-macro` procedural macro crate, which should lead to faster build times for Cranelift when it is using pre-built peephole optimizers.
This commit is contained in:
@@ -407,7 +407,11 @@ fn gen_opcodes(all_inst: &AllInstructions, fmt: &mut Formatter) {
|
||||
All instructions from all supported ISAs are present.
|
||||
"#,
|
||||
);
|
||||
fmt.line("#[repr(u16)]");
|
||||
fmt.line("#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]");
|
||||
fmt.line(
|
||||
r#"#[cfg_attr(feature = "enable-peepmatic", derive(serde::Serialize, serde::Deserialize))]"#
|
||||
);
|
||||
|
||||
// We explicitly set the discriminant of the first variant to 1, which allows us to take
|
||||
// advantage of the NonZero optimization, meaning that wrapping enums can use the 0
|
||||
@@ -589,6 +593,24 @@ fn gen_opcodes(all_inst: &AllInstructions, fmt: &mut Formatter) {
|
||||
fmt.empty_line();
|
||||
}
|
||||
|
||||
fn gen_try_from(all_inst: &AllInstructions, fmt: &mut Formatter) {
|
||||
fmt.line("impl core::convert::TryFrom<u16> for Opcode {");
|
||||
fmt.indent(|fmt| {
|
||||
fmt.line("type Error = ();");
|
||||
fmt.line("#[inline]");
|
||||
fmt.line("fn try_from(x: u16) -> Result<Self, ()> {");
|
||||
fmt.indent(|fmt| {
|
||||
fmtln!(fmt, "if 0 < x && x <= {} {{", all_inst.len());
|
||||
fmt.indent(|fmt| fmt.line("Ok(unsafe { core::mem::transmute(x) })"));
|
||||
fmt.line("} else {");
|
||||
fmt.indent(|fmt| fmt.line("Err(())"));
|
||||
fmt.line("}");
|
||||
});
|
||||
fmt.line("}");
|
||||
});
|
||||
fmt.line("}");
|
||||
}
|
||||
|
||||
/// Get the value type constraint for an SSA value operand, where
|
||||
/// `ctrl_typevar` is the controlling type variable.
|
||||
///
|
||||
@@ -1147,7 +1169,10 @@ pub(crate) fn generate(
|
||||
gen_instruction_data_impl(&formats, &mut fmt);
|
||||
fmt.empty_line();
|
||||
gen_opcodes(all_inst, &mut fmt);
|
||||
fmt.empty_line();
|
||||
gen_type_constraints(all_inst, &mut fmt);
|
||||
fmt.empty_line();
|
||||
gen_try_from(all_inst, &mut fmt);
|
||||
fmt.update_file(opcode_filename, out_dir)?;
|
||||
|
||||
// Instruction builder.
|
||||
|
||||
Reference in New Issue
Block a user