[meta] Refactor instruction predicates to distinguish format and type checks;

Also add the instruction format name in format predicates, since they're
going to be used when generating encodings.
This commit is contained in:
Benjamin Bouvier
2019-05-29 17:20:34 +02:00
parent f1d1d1e960
commit 18fb87cd9c
2 changed files with 69 additions and 19 deletions

View File

@@ -449,6 +449,7 @@ impl Apply {
continue; continue;
} }
pred = pred.and(InstructionPredicate::new_is_field_equal( pred = pred.and(InstructionPredicate::new_is_field_equal(
iform.name,
&format_field, &format_field,
arg.to_rust_code(var_pool), arg.to_rust_code(var_pool),
)); ));

View File

@@ -551,12 +551,39 @@ fn verify_ctrl_typevar(
Ok(other_typevars) Ok(other_typevars)
} }
/// A basic node in an instruction predicate: either an atom, or an AND of two conditions. pub enum FormatPredicateKind {
pub enum InstructionPredicateNode { /// Is the field member equal to the expected value (stored here)?
/// Is the field member (first member) equal to the actual argument (which name is the second IsEqual(String),
/// field)? }
IsFieldEqual(String, String),
pub struct FormatPredicateNode {
_format_name: &'static str,
field_name: &'static str,
kind: FormatPredicateKind,
}
impl FormatPredicateNode {
fn new(
_format_name: &'static str,
field_name: &'static str,
kind: FormatPredicateKind,
) -> Self {
Self {
_format_name,
field_name,
kind,
}
}
fn rust_predicate(&self) -> String {
match &self.kind {
FormatPredicateKind::IsEqual(arg) => {
format!("crate::predicates::is_equal({}, {})", self.field_name, arg)
}
}
}
}
pub enum TypePredicateNode {
/// Is the value argument (at the index designated by the first member) the same type as the /// Is the value argument (at the index designated by the first member) the same type as the
/// type name (second member)? /// type name (second member)?
TypeVarCheck(usize, String), TypeVarCheck(usize, String),
@@ -564,6 +591,27 @@ pub enum InstructionPredicateNode {
/// Is the controlling type variable the same type as the one designated by the type name /// Is the controlling type variable the same type as the one designated by the type name
/// (only member)? /// (only member)?
CtrlTypeVarCheck(String), CtrlTypeVarCheck(String),
}
impl TypePredicateNode {
fn rust_predicate(&self) -> String {
match self {
TypePredicateNode::TypeVarCheck(index, value_type_name) => format!(
"func.dfg.value_type(args[{}]) == {}",
index, value_type_name
),
TypePredicateNode::CtrlTypeVarCheck(value_type_name) => {
format!("func.dfg.ctrl_typevar(inst) == {}", value_type_name)
}
}
}
}
/// A basic node in an instruction predicate: either an atom, or an AND of two conditions.
pub enum InstructionPredicateNode {
FormatPredicate(FormatPredicateNode),
TypePredicate(TypePredicateNode),
/// A combination of two other predicates. /// A combination of two other predicates.
And(Vec<InstructionPredicateNode>), And(Vec<InstructionPredicateNode>),
@@ -572,17 +620,8 @@ pub enum InstructionPredicateNode {
impl InstructionPredicateNode { impl InstructionPredicateNode {
fn rust_predicate(&self) -> String { fn rust_predicate(&self) -> String {
match self { match self {
InstructionPredicateNode::IsFieldEqual(field_name, arg) => { InstructionPredicateNode::FormatPredicate(node) => node.rust_predicate(),
let new_args = vec![field_name.clone(), arg.clone()]; InstructionPredicateNode::TypePredicate(node) => node.rust_predicate(),
format!("crate::predicates::is_equal({})", new_args.join(", "))
}
InstructionPredicateNode::TypeVarCheck(index, value_type_name) => format!(
"func.dfg.value_type(args[{}]) == {}",
index, value_type_name
),
InstructionPredicateNode::CtrlTypeVarCheck(value_type_name) => {
format!("func.dfg.ctrl_typevar(inst) == {}", value_type_name)
}
InstructionPredicateNode::And(nodes) => nodes InstructionPredicateNode::And(nodes) => nodes
.iter() .iter()
.map(|x| x.rust_predicate()) .map(|x| x.rust_predicate())
@@ -614,18 +653,28 @@ impl InstructionPredicate {
.next() .next()
.unwrap() .unwrap()
.0; .0;
InstructionPredicateNode::TypeVarCheck(index, value_type.rust_name()) InstructionPredicateNode::TypePredicate(TypePredicateNode::TypeVarCheck(
index,
value_type.rust_name(),
))
} }
pub fn new_is_field_equal( pub fn new_is_field_equal(
format_name: &'static str,
format_field: &FormatField, format_field: &FormatField,
imm_value: String, imm_value: String,
) -> InstructionPredicateNode { ) -> InstructionPredicateNode {
InstructionPredicateNode::IsFieldEqual(format_field.member.into(), imm_value) InstructionPredicateNode::FormatPredicate(FormatPredicateNode::new(
format_name,
format_field.member,
FormatPredicateKind::IsEqual(imm_value),
))
} }
pub fn new_ctrl_typevar_check(value_type: &ValueType) -> InstructionPredicateNode { pub fn new_ctrl_typevar_check(value_type: &ValueType) -> InstructionPredicateNode {
InstructionPredicateNode::CtrlTypeVarCheck(value_type.rust_name()) InstructionPredicateNode::TypePredicate(TypePredicateNode::CtrlTypeVarCheck(
value_type.rust_name(),
))
} }
pub fn and(mut self, new_node: InstructionPredicateNode) -> Self { pub fn and(mut self, new_node: InstructionPredicateNode) -> Self {