makepad/libs/relax/compiler/tests/n01_const_loop_table.rs
Admin b22a714840 makepad run: the Rust JIT (libs/relax) and makepad-remote
The JIT that runs makepad apps from source: lexer, front end, type checker,
lazy borrow checker (Gandalf; `--check-first` opts in), codegen, session and
warm/cold caches keyed by compiler stamp, provided crates bound late,
startup images, live patching. User-facing name is `makepad run` (binary
`makepad`, MAKEPAD_RUN_* env, ~/.makepad-run); libs/relax stays the internal
library name. `makepad check` reports rustc-style diagnostics with rustc
error codes and checks a whole workspace (`--workspace`). Runs on macOS,
Linux, Windows and Android. makepad-remote: one tool schema for apps and the
WM (app/1): grabs, captures, traces, frame profiles and tweaks.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-13 12:26:21 +02:00

100 lines
3.2 KiB
Rust

#[derive(Clone, Copy, PartialEq, Eq)]
struct Key(u64);
impl Key {
const SEED: u64 = 0xd6e8_feb8_6659_fd93;
pub const fn from_bytes(seed: u64, id_bytes: &[u8], start: usize, end: usize, or: u64) -> Key {
let mut x = seed;
let mut i = start;
while i < end {
x = x.overflowing_add(id_bytes[i] as u64).0;
x ^= x >> 32;
x = x.overflowing_mul(0xd6e8_feb8_6659_fd93).0;
x ^= x >> 32;
x = x.overflowing_mul(0xd6e8_feb8_6659_fd93).0;
x ^= x >> 32;
i += 1;
}
Key((x & 0x0000_3fff_ffff_ffff) | or)
}
}
#[derive(Clone, Copy)]
pub struct Entry {
pub len: u8,
pub lanes: [u8; 4],
}
const SLOTS: usize = 2048;
/// The 680 swizzle names by id, open-addressed on the id's low bits (a third
/// full). Built at compile time from the two lane alphabets, so a lookup is a
/// probe or two instead of a 680-arm `match` per call site.
static TABLE: [(Key, Entry); SLOTS] = build_table();
const fn build_table() -> [(Key, Entry); SLOTS] {
let mut table = [(Key(0), Entry { len: 0, lanes: [0; 4] }); SLOTS];
let alphabets: [&[u8; 4]; 2] = [b"xyzw", b"rgba"];
let mut alphabet = 0;
while alphabet < alphabets.len() {
let mut len = 1;
while len <= 4 {
// Every lane combination of this length, first lane most significant.
let mut code = 0;
while code < 1 << (2 * len) {
let mut name = [0u8; 4];
let mut lanes = [0u8; 4];
let mut i = 0;
while i < len {
lanes[i] = ((code >> (2 * (len - 1 - i))) & 3) as u8;
name[i] = alphabets[alphabet][lanes[i] as usize];
i += 1;
}
let id = Key::from_bytes(Key::SEED, &name, 0, len, 0);
let mut slot = id.0 as usize & (SLOTS - 1);
while table[slot].0 .0 != 0 {
slot = (slot + 1) & (SLOTS - 1);
}
table[slot] = (
id,
Entry {
len: len as u8,
lanes,
},
);
code += 1;
}
len += 1;
}
alphabet += 1;
}
table
}
/// The swizzle a field name of a pod vector stands for, if it is one.
pub fn lookup(id: Key) -> Option<Entry> {
let mut slot = id.0 as usize & (SLOTS - 1);
loop {
let (key, swizzle) = TABLE[slot];
if key.0 == 0 {
return None;
}
if key == id {
return Some(swizzle);
}
slot = (slot + 1) & (SLOTS - 1);
}
}
#[test]
fn static_const_loop_matches_runtime() {
let runtime = build_table();
let mut count = 0;
for i in 0..SLOTS {
if runtime[i].0.0 != 0 { count += 1; }
assert_eq!(TABLE[i].0.0, runtime[i].0.0, "key {}", i);
assert_eq!(TABLE[i].1.len, runtime[i].1.len, "len {}", i);
assert_eq!(TABLE[i].1.lanes, runtime[i].1.lanes, "lanes {}", i);
}
assert_eq!(count, 680);
assert_eq!(lookup(Key::from_bytes(Key::SEED, b"xy", 0, 2, 0)).unwrap().len, 2);
}