5 ms·
Writing a C Compiler, in Zig (2025)
- scatbot 7mo agoCool project. Feels like writing a C compiler in Zig aligns nicely with the old "maintain it in Zig" idea that was part of Zig's early value proposition. Is that still considered a relevant goal today? Longer term it also makes me wonder whether something like this could eventually reduce reliance on Clang/LLVM for the C frontend in zig's toolchain.
- spiffyk 7mo agoThere is actually another C compiler written in Zig, Aro[1], which Zig started using since 0.16 for its TranslateC module. [1]: https://github.com/Vexu/arocc https://github.com/Vexu/arocc
- fuhsnn 7mo agoLooking at the repo, the author seemed a little fed up [1] with the nature of lower level language and quitted. [1] https://github.com/asibahi/paella/blob/main/writeup/c19.md#user-content-fn-month-f690d35c5c3bc8477be727677652c31f https://github.com/asibahi/paella/blob/main/writeup/c19.md#u...
- dwroberts 7mo agoFeels like maybe something lost in translation with their explanation - they say they were fed up of data structures etc. but they returned to Rust? I’m assuming there’s something a bit more nuanced about what they got tired of with Zig
- ecshafer 7mo agoI think Rust is "higher level" than C or Zig in the sense that there are most abstractions than C or Zig. Its not Javascript, but it is possible to program Rust without worrying too much about low level concerns.
- flykespice 7mo agoWhich is still a crazy claim considering Rust is often told about having strong bureaucracy around even sharing variables (borrow checker).
- namr2000 7mo agoThe languages trade complexity in different areas. Rust tries to prevent a class of problems that appear in almost all languages (i.e two threads mutating the same piece of data at the same time) via a strict type system and borrow checker. Zig won't do any of that but will force you to think about the allocator that you're using, when you need to free memory, the exact composition of your data structures, etc. Depending on the kind of programmer you are you may find one of these more difficult to work with than the other.
- slopinthebag 7mo agoThere are some cases in Rust where the borrow checker rejects valid programs, in those cases it may be because of a certain data structure in which case you probably have many crates available to solve the issue, or you can solve it yourself with boxing, cloning, or whatever. The vast majority of the time (imo) the borrow checker is just checking invariants you have to otherwise hold and maintain in your head, which is harder and more error prone. The actual hard part of Rust is dealing with async, especially when building libraries. But thats the cost of a zero-cost async abstraction I suppose.
- Ygg2 7mo agoExcept if you need to expose or consume a C API, or you need to use some obscure performance improvement.
- Pay08 7mo agoFuck it, by that logic C and Python are the same language.
- NooneAtAll3 7mo ago> in the sense that there are most abstractions is it a typo for more abstractions? or is there some different meaning?
- namr2000 7mo agoRust is a world away from Zig as far as being low-level. Rust does not have manual memory management and revolves around RAII which hides a great deal of complexity from you. Moreover it is not unusual for a Rust project to have 300+ dependencies that deal with data structures, synchronization, threading etc. Zig has a rich std lib, but is otherwise very bare and expects you to implement the things you actually want.
- Ygg2 7mo agoThis depends on what you mean by low level. Commonly it means, how much you need to take care about minute, low-level issues. In that way C, Rust, and Zig are about the same. Dependencies have nothing to do with low-level vs. high-level but just package management, how well the language composes, and how rich the standard library is. Are assumptions in package A able to affect package B. In C that's almost impossible to avoid, because different people have different ideas about how long their objects live. Having a rich standard library isn't just a pure positive. More code means more maintenance.
- namr2000 7mo agoI agree with you that package management has nothing to do with how low-level a language is. That being said Rust is definitely a much higher level language than either C or Zig. The availability of `Arc` and `Box`, the existence and reliance on `drop`, and all of `async` are things that just wouldn't exist in Zig and allow Rust programmers to think at higher levels of abstraction when it comes to memory management. > Having a rich standard library isn't just a pure positive. More code means more maintenance. I would argue it's much worse to rely on packages that are not in the standard library since its harder to gain trust on maintenance and quality of the code you rely on. I do agree that more code is almost always just more of a burden though.
- Ygg2 7mo ago> That being said Rust is definitely a much higher level language than either C or Zig. The availability of `Arc` and `Box`, the existence and reliance on `drop` I mean, C++ have RAII and stuff like unique pointer, does that make it higher level than Zig? And what if you don't use Arc or Box? Is your program now lower level than baseline Rust? As I said, depends a lot about what you mean by low level.
- mrkeen 7mo agoThe author was fed up with not having data structures already provided, and needing to roll his own
- dwroberts 7mo agoNot really understanding what this would be though, zig has all the basic stuff you would expect in its stdlib (hashmap, queues, lists etc) just like Rust
- Pay08 7mo agoThis is from last year, the stdlib was much more bare back then.
- resonancel 7mo agoThen it's actually the immature zig ecosystem that rubbed the author the wrong way, not zig the language itself. Not that the ecosystem isn't important, but IMO a language only truly fails you when it doesn't offer the composability and performance characteristics necessary for your solution.
- slopinthebag 7mo agoWhile you can obviously write low level code in Rust and manage allocations, memory, use pointers etc, you can also write much higher level code leveraging abstractions both in Rust itself and its' rich ecosystem. If you're coming from higher level languages it's much friendlier than C/C++ or Zig. I think I would struggle to write C or Zig effectively but I have no issues with Rust and I really enjoy the language.
- MatthiasPortzel 7mo agoI’ve just read the two functions there by that footnote, `reaching_copies_meet`. I have so much code review feedback just on code style, before we even get into functionality. And it’s like 20 lines. (The function shouldn’t return an error set, it should take an allocator, the input parameter slices should be const, the function shouldn’t return either the input slice or a newly allocated slice.) It’s interesting how Zig clicked for me pretty quickly (although I have been writing it for a couple of years now). But some of the strategies of ownership and data oriented design I picked up writing JavaScript. Sometimes returning a new slice and sometimes returning the same slice is a problem for memory cleanup, but I wouldn’t do it even in JavaScript because it makes it difficult for the caller to know whether they can mutate the slice safely. I suspect that there’s a way to write this algorithm without allocating a temporary buffer for each iteration. If I’m right that it’s just intersecting N sets, then I would start by making a copy of the first set, and on each iteration, removing items that don’t appear in the new set. I suspect the author is frustrated that Zig doesn’t have an intersect primitive for arrays, but usually when the Zig standard library doesn’t have something, it’s intentionally pushing you to a different algorithm.
- z0ltan 7mo ago[dead]
- zengid 7mo agoQuite a footnote [0]: > I do not know if it is me being bored with the project, or annoyed with having to build and design a data structure, that has soured me on this project. But I have really at this point lost most motivation to continue this chapter. The way Zig is designed, it makes me deal with the data structure and memory management complexity head on, and it is tiresome. It is not "simpler" than, say, Rust: it just leaves the programmer to deal with the complexity, <strike-through>gaslighting the user</strike-through> claiming it is absolutely necessary. [0] https://github.com/asibahi/paella/blob/main/writeup/c19.md#user-content-fn-month-f690d35c5c3bc8477be727677652c31f https://github.com/asibahi/paella/blob/main/writeup/c19.md#u...
- flossly 7mo agoI thought Zig has a C compiler built in? Or is it just the Zig build system that's able to compile C, but uses an external compiler for that? Still a proper programmer-flex to build another one.
- spiffyk 7mo agoZig actually bundles LLVM's Clang, which it uses to compile C with the `zig cc` command. But the long term goal seems to not be so tightly coupled to LLVM, so I'm expecting that to move elsewhere. They still do some clever stuff around compiler-rt, allowing it to be better at cross-compilation than raw Clang, but the bulk of it is mostly just Clang. There is also another C compiler written in Zig, Aro[1], which seems to be much more complete than TFA. Zig started using that as a library for its TranslateC functionality (for translating C headers into Zig, not whole programs) in 0.16. [1]: https://github.com/Vexu/arocc https://github.com/Vexu/arocc
- Pay08 7mo agoThey're not planning on dropping Clang.
- Meneth 7mo agoThey kinda are: "This issue is to fully eliminate LLVM, Clang, and LLD libraries from the Zig project." https://github.com/ziglang/zig/issues/16270 https://github.com/ziglang/zig/issues/16270
- flykespice 7mo agoI find that a very bold move, how will they reivent the wheel on the man-years of optimization work went into LLVM to their own compiler infrastructure?
- geodel 7mo agoAll that will still be available just not in main zig repo. Someone may have asked same question about LLVM when GNU compiler exist.
- 0x1da49 7mo ago[flagged]
- groos 7mo agoI'm not sure why people seem to be under the impression that writing a compiler means that the language the compiler is implemented in should have "low level" features. A compiler is just a text -> text translation tool if you can leverage other tools such as an assembler and never needs to access machine level instructions. E.g., Pascal compilers have traditionally been written in Pascal, hardly a language which conjures up a "low level" image. Even when an assembler isn't available, all your implementation language needs to support, in terms of "low level" features, is writing of bytes to a file. But manipulating instruction and file formats and such can be tedious if your language doesn't have the right capabilities but it's not impossible.
- munificent 7mo ago> I'm not sure why people seem to be under the impression that writing a compiler means that the language the compiler is implemented in should have "low level" features. Performance. You definitely can write a compiler in a high-level language and given the choice I certainly prefer to on my hobby projects. Having a garbage collector makes so many compiler algorithms and data structures easier. But I also accept that that choice means there's an upper limit to how fast my compiler will. If you're writing a compiler that will be used to (at least aspirationally) compile huge programs, then performance really matters. Users hate waiting on the compiler. When you want to squeeze every ounce of speed you can get out of the hardware, a low-level language that gives you explicit control over things like memory layout matters a lot.
- LeFantome 7mo agoDoes “low level” translate to performance? Is Rust a “low level” language? Take C#. You can write a compiler in it that is very fast. It gives you explicit control over memory layout of data structures and of course total control over what you wrote to disk. It is certainly not “low level”.
- munificent 7mo ago> It gives you explicit control over memory layout of data structures Some with structs, yes. But overall it doesn't give you much control over where things up in memory once references get involved compared to C, C++, or Rust.
- mastermage 7mo agoCool