optimizing, small, simple, compiler backend.
VXCC uses SSA IR with block arguments instead of the commonly used phi-nodes.
VXCC is licenced under the permissive Apache 2.0 license with LLVM Exceptions
- frontend generates non-SSA IR
- backend converts it to SSA
- backend applies optimizations
- backend converts it to "LL IR" (non-SSA + labels) and performs some more optimizations
- simple code generation
- easily modifyable and readable code
- not much special knowladge required
- easy to implement code generation for any architecture
- make it easy for people to learn about compiler backends
- good-ish optimizations
- beat QBE in terms of generated code speed
- reach complexity of GCC or even LLVM
- beat GCC or LLVM
goal | progress | |
---|---|---|
amd64 codegen | done (for now) | |
basic optimizations | done | |
rv32im codegen | in progress | |
proper register allocator & ISEL rework | planned | |
floating point numbers | planned |
use the ./build.sh build
one of clang
, gcc
, or tcc
: automatically detected. different C compiler can be used by doing CC=someothercc ./build.sh [build|test]
(test
can be executed after build
to run all tests)
python3
: it is recommended to create a venv in the repository root using python -m venv venv
Link with all files returned by ./build.sh libfiles
(at time of writing, only build/lib.a
)
this is meant to be extremely easy to do (for the frontend developer)
There is some documentation in frontend_dev_doc.md
.
You can also uselook at the C3C fork in the src/compiler/vxcc_*
files.
If you have any questions, you can ask me on Discord (alex_s168
) or send me an E-Mail
all contributions are welcome! Don't hesitate to ask me if you have any questions.
please do not currently change anything related to:
- codegen system / isel & regalloc (because I want to re-do it in a specific way)
(if you want to do any of the following, please contact me first for exact details)
id | task | money | dependencies |
---|---|---|---|
1. | target-independent nasm-style assembly parser + conditional prefix like {z} mov r0, 1 |
100€ (~107$) | |
2. | refactor number data types to allow non-power-of-2 bit widths, and also add different float types | 50€ (~ 51$) | |
3. | lower ints pass. asks backend for supported types. lower arbitary-width integers | 100€ (~103$) | depends on 2 |
4. | identify passes by names and use S-expr KV maps for config. describe pass pipeline using S-exprs instead | 100€ (~103$) | |
5. | plugin system (ask me for details) | 200€ (~207$) | depends on 4 |
6. | lower IEEE 754 floats pass. asks backend for supported types. emulate F16,F32,F64 via what backend has | 200€ (~207$) | depends on 2, 10 |
7. | space-efficient binary (de-)serialization of SNode | 100€ (~103$) | |
8. | lower fixed-point floats pass. configurable fixed-point floating point emulation | 100€ (~103$) | depends on 2, 9, 10 |
9. | lower mul/div pass. lowers {MUL, {U,S}DIV} that are not supported by backend | 100€ (~103$) | |
10. | add ops for all common float math operations. add pass that lowers unsupported ones to libm calls | 200€ (~207$) | |
11. | loop (and if statement) invariant code movement pass | 50€ (~ 51$) | |
12. | loop unswitch pass: move if inside loop to outside if possible. | 25€ (~ 26$) |
- variable inlining
- duplicate code removal
- cmoves
- tailcall
- simplify loops and ifs
- simple pattern replacement of bit extract and similar
- compile time constant eval
input:
fn void strcpy(char* dest, char* src) @export
{
for (usz i = 0; src[i] != '\0'; i ++)
dest[i] = src[i];
}
output:
strcpy:
xor r11d, r11d
.l0:
mov r9b, byte [rsi + 1 * r11]
test r9b, r9b
je .l1
mov byte [rdi + 1 * r11], r9b
lea r8, [r11 + 1]
mov r11, r8
jmp .l0
.l1:
ret
This will improve in the close future.
You need to complete these tasks (in any order):
- add your target to every place with the comment
// add target
. (you can usegit grep -Fn "// add target"
to find them) - write a code generator (see ETC.A or X86 backend as reference) and add the file to the
build.c
- add support for it to frontends?