Rust-Based Complete Compiler for Mini Expression Language & Control Flow
This project implements a two-stage Rust compiler toolchain that lowers a small language into x86-64 assembly following the System V calling convention.
-
first/β Part 1: expression-only language- Input:
testN.exp(e.g.,a * b + 5 * c) - Output:
foofunction in x86-64 assembly (.s) - Used with small C drivers to run the expression.
- Input:
-
second/β Part 2: full mini-imperative language- Supports:
args,intdeclarations, assignment,if/else,while,return, comparisons. - Input:
testN.rucomp - Output:
foofunction in x86-64 assembly (.s), run via C drivers.
- Supports:
All regression tests and C harnesses live under tests/, and a top-level Makefile automates building and running everything.
- Part 1: Expression β x86-64
- Emits a function:
```
.text
.global foo
foo:
pushq %rbp
movq %rsp, %rbp
...
movq %rbp, %rsp
popq %rbp
ret
```
- Arguments are assumed to be in:
```
%rdi, %rsi, %rdx, %rcx, %r8, %r9
```
- Part 2: Full Program β x86-64 with Stack Frame
- Allocates stack slots for all args and local vars:
- Each identifier β a negative offset from %rbp:
```
pushq %rbp
movq %rsp, %rbp
subq $FRAME_SIZE, %rsp # space for locals
# store incoming arguments
movq %rdi, -8(%rbp) # a
movq %rsi, -16(%rbp) # b
...
```
- Languages / Tools
- Rust + Cargo
- C (for test harnesses)
- Makefile (for regression automation)
- clang (macOS, targeting -arch x86_64)
The instructions to run & build this project is in another ReadME placed inside the tests folder π.
-
Optimizations:
- Common subexpression elimination for repeated subtrees (Part 1).
- Dead code elimination in Part 2.
-
Better register allocation:
- Avoid push/pop for every operation.
- Use more caller-saved registers intelligently.
-
Extended language features:
- Multi-argument functions, call/return.
- Arrays or simple heap allocation.
- More operators (division, modulo, logical &&, ||)
- Kelvin Ihezue