We can pass a flag to Cargo that is in turn passed to rustc to emit intermediate assembly files for the whole contents of a crate:
$ RUSTFLAGS="--emit=asm" cargo rustc --release
After running this, indeed we can see a whole lot of .s files under target/$TARGET/release:
$ ls target/avr-atmega32u4/release/deps/*.{s,elf}
target/avr-atmega32u4/release/deps/avr_config-e311e93c086c3db0.s
target/avr-atmega32u4/release/deps/avr_delay-157ca9fb1a916f1a.s
target/avr-atmega32u4/release/deps/avr_progmem-9dc1e040eb728712.s
target/avr-atmega32u4/release/deps/avr_std_stub-c3510b4296c6559e.s
target/avr-atmega32u4/release/deps/cfg_if-21f3790d6886cc57.s
target/avr-atmega32u4/release/deps/compiler_builtins-d2b51c47ad38c941.s
target/avr-atmega32u4/release/deps/core-195cf775332e0617.s
target/avr-atmega32u4/release/deps/ruduino-15843435a02e3c3a.s
target/avr-atmega32u4/release/deps/rustc_std_workspace_core-7426025ff9d9438f.s
target/avr-atmega32u4/release/deps/ufmt-b3d2cb48639acfb8.s
target/avr-atmega32u4/release/deps/ufmt_write-4e35e82da143e2d5.s
target/avr-atmega32u4/release/deps/worduino_avr-b35d7970ef451ba9.elf*
target/avr-atmega32u4/release/deps/worduino_avr-b35d7970ef451ba9.s
target/avr-atmega32u4/release/deps/worduino_engine-1dc7446bd9d04ccf.s
How do I change some of these and then continue with the same assembly and linking process? So let's say I edit the file
target/avr-atmega32u4/release/deps/worduino_engine-1dc7446bd9d04ccf.s, how do I then ask Cargo to create a new version of worduino_avr-b35d7970ef451ba9.elf with otherwise the same link-time settings as the original invocation of cargo rustc?
To my surprise, it turns out, at least for AVR, the assembly code corresponding to the toplevel crate contains everything needed, no linking required. So for e.g. LLVM intermediate files, we can use
llcfor static compilation, and then GCC for trivial linking:This produces a valid ELF file in
foo.elf, however, it is not exactly the same as the one produced by Rust, which is concerning:This seems to be because
foo.oitself doesn't exactly match the intermediate object fileworduino_avr-b35d7970ef451ba9.worduino_avr.124c28c8-cgu.0.rcgu.ocreated by Rust; I'm not sure what exactly is going on here.Functionally, loading the resulting
.elffile into an AVR simulator, it seems that the result matches the behaviour of the real Rust output, so that's good. Still, it would be better if we could replicate the.elffile exactly.Anyway, moving on the next question is how to do the same, but from assembly
.sfiles instead of.bc. We should be able to replacellcwithllvm-mcin the above pipeline:However, here we hit another problem where
llvm-mcmis-assembles the file.