vyre-conform 0.1.0

Conformance suite for vyre backends — proves byte-identical output to CPU reference
Documentation
use super::{pair_bytes, sig, triple_bytes, u32_bytes, InputGenerator};
use crate::spec::types::OpSignature;

/// Generates edge-case u32 inputs (0, 1, MAX-1, MAX, powers of 2, all-ones patterns).
pub struct EdgeCases;

impl InputGenerator for EdgeCases {
    fn name(&self) -> &'static str {
        "edge_cases"
    }

    fn handles(&self, signature: &OpSignature) -> bool {
        sig::is_u32_any(signature)
    }

    fn generate(&self, signature: &OpSignature, _seed: u64) -> Vec<(String, Vec<u8>)> {
        let values = edge_values();
        if sig::is_unary_u32(signature) {
            values
                .iter()
                .map(|value| (format!("edge:{value:#010x}"), u32_bytes(*value)))
                .collect()
        } else if sig::is_binary_u32(signature) {
            let mut out = Vec::with_capacity(values.len() * values.len());
            for left in &values {
                for right in &values {
                    out.push((
                        format!("edge_pair:{left:#010x}:{right:#010x}"),
                        pair_bytes(*left, *right),
                    ));
                }
            }
            out
        } else if sig::is_ternary_u32(signature) {
            let triples = [
                (0, 0, 0),
                (0, 1, u32::MAX),
                (u32::MAX, 1, 0),
                (0x8000_0000, 31, 32),
                (0x5555_5555, 0xAAAA_AAAA, 0xFFFF_0000),
            ];
            triples
                .into_iter()
                .map(|(a, b, c)| {
                    (
                        format!("edge_triple:{a:#010x}:{b:#010x}:{c:#010x}"),
                        triple_bytes(a, b, c),
                    )
                })
                .collect()
        } else {
            Vec::new()
        }
    }
}

fn edge_values() -> Vec<u32> {
    let mut values = vec![
        0,
        1,
        u32::MAX,
        u32::MAX - 1,
        0x5555_5555,
        0xAAAA_AAAA,
        0x8000_0000,
        2,
        3,
        5,
        7,
        11,
        13,
        17,
        19,
        23,
        29,
        31,
        65_521,
        65_537,
        0x0000_FFFF,
        0x0001_0000,
        0x0001_0001,
        0x7FFF_FFFF,
        0x8000_0001,
        i32::MIN as u32,
        i32::MIN.wrapping_add(1) as u32,
        i32::MAX as u32,
        i32::MAX.wrapping_sub(1) as u32,
    ];
    for shift in 0..32 {
        values.push(1_u32 << shift);
    }
    values.sort_unstable();
    values.dedup();
    values
}