vyre-conform 0.1.0

Conformance suite for vyre backends — proves byte-identical output to CPU reference
Documentation
//! Static mutation catalog.

use super::{BinOpKind, Branch, Mutation};
use crate::spec::types::DataType;

/// The complete mutation catalog.
///
/// Every entry must have a working `apply` implementation and a
/// deterministic `class_of` mapping.
pub const MUTATION_CATALOG: &[Mutation] = &[
    Mutation::ArithOpSwap {
        from: BinOpKind::Add,
        to: BinOpKind::Sub,
    },
    Mutation::ArithOpSwap {
        from: BinOpKind::Sub,
        to: BinOpKind::Add,
    },
    Mutation::ArithOpSwap {
        from: BinOpKind::Mul,
        to: BinOpKind::Div,
    },
    Mutation::ArithOpSwap {
        from: BinOpKind::Div,
        to: BinOpKind::Mul,
    },
    Mutation::ArithOpSwap {
        from: BinOpKind::Mul,
        to: BinOpKind::Add,
    },
    Mutation::ArithOpSwap {
        from: BinOpKind::Shl,
        to: BinOpKind::Shr,
    },
    Mutation::ArithOpSwap {
        from: BinOpKind::Shr,
        to: BinOpKind::Shl,
    },
    Mutation::WrappingAddToSaturatingAdd,
    Mutation::WrappingAddToCheckedAdd,
    Mutation::ConstantIncrement { by: 1 },
    Mutation::ConstantIncrement { by: -1 },
    Mutation::ConstantZeroToOne,
    Mutation::ConstantOneToZero,
    Mutation::ConstantMaxToZero,
    Mutation::IntegerConstantBitFlip { bit: 0 },
    Mutation::IntegerConstantBitFlip { bit: 31 },
    Mutation::FloatConstantBitFlip { bit: 0 },
    Mutation::FloatConstantBitFlip { bit: 31 },
    Mutation::CompareOpSwap {
        from: BinOpKind::Lt,
        to: BinOpKind::Le,
    },
    Mutation::CompareOpSwap {
        from: BinOpKind::Le,
        to: BinOpKind::Lt,
    },
    Mutation::CompareOpSwap {
        from: BinOpKind::Le,
        to: BinOpKind::Ge,
    },
    Mutation::CompareOpSwap {
        from: BinOpKind::Gt,
        to: BinOpKind::Ge,
    },
    Mutation::CompareOpSwap {
        from: BinOpKind::Ge,
        to: BinOpKind::Gt,
    },
    Mutation::CompareOpSwap {
        from: BinOpKind::Ge,
        to: BinOpKind::Le,
    },
    Mutation::CompareOpSwap {
        from: BinOpKind::Eq,
        to: BinOpKind::Ne,
    },
    Mutation::CompareOpSwap {
        from: BinOpKind::Ne,
        to: BinOpKind::Eq,
    },
    Mutation::CompareOpSwap {
        from: BinOpKind::Lt,
        to: BinOpKind::Gt,
    },
    Mutation::CompareInvert,
    Mutation::BitOpSwap {
        from: BinOpKind::And,
        to: BinOpKind::Or,
    },
    Mutation::BitOpSwap {
        from: BinOpKind::Or,
        to: BinOpKind::And,
    },
    Mutation::BitOpSwap {
        from: BinOpKind::Xor,
        to: BinOpKind::And,
    },
    Mutation::BitOpSwap {
        from: BinOpKind::Xor,
        to: BinOpKind::Or,
    },
    Mutation::BitNotDelete,
    Mutation::BitAndMaskDelete,
    Mutation::ControlFlowDelete { branch: Branch::If },
    Mutation::ControlFlowDelete {
        branch: Branch::Else,
    },
    Mutation::ControlConditionInvert,
    Mutation::ControlLoopRangeEndIncrement,
    Mutation::ControlLoopRangeEndDecrement,
    Mutation::ControlLoopRangeStartIncrement,
    Mutation::ControlBreakToContinue,
    Mutation::ControlContinueRemove,
    Mutation::ControlFlowSkip,
    Mutation::BufferIndexShift { by: -1 },
    Mutation::BufferIndexShift { by: 1 },
    Mutation::BufferCountShift { by: -1 },
    Mutation::BufferCountShift { by: 1 },
    Mutation::BufferIndexClampFirst,
    Mutation::BufferIndexClampLast,
    Mutation::BufferReadWriteSwap,
    Mutation::AtomicOrderingWeaken,
    Mutation::AtomicOrderingAcqRelWeaken,
    Mutation::IrBinOpSwap {
        from: BinOpKind::Add,
        to: BinOpKind::Sub,
    },
    Mutation::IrDataTypeSwap {
        from: DataType::U32,
        to: DataType::I32,
    },
    Mutation::IrDeleteLaw { op: "add" },
    Mutation::IrSwapReferenceFn {
        op: "add",
        wrong_op: "sub",
    },
    Mutation::IrBufferAccessSwap,
    Mutation::IrRemoveValidationRule,
    Mutation::BytecodeConverterSwap {
        from_opcode: 0x01,
        to_opcode: 0x02,
    },
    Mutation::IrWrongWgslOp,
    Mutation::IrWorkgroupSizeChange,
    Mutation::IrWorkgroupStrideMul { factor: 2 },
    Mutation::IrWorkgroupStrideDiv { divisor: 2 },
    Mutation::IrWorkgroupSizeMul { factor: 2 },
    Mutation::IrWorkgroupSizeDiv { divisor: 2 },
    Mutation::IrWorkgroupSizeOffset { by: -1 },
    Mutation::IrWorkgroupSizeOffset { by: 1 },
    Mutation::LowerRemoveBoundsCheck,
    Mutation::LowerRemoveShiftMask,
    Mutation::LawFalselyClaim {
        law: "Commutative",
        op: "add",
    },
    Mutation::LawFalselyClaim {
        law: "Associative",
        op: "add",
    },
    Mutation::LawIdentityCorrupt {
        op: "add",
        wrong: 1,
    },
    Mutation::LawAbsorbingCorrupt {
        op: "mul",
        wrong: 0,
    },
];

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn catalog_contains_required_wave4_operators() {
        assert!(MUTATION_CATALOG
            .iter()
            .any(|m| matches!(m, Mutation::IntegerConstantBitFlip { .. })));
        assert!(MUTATION_CATALOG
            .iter()
            .any(|m| matches!(m, Mutation::FloatConstantBitFlip { .. })));
        assert!(MUTATION_CATALOG
            .iter()
            .any(|m| matches!(m, Mutation::IrWorkgroupStrideMul { .. })));
        assert!(MUTATION_CATALOG
            .iter()
            .any(|m| matches!(m, Mutation::IrWorkgroupStrideDiv { .. })));
        assert!(MUTATION_CATALOG
            .iter()
            .any(|m| matches!(m, Mutation::IrWorkgroupSizeMul { .. })));
        assert!(MUTATION_CATALOG
            .iter()
            .any(|m| matches!(m, Mutation::IrWorkgroupSizeDiv { .. })));
        assert!(MUTATION_CATALOG
            .iter()
            .any(|m| matches!(m, Mutation::IrWorkgroupSizeOffset { .. })));
        assert!(MUTATION_CATALOG
            .iter()
            .any(|m| matches!(m, Mutation::AtomicOrderingAcqRelWeaken)));
        assert!(MUTATION_CATALOG
            .iter()
            .any(|m| matches!(m, Mutation::BufferCountShift { by: -1 })));
        assert!(MUTATION_CATALOG
            .iter()
            .any(|m| matches!(m, Mutation::BufferCountShift { by: 1 })));
        assert!(MUTATION_CATALOG.iter().any(|m| matches!(
            m,
            Mutation::CompareOpSwap {
                from: BinOpKind::Le,
                to: BinOpKind::Ge
            }
        )));
        assert!(MUTATION_CATALOG.iter().any(|m| matches!(
            m,
            Mutation::CompareOpSwap {
                from: BinOpKind::Ge,
                to: BinOpKind::Le
            }
        )));
        assert!(MUTATION_CATALOG
            .iter()
            .any(|m| matches!(m, Mutation::ControlFlowSkip)));
    }
}