Skip to content

std.cpu

std.cpu provides typed runtime CPU-feature detection for explicit dispatch. It shares one target-independent feature vocabulary with @target_feature, build configuration, semantic interfaces, artifacts, and the runtime ABI.

Feature

Feature is a closed, flat enum. Its variants are canonical Zynx names, not LLVM strings or aliases:

Zynx
export enum Feature {
	X86Sse2,
	X86Sse42,
	X86Avx,
	X86Avx2,
	X86Avx512F,
	X86Fma,
	X86Popcnt,
	X86Bmi2,
	Aarch64Neon,
	Aarch64DotProd,
	Aarch64Sve,
	Aarch64Fp16,
	Aarch64Bf16,
	Aarch64I8mm,
	WasmSimd128,
	WasmRelaxedSimd,
	WasmAtomics,
}

The architecture prefix is part of every variant. This makes a feature's target family visible and prevents backend-specific names such as fullfp16 from entering source APIs. The three Wasm* variants describe artifact-wide Wasm capabilities; they are not host-CPU probes.

API

Zynx
import std.cpu;

fn main() {
	let fast = cpu.has(.X86Avx2);
}

has(feature: Feature) -> bool

has does not allocate and does not throw. It returns true only when the requested feature is available for every eligible CPU on which this process can execute, including the operating system's required state support. The answer is stable for the lifetime of the process. If the runtime cannot make that full guarantee, it returns false.

A feature from a different architecture returns false; it is not an error. Target-baseline features may be folded to true, but compilation must never probe the compiler host to answer a target program's query. On Wasm, cpu.has(.Wasm...) reflects the artifact baseline and is therefore constant for that artifact.

There is deliberately no has_all helper. Compose ordinary Boolean checks when dispatch needs several runtime facts.

Runtime Dispatch With @target_feature

@target_feature accepts one or more Feature values and only enables features. Strings, aliases, comma lists, and +/- entries are not part of the language surface.

Zynx
import std.cpu;

@target_feature(.X86Avx2, .X86Fma)
fn sum_fast(v: [i32]) -> i32 {
	var total = 0;
	for x in v {
		total += x;
	}
	return total;
}

fn sum_portable(v: [i32]) -> i32 {
	var total = 0;
	for x in v {
		total += x;
	}
	return total;
}

fn sum(v: [i32]) -> i32 {
	if cpu.has(.X86Avx2) && cpu.has(.X86Fma) {
		unsafe {
			return sum_fast(v);
		}
	}
	return sum_portable(v);
}

The runtime Boolean is evidence held by the programmer, not a static type proof, so a baseline function still needs an explicit unsafe block. A static caller whose own normalized @target_feature set contains the callee's full normalized set may call it safely. Feature-bearing functions cannot be coerced to callable values until callable types can preserve their requirements, and the attribute is invalid on main and extern functions.

Prerequisites are normalized by the compiler. Duplicates, variants unknown to the active language/SDK registry, and variants for the wrong target are compile errors; wrong-target diagnostics should suggest an @arch-guarded declaration.

For Wasm, a per-function @target_feature(.Wasm...) is legal only when that feature is already enabled artifact-wide. Otherwise compilation fails rather than producing a function that cannot be represented by the artifact's feature contract.

Whole-build CPU and feature policy is documented in the Build Reference. Public build metadata uses stable Zynx Feature Registry names; backend feature strings are not a portable interface.

Released under the MIT License.