File for divorce from LLVM
github.com
github.com
But man, it seems to me (uneducated on the challenges zig faces w/LLVM) that this shifts the team's capacity away from zig and towards things like binutils. When I read the headline I assumed that they were throwing out the compiler (IIRC they had mostly/totally excised it already). But for a project like zig it just seems like there's a lot to be gained from keeping it.
That said -- the prospect of rewriting a lot of the stuff that's in the LLVM project now in zig instead of c++ - that's pretty cool and ambitious. Just as ambitious as it was for Lattner to create LLVM, I suppose.
But code that's accidentally quadratic - well, that's bound to happen to zig too, if it's as popular and useful as LLVM project is.
It is difficult for me to imagine Zig succeeding without a similar capability - which is to say I hope they do not follow through on this milestone.
In zig you _can_ actually start with a c codebase and rewrite it file by file in zig and you _can_ include c headers in your zig files verbatim. Both of these are not possible in rust.
This milestone is only gonna remove the c++ (and objective c/c++) compiler for now from zig cc. So while you could argue this will ostracize people rewriting their c++ codebases in zig, I don't imagine there's actually many people like that. EDIT: I just looked at the discussion and there's actually a lot of people that use the c++ capapbilities.
well, you can: i have done this, with Rust. but yes, it’s more the type of thing that well-resourced companies do rather than solo devs, because even with Bindgen and the like Rust really wants the atomic codegen unit to be the “library”, not C’s notion of a “compilation unit”. still, C FFI compatibility is exactly why porting from C to rust incrementally is feasible while C to, say Java, is probably a bigger leap.
In Zig that all "just works" with the standard Zig install.
https://github.com/floooh/sokol
...inspired by:
https://github.com/nothings/stb
(here's how the sokol headers are integrated into a Zig project, note that there is only a build.zig which builds everything: https://github.com/floooh/kc85.zig)
But it's not so much about build systems, but requiring a separate compiler toolchain to build any C++ or ObjC dependencies (Rust needs this, Zig currently does not - unless that controversial proposal is implemented).
(also even complex C++ libraries can be wrapped in a build.zig, so you don't require a separate build system like cmake for the C++ dependencies)
Similarly I don't really understand why you want one toolchain for a multi-language project. It's not that useful or convenient since it's going to need to be orchestrated with a buildsystem somehow.
Like with Rust, you probably only have a build.rs file. It invokes a separate (possibly multiple) toolchains. Or with CMake. A simple project has a single CMakeLists.txt that can invoke any number of toolchains. I don't see why zig can't do that with a build.zig file, or why it matters.
(also it's a myth that STB style libs increase compile time, that's only true for typical C++ header-only libs with inline methods and template code)
> In zig you _can_ actually start with a c codebase and rewrite it file by file in zig and you _can_ include c headers in your zig files verbatim. Both of these are not possible in rust.
You can. Either via FFI and bindgen-ing headers, or by using c2rust. The latter is not just a toy ambitious project, but actually a very impressive piece of engineering and does produce a result where you can transpile a project or file and start rewriting file-by-file or function-by-function.
It also doesn't supportal a good amount of more complicated c features.
It's a help for sure, but the few times I tried I ended up just doing the rewrite by hand instead to actually cover all the cases.
Everything else are aspiring extras in the cinema of programing languages, waiting on the sidelines for that major role that will come someday, it really will, one just has to believe enough.
Additionally JetBrains has their fingers all over the place in Android.
Kotlin, Android Studio a mix of InteliJ and Clion, Compose,...
https://miro.medium.com/v2/resize:fit:720/format:webp/1*sojK...
Kotlin would be likely still nowhere without Google and Android.
For all practical purposes ART has turned into the Kotlin Virtual Machine.
However it so happens, that to keep the advantage of using Java libraries in the Android ecosystem, they actually need to support newer Java libraries unless they feel like rewriting all of them into Kotlin.
So Android 12 and 13 got a subset of Java 11 LTS, and Android 14 is getting Java 17 LTS support.
That doesn't change the reasoning that Android is all about Kotlin nowadays, unless one is writing platform code itself.
A big difference is there was an element of no choice to LLVM, at least in Apple’s takeover of the project: GCC didn’t want to allow / do what Apple wanted / needed out of it.
Edit: additional bit I remembered, this statement is prefixed with something like 'you may start thinking you project will be cheaper/more efficient if you develop a launch vehicle suited to your particular mission instead of compromising on an existing one, but', then the above.
39. Any exploration program which "just happens" to include a new launch vehicle is, de facto, a launch vehicle program.
No. It's an unaccepted proposal.
I think it's same to assume it's an official goal, now.
https://github.com/ziglang/zig/issues?q=is%3Aissue+label%3Ap...
Ime, the optimizing passes of a compiler are easy and fun to write. You have to read research papers to understand how register allocation and ssa form works, but it's fun code to write. You just send the ir through various optimizing passes, each refining it in some way. You can write high-quality optimization passes without llvm. But then you want to linearize your ir into machine code. This step is boring and mundane to write unless you care about all the different ways x86-32/64 can encode a "mov [eax+8*ebx], 123" instruction. If you are optimizing for binary size, do you want to bother measuring on which platforms "push eax; push eax; push eax" is shorter than "add rsp,12"? And this is just for x86. Multiply it tenfold for all the other non-x86 architectures irrelevant to most developers. The chance of having major bugs in the code generator for obscure architectures that stay undetected for years is very high.
The second issue is bootstrapping. What compiles the Zig compiler written in Zig? You could, for example, have a non-optimizing minimal Zig compiler written in C that compiles the Zig compiler. But since it's non-optimizing, the Zig compiler would need to be recompiled with the optimizing Zig compiler. Not unsolvable problems, but ime long and complicated build processes risk driving away potential contributors.
Makes sense, kind of silly to have to bundle a 100MB+ copy of LLVM if you don't need it for the common case, and if you're a developer you'll probably have it installed already anyway.
The problem could be that it'll be hard to guarantee that your Zig installation works properly with the version of LLVM you have installed? We'll see..
I use Zig as a C++ compiler on my Rust project since it was the least painful way to do cross-compilation in GitHub Actions.
I'd recently been reading a bit more about zig, and even tried out using it as an easy way to compile c++ with llvm without having to fuss with system packages -- transitioning from c/c++ to zig was a major selling point
It just seems really abrupt, certainly unexpected. I'm not saying it's the right/wrong thing for the project -- just really really out of left field from my point of view
The loss of C++ compatibility effectively removes the biggest thing that my Zig fan friends mention to me.
The loss of performance (however temporary they say) is the other piece they mention.
For casual readers, it's a proposal, not something decided
The sub-items of this task are still valuable to complete even if this overarching proposal were declined. Most of them are not being completed as a prerequisite for this proposal. There are benefits gained even without the full removal of LLVM.
I can really respect the really wide-reaching views and goals of Andrew with zig and in proposals like this, even if I don't agree.
It's your language so do whatever you want but please adjust the branding accordingly...
People know that, but it's difficult to avoid using it for real things once you've tried it and it works :D.
I haven't done that with Zig, but with Kotlin things like serialization/coroutines/kotest/KAPT (it was the same feeling: oh this stuff is "Experimental" but so cool, I can't do real Kotlin without them!!)... well yeah, I spent many hours rewriting stuff due to that, and totally acknowledge that was on me.
To what benefit? Isn't this a waste of resources?
It will NOT reimplement everything, if you read the proposal, it's in favour of changing the LLVM dependency (the libs) not dropping LLVM IR generation, this will come with performance regression since now will be up to the team to get the correct IR, and making decisions LLVM IR generation does already in LLVM
The problem is that clang is being dropped, which means, unless we have a new C++ front made in zig (a-la AroCC for C) we are gonna suffer quite a bit for projects using C++ with zig.
that seems a monumental undertaking.
Writing a C++ compiler is several order of magnitude more complicated than writing a C, Java, Go or Zig compiler. There's a very good reason there are only 3 in existence despite how ubiquitous C++ is (and even then, it takes years for them to keep up with the latest standards). C++'s grammar is type 0, there's isn't even an EBNF definition of it because it's pratically impossible to write a complete one. Clang only succeeded thanks to massive investments from the biggest players in the industry, and GCC/MSVC simply grew alongside the language. All other C++ compilers died a horrible death a long time ago.
There are essentially only four extant C++ front-end implementations: GCC, Clang, MSVC, and EDG. All other C++ compilers are based on one of these four implementations, or have since gone extinct. (Except maybe Green Hills, but I can't recall anymore if their front-end is still in-house.)
Im guessing you'll have two categories of tier 1 support: - Built-in tier 1 support. - Tier 1 support through the optional LLVM backend.
If they already have tier 1 support for an architecture, I don't see why they'd loose that support when they make the LLVM backend an optional dependency?
And as Andrew writes in the proposal, this way might provide a path for better support for more obscure architectures. I would happily work on a backend for Zig for some interesting processor architecture. No way I will ever contribute to LLVM. Working with C++ in not something I'll ever do to fun
1. gdc - based on the Gnu compiler collection back end
2. ldc - based on the LLVM back end
3. dmd - based on the x86 code generator that I wrote for Zortech/Symantec/Digital Mars
They each have their pluses, minuses, and targets. But the D language each supports is the same.
Overall, our users like the choice. Some even use more than one.
(Nothing wrong with it, just a bit funny how predictable it has become)
I guess the interesting difference in approach here, is that D seems to have completely separate compilers, while it looks like the main Zig compiler will support LLVM as a backend if you have it installed? If true, I like the approach Zig is going for.
All 10 of them? I mean, if Zig's target is eventual wide adoption, DLang is not a good precedent to model upon.
That allows people to use the fastest compiler during development, and the fastest runtime (or smallest memory footprint) compiler for the final release, which is really useful.
Also, just having a language specification which all compilers adhere to ensures that the language is stable and won't just break things under you (for better or worse, there are advantages for languages like Zig that can still change anything they want in order to make the language more consistent/cleaner/more powerful). I tend to value this stability a lot more these days - it lets me put all my effort in creating real value for users instead of constantly keeping up with development tools.
Which is the exact opposite of what the intention behind this proposal is, which is to make the language more maintainable.
Technologically D suffers more from having a single frontend implementation than having multiple backends.
If this proposal is accepted, I personally think Zig will drop to the popularity level of Hare or other extremely niche languages. Getting my colleagues to even try Zig out required me sending them articles about how Uber was using it in production. There is no way my colleagues would even have given it a second thought if it didn't have immediate value to their existing projects.
But I get where the proposal is coming from. LLVM compile times can seem awful, and there's lots of neat optimization tricks you could implement with your own byte code. And dealing with bugs in LLVM is basically a no-go, I've seen this happen in the Julia ecosystem as well.
If my recommendations are worth anything, I think Zig should
1. Use a custom bytecode for debug builds - fast build times, fast debug times etc 2. Use LLVM for release builds - fast runtime performance, slow release performance
If they can manage 1.) while still maintaining support for cross compiling C/C++ (just pass that part off to LLVM?) I think that might be the best of all worlds, with the tradeoff that there's additional backend code to maintain.
As one of the folks dealing with LLVM bugs in the Julia ecosystem.
Yes it requires a distinct skillet different from working on the higher-level Julia compiler and yes it can sometimes take ages to merge bugfixes upstream, but we actually have a rather good and productive relationship with upstream and the project would get a lot less done if we decided to get rid of LLVM.
In particular GPU support and HPC support (hello PPC) depends on it.
But this is also why we maintain the stance that people need to build Julia against our patchset/fork and will not invest time in bugs filled against Julia builds that didn't use those patches. This happens in particular with distro builds.
If it weren't for the author, I'd have dismissed the whole thing as a low-effort GitHub issue by a Zig newbie. The underestimation of the work involved, the backhanded dismissal of all the work that has gone into LLVM, the "obviously we can do it cheaper, faster, better" confidence/machoism that exudes from each sentence or claim.. I'm disappointed.
I've had nothing but respect for Andrew's work in the past so I'm going to extend him some grace and the benefit of the doubt and say that maybe it was just written in haste or on a whim without paying attention to how it came across. But it's not something that inspires me with confidence or lends me to give the proposal itself more of a chance.
I bet you'll solve P=NP before finishing that C++ parser.
I think this might be the right choice. C is currently used heavily in the embedded world, and that’s a space where llvm is not good. If I was Zig, I’d want to be able to target all the microcontrollers and this is the only real way to achieve that.
If zig cc and zig c++ die I would instantly stop using the language!
My peanut gallery observation is that a very bright person named Andrew set out on a journey of hard work to come up with a new language. Along the way he (and others) solved many tough ancillary problems related to the toolchain of this new language and how it should provide a useful path for interoperability and migration from code written in other languages.
The toolchain innovations were noticed, embraced, and leveraged by users of other languages as it made their lives easier in contexts where they weren't even using the Zig language.
Now, for Andrew to make even more innovative progress on his endeavor, he needs to undo some of the toolchain innovation and remove complexity that was initially used to bootstrap his endeavor. Removing complexity (from language) is one of the admired traits of this bright person, and here they are applying that good trait again to move the whole project forward.
But 'lo! Other users of the toolchain innovation will be affected... some would say they even appear "entitled" to these innovations... as if their collective need somehow outweighs Andrew's right to direct his energies to his project in the way he decides.
This whole thing smells like a story I read once... I think it was called "The Fountainhead".
I think the disappointment might come with the ratio who choose zig-cc.
1. "We can attract direct contributions from Intel, ARM, RISC-V chip manufacturers, etc., who have a vested interest in making our machine code better on their CPUs."
They are nowhere near popular enough (or used enough by some particularly important customer) for any major architecture vendor to spend any time contributing except as someone's random side project. To think otherwise is ... really out there.
2. "We can implement our own optimization passes that push the state of the art of computing forward."
There are in fact, no magic bullets. Once you pass the baseline of optimization capability, the reason these compilers do well is because they've been worked on forever, and made better 0.2% at a time.
Also, anything you implement they can implement. Maybe it takes annotations, or whatever, but that's about speed and not capability.
3. "Compilation speed is increased by orders of magnitude."
Uh, not if you are doing #2. Most optimization passes, especially when you are first productionizing research, are quite bad. It takes a tremendous amount of applied engineering to make them fast.
This is what i did on both GCC and LLVM. Implement and speed up ad nauseum. I implemented plenty of high-optimization-value, never been productionized before algorithms. It usually took a few versions and lots of slow-compiler bugs to figure out the best way to implement. It turns out most researchers are not spending their time working on the compilation speed. At best, they care that it's passable.
For existing well-productionized algorithms (which don't push the state of the art), you will not get orders of magnitude speedup. You may get some percent depending on how you structure your compiler.
There are certainly slow parts of LLVM, but it's hubris to believe you are going to make something both better optimizing, and seriously faster, for this kind of language. There are other languages for which it is true. Zig is super unlikely to to be one of them.
The way you gain compilation speed for this kind of language is to optimize less. Spend as little time processing things into machine code as possible, using as fast of algorithms as possible, and where you can't, relying on heuristics and such more to help generate good enough code most of the time.
There is more, but man, this feels out there.
If they said "we want to get 90% of the performance at 60% of the cost", sure, maybe. But saying, basically, we will get >100% of the performance at "orders of magnitude" (their claim) less cost is just, as i said, a wild idea. I wish them the best of luck.
Everyone who tries to reinvent good infrastructure is doomed to discover why that infrastructure was invented in the first place .
It seems like a lot of work but also doable to create something that is orders of magnitude faster than LLVM for unoptimized debug builds. Furthermore, the Zig compiler might be an easier thing to work with than LLVM/Clang for doing productionizing of optimization research.
LLVM already has decades of research applied to it to make it produce fast code, it will be incredibly challenging to even match its performance across all the targets it supports let alone improve on it in significant ways. It would be better to spend the time building an optimization pipeline for Zig itself and being more thoughtful about what code you send to LLVM versus trying to replace it wholesale.
For reference to anyone else, this is what they’re referring to
https://webkit.org/blog/5852/introducing-the-b3-jit-compiler...
I read the claims and comments differently than you, fwiw. It definitely reads like people who think they can make it both faster and better.
I feel like Go already went through a whole saga of this where the community started with "LLVM and SSA are bad and slow", then a few years go by and they end up building their own SSA IR and spending a bunch of time trying to bring compilation time closer to what it was before as it made everything much slower.
I've been a contributor since the Go compiler was a tree-based C program and I've never heard anyone say that. What they said (and it's in the Go FAQ page) is: "At the beginning of the project we considered using LLVM for gc but decided it was too large and slow to meet our performance goals." [1]
If you're building a language with the explicit goal to make it compile fast, it's objectively true that starting out with LLVM is not the best approach. You'll get incredible runtime performance of the generated code since the early days, but NOT fast compilation. The Go makers choose a different tradeoff.
> and they end up building their own SSA IR
They switched to a SSA IR because it was a good idea to begin with, after an initial phase with the tree-base prototype. I've also never heard anyone argue that "SSA is bad", despite what you claim. The first compiler was tree-based because they reused a simple tree-based C compiler from plan9.
> building their own SSA IR and spending a bunch of time trying to bring compilation time closer to what it was before as it made everything much slower
The new compiler was ported to Go (machine-rewritten from C) and that's the main reason it was ~2x slower than the old compiler. It's not due to the switch to a SSA-IR.
Yes, this is totally true.
It's also possible to affect this in theory but hard in practice. Usually you shoot for making it O(N^2) (or whatever) where N is the number of variables you want to try to optimize instead of N being number of blocks.
The complete GVN and GVN-PRE in LLVM is theoretically N^3 or N^4, but as engineered it's often much faster (while getting more optimization) or at least not more than a few percent slower than the the existing O(N^2) GVN. It achieves this by being sparser in most cases. The old GVN has to iterate the algorithm, and iterates non-sparsely. Everything is reprocessed because it doesn't know what can change. The new one iterates only the things that could change using fine grained dependency tracking (something akin to how sparse constant prop works). This is often the best you can do.
I will say it's possible to affect these time bounds in theory because if you go down the single static rabbit hole, you realize it's more generally applicable. Kenny (and others) proved this in his thesis about sparse dataflow. That was the whole point. SSA is just one example of a form that enables things to be linear time (and in fact, you can do it without SSA at all using interval methods and such). There are papers that show this about other SS* forms and show examples, but they were mostly (sadly) ignored.
Concretely, for most optimizations like PRE/etc, there are linear time single static transforms of the IR that will make the optimization linear time (Or at least remove a factor of N for you) by explicitly exposing the dataflow in a way that matches what the optimization algorithm wants.
This is awesome in theory - like really cool when you think about it (if you are a compiler nerd), but also completely impractical (at least, AFAIK). Rewriting the IR form for each optimization to the exact requirements of the optimization (single static use, single static exposed uses, single static upwards exposed uses, single static exposed defs, etc) is much more expensive in practice than well engineered, higher complexity, "N in the number of variables" optimizations.
Equality saturation stands more of a chance, IMHO.
The ability to build mixed C/C++/ObjC/Zig projects without having to deal with multiple compiler toolchains was indeed one of the killer features of Zig to me and the one thing that separated Zig from other "better C" attempts.
Hopefully the Zig project is at least thinking about bundling a Clang toolchain with the vanilla Zig distribution, and call Clang from 'zig cc'. To the user this wouldn't make a difference compared to the current feature set (apart from losing backend support for some CPU architectures), but still decouple Clang and LLVM from Zig.
[1] https://en.wikipedia.org/wiki/All_your_base_are_belong_to_us
> In exchange, Zig gains these benefits:
> - All our bugs are belong to us.
> - …
It’s more that Hacker News tends to collectively frown upon posts that are only jokes, if I had to guess.
Hopefully if any of that functionality gets removed someone manages to fork off the "C/C++ magic" part into its own project. Clang itself is much less convenient to use.
As someone who works on an LLVM-based compiler at $DayJob and also has written a compiler front-end that uses LLVM in my free time, I do have a ton of gripes, but any time I feel particularly frustrated by them, I spend a little bit of time working on my non-LLVM backend. After a few days of angry swearing with little to show for it, I go back to working with LLVM with a much greater appreciation for what it's giving me.
1. Needing to support tons of different platforms with various different documented and undocumented behaviours
2. Needing to support many languages with specifically undefined behaviour.
Trying to bridge the undefined nature of the two sides means that things can be fragile. Assumptions that worked for one set of undefined problems may not work for another.
But so much depends on LLVM these days that I can’t think of it as anything but a success. A flawed success but one that is doing its best to bring order to a naturally chaotic problem space.
GCC and MSVC have similar problems because it’s inherent to the problem space. So while it’s frustrating hitting those bugs, everyone in the space knows they aren’t fundamental issues with the project itself.
LLVM does have plenty of incidental problems which are clearly fixable and just need a lot of work, but even if you fixed all of them you'd still have people who use LLVM ranting about it.
brew uninstall zig. Thats what I did when I read it. I do not want to waste any of my time on soon to be dustbin tech.
Coming from a Windows world when my gigantic C++ project is hidden inside a vcxproj I dont delve into that often, I tried to compile a standard autoconf based project into wasm the other week and eventually gave up.
Use autoconf to create your cmake to create your make which builds your lib? and wrap all those calls with emscripten calls...or something along those lines. It was exhausting. Eventually it errored out becuase it couldn't decide if the size of a size_t was available. I was tempted to just remove that line from the cmake.
As it is know, Uber - and some other heavily-capitalized firms (BigTech or otherwise) - use Zig (at least) for "straightforward" C++ compilation.
- What about asking your managers to seriously fund the Zig project?
It's only fair from all the value you're getting from it. And, then, reinventing an important part of the huge wheel that's LLVM wouldn't be such a seemingly unfeasible tall order.
Can't LLVM be optional, and have unit tests guarantee that it works as before?
The above, or - as mentioned elsewhere, implement a C++ compiler in Zig: quickly, and before making any breaking changes - quite a tall order.
Or bring into Zig an existing pure-C, C++ compiler.
...TinyC/libtcc? PCC? LCC? (wild guesses)
Of course, GCC could be brought in, and compiled with Zig ;)
This part is pretty solid, even if all the dependencies is hard to deal with, I am not convinced that building your own would lead to better results.
The most annoying part is the slow compilation in non-release, this can be fixed more easily with support for a minimal number of targets.
It's his language, obviously, but I strongly suspect that if this PR goes through, it will completely kill any kind of momentum that Zig has today and will most likely doom the language to obscurity.
Which would be a real shame.