New Aarch64 Back End
57 comments
·July 24, 2025conorbergin
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.
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.
> [...]
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.
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
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!
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!