Jump to content

LLVM-MOS


Recommended Posts

Just wanted to drive by and toss this out there:

https://llvm-mos.org/wiki/Welcome

https://github.com/llvm-mos

I've been poking around on the beginnings of a game, something I wish I'd known enough to be able to do 35 years ago...  I was using KickC, which is very cool, but I was running into too many issues and starting to spend more time on workarounds than on programming.  Then, yesterday, I found out that there's an actively developed and complete 6502 backend for LLVM, which means you can do pretty much anything the LLVM frontends can do and then spit it out to your 6502.  Library support may be challenging, of course.  As of today, only the C64 (and Atari 800) has linker target files, but I've played with them (they're compatible with GCC ld linker scripts) and it shouldn't be too hard to create new ones for other targets.  If you follow that link, you'll see that they've built programs for VIC-20, Apple IIe, C64, and even built a simple Rust program onto an Atari 800.  Creating target files for the X16 shouldn't be particularly difficult.

That having been said, don't expect any of the IO (printf, gets, files) to magically work out of the box today.  This is in _ACTIVE_ development, and their focus is currently on C64.  The backend 6502 codegen passes all LLVM unit tests (a few thousand), and that was announced in a post from just a few days ago.

But if you're willing to just hammer the hardware with your own routines, well, it's pretty slick.  I haven't gotten around to X16 programming yet, but I wanted to attach a screenshot of what I've been working on as compiled by LLVM-MOS's clang compiler for the C64.  I've been building the project to cross compile for the PET, VIC-20, C64, and C128 with different graphics on each, so I should probably just add an X16 target 🙂

hexgame.png

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

I'm going to leave it to the LLVM-MOS guys to give status (although, my experience suggests that they are actually further along than this page suggests):

https://llvm-mos.org/wiki/Current_status

Also, to answer "why?" and also performance/features kinds of questions:

https://llvm-mos.org/wiki/Rationale

(I find the "Findings" section at the bottom especially interesting)

Link to comment
Share on other sites

Is that a comment on compilation speed or C++ speed?

If you're concerned about compilation speed, LLVM-MOS is currently much faster than KickC for my project.

If you're concerned about C++ performance, that has been corrected and refuted for at least 10 years.  High-level optimization kicks the crud out of low-level peephole optimization.

LLVM is crazy fast to compile, AND it optimizes the heck out of the intermediate code that it generates, discarding all of the abstractualization overhead that simplistic C++ compilers in ye olden dayes created.  What it hands off to the back end is already optimized enough that a straightforward 6502 code generation is sufficient to outperform most people's expectations (see the "Findings" section in the link above).  And the LLVM-MOS guys haven't even started looking at "codegen level" optimizations yet.

  • Like 1
Link to comment
Share on other sites

12 minutes ago, DigitalMonk said:

Is that a comment on compilation speed or C++ speed?

It's about what kind of 6502/X16 code would be generated from an LLVM iostream implementation. Using C++ is nice, but using the language as intended on a 6502-based system is a bit dicey. What's lean and efficient on an x86-64 or ARM64 with GB of RAM could still be bloated and sluggish on a 6502 with kB of RAM.

Link to comment
Share on other sites

5 minutes ago, SlithyMatt said:

It's about what kind of 6502/X16 code would be generated from an LLVM iostream implementation. Using C++ is nice, but using the language as intended on a 6502-based system is a bit dicey. What's lean and efficient on an x86-64 or ARM64 with GB of RAM could still be bloated and sluggish on a 6502 with kB of RAM.

Note that I'm not necessarily talking about using the entire standard C++ library (though for some app types that would be fine as well). More than anything what I really want is efficient expression of template based code (including templates in the standard library).

There are freestanding and hosted expectations. I don't necessarily need hosted. I would love freestanding.

Link to comment
Share on other sites

You might be surprised by how little bloat is in modern iostream implementations.  Memory allocation, copying, and deallocation are performance headaches for all computers, regardless of how much they have.  The C++ standards team have spent a huge amount of time and effort making the core libraries lean and efficient, with minimal unnecessary copying and heap interaction.

That being said, I personally don't care about iostream and never use it.  C++ still provides stronger type checking, readily available data structures, and many benefits that I use all the time in small embedded projects.  How many X16 are going to be doing text work where "I don't really care that much about formatting, just push this information out there"?  If anything, I'd think a low resolution text screen would be a bigger problem, because you have to be so careful about exactly how you display everything (and iostreams is ridiculously annoying for formatting issues).

And I definitely second Scott's comments.  Even if I loved iostream, nothing in my project would benefit from having it...

I just know that a lot of people hate C++ because "it's so bloated", and that just isn't the case any more in either space or speed.

  • Like 1
Link to comment
Share on other sites

Even if it's a freestanding application with no iostream or other standard library calls, this is still not a bare-metal Raspberry Pi were talking about here. The X16 is much, much smaller. You will still need a separate frame stack and probably a heap to make C++ worthwhile. You could allocate everything statically, and then you just have classes standing in for structs and not doing any of the actual OO things. The question really becomes, "what is the value added by developing with C++ over C for the X16?" Sure, you COULD do it, but is it really going to make development any more efficient or enjoyable? Or is it just a parlor trick of "hey, look: 8-bit C++" and then you go back to assembly or just plain old C to develop a real application?

Link to comment
Share on other sites

It's also a bit of a moot point today, because the LLVM-MOS team is focusing on C.  The C++ headers aren't there yet.  But that's more an issue of having the time to put them in and test them all.  No real reason why they wouldn't work.

Unfortunately, that does mean that all those wonderful STL tools and libraries aren't available yet.  But it's just a matter of time.  And the C++ LANGUAGE features are there, so it's entirely possible that you could use Boost header-only libraries to get some heavy lifting done...

 

Link to comment
Share on other sites

8 minutes ago, SlithyMatt said:

Even if it's a freestanding application with no iostream or other standard library calls, this is still not a bare-metal Raspberry Pi were talking about here. The X16 is much, much smaller. You will still need a separate frame stack and probably a heap to make C++ worthwhile. You could allocate everything statically, and then you just have classes standing in for structs and not doing any of the actual OO things. The question really becomes, "what is the value added by developing with C++ over C for the X16?" Sure, you COULD do it, but is it really going to make development any more efficient or enjoyable? Or is it just a parlor trick of "hey, look: 8-bit C++" and then you go back to assembly or just plain old C to develop a real application?

First off, the X16 is going to have 512kB or 2MB of RAM, right?  C++ was absolutely used on DOS machines with that "little" memory.  Yes, the paging nature adds some complexity, but it adds complexity for everybody.  Once it's handled in the runtime library, we'd be able to (mostly) forget about it as application developers.  We'd probably want some way to hint things to pack heap items into common heap pages for maximum efficiency, but that problem was addressed decades ago by overlay linkers.

As for speed, that 8MHz 6502 is comparable to a 32MHz z80, so faster than any 8086 that was ever meaningfully fielded.

PLEASE REMEMBER:  Arduino's use C++ as their core language, and most of them have less memory than even the starting X16 is going to have.  IN PARTICULAR,

The ATmega328 chip found on the Uno has the following amounts of memory:

Flash  32k bytes (of which .5k is used for the bootloader)
SRAM   2k bytes
EEPROM 1k byte

Yep.  2kB of RAM and only 32kB of flash.  I could pack __ANY__ Arduino Uno sketch, libraries and everything into just over half of a C64.  And believe me, Arduino uses iostreams.

Personally, I'd say being able to take the growing makerspace of Arduino hackers and bring them to the 6502 world would be a Good Thing(TM)

Link to comment
Share on other sites

This is supposed to be a teaching computer.  Anything that adds to that goal is great. Being able to program in lots of different languages or classes of languages is definitely to be encouraged. 

Anyone want to take a crack at LISP?

Link to comment
Share on other sites

25 minutes ago, kelli217 said:

I think it might be time to drag out this old link that was posted about 12 times to the Facebook community.

Thank you.  And I feel the need to point out that the code generation in that particular effort is very messy.  He uses an x86 compiler to generate x86 assembly, then rams that through his own x86->6502 translator.  Which works, but all that x86 code thought that integers were 32 bit.  The LLVM-MOS effort uses 16 bit as the default int, 8 bit chars, and 32 bit longs (which is the approach taken by many, many compilers in the 16 bit era).  So the LLVM-MOS output will already be much cleaner, smaller, and faster than the code generated in that video.

Link to comment
Share on other sites

15 minutes ago, Ed Minchau said:

This is supposed to be a teaching computer.  Anything that adds to that goal is great. Being able to program in lots of different languages or classes of languages is definitely to be encouraged. 

Anyone want to take a crack at LISP?

Well, Micro-LISP exists for the C64, so doing it on the X16 should be easy...

micro-lisp.pdf

Link to comment
Share on other sites

26 minutes ago, DigitalMonk said:

The ATmega328 chip found on the Uno has the following amounts of memory

I don't doubt you could pack a very simple C++ program into that much memory. But you are also dealing with a MUCH faster processor than an 8MHz 6502, and a much simpler system that doesn't have to do things like manage VERA graphics and play PSG sound effects.

As for C++ on mid-80s DOS PCs, it was not really a common thing, and I don't know of any commercial software that was developed using C++ for that platform in that era. C++ didn't really take off on Wintel PCs until the advent of Visual C++, and that was really for 486 machines and better.

Look, I don't want to discourage people from trying anything, but just to manage expectations. We have the gift of the X16: a machine so beautifully simple and yet so capable it becomes a joy to program in assembly language or in very simplified C and create really wonderful software. Adding all this complexity and abstraction is just going to give you something watered down, a less capable PC. Again, JUST MY OPINION, but this goes into the territory of just getting a Raspberry Pi and doing C++ development there. Or python or whatever.

  • Like 1
Link to comment
Share on other sites

7 minutes ago, SlithyMatt said:

I don't doubt you could pack a very simple C++ program into that much memory. But you are also dealing with a MUCH faster processor than an 8MHz 6502, and a much simpler system that doesn't have to do things like manage VERA graphics and play PSG sound effects.

As for C++ on mid-80s DOS PCs, it was not really a common thing, and I don't know of any commercial software that was developed using C++ for that platform in that era. C++ didn't really take off on Wintel PCs until the advent of Visual C++, and that was really for 486 machines and better.

Look, I don't want to discourage people from trying anything, but just to manage expectations. We have the gift of the X16: a machine so beautifully simple and yet so capable it becomes a joy to program in assembly language or in very simplified C and create really wonderful software. Adding all this complexity and abstraction is just going to give you something watered down, a less capable PC. Again, JUST MY OPINION, but this goes into the territory of just getting a Raspberry Pi and doing C++ development there. Or python or whatever.

The first DOS C++ compiler as far as I know (at least the first I used) was Turbo C++ which I think was released in 1990. But that is pre-standard C++, much less modern C++17 / C++20. The current language definition has so much optimization opportunity with const, constexpr, templates and lambda functions (only const was supported in 1990) that it might as well be a different language. You simply can't compare 1990 era C++ with 2020 era C++.

In many ways it is the difference between a simple machine language monitor that only recognizes mnemonics, addressing modes, and hex numbers, and a fully featured macro assembler that allows you to build your own assembler syntax with relocatable segments ala ca65 / ld65 or comparable systems.

The video linked above basically gives you a freestanding implementation of "modern C++" that can be used to generate 6502 family assembly, though with more tools in the toolchain to jump through. Getting an LLVM supported way that doesn't require translation from 32-bit x86 to 8-bit 6502 is just a little more neat of a process *if* it generates the equivalent of hand rolled assembly language.

Certainly I'm not trying to tell the world they should use C++ instead of assembly on a X16. I'm saying I'd like a good optimizing compiler for C++ that would support the X16. In that case, you can have functions that are evaluated at compile time and have zero stack parameter passing overhead, because the compiler is smart enough to see that all the information to inline the function is available at compile time.

Sorry for the tautological statement...

  • Like 1
Link to comment
Share on other sites

Microsoft's first C++ was apparently also released in 1990, though I have no idea how well it worked.

I was working for Clark Development Company between 1992 & 1995, and I used Borland C++ for the PCBoard Programming Language which was very well received. We were already using Borland Turbo C & Turbo Assembler for PCBoard, and I convinced them to allow me to use C++ for the scripting language we added to PCBoard v15. I saw that code recently and it is not pretty (I was much younger and less experienced) but it predated Visual C++ v1 in 1993.

https://en.wikipedia.org/wiki/PCBoard#History for a brief history of PCBoard / PPL (though it doesn't discuss the fact that it was C++) for those who are interested.

Link to comment
Share on other sites

None of what I've been saying is meant as flame, though I'm sure it reads like that.  I do get heated because of misunderstandings about what C++ is now, and because of how frequently those misunderstandings are repeated in public forums where people who are coming to learn just pick it up as "truth" and continue the problem.

"all this complexity and abstraction"...  C++ is only complex if you need it to be.  Abstraction is a very useful tool to increase programmer efficiency.  And neither needs to water down anything.  All the heavy lifting of expanding out the abstractions/complexities happens at compile time.  Then it gets optimized back down to just the parts you were using.  Which you were going to be using no matter what language you used.  And then that minimal pseudo code is converted to 6502 opcodes.

With new compilers and libraries (and LLVM is the newest, pretty much), C++ has repeatedly beaten C at performance tests.  And not because the runtime has some huge library component that wouldn't fit on a 6502, but because modern C++ compilers write better C than C programmers do.  And they do it because they simultaneously get the benefit (from all that complexity and abstraction) of better understanding what the programmer was actually trying to do (ie, if I use the std::nth_element algorithm, the compiler knows much more about what I'm trying to do than if it was just looking at some for loops and conditionals) AND of being a tireless worker with nearly limitless concentration and memory who can see opportunities for code reuse, simplification, etc.  Oh, and all that cool pre-computation that lets games and demos run so fast?  In modern C++, the compiler automatically figures out if a string of execution -- even if it spans multiple function calls -- is actually a constant and can be performed at compile time so that the final result is just stomped directly into the opcode.

