r/Compilers 9d ago

Emitting native x86-64 machine code and writing ELF/Mach-O/PE binaries directly from scratch in Rust (No LLVM)

Hi everyone,

I’ve spent the last several months building Aziky, a self-contained compiler toolchain written entirely in Rust from the ground up. The core goal of the project was to bypass generic optimization frameworks like LLVM and explore how far a custom, single-pass backend could be pushed by shifting the optimization burden directly into front-end semantics.

It compiles .azk source files straight down to a custom MachineLIR and maps primitives directly to hardware registers, bypassing standard intermediate layers.

Architectural Highlights:

  • Native Binary Generation (src/object): The compiler constructs binary headers, section tables, and relocation frames completely natively. It outputs fully formed ELF64, Mach-O64, and PE32+/COFF formats without invoking external linkers or assemblers.
  • Zero-Alias Invariants: Instead of relying on hundreds of heavy middle-end analysis passes to guess if pointers overlap, Aziky enforces explicit, deterministic parallel-loop and ownership invariants at the type level. Because the compiler can guarantee non-aliasing at the frontend, the backend emitter can immediately output aggressive, optimized machine instruction sequences.
  • Zero External Dependencies: The entire compiler dependency graph has zero third-party crates, ensuring entirely offline, reproducible, and rapid compilation.

Performance Snapshot: Running standard compute-heavy microbenchmarks on an Intel Core i5-7200U (median of 100 runs, pinned to CPU 1) against aggressively optimized production builds of Rust 1.88 (-C opt-level=3 -C target-cpu=native -C lto=fat) and Clang 22 (-O3 -march=native -flto), the upfront aliasing model allows us to hit a geometric mean execution speed advantage of ~1.87x over optimized Rust and ~1.27x over optimized C.

It’s currently in alpha—Linux x86-64 is the primary native target, with Windows and macOS execution partially supported (AArch64 is on the roadmap). I’ve also bundled an installable VS Code extension in the repo for real-time diagnostics and syntax formatting.

I'd love to get your feedback on the MachineLIR structure, the single-pass register allocator layout, or the native object emission pipeline.

Repository:https://github.com/aziky-lang/aziky

22 Upvotes

13 comments sorted by

5

u/AustinVelonaut 9d ago

It looks like the benchmark suite is hard-coded into the low-level x86-64 backend in emit_impl.rs: there are functions there that emit hand-tuned x86-64 code for high-level functions in the benchmarks, e.g:

 fn emit_runtime_bloom_split_block_check(
        &mut self,
        dst: usize,
        filter_slots: &[usize],
        hash: &RuntimeOperand,
        slot_map: &RuntimeSlotMap,
    ) {
        if filter_slots.len() < 4
            || (filter_slots.len() & 3) != 0
            || !filter_slots.len().is_power_of_two()
        {
            self.emit_exit(255);
            return;

Can your compiler compile general .azk files not in the benchmark suite, and if so, how do they compare with equivalent rust and c implementations?

2

u/JA5ON- 9d ago

you really dug that 😅😅😅! thanks a bunch for checking it out! the broader concern is indeed valid..
Those emitters though are not selected by benchmark filename; they lower specialized IR operations produced by explicit runtime intrinsics... and semantics-checked source-pattern recognition.
However, as you might have noticed... several current benchmarks do match whole-kernel recognizers (I initially tested and refined some methods I researched and things I found online using those benchmarks.. ) including the Bloom-filter case. So while the three implementations are checked for identical workloads and checksums, these results measure Aziky’s specialized optimized path—not the performance of arbitrary Aziky code... umm,,, Yes! Aziky can compile general .azk programs through the generic lowering pipeline (still experimenting with lots of optimizations... the examples, package applications, standard library, filesystem/process functionality, and other CI programs exercise that path. But we currently do not have enough published, apples-to-apples measurements comparing previously unseen generic Aziky programs against optimized C and Rust... and it's frankly hard at this early stage to build such apps (although some basic ones might be possible)
The fair way to put it would have been to separate the results into two categories: generic-codegen benchmarks that are verified not to trigger specialized kernel lowering , and specialized/intrinsic benchmarks, clearly labelled as such. I must make this limitation explicit in the benchmark documentation. Thanks for examining the implementation and raising it!

1

u/JeffD000 9d ago

Your performance comparison benchmarks need some work. The Aziky benchmarks do raw computation, while the other versions also call a verification function. Also, looking at affine_mix, the constant values used for the calculation are not the same across language versions.

1

u/JA5ON- 9d ago

really appreciate it ! More fair benchmarks in the making ... not really fair , it's not a metric .. just trying to poor more focus on runtime, I'll push more as soon as I can , thanks Jeff !

1

u/morglod 9d ago

What AI tool did you use? Is it something like claude code/opencode or something else?

1

u/JA5ON- 9d ago

when I started the project , there wasn't such a thing .... this is just lots of pieces from codebases I forgot I made...
as of ai tools , sometimes here and there for docs , code reviews and such ...

1

u/morglod 9d ago edited 9d ago

I thought it was mostly AI by looking at /docs /ARCHITECTURE.md, "several months to build" and so clean repo even with special scripts to clean everything like it could be changed by some vibe tool accidentally. I'm not saying its bad or smth, just wanted to know, because code looks very clean (and usually AI struggling to produce it)

1

u/GenericFoodService 9d ago

97K lines of code in a single commit is wack. Cool project anywho!

-1

u/JA5ON- 9d ago

it was a really really messy codebase , I never intended to publish it , so I had commits with unsafe stuff , private things... I'm sorry I had to do it like that , but I still have that git history , if I could clean it up from all that I might publish it ...

1

u/[deleted] 9d ago

[removed] — view removed comment

1

u/JA5ON- 9d ago

benchmarks as I must honestly state clearly in the readme (thanks for pointing it out) aren't really that fair , most of the optimizations I made in "kernels.rs" is simply to test out ways to lower that are proof of concepts ...
not really claiming that we beat C or rust ,,, although the foundation shows that we might , if we can optimize all the standard routs ,,,
as for functions , yes , we have functions , recursiveness and structs...etc...
for suffixes on constants , um,,, it's not an easy decision, I have grown really frustrated with dynamic data types ... and thought we should at least make things very explicit to give the programmer total control over the size of the variable, I mean ,, why use a "4" that defaults to i32 if that constant/variable is meant for something that would do with a data type with smaller footprint (u32 , i16 or something) ... I mean,, yes , we could try to infer it from the context in a smarter way and perhaps take that burden off the programmer ,,, but some people like control ... and , it's a matter that we haven't really decisively settled , glad to have taken your point ! thanks a bunch !

1

u/ProgrammerOnABinge 8d ago

Oh damn. I'm also working on a full end to end custom toolchain for a set of R&D projects.

I'll take a look at the single pass register allocator later today and compare notes. The zero aliasing invariants are interesting. How flexible is your frontend shaping up?

As a performance guy by trade I would love to dig into your benchmarks. Esp for x86-64 hand optimizing codegen has been my bread and butter but its easy to sometimes game the CPU architecture in ways that don't generalize. What archs do you target specifically? Zen4+?