use crate::ir_inner::model::program::Program;
pub use vyre_spec::CpuFn;
pub trait CpuOp {
fn cpu(input: &[u8], output: &mut Vec<u8>);
}
pub trait CategoryAOp {
fn program() -> Program;
}
#[deprecated(
note = "structured_intrinsic_cpu is a non-executable fallback sentinel. Implement typed GPU lowering for the op."
)]
#[inline(never)]
pub fn structured_intrinsic_cpu(input: &[u8], output: &mut Vec<u8>) {
let _ = input;
output.clear();
std::hint::black_box(&SENTINEL_BODY_MARKER);
}
static SENTINEL_BODY_MARKER: u8 = 0xA7;
#[allow(deprecated)]
pub static SENTINEL_CPU_REF: CpuFn = structured_intrinsic_cpu;
#[must_use]
pub fn is_cpu_reference_sentinel(f: CpuFn) -> bool {
std::ptr::fn_addr_eq(f, SENTINEL_CPU_REF)
}
#[deprecated(
note = "use is_cpu_reference_sentinel; CPU reference sentinels are explicit oracles, not runtime fallbacks"
)]
#[must_use]
pub fn is_fallback_cpu_ref(f: CpuFn) -> bool {
is_cpu_reference_sentinel(f)
}
#[cfg(test)]
#[allow(deprecated)]
mod tests {
use super::*;
#[test]
fn the_sentinel_static_is_recognised_as_the_sentinel() {
assert!(is_cpu_reference_sentinel(SENTINEL_CPU_REF));
}
#[test]
fn the_sentinel_survives_being_stored_and_read_back() {
let stored: CpuFn = SENTINEL_CPU_REF;
let copied = stored;
assert!(is_cpu_reference_sentinel(copied));
}
#[test]
fn is_cpu_reference_sentinel_detects_structured_intrinsic() {
assert!(is_cpu_reference_sentinel(structured_intrinsic_cpu));
}
#[test]
fn is_cpu_reference_sentinel_rejects_other_fn() {
#[allow(clippy::ptr_arg)] fn custom_cpu(_input: &[u8], _output: &mut Vec<u8>) {}
assert!(!is_cpu_reference_sentinel(custom_cpu));
}
#[test]
fn another_do_nothing_cpu_fn_is_not_the_sentinel() {
#[allow(clippy::ptr_arg)]
fn also_clears(_input: &[u8], output: &mut Vec<u8>) {
output.clear();
}
assert!(!is_cpu_reference_sentinel(also_clears));
}
#[test]
fn an_empty_lowering_table_carries_the_sentinel_and_a_populated_one_does_not() {
#[allow(clippy::ptr_arg)]
fn real_cpu_ref(input: &[u8], output: &mut Vec<u8>) {
output.extend_from_slice(input);
}
let empty = crate::dispatch::dialect_lookup::LoweringTable::empty();
assert!(
is_cpu_reference_sentinel(empty.cpu_ref),
"LoweringTable::empty must leave the sentinel in the reference slot"
);
let populated = crate::dispatch::dialect_lookup::LoweringTable::new(real_cpu_ref);
assert!(
!is_cpu_reference_sentinel(populated.cpu_ref),
"a table built with a real CPU reference must not look like the sentinel"
);
}
#[test]
fn structured_intrinsic_clears_output_without_flat_result() {
let mut output = vec![1, 2, 3];
structured_intrinsic_cpu(b"input", &mut output);
assert!(output.is_empty());
}
}