code wiki / (root) / nx_hw_simd_caps.nx

nx_hw_simd_caps.nx

buildroot/runtime/nx_hw_simd_caps.nx

7629 B201 linesdepth 2pulls 2 transitivereach 1 importersview sourcekind tooltopic hw
docsdependenciesstructsconstsfunctions

about

nx_hw_simd_caps.nx -- runtime SIMD capability detection. Reads /proc/cpuinfo and looks for vendor-specific flag tokens. Sovereign: pure NishiLang, no libc, no /sys probe utilities, no CPUID inline-asm dep. Works on every Linux arch the substrate targets (x86_64, RV64, AArch64, etc.) -- /proc/cpuinfo is the kernel's canonical CPU-feature reporting surface. HISTORICAL NOTE: this module was the smoke that surfaced the gp-relative relaxation bug fixed 2026-05-16. When 6 statics fall within a single 4 KiB BSS window, the assembler optimizes auipc+addi global-address sequences into addi(gp)+addi, but our minimal crt0 doesn't initialize gp, so reads/writes dereferenced garbage. Fixed in riscv.c by always emitting `.option norelax` -- the bug class is now structurally impossible regardless of static count. See docs/NISHILANG_CONCURRENCY.md "Pitfalls" section for the diagnosis trail. Why probe at runtime instead of compile-time: - One binary can dispatch scalar / AVX2 / AVX-512 paths based on the actual chip it runs on (vs N separate builds) - Honest cardinal: refuse silent CPU-feature assumptions; ask the kernel what it actually has Use: if nx_hw_has_avx512() == 1 { use_avx512_path() } else if nx_hw_has_avx2() == 1 { use_avx2_path() } else { use_scalar_path() } Cost: ~4 KiB stack buffer + one sys_openat + one sys_read + linear scan. Acceptable to call once at startup; cache in a static for repeated checks. Caches: once probed, results are stored in static i64 slots so subsequent calls are zero-syscall.

dependencies 1 imports · 1 importers

nx_syscalls.nx nx_hw_simd_caps.nx nx_hw_simd_caps_test.nx

imports: nx_syscalls.nx

imported by: nx_hw_simd_caps_test.nx

call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown

main _caps_smoke_run nx_hw_has_avx2 _nx_hw_caps_init sys_mmap _nx_hw_read_cpuinfo sys_read sys_close _nx_hw_tok_lit _nx_hw_has_token nx_hw_has_avx512 _nx_hw_caps_init ↻ nx_hw_has_rvv _nx_hw_caps_init ↻ nx_hw_has_neon _nx_hw_caps_init ↻ nx_hw_simd_i64x4_available _nx_hw_caps_init ↻

structs

none

consts

45const NX_CPUINFO_BUF: i64 = 8192

functions

56func _nx_hw_read_cpuinfo(buf: *u8, cap: i64) -> i64
called by 1: _nx_hw_caps_init calls 2: sys_readsys_close
70func _nx_hw_has_token(buf: *u8, buf_len: i64, tok: *u8, tok_len: i64) -> i64
called by 1: _nx_hw_caps_init
109func _nx_hw_tok_lit(buf: *u8, s_byte_0: i64, s_byte_1: i64, s_byte_2: i64,
called by 1: _nx_hw_caps_init
130func _nx_hw_caps_init() -> i64
161func nx_hw_has_avx2() -> i64 { _nx_hw_caps_init(); return NX_HW_HAS_AVX2 }
162func nx_hw_has_avx512() -> i64 { _nx_hw_caps_init(); return NX_HW_HAS_AVX512 }
163func nx_hw_has_sse4_2() -> i64 { _nx_hw_caps_init(); return NX_HW_HAS_SSE4_2 }
called by 1: sum_all_caps calls 1: _nx_hw_caps_init
164func nx_hw_has_rvv() -> i64 { _nx_hw_caps_init(); return NX_HW_HAS_RVV }
165func nx_hw_has_neon() -> i64 { _nx_hw_caps_init(); return NX_HW_HAS_NEON }
170func nx_hw_simd_i64x4_available() -> i64
189func _caps_smoke_run() -> i64
198func main() -> i64
calls 1: _caps_smoke_run