Hey all, I started working on getting clang/LLVM to output ELF binaries for IRIX a few weeks ago. I noticed a while back that LLVM already has 99% of what you need to get working binaries for IRIX. Its MIPS support is pretty good and it already supports a wide range of MIPS processors, and it also has support for the 3 major MIPS ABIs that IRIX uses, o32, n32, and n64. As a matter of fact, you don't even need to necessarily modify LLVM in any way to be able to get freestanding object files that can theoretically be linked on IRIX. To my understanding, user Eschaton attempted to use LLVM in this way. I wanted to take it a step further however, and get full blown IRIX support integrated into clang and LLVM, as well as to be able to natively host the full LLVM suite on IRIX itself.
I started off with just attempting to get LLVM itself to build & run on IRIX, the main changes here were just small #ifdef __sgi patches to some files to fix some build errors, however I pretty quickly ran into a brick wall, linking all the LLVM static libraries to produce the various executables quickly caused the n32 GCC/binutils to OOM. After banging my head against the wall for a few days trying to get a full n64 toolchain. I gave up and switched gears to instead try and teach clang about IRIX. This was actually relatively easy, LLVM has a very clean & easy to read codebase, and it already has plenty of OS drivers built in. For IRIX, I decided to mostly copy Hurd's driver file, and just make changes here and there to specify IRIX's dynamic linker and system directories. There were some other miscellaneous changes I had to make in other files, mostly relating to target triplets, although I did also have to specify an IRIX OS Target, which again, wasn't hard at all.
Finally I built LLVM with only clang enabled, and I tested it... my hello world didn't build... clang was specifying that SGUG's LD link using elf32btsmipn32, which it didn't support. I made a quick patch to clang to instead pass elf32bmipn32 if the target OS is IRIX. This time the build failed again, but for a different reason; for some reason binutils couldn't find the C runtime or libgcc even though I had them in the sysroot I had passed to binutils when I built it. I then had an epiphany, I could just have clang output object files, then link them on a real SGI, similar to what the OpenVMS developers did when they were porting LLVM. I uploaded helloworld.o to an Octane, then ran gcc on it to link it, and whaddya know, it printed "Hello world from LLVM on an SGI!"
Building helloworld.c on my desktop
Linking and running helloworld.o on IRIX
That was pretty cool, but I wanted to see if my clang/LLVM patches in combo with SGUG binutils on the Octane could handle something a bit more complex, so I got to work on building figlet. I immediately ran into some compilation errors. These were related to types, so I assumed that I needed to use the same include-fixed that GCC uses on IRIX. I added a system include to the IRIX driver for a /usr/include-fixed in addition to the usual /usr/include. However even with these fixes, figlet still didn't build.
I was beginning to think that maybe I'd just gotten lucky after all with the hello world program. But then I realized that the IRIX standard C library enables/disables various types and prototypes depending on what flags the compiler has enabled by default. I didn't feel like putting in the work to add them to clang yet, so I instead printed out all the predefines GCC has on IRIX, then stuck all of them into an irix-defines.h file, and added that to the top of all figlet source files so all of the predefines would apply before any IRIX headers were included. This actually worked, although it resulted in incredibly spammy output during the build since a lot of preprocessor macros were getting redefined by clang, or by the various system headers. I got my figlet object files and uploaded them all to the Octane. Figlet linked and actually ran!
There's plenty of work to be done to get a useful LLVM toolchain for IRIX, for one, the various predefines GCC has for IRIX need to be added to clang so you don't have to stick an irix-defines.h into every source file you want to compile. I also want to have clang/LLVM ported directly to IRIX so you don't need to compile software using two different computers. Finally, I want to eventually be able to have a full LLVM toolchain that uses LLD, as well as LLDB. A few longer term goals would be to have full C ABI compatibility with MIPSPro so there aren't any issues with struct alignment, to get LLD to emit debugging symbols that can be read by DBX, and finally, to clean up the patches enough to upstream IRIX support.
Link to the LLVM fork:
https://github.com/aurxenon/llvm-project-irix
One other thing I forgot to note, the target triplet is a bit broken at the moment, it thinks it's building for mips64-sgi-irix6.5, even though it then builds for 32 bit MIPS, with n32 ABI. Not entirely sure what's causing that, but I'll probably figure it out at some point.