use super::{pair_bytes, sig, triple_bytes, u32_bytes, InputGenerator};
use crate::spec::types::OpSignature;
pub struct U32Pathological;
impl InputGenerator for U32Pathological {
fn name(&self) -> &'static str {
"`u32` pathological"
}
fn handles(&self, signature: &OpSignature) -> bool {
sig::is_u32_any(signature)
}
fn generate(&self, signature: &OpSignature, _seed: u64) -> Vec<(String, Vec<u8>)> {
if sig::is_unary_u32(signature) {
unary_pathological()
} else if sig::is_binary_u32(signature) {
binary_pathological()
} else if sig::is_ternary_u32(signature) {
ternary_pathological()
} else {
Vec::new()
}
}
}
fn unary_pathological() -> Vec<(String, Vec<u8>)> {
vec![
("patho:i32_min", u32_bytes(0x8000_0000)),
("patho:i32_max", u32_bytes(0x7FFF_FFFF)),
("patho:i32_neg1", u32_bytes(0xFFFF_FFFF)),
("patho:single_msb", u32_bytes(0x8000_0000)),
("patho:single_lsb", u32_bytes(0x0000_0001)),
("patho:clz_1", u32_bytes(1)), ("patho:clz_max", u32_bytes(u32::MAX)), ("patho:clz_zero", u32_bytes(0)), ("patho:clz_msb", u32_bytes(0x8000_0000)), ("patho:reverse_palindrome", u32_bytes(0x8001_0080)),
("patho:reverse_all_high", u32_bytes(0xFFFF_0000)),
]
.into_iter()
.map(|(label, bytes)| (label.to_string(), bytes))
.collect()
}
fn binary_pathological() -> Vec<(String, Vec<u8>)> {
let mut out = Vec::new();
for shift in [0, 1, 15, 16, 30, 31, 32, 33, 63, u32::MAX] {
out.push((
format!("patho:shift:{shift}"),
pair_bytes(0xDEAD_BEEF, shift),
));
out.push((format!("patho:shift_one:{shift}"), pair_bytes(1, shift)));
out.push((
format!("patho:shift_max:{shift}"),
pair_bytes(u32::MAX, shift),
));
}
for divisor in [0, 1, 2, 3, 7, 16, 256, u32::MAX] {
out.push((format!("patho:div_by:{divisor}"), pair_bytes(100, divisor)));
out.push((
format!("patho:div_max_by:{divisor}"),
pair_bytes(u32::MAX, divisor),
));
out.push((
format!("patho:div_zero_by:{divisor}"),
pair_bytes(0, divisor),
));
}
out.push(("patho:add_overflow".to_string(), pair_bytes(u32::MAX, 1)));
out.push((
"patho:add_overflow2".to_string(),
pair_bytes(u32::MAX, u32::MAX),
));
out.push(("patho:sub_underflow".to_string(), pair_bytes(0, 1)));
out.push(("patho:sub_underflow2".to_string(), pair_bytes(0, u32::MAX)));
out.push((
"patho:mul_overflow".to_string(),
pair_bytes(u32::MAX, u32::MAX),
));
out.push((
"patho:mul_overflow2".to_string(),
pair_bytes(0x10000, 0x10000),
));
out.push(("patho:mul_by_zero".to_string(), pair_bytes(u32::MAX, 0)));
out.push(("patho:eq_zero".to_string(), pair_bytes(0, 0)));
out.push(("patho:eq_max".to_string(), pair_bytes(u32::MAX, u32::MAX)));
out.push((
"patho:cmp_adjacent".to_string(),
pair_bytes(u32::MAX - 1, u32::MAX),
));
out.push(("patho:rot_0".to_string(), pair_bytes(0xDEAD_BEEF, 0)));
out.push(("patho:rot_16".to_string(), pair_bytes(0xDEAD_BEEF, 16)));
out.push(("patho:rot_32".to_string(), pair_bytes(0xDEAD_BEEF, 32)));
for offset in [0, 1, 16, 31] {
for count in [0, 1, 16, 31] {
let packed = offset | (count << 5);
out.push((
format!("patho:extract:off{offset}_cnt{count}"),
pair_bytes(0xDEAD_BEEF, packed),
));
}
}
out.push(("patho:clamp_zero_bounds".to_string(), pair_bytes(50, 0)));
out.push((
"patho:clamp_max_bounds".to_string(),
pair_bytes(50, 0xFFFF_FFFF),
));
out.push(("patho:clamp_at_low".to_string(), pair_bytes(0, 0x0005_0003)));
out.push((
"patho:clamp_at_high".to_string(),
pair_bytes(u32::MAX, 0x0005_0003),
));
out
}
fn ternary_pathological() -> Vec<(String, Vec<u8>)> {
[
("patho:ternary_zero_span", 0, 0, 0),
("patho:ternary_full_span", u32::MAX, 0, 32),
("patho:ternary_cross_boundary", 0xDEAD_BEEF, 31, 33),
(
"patho:ternary_signed_edges",
i32::MIN as u32,
i32::MAX as u32,
u32::MAX,
),
]
.into_iter()
.map(|(label, a, b, c)| (label.to_string(), triple_bytes(a, b, c)))
.collect()
}