A Haxe compiler with a tiered JIT, Cranelift and LLVM backends, and no garbage collector.
One codebase, one runtime, four places to put it. WebAssembly is not an afterthought here — it goes through the same optimized MIR as the native backends and ships as a core module, a WASI P2 component, or a browser bundle.
Native binaries through LLVM, or the Cranelift JIT while you work. Threads, sockets and the full runtime, plus NUMA-aware worker pinning on servers.
The same native path on Apple silicon and Intel, with a worker pool that adapts to the machine instead of fighting it.
Native binaries through the MSVC toolchain, with the same tiered JIT and the same runtime you develop against elsewhere.
Core modules, WASI P2 components, and a browser harness — the same MIR through the same optimization passes as the native backends.
Haxe already has the type system, the macros and the ergonomics. What it hasn't had is a compiler that goes straight to machine code, frees memory without a collector, and optimizes once for every backend. That's what Rayzor does — with the Haxe you already write.
An optimization ships after it's proven correct. Drop insertion and inline are guarantees, not hints, so they run at every level — including -O0.
The compiler works out when to free things. No pauses in the middle of a frame, and you can annotate one class at a time.
Dominance, loop structure and escape info are computed once and reused by every pass that needs them.
MIR collections are ordered on purpose, so codegen is reproducible build after build.
Parsing, type checking, module caching and bundling all skip what hasn't changed. Caching is on by default.
Every backend reads the same SSA, so a pass written for the JIT also speeds up your native binary and your wasm module.
Transpilation. The official Haxe compiler is very good at emitting JavaScript, Python and PHP — Rayzor has no such target and won't. Use the official compiler when you ship source, Rayzor when you ship machine code.
The compiler decides when every value is freed, from last-use and escape analysis. You reach for annotations only where aliasing actually matters.
Same Haxe source on every target. Rayzor is faster than HashLink outright, faster than the JVM without paying its startup, and faster than hxcpp on floating-point work — and it gets there in tens of milliseconds of compile time, not hundreds.
That compile column is the part you feel all day. No C++ toolchain to set up, no JVM to warm, no separate build step before you can run — rayzor run starts executing while the optimizer is still working. And it's a cold number: the BLADE cache keeps every unchanged module compiled, so the second build compilation is instant.
3 measured iterations, mean reported. INTEL(R) XEON(R) PLATINUM 8573C, linux, x86_64, 2026-08-24.
Full results, regenerated by CI ↗execution only, mean of 10 measured runs · milliseconds, smaller is better
axis clips at 4× the fastest — ▸ marks a bar past the edge, real value labeled
The SIMD* family is first-class Haxe — 128- and 256-bit, float and integer lanes — with tuple and array literals, real operator overloads, and a full math surface: dot, normalize, magnitude, lerp. It lowers to NEON, SSE2 or WASM SIMD128, with a scalar fallback where none exists.
The interpreter handles vector types, and functions that use SIMD are promoted on first call — so vector work runs compiled from the start without giving up instant startup.
How it lowers ↗Point Rayzor at a .hx file, or hand it the build.hxml you already have.
Long-running processes where a collector pause is a latency spike you can't explain to anyone. Memory is freed by analysis, so tail latency is a property of your code, not the runtime's mood.
Frame budgets don't survive a stop-the-world pause. Ownership annotations put allocation lifetimes where you can see them, and the JIT means iteration doesn't wait on a full build.
The parts that usually push people out of Haxe and into C: vector types, thread pools that don't re-spawn, and control over which core does what.
Nue runs local language models on the Rayzor runtime. The tokenizer, the quantized matmul kernels, the KV cache and the scheduler are all written in Haxe — a workload people normally assume you have to write in C or Rust.
Every kernel is benchmarked against the Rust version it replaces. When Haxe is slower, that's treated as something to fix in the kernel, the thread pool or the compiler — not a reason to drop back to Rust.
Browse nue/ in the repoQwen2.5-0.5B, interleaved arms, medians, verified with zero FFI calls.
Parity is met and beaten on k-quant; INT8 sits within 5% and is closing. FFI is reserved for platform APIs — AMX, CoreML, VNNI — never for kernels Haxe could write.
We're working on consuming the official Haxe compiler's output directly and lowering it into Rayzor MIR. Keep the frontend you already trust — full Haxe 4.x, every macro, every library — and get native codegen, ownership and the tiered runtime underneath it.
No rewrite, no second dialect. The same build you run today, ending in machine code.
Follow the discussion ↗Standard library coverage and optimization tuning are the active fronts. Both are good first patches.