[meta] Add instruction predicates;
This commit is contained in:
@@ -499,3 +499,102 @@ fn verify_ctrl_typevar(
|
||||
|
||||
Ok(other_typevars)
|
||||
}
|
||||
|
||||
/// A basic node in an instruction predicate: either an atom, or an AND of two conditions.
|
||||
pub enum InstructionPredicateNode {
|
||||
/// Is the field member (first member) equal to the actual argument (which name is the second
|
||||
/// field)?
|
||||
IsFieldEqual(String, String),
|
||||
|
||||
/// Is the value argument (at the index designated by the first member) the same type as the
|
||||
/// type name (second member)?
|
||||
TypeVarCheck(usize, String),
|
||||
|
||||
/// Is the controlling type variable the same type as the one designated by the type name
|
||||
/// (only member)?
|
||||
CtrlTypeVarCheck(String),
|
||||
|
||||
/// A combination of two other predicates.
|
||||
And(Vec<InstructionPredicateNode>),
|
||||
}
|
||||
|
||||
impl InstructionPredicateNode {
|
||||
fn rust_predicate(&self) -> String {
|
||||
match self {
|
||||
InstructionPredicateNode::IsFieldEqual(field_name, arg) => {
|
||||
let new_args = vec![field_name.clone(), arg.clone()];
|
||||
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
|
||||
.iter()
|
||||
.map(|x| x.rust_predicate())
|
||||
.collect::<Vec<_>>()
|
||||
.join(" &&\n"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct InstructionPredicate {
|
||||
node: Option<InstructionPredicateNode>,
|
||||
}
|
||||
|
||||
impl InstructionPredicate {
|
||||
pub fn new() -> Self {
|
||||
Self { node: None }
|
||||
}
|
||||
|
||||
pub fn new_typevar_check(
|
||||
inst: &Instruction,
|
||||
type_var: &TypeVar,
|
||||
value_type: &ValueType,
|
||||
) -> InstructionPredicateNode {
|
||||
let index = inst
|
||||
.value_opnums
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter(|(_, &op_num)| inst.operands_in[op_num].type_var().unwrap() == type_var)
|
||||
.next()
|
||||
.unwrap()
|
||||
.0;
|
||||
InstructionPredicateNode::TypeVarCheck(index, value_type.rust_name())
|
||||
}
|
||||
|
||||
pub fn new_is_field_equal(
|
||||
format_field: &FormatField,
|
||||
imm_value: String,
|
||||
) -> InstructionPredicateNode {
|
||||
InstructionPredicateNode::IsFieldEqual(format_field.member.into(), imm_value)
|
||||
}
|
||||
|
||||
pub fn new_ctrl_typevar_check(value_type: &ValueType) -> InstructionPredicateNode {
|
||||
InstructionPredicateNode::CtrlTypeVarCheck(value_type.rust_name())
|
||||
}
|
||||
|
||||
pub fn and(mut self, new_node: InstructionPredicateNode) -> Self {
|
||||
let node = self.node;
|
||||
let mut and_nodes = match node {
|
||||
Some(node) => match node {
|
||||
InstructionPredicateNode::And(nodes) => nodes,
|
||||
_ => vec![node],
|
||||
},
|
||||
_ => Vec::new(),
|
||||
};
|
||||
and_nodes.push(new_node);
|
||||
self.node = Some(InstructionPredicateNode::And(and_nodes));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn rust_predicate(&self) -> String {
|
||||
match &self.node {
|
||||
Some(root) => root.rust_predicate(),
|
||||
None => "true".into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user