use super::{BinOpKind, Branch, Mutation};
use crate::spec::types::DataType;
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)));
}
}