I’ve since realized that writing a version of NQP on LLVM from scratch would be either quite a lot of work or, by taking as many of the .nqp files as I can from the exisiting NQP for a self-compiling compiler, essentialy the same as a porting of NQP. So, I’ve instead tried poking around in the NQP codebase to see where I’d be spending a lot of time doing such a port.
In NQP there are two directories where I’ll likely focus my attention first: ops/ and pmc/ . ops/ contains the opcode extensions for Parrot (IIUC), while pmc/ contains the custom Parrot PMCs for use in NQP. Both of these folders take advantage of a mechanism in Parrot that allows for a modification of the language of Parrot externally, without modifying Parrot itself or recompiling the entirety of it.
LLVM has no such mechanism. If I wanted to modify the language of LLVM like what ends up happening in Parrot, I’d not only have to modify the actual LLVM codebase, but instructions (opcodes) and types are two of the things that, when added, break LLVM’s bitcode format. Not good. To be fair, I could implement the instructions as intrinsics instead, but that still leaves types, and modifying LLVM from within still seems like a Bad Thing™.
My current theoretical solution is to replace the files in ops/ and pmc/ with hand-coded .ll offering up the same functionality. ops/ is easy enough, I can just implement those opcodes as regular ol’ LLVMIR functions. pmc/ is a bit trickier, because LLVMIR provides no classes or any such thing. But just because OOP isn’t built-in, doesn’t mean I can’t do OOP. I’d either use LLVMIR structures (with normal variables as “attributes” and pointers to functions as “methods”), or just create a mess of LLVMIR that in the end handles like objects, from the outside.
Questions I’ll certainly have to ask on the llvm-dev mailing list, for sure.
I have two last concerns with putting NQP on LLVM. The first is where the actual generation of PIR starts. I have yet to find the spot where PIR instructions are emitted, which makes me think that’s all handled in Parrot, with NQP just sending it a structure representing the NQP code it parsed. If this is the case, then that’d be interesting to port to LLVM. Since it’s best to let LLVM generate LLVMIR for me, I’d likely end up writing a C/++ “middleman” of sorts between the .nqp files of NQP and LLVM, where this C/++ middleman takes what NQP’s final output is and sends it through LLVM’s IR generators.
The final concern is where to begin coding so that it takes the least code before I can test the porting of NQP as it goes. I really wouldn’t feel good about doing the entire port without running tests frequently (or even once).
Questions I’ll certainly have to ask jnthn, for sure.
This sounds like a difficult, but fun, project. I hope it is.