I’ve read this article every time it’s gotten posted here and it’s always gone a little over my head. I was able to follow how he used 8 x86_64 registers for the VM’s stack slots and how the VM instructions were implemented. How the padding and alignments of each version of the instructions was calculated is impressive and I can imagine how much of a chore it would be to figure out with a normal assembler.
Using SBCL as a macro-assembler is extremely cool, and then allowing CL code to call into the VM is where it really blows my mind.
Obviously it’s been over a decade since this article was written. For someone less familiar with SBCL internals (or CL in general), would something like AsmJit or Iced be a good way to achieve similar things?
Try pair reading it with a good thinking LLM like GPT 5.5 or Claude Opus. I found it help me a lot.
I have started learning SBCL internal from the beginning of this year with the help of GPT, and I really want to contribute to SBCL compiler someday in future.
> Using SBCL as a macro-assembler is extremely cool, and then allowing CL code to call into the VM is where it really blows my mind.
Absolutely. I think TFA is hooking into the actual code emitter used by SBCL's evaluator-compiler, since it's not actually primitive, but implemented in Lisp and loaded into the image itself.
My guess at context: from the earliest days of Lisp, I think there was an expectation that Lisp systems would expose as much of their internals as possible... including their internal JIT, which is being plugged into here. I think the name for it was the "LISP Assembly Program" (LAP).
This is basically how bare metal Lisps used to work, all the way when Lisp based OSes from various vendors happened (aka Lisp Machines / Interlisp-D / StarLisp...).
The approach is similar to Forth.
You have a few key forms that provide the required integration points with the hardware, those are the few ones written in Assembly.
Including the reader and at least some of the macro capabilities.
Then everything else is built from them.
For a time travel into those days see the recovered Interlisp-D system from Xerox PARC, https://interlisp.org/
Related. Others?
SBCL: The Assembly Code Breadboard - https://news.ycombinator.com/item?id=39859849 - March 2024 (19 comments)
SBCL: Assembly code breadboard (2014) - https://news.ycombinator.com/item?id=28450473 - Sept 2021 (4 comments)
SBCL: The Ultimate Assembly Code Breadboard (2014) - https://news.ycombinator.com/item?id=11959147 - June 2016 (2 comments)
SBCL: The Ultimate Assembly Code Breadboard - https://news.ycombinator.com/item?id=7408807 - March 2014 (75 comments)
https://news.ycombinator.com/item?id=39859849 - 19 comments, March 2024
Inserted above. Thanks!
I’ve read this article every time it’s gotten posted here and it’s always gone a little over my head. I was able to follow how he used 8 x86_64 registers for the VM’s stack slots and how the VM instructions were implemented. How the padding and alignments of each version of the instructions was calculated is impressive and I can imagine how much of a chore it would be to figure out with a normal assembler.
Using SBCL as a macro-assembler is extremely cool, and then allowing CL code to call into the VM is where it really blows my mind.
Obviously it’s been over a decade since this article was written. For someone less familiar with SBCL internals (or CL in general), would something like AsmJit or Iced be a good way to achieve similar things?
Try pair reading it with a good thinking LLM like GPT 5.5 or Claude Opus. I found it help me a lot.
I have started learning SBCL internal from the beginning of this year with the help of GPT, and I really want to contribute to SBCL compiler someday in future.
They definitely do embrace merging AI slop now, so they might even take pull requests.
> Using SBCL as a macro-assembler is extremely cool, and then allowing CL code to call into the VM is where it really blows my mind.
Absolutely. I think TFA is hooking into the actual code emitter used by SBCL's evaluator-compiler, since it's not actually primitive, but implemented in Lisp and loaded into the image itself.
My guess at context: from the earliest days of Lisp, I think there was an expectation that Lisp systems would expose as much of their internals as possible... including their internal JIT, which is being plugged into here. I think the name for it was the "LISP Assembly Program" (LAP).
This is basically how bare metal Lisps used to work, all the way when Lisp based OSes from various vendors happened (aka Lisp Machines / Interlisp-D / StarLisp...).
The approach is similar to Forth.
You have a few key forms that provide the required integration points with the hardware, those are the few ones written in Assembly.
Including the reader and at least some of the macro capabilities.
Then everything else is built from them.
For a time travel into those days see the recovered Interlisp-D system from Xerox PARC, https://interlisp.org/
https://www.stylewarning.com/posts/nbody/ might be a good addition, it showcases some higher level stuff added in sb-simd.