Feature Request: Support for llvm-mos and mos target

I think we should be able to use llvm-mos to compile a program targeting the 6510 processor for the Commodore 64. A branch of the rustc compiler was created to compile for this target at rust-mos, however it is ultimately not able to be realistically maintained as a separate branch of the rustc compiler. It would be useful for experimental support for this target to be integrated into the main compiler.

An associated thread describing some of the issues of creating a mos target is shown at this link: Adding mos target using llvm-mos.

1 Like

We can only depend on a single LLVM version at a time, so unless llvm-mos gets merged into upstream LLVM, I think rust support for it will have to remain in a rust fork.

1 Like

When reading Adding a new target from the "Rust Compiler Development Guide" it states that "If you have a local LLVM checkout that is already built, you may be able to configure Rust to treat your build as the system LLVM to avoid redundant builds". Is there some way to create a system where one can have custom defined targets that use local LLVM builds so we don't violate the fact that

We can only depend on a single LLVM version at a time

Though this is a substantially different request due my different understanding (hopefully) evolving, if we could make custom target plugins for the rustc compiler which covered these more niche targets without forcing the compiler to be forked I think it would help immensely. Is this a practical, feasible, and desirable idea or is there something that I'm failing to understand?

The main 2 issues I want to resolve simultaneously are:

  1. Support for Commodore 64 as a target
  2. Avoiding the creation of a fork (as those will likely die due to lack of maintenance)

With those constraints I think the only way to resolve them is to create some mechanism for plugins to define custom targets so that only the plugin has to be maintained.

Wouldn't this be the case for obscure architectures anyway? Or are you proposing to add additional maintenence burden for things almost no one uses onto the existing maintainers?

More code to maintain makes refactoring harder. This is one reason the Linux kernel has recently been dropping multiple old architectures, such as IA64, some Mips variants and most recently older SPARC (or maybe that last one was still being debated, don't quite remember).

I question how many tens of people actually want to compile rust for C64. Given the limitations of the platform (64 kB RAM), it seems more suitable to BASIC and assembly.

As well as running vintage games and software for nostalgia reasons of course (nothing wrong with that, I still have my first computer, but I wouldn't want to install or run modern software on that).

1 Like

That still requires rebuilding rustc itself against the LLVM fork. And you need to make sure that the LLVM stays up to date as we only support the last couple of LLVM releases.

It is possible to modify rustc_codegen_llvm to be able to build as external codegen backend, but that still needs some trickery to add support for abi calculations for the new target and you effectively have to fork part of rustc and the external codegen backend interface is unstable and changes pretty much every nightly. I personally think this is even worse than forking the entirety of rust as you can't just rebase patches on top of the latest rust version anymore but have to extract all rustc_codegen_llvm changes and ensure your patches don't get lost.

Does upstream GCC support this target by the way? If so being able to use it with an unmodified rustc_codegen_gcc may be a stronger reason to upstream the abi calculations and target specs.

Or are you proposing to add additional maintenence burden for things almost no one uses onto the existing maintainers

A bit of a cynical take on the idea of a plugin system. Obviously I don't want the project maintainers to work on targets for niche systems like the C64, I just want the ability to make custom targets for those systems without having to create a fork of rustc that can't realistically be maintained so that I only have to maintain the target's configuration and not the entire rustc compiler. The thought is that this would add the burden for maintaining some system where more custom targets could be defined but it would also offload the responsibility for actually defining those targets, hopefully making things easier overall

Does upstream GCC support this target by the way

Not to my knowledge.

It is possible to modify rustc_codegen_llvm to be able to build as external codegen backend, but that still needs some trickery to add support for abi calculations for the new target and you effectively have to fork part of rustc and the external codegen backend interface is unstable and changes pretty much every nightly

Thank you for the explanation. I think this is the part where my limited understanding becomes clear and I think I'm out of my depth to understanding the implications of my suggestion. I'll try to revisit this topic later but at this point I understand what your stating now which is that one would need to modify the abi itself for this purpose and either merge and maintain the changes or fork and modify one of the most volatile region in order for this to work. At this point I don't think I have the technical capability to do either but in some time I'll come back with a hopefully better proposal to this end. I think it would be great if rust had the same diversity and ubiquity of compile targets as C does and I think expanding the ability to define completely custom targets would help (though I still need to learn more about the precise mechanisms of compilation)

1 Like

6502 is famous for being difficult even for C to target. C and Rust assume a CPU with a separate stack and registers, and the special page 0 being sort-of both but not quite either of them makes it really challenging to emit good code. And on this platform there's not enough processing and RAM to tolerate bad code. I don't see this being useful beyond nerd-cred of printing "Hello World" on a C64.

1 Like

Hey, I'm the maintainer of llvm-mos; came across this thread earlier today. There's just a couple points I'd like to pick at.

We do actually produce fairly good code, ranging from barely not-OK to quite good. We do a lot of whole-program analyses to convert soft stack usage to a "compiled stack" similar to a few other embedded compilers. Instead of the usual "reasons C is hard", the main limitation of the code generator is currently that the LLVM register allocator just isn't terribly good at straight-line register allocation for the platform.

I also sync from upstream LLVM before each release, and we have a roughly weekly release cadence. Bus factor is relatively low, though.

As part of the project we maintain a Clang backend. It has a moderately complete translation of the C99 ABI for the 6502, including VLAs. No TLS, PIC, etc., yet but broad plans have been laid for these.

The existing rust-mos fork was always considerably less complete; it mostly consisted of rustc backend snippets copied from AVR, with many left as TODOs. Ideally we'd have something complete on the level of the clang backend that we could maintain as part of the llvm-mos release cycle, but I have relatively little Rust experience, and I pretty much already have my hands full with LLVM and Clang.

I can vouch for a considerable amount of interest in using Rust on the 6502, if only because some folks really really like Rust, and because it's just about the highest level language that one could even imagine being sufficiently performant for 6502 applications.

So in summary, I wouldn't say it's unrealistic to maintain a fork of rustc for a moderately long term, as that's currently being done for llvm-mos. But it is intrinsically a lot of work, and I don't think there's any real way to shortcut that, given the speed at which (at least) LLVM changes. Someone who really wants to see Rust on the 6502 would need to build up a similar degree of competence with rustc as we have w/ LLVM for this to work.

4 Likes