Ecosyste.ms: Awesome

An open API service indexing awesome lists of open source software.

Awesome Lists | Featured Topics | Projects

https://github.com/PhilippRados/wrecc

A x86_64 C99 compiler written in Rust from scratch
https://github.com/PhilippRados/wrecc

c codegen compiler from-scratch rust

Last synced: about 2 months ago
JSON representation

A x86_64 C99 compiler written in Rust from scratch

Awesome Lists containing this project

README

        





[![Test](https://github.com/PhilippRados/wrecc/actions/workflows/test.yml/badge.svg)](https://github.com/PhilippRados/wrecc/actions/workflows/test.yml)
![](https://img.shields.io/github/license/PhilippRados/wrecc)
![](https://img.shields.io/badge/made_for-UNIX-lightgrey)
![](https://img.shields.io/badge/Architecture-x86--64-blue)

`wrecc` is a small,lean x86-64 C99 compiler written from scratch. The name is a play on the word _wreck_ which describes a rusting ship on the sea floor.
The compiler emits [x86-64](https://en.wikipedia.org/wiki/X86-64) assembly in [AT&T syntax](https://staffwww.fullcoll.edu/aclifton/courses/cs241/syntax.html), it adheres to the [System V ABI](https://wiki.osdev.org/System_V_ABI) which I could only test for Ubuntu and Macos. There are no dependencies you only need your assembler and linker which the compiler then invokes to create the final binary.

### Table of contents
* [Installation](#installation)
+ [Pre-built binaries](#binaries)
+ [Cargo](#cargo)
* [Features](#features)
+ [Preprocessor](#preprocessor)
+ [Compiler](#compiler)
+ [Supported keywords](#keywords)
+ [Unimplemented features](#unimplemented)
+ [Error messages](#errors)
+ [Ast pretty-printer](#ast)
* [Testing](#testing)
+ [Unit-tests](#unit)
+ [Snapshot-tests](#snap)
+ [Fuzzer](#fuzzer)
* [Troubleshooting](#troubleshooting)
* [Contribution](#contribution)
* [Project goals](#goals)
* [Resources](#resources)

## Installation
### Pre-built binaries
If you don't have the rust toolchain installed on your system you can install the latest binary (MacOs, Linux) from the releases directly:
```
curl --proto '=https' --tlsv1.2 -LsSf https://github.com/PhilippRados/wrecc/releases/download/v0.2.0/wrecc-installer.sh | sh
```
### Cargo
Using `cargo binstall`
```
cargo binstall wrecc
```
or building from source
```
cargo install wrecc
```

## Features
Since not all keywords are currently implemented wrecc uses [custom standard-headers](https://github.com/PhilippRados/wrecc/tree/master/include) which are built directly into the binary
### Preprocessor
The preprocessor implements all [C99 preprocessor directives](https://en.cppreference.com/w/c/keyword), except `#line`, `#error` and `#pragma`. Most prominently it currently also misses function-like macros which are on the agenda though.

### Compiler
#### Supported Keywords
keywords

#### Other than that it even supports:

Aggregate initialization with designated initializers

```C
struct {
union {
int foo;
long baz;
} nested;
int array[16];
} bar = { .nested.foo = 3, .array[6] = 1};
```

Function pointers

```C
#include

typedef int (*BinaryOperation)(int, int);
typedef struct {
BinaryOperation add;
BinaryOperation subtract;
} Calculator;

int add(int a, int b) { return a + b; }
int subtract(int a, int b) { return a - b; }

int main() {
Calculator calc = {add, subtract};

printf("Result of addition: %d\n", calc.add(10, 5));
printf("Result of subtraction: %d\n", calc.subtract(10, 5));
}

```

Constant folding

```C
char **string_offset = (char **)&"hello" + (int)(3 * 1);
int array[(long)3 * 2 - 1];
```

#### Unimplemented Features
Aside from the missing keywords these are the main missing features:
- [x] Arrays with unspecified size
- [x] Compiling multiple files at once
- [ ] Raw structs/unions as function argument-/return-types
- [ ] Floating point types

Here is a list of all the stuff still missing: [todo](https://placid-eris-c19.notion.site/check-all-errors-from-c-testsuite-6f3fa2a3c24a4711b5e89f45354db540?pvs=4)

### Error messages
Wrecc also has nice looking messages. Error reporting doesn't stop after the first error. Using the `--no-color` option you can switch off color-highlighting in errors. Currently there are only errors and no warnings.


C code
Errors




```C
int foo(void);
int main() {
int a = foo(1);
long *p = a;

return p * 2;
}
```


error

### Ast pretty-printer
When compiling using the `--dump-ast` option it prints the parse-tree


C code
AST




```C
#define SIZE 16
void foo(char);
int main() {
int arr[SIZE] = {1, 2};
char p = (char)(*arr + 3);

switch (p) {
case 'c':
foo(p);
}
}
```



```
Declaration:
-Decl: 'foo'
FuncDef: 'main'
-Declaration:
--Init: 'arr'
---Aggregate:
----Scalar:
-----Literal: 1
----Scalar:
-----Literal: 2
-Declaration:
--Init: 'p'
---Scalar:
----Cast: 'char'
-----Grouping:
------Binary: '+'
-------Unary: '*'
--------Ident: 'arr'
-------Literal: 3
-Switch:
--Ident: 'p'
--Block:
---Case:
----Literal: 99
----Expr:
-----FuncCall:
------Ident: 'foo'
------Ident: 'p'
```

#### Inspect all options by running `wrecc --help`

## Testing
#### Unit tests
```
cargo test --workspace
```
#### Snapshot testing
This runs all [fixtures](https://github.com/PhilippRados/wrecc/tree/master/tests/fixtures) and compares them to the expected [snapshot](https://github.com/PhilippRados/wrecc/tree/master/tests/snapshots)
```
bash tests/snapshot_tests.sh
```
#### Fuzzer
Runs the fuzzer using [afl.rs](https://github.com/rust-fuzz/afl.rs)
```
// in fuzzer directory
cargo afl build
cargo afl fuzz -i inputs -o outputs target/debug/fuzz_target
```

## Troubleshooting
Reasons for `wrecc` not working properly on your machine:
- Unsupported architecture/OS
- Cannot find libc in standard library search paths (can be fixed by passing custom search path using `-L ` option)
- If it's not mentioned in the [unimplemented features](#unimplemented) section then please raise an issue

## Contribution
If you want to help me with this compiler I would really welcome it. The easiest place to start is probably by implementing one of the missing keywords/types mentioned in the [unimplemented features](#unimplemented) section. Make sure all tests still pass and implement your own if it's something new that is not already being tested.

Have a look at the [documentation](https://docs.rs/wrecc_compiler/latest/wrecc_compiler/) to get a high level overview of the compiler pipeline.

## Project goals
- Not relying on custom headers
- Passing all C99 tests in [c-testsuite](https://github.com/c-testsuite/c-testsuite)
- Compiling real-world C projects like [Git](https://github.com/git/git/tree/master)

## Resources
The following resources helped me in building this compiler:
- [Crafting Interpreters](https://craftinginterpreters.com/)
- Engineering a Compiler (Book)
- [acwj](https://github.com/DoctorWkt/acwj)
- [saltwater](https://github.com/jyn514/saltwater)
- [chibicc](https://github.com/rui314/chibicc)