pub const I31_DISCRIMINANT: u64 = 1;
pub const NON_NULL_NON_I31_MASK: u64 = !I31_DISCRIMINANT;
#[repr(u32)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
#[rustfmt::skip]
#[allow(missing_docs)]
pub enum VMGcKind {
ExternRef = 0b010000 << 26,
ExternOfAnyRef = 0b011000 << 26,
AnyRef = 0b100000 << 26,
AnyOfExternRef = 0b100100 << 26,
EqRef = 0b101000 << 26,
ArrayRef = 0b101001 << 26,
StructRef = 0b101010 << 26,
}
impl VMGcKind {
pub const MASK: u32 = 0b111111 << 26;
pub const UNUSED_MASK: u32 = !Self::MASK;
pub fn from_high_bits_of_u32(val: u32) -> VMGcKind {
let masked = val & Self::MASK;
match masked {
x if x == Self::ExternRef as u32 => Self::ExternRef,
x if x == Self::ExternOfAnyRef as u32 => Self::ExternOfAnyRef,
x if x == Self::AnyRef as u32 => Self::AnyRef,
x if x == Self::AnyOfExternRef as u32 => Self::AnyOfExternRef,
x if x == Self::EqRef as u32 => Self::EqRef,
x if x == Self::ArrayRef as u32 => Self::ArrayRef,
x if x == Self::StructRef as u32 => Self::StructRef,
_ => panic!("invalid `VMGcKind`: {masked:#032b}"),
}
}
pub fn matches(self, other: Self) -> bool {
(self as u32) & (other as u32) == (other as u32)
}
}
#[cfg(test)]
mod tests {
use super::VMGcKind::*;
use crate::prelude::*;
#[test]
fn kind_matches() {
let all = [
ExternRef,
ExternOfAnyRef,
AnyRef,
AnyOfExternRef,
EqRef,
ArrayRef,
StructRef,
];
for (sup, subs) in [
(ExternRef, vec![ExternOfAnyRef]),
(ExternOfAnyRef, vec![]),
(AnyRef, vec![AnyOfExternRef, EqRef, ArrayRef, StructRef]),
(AnyOfExternRef, vec![]),
(EqRef, vec![ArrayRef, StructRef]),
(ArrayRef, vec![]),
(StructRef, vec![]),
] {
assert!(sup.matches(sup));
for sub in &subs {
assert!(sub.matches(sup));
}
for kind in all.iter().filter(|k| **k != sup && !subs.contains(k)) {
assert!(!kind.matches(sup));
}
}
}
}