Yes, an expert C programmer can outperform an average C++ programmer.  But I suspect an expert C++ programmer could outperform an expert C programmer.  And it's really about the averages anyway, if this is a learning computer, and in the average case, C++ gives an average programmer the benefits of an expert programmer under-the-hood.

Nothing about the C++ experience would be "watered down."  You don't write the same kinds of programs on an X16 that you write on a generic PC, but that doesn't mean that the tools that have been constantly improving for decades aren't a good fit.  Anything that would require a heap or other "bloat" in C++ would require the exact same capability from C, but be much more likely to leak in C because C only has dumb pointers, while C++ provides dumb pointers, reference counted pointers, weak pointers, and unique pointers.

"C++ is unwieldy" is an old trope that has been repeated for so long that many people don't even question it.  But it simply isn't true.  It comes from the time when C++ was basically just a hairy preprocessor in front of C code.  Anything after C++11 is a completely different beast, and things are accelerating.

One last thing I'm going to throw out there, and then I swear I'm going to try to stop...  C++ isn't really about "Object Oriented Programming" any more.  Sure, it's still got classes.  But the originators of OOP figured out (after 20 years or so of people trying to work out the issues) that OOP doesn't deliver on its promises.  OOP is also where all of the heap flail and bloat came from.  So, when you look at what gets C++ programmers excited now, it's mostly about template metaprogramming -- making the compiler write the tedious dreck for you (which the optimizer then pares down to only the bits you actually used).  If you think that's only for wizards or academia, look at KickAssembler, whose primary claim to fame is its extensive metaprogramming capabilities.  Now, personally, while I am super stoked by the things you can do with metaprogramming, I will be the first to admit that C++'s syntax is ugly, and there are other languages out there that do it easier and more cleanly.  But you REALLY can't get those compilers for specialized processors and systems, and most of them do require a hefty runtime.  C++ remains one of the few languages that can give you every tool you could hope for and yet still run on a tiny constrained system (note that the LLVM-MOS guys made code for a VIC-20, so...)   Rust is another, which also provides a lot of compile time guarantees about correct memory usage without requiring any runtime on the host, and someone has already shown using LLVM-MOS as a backend for Rust to generate a program on a 6502 machine.  C++ remains a "system programming language", one of the few out there that meet the criteria of driving hardware at its lowest level.

