Skip to content(if available)orjump to list(if available)

New Aarch64 Back End

New Aarch64 Back End

57 comments

·July 24, 2025

conorbergin

Zig is becoming a real do-everything tool for me. I was learning gpu programming recently and found you could compile it to SPIR-V!

AndyKelley

Oh yeah, everyone is sleeping on this use case. Plenty of work to go before we can advise people to try it out yet, but being able to share packed structs, enums, and compile-time logic across CPU and GPU code is going to be, quite literally, a game changer.

miki123211

Is this just for graphics programming, or are ML / scientific computing use cases (compiling to Cuda / SASS) considered too?

sgt

Forgive my ignorance but what would be some practical use cases for this, for someone who hasn't been doing any GPU programming to understand? I guess Machine Learning?

wiz21c

currently, when you want to write a sahder, you have to use a specific language for that (gl/sl or some other). That's a pain because that language is C-like and most likely pretty close to your host language (C,Rust,Zig whatever). Moreover, you must pass information to these shaders (uniforms) and it means you have to write code to copy from you haost lang data structures to the data strctures of the shaders (which , once again, are pretty close to those in your host language). Shader languages don't usually have "import" mechanism, so building with them is painful. And their syntax is very light, so having syntactic sugar coming from the host language would be cool.

So yeah, writing shader in something else than Gl/SL, wgsl would make our life so much easier...

andyfleming

Is that similar to the functionality they're targeting with Mojo?

ummonk

I’m a little confused reading this. Is MIR short for “machine intermediate representation” instead of “medium intermediate representation”? I generally expect IRs to be relatively platform-independent but it sounds like the “MIR” here is close to Aarch64 binary?

TUSF

Zig has a couple of IR layers. Generally, Zig's compiler goes: AST → ZIR → AIR, and from there it'll either emit LLVM bitcode or one of its own, platform-specific "Machine IR"

sakras

Likely refers to Machine IR, a lower level representation that normal LLVM IR lowers to?

cogman10

In rust it's mid-level IR.

Here's what that all means in rust terms [1]. I assume zig doing something similar.

[1] https://blog.rust-lang.org/2016/04/19/MIR/

MuffinFlavored

What's the motivation to avoid LLVM backends?

mananaysiempre

> In exchange [for eliminating the dependency on LLVM], Zig gains these benefits:

> All our bugs are belong to us.

> The compiler becomes trivial to build from source and to bootstrap with only a C compiler on the host system.

> We stop dealing with annoying problems introduced by Linux distributions and package managers such as Homebrew related to LLVM, Clang, and LLD. There have been and continue to be many.

> The Zig compiler binary goes from about 150 MiB to 5 MiB.

> Compilation speed is increased by orders of magnitude.

> [...]

https://github.com/ziglang/zig/issues/16270

donio

The Go toolchain is a nice illustration of this approach working in practice. It fully bootstraps in 90 seconds on my aging laptop and since it's fully self-hosted it doesn't even need a C compiler unless you want cgo support.

LLVM takes 2 hours to build on the same host and zig (with the LLVM backend) is another 20 minutes. It will be awesome if that can be brought down to 2 minutes or less.

AndyKelley

Is that building Go with Go? Or actual bootstrapping? Check this out...

Building Zig with Zig:

    andy@bark ~/s/zig (master)> time zig build
    
    ________________________________________________________
    Executed in   11.67 secs    fish           external
Bootstrapping with only a C compiler dependency (not even make or shell!):

    andy@bark ~/s/zig (master)> time cc -o bootstrap bootstrap.c; and time ./bootstrap
    
    ________________________________________________________
    Executed in   55.10 millis    fish           external
    
    gcc -o zig-wasm2c stage1/wasm2c.c -O2 -std=c99
    ./zig-wasm2c stage1/zig1.wasm zig1.c
    gcc -o zig1 zig1.c stage1/wasi.c -std=c99 -Os -lm
    ./zig1 lib build-exe -ofmt=c -lc -OReleaseSmall --name zig2 -femit-bin=zig2.c -target x86_64-linux --dep build_options --dep aro -Mroot=src/main.zig -Mbuild_options=config.zig -Maro=lib/compiler/aro/aro.zig
    ./zig1 lib build-obj -ofmt=c -OReleaseSmall --name compiler_rt -femit-bin=compiler_rt.c -target x86_64-linux -Mroot=lib/compiler_rt.zig
    gcc -o zig2 zig2.c compiler_rt.c -std=c99 -O2 -fno-stack-protector -Istage1 -Wl,-z,stack-size=0x10000000 -pthread
    
    ________________________________________________________
    Executed in  305.06 secs    fish           external

