|
|
|
|
|
by titzer
1763 days ago
|
|
> Why can't we have a compiler with built in system call support? Funny you should ask that. That is exactly how Virgil's compiler supports the Linux (and Darwin) kernels. Other than generating a small amount of startup assembly (10-20 ins), the compiler just knows the ELF (and MachO) binary formats and the calling conventions of the respective kernels. With some unsafe escape hatches (e.g. getting a pointer into the middle of a byte array), the rest is regular Virgil code that calls the kernel directly. Take a look, I've been working on this for more than 10 years: https://github.com/titzer/virgil/blob/master/rt/x86-64-linux... The "Linux.syscall" is a special operator know to the compiler and it will let you pass an int (the syscall number) and whatever arguments you want (any types--it is implemented with flattening and polymorphic specialization) to the kernel. With this I have implemented all kinds of stuff, including the userspace runtime system and even a JIT compiler (for my new Wasm engine). |
|
I started looking into this myself some years ago. Even started developing a liblinux with process startup code and everything. Abandoned it after I found the kernel itself had an awesome nolibc.h file that was much more practical for my C programming needs:
https://elixir.bootlin.com/linux/latest/source/tools/include...
My code is in a bad state but if you'd like to take a look:
https://github.com/matheusmoreira/liblinux
It's amazing how this really lets you do everything... Want a JIT compiler? Map some executable pages and emit some code. You can statically allocate memory at process startup and use that for bootstrapping code. This lets you implement dynamic memory allocation and even garbage collection in your own language.