GCC貢獻者Andrea Corallo宣佈了gccemacs On elisp running native,用libgccjit編譯elisp爲ELF shared objects。libgccjit在這裏沒有用作JIT,而是驅動GCC進行優化和生成ELF。
倉庫:https://gitlab.com/koral/gccemacs/commits/dev
作者創建這個專案的動機和方法:
On my side the long story short is about this:
I was already into gcc and libgccjit. I thought was cool to apply these to some lisp implementation. I decided to have Emacs as a target cause I imagined would have been useful and because I’m obviously an Emacs user and fan.
I wanted to do something with the potential to be completed and up streamed one day. Therefore I discarded the idea of writing the full lisp front-end from scratch. On the other side I considered the idea seen in previous projects of reusing the byte-compiler infrastructure quite clever.
The original plan was the to do something like Tromey’s jitter but gcc based and with a mechanism to reload the compiled code. So I did it.
I had a single pass compiler all written in C that was decoding the byte code and driving libgccjit.
I was quite unhappy with that solution for two reasons:
1- The C file was getting huge without doing anything really smart.
2- After some test and observation became clear that to generate efficient code this approach was quite limited and a more sophisticated approach with a propagation engine and the classical compiler theory data structures was needed. The idea of just driving gcc and having everything magically optimized was simply naive.
So I came up with the idea of defining LIMPLE and using it as interface between the C and the lisp side of the compiler.
In this way I had the right IR for implementing the ‘clever’ algorithmic into lisp and the C side has just to ‘replay’ the result on libgccjit. Moreover it saved me from the pain of exposing libgccjit to lisp.
I then realized I could, instead of decoding op-codes, just spill the LAP from the byte-compiler. This makes the system simpler and more robust cause I get also information on the stack depth I can double check or use during limplification.
Lastly I managed to reuse the information defined in the byte-compiler on the stack offset of every op to generate automatically or semi the code of my compiler for the translation from LAP to LIMPLE for good part of the op codes.
The rest just iterating over tests debugging and implementing.
C部分主要加了src/comp.c
% git diff master...dev --stat
configure.ac | 29 +
lisp/emacs-lisp/bytecomp.el | 47 +-
lisp/emacs-lisp/comp.el | 1917 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/Makefile.in | 8 +-
src/comp.c | 3480 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
src/data.c | 13 +
src/emacs.c | 5 +
src/eval.c | 6 +
src/lisp.h | 7 +
src/lread.c | 38 +-
src/pdumper.c | 8 +-
test/src/comp-test-funcs.el | 393 +++++++++++++
test/src/comp-tests.el | 487 ++++++++++++++++
13 files changed, 6422 insertions(+), 16 deletions(-)
git clone https://gitlab.com/koral/gccemacs --branch=dev; cd gccemacs
./autogen.sh
./configure
make -j
src/emacs -Q
evaluate (native-compile "a.el")
可以構建出shared object a.eln
,可以用require or load-file加載。