cxr

Sometime after Minix 3 but before it had attained the critical mass for a self-sustaining community, compilation times went from 10 minutes on low-end hardware to ~3 hours, and the answer to the question "Why?" was "LLVM/clang".

wiz21c

maybe I'm wrong, but rust is still using LLVM. When I see that list of benefits, I wonder why rust is still on LLVM... (honest question, I use rust everyday and I'm happy with it, except for compilation times :-) )

zozbot234

Rust has cranelift as a natively bootstrapped alternative these days. No different from Golang or Zig.

rowanG077

Rust depends heavily on the llvm optimization pipeline afaik. So it would be a heavy investment to write native backends.

remindmeagain

Does this mean `zig c++` is going away with LLVM dropped? That would be a shame - so useful.

flohofwoe

AFAIK the current plan for zig cc is outlined here:

https://github.com/ziglang/zig/issues/20875

E.g. LLVM will still be around one way or another, just not as deeply integrated as it is now.

forrestthewoods

As long as Zig builds the glibc shim libraries those can be used in a separate Clang build system.

It’d be nice if Zig added a command to emit them more explicitly to use in non-Zig build systems. Would be awesome actually. Plz?

ethan_smith

Zig's self-hosted compiler reduces compile times, enables better cross-compilation, allows finer control over codegen optimizations, and eliminates the large LLVM dependency which simplifies distribution and bootstrapping.

tw061023

LLVM is basically a resource pool for C++ compiler development. As such, it is highly C++ specific and leaks C++ semantics everywhere.

It's especially funny when this happens in Rust, which is marketed as a "safer" alternative.

Would you like a segfault out of nowhere in safe Rust? The issue is still open after two years by the way: https://github.com/rust-lang/rust/issues/107975

saghm

It's not clear to me what you mean by default with regards to that issue. As far as I can tell, there's not really any indication that this is undefined behavior. Yes, there seems to be to a bug of some sort in the code being generated, but it seems like a stretch to me to imply that any bug that generates incorrect code is necessarily a risk of UB. Maybe I'm missing some assumption being made about what the pointers not being equal implies, but given that you can't actually dereference `*const T` in safe Rust, I don't really see where you're able to draw the conclusion that having two of them incorrectly not compare as equal could lead to unsafety.

tux3

If you read the Github issue, this one was weaponized fairly straightforwardly by taking the difference between the two pointers.

The difference is zero, but the compiler thinks it is non-zero because it thinks they are unequal.

From there you turn it into type confusion through an array, and then whatever you want. Almost any wrong compiler assumption can be exploited. This particular way to do it has also been used several times to exploit bugs in Javscript engines.

ncruces

Yeah, using LLVM for anything trying to avoid UB is crazy.

I got involved in a discussion with a Rust guy when trying to get C with SIMD intrinsics into wasi-libc where something that the C standard explicitly state is “implementation defined” (and so, sane, as we're targeting a single implementation - LLVM) can't be trusted, because LLVM may turn it back into UB because “reasons.”

At this point Go and Zig made the right choice to dump it. I don't know about Rust.

https://github.com/WebAssembly/wasi-libc/pull/593

AndyKelley

It sounds like you have a fundamental misunderstanding about undefined behavior. It's easy to emit LLVM IR that avoids undefined behavior. The language reference makes it quite clear what constitutes undefined behavior and what does not.

The issue is that frontends want to emit code that is as optimizeable as possible, so they opt into the complexity of specifying additional constraints, attributes, and guarantees, each of which risks triggering undefined behavior if the frontend has a bug and emits wrong information.

pjmlp

Which is why nowadays most frontends have been migrating to MLIR, and there is also ongoing work for clang as well.

AndyKelley

How does migrating to MLIR address the problem?

sakras

Likely performance - LLVM is somewhat notorious for being slower than ideal.

null

[deleted]

EricRiese

+28,242 −3,737

LGTM

webdevver

honestly those numbers should be the other way around. extra 25k for an aarch64 backend...

actually kind of sus. they should be able to do it in 10kloc. the cpu does most of the heavy lifting anyway. i certainly hope they aren't scheduling insns or doing something silly like that!