(I'm 50, and I've fought with lack of C++ in the embedded world for decades.  And even when it was available, it would be the ancient C++98 variant, which did still have all the issues you're worried about.  My life changed immensely when the embedded tools I have to use FINALLY introduced C++11 almost 10 years after it was ready.  Fortunately for me, they've been a little zippier since then, and they're up to C++17 support.  It still amazes me, when GCC and LLVM are freely available and more powerful than any proprietary compiler that these chip makers continue to put out their own garbage...)

(Oh, and I would _NEVER_ suggest trying to write a C++ compiler to run ON the X16.  That would be horrible.)

  • Thanks 1
Link to comment
Share on other sites

Interesting (to me) aside: I got the job working on PCBoard in part because I had written my own BBS for my C=64 in the mid 80s. It wasn't *great* but it demonstrated I had experience in the "market" (though I only wrote it for myself and never actually marketed it).

Link to comment
Share on other sites

1 minute ago, Scott Robison said:

Challenge accepted! #hahaha

DO IT!!!

Upon reflection:  Oh lord...  I mean, I suppose you could always cram the LLVM source code through LLVM-MOS.  I don't know how huge the resulting PRG would be, since there is a LOT of logic in LLVM. 

I've looked into using a C compiler on the C64, and that was insane.  You had to have either two or three floppy drives to even start, and all the steps were separate, and just argh...

I would also like to mention, for those who might not be old enough to know, that back in the day a whole lot of commercial programming was cross-development as well.  Programmers worked on minicomputers that crunched out binaries to test on the little home computers.  Home programmers programmed on their computer 'coz it was the only thing they had and they were having fun, but once time and efficiency got into it, compilation moved off to bigger machines.  So using LLVM's giant brain on a 32-core Ryzen to develop X16 code isn't as ridiculous as it might otherwise sound.  It's just the modern version of what they used to do, and saves you tearing out (as much of) your hair.

Link to comment
Share on other sites

4 minutes ago, DigitalMonk said:

I've looked into using a C compiler on the C64, and that was insane.  You had to have either two or three floppy drives to even start, and all the steps were separate, and just argh...

The only reason C or C++ might be possible on X16 would be the 512K to 2048K of banked RAM. All those floppies were compensating for the lack of RAM (or so is generally my experience).

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...

Important Information

Please review our Terms of Use