A proof-of-concept minimal LLVM-like compiler that generates an Intermediate Representation (IR) and supports the addition of multiple frontends and backends.
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Frontend │────▶│ IR │────▶│ Backend │
│ (C, ...) │ │ (optimized) │ │ (aarch64,...│
└─────────────┘ └─────────────┘ └─────────────┘
The compiler follows the classic three-phase design:
- Frontend: Parses source code and generates IR
- IR: A typed intermediate representation with optimization passes
- Backend: Converts IR to target-specific assembly
| Frontends | Backends |
|---|---|
| C | aarch64 |
The IR uses an LLVM-inspired syntax:
define i32 @main() {
%0 = alloca i32
%1 = add i32 1, 3
store i32 %1, ptr %0
%2 = load i32, ptr %0
%3 = add i32 3, 4
%4 = mul i32 %3, %2
%5 = add i32 %4, 1
ret i32 %5
}npm installnpm start <source-file> <target-file> -s <source-language> -t <target-arch>| Option | Description | Values |
|---|---|---|
-s, --source |
Source language | c |
-t, --target |
Target architecture | aarch64 |
Compile a C file to aarch64 assembly:
npm start test1.c output.asm -s c -t aarch64clang -arch arm64 -o output output.asm
./output
echo $? # prints the return valuenpm test # run tests
npm check # type check
npm lint # lintCreate a new directory under frontend/ and implement:
- Tokenizer
- Parser (AST generation)
- Processor (AST processing)
- Codegen (AST → IR)
Then add the language option in index.ts.
Create a new directory under backend/ and implement a codegen function that converts IntermediateFunction[] to assembly string.
Then add the architecture option in index.ts.