Ecosyste.ms: Awesome

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

Awesome Lists | Featured Topics | Projects

https://github.com/keiichiw/constexpr-8cc

Compile-time C Compiler implemented as C++14 constant expressions
https://github.com/keiichiw/constexpr-8cc

c c-plus-plus compiler constexpr joke

Last synced: 3 days ago
JSON representation

Compile-time C Compiler implemented as C++14 constant expressions

Awesome Lists containing this project

README

        

# constexpr-8cc: Compile-time C Compiler ![Build Status](https://github.com/keiichiw/constexpr-8cc/actions/workflows/main.yml/badge.svg)

[constexpr-8cc](https://github.com/keiichiw/constexpr-8cc) is a compile-time C compiler implemented as C++14 constant expressions.
This enables you to **compile while you compile!**
This project is a port of [8cc](https://github.com/rui314/8cc) built on [ELVM Infrastructure](https://github.com/shinh/elvm).

[Constant expressions in C++](http://en.cppreference.com/w/cpp/language/constant_expression) are expressions that can be evaluated at compile-time.
In C++14, [by relaxing constrains](https://isocpp.org/files/papers/N3652.html), constant expressions became so **powerful** that **a C compiler can be implemented in**!

In constexpr-8cc, the main routine for compilations of C programs is implemented in a C++14 `constexpr` function.
Therefore, if you compile `8cc.cpp` to a binary file by g++, compilation of a C program will be performed as a compile-time computation and the result of this C compilation will be embedded into the generated binary.
In this sense, constexpr-8cc is a **compile-time C compiler**.

The following is the `main` function in [8cc.cpp](https://github.com/keiichiw/constexpr-8cc/blob/master/8cc.cpp).
```c++
int main() {
// Compile-time
constexpr buffer buf = eight_cc(); // Compile C code into ELVM IR
constexpr unsigned int output_size = buf.size;

static_assert(0 <= output_size && output_size < EIGHT_CC_OUTPUT_LIMIT, "8cc: Error");

// Run-time
for(int i = 0; i < output_size; ++i) {
putchar(buf.b[i]);
}
}
```
In this program, the return value of `eight_cc` is stored into the variable `buf` with a `constexpr` specifier.
Thus, you will find that the compilation of a C program is done in compile-time.

## Requirements

`constexpr-8cc` requires Linux with >g++-6.2. I confirmed `./test/hello.c` can be compiled with `g++-6.2`, `g++-8.3` and `g++-9.3` at least.

* g++-6.2 worked without any extra flag related to constexpr as there was no limitation of constant's loop counts at this version.
* With g++-8.3, I needed to enlarge constexpr's loop count with `-fconstexpr-loop-limit`. The maximum number we can specify is `2**31 - 1`.
* With g++-9.3, in addition to `-fconstexpr-loop-limit`, enlarging `-fconstexpr-ops-limit` was needed.
* There is no guarantee that it works with other versions of g++.
* I couldn't make it work with clang++ as clang++ has more strict limitation of constexpr loop counts.

## How to run

### Compilation by `run_8cc.py`
In order to try constexpr-8cc easily, use `run_8cc.py`.
```shell
$ ./run_8cc.py x86 ./test/hello.c -o ./hello.exe # It takes about 3 minutes on my laptop
$ chmod +x ./hello.exe # 'hello.exe' is i386-linux binary
$ ./hello.exe
Hello, world!
```
You can change the target language of compilations like the following:
```shell
$ ./run_8cc.py py ./test/hello.c -o ./hello.py # target language is Python
$ python ./hello.py
Hello, world!
```
For more information about this script, type `$ ./run_8cc.py -h`.

### Compilation by hand
If you want to compile `8cc.cpp` manually, please look at `config.hpp`.
In this file, the variable `EIGHT_CC_INPUT_FILE` is defined.
`EIGHT_CC_INPUT_FILE` should be a name of a file that contains a source C program as a C++ string literal.
This string will be embedded in 8cc.cpp at pre-processing-time and used as an input of the compile-time computation.

So, before compiling `8cc.cpp` manually, you have to convert a raw program to a string literal like the following:
```shell
$ sed '1s/^/R"(/' ./test/hello.c | sed '$s/$/\n)"/' > ./test/hello.c.txt # Convert C to string literal
$ g++-6 ./8cc.cpp -o eir_gen.out
$ ./eir_gen.out > ./test/hello.eir # eir_gen.out outputs ELVM IR
$ sed -i '1s/^/R"(x86/' ./test/hello.eir # Convert IR to string literal
$ sed -i '$s/$/\n)"/' ./test/hello.eir
$ g++-6 ./elc.cpp -o exe_gen.out
$ ./exe_gen.out > ./hello.exe # exe_gen.out outputs i386-linux binary
$ chmod +x ./hello.exe
$ ./hello.exe
Hello, world!
```
## How was constexpr-8cc generated?
When you see [`8cc.hpp`](https://github.com/keiichiw/constexpr-8cc/blob/master/8cc.hpp), you will know this program was not written by hand.
Actually, I used [ELVM Compiler Infrastructure](https://github.com/shinh/elvm) to generate it.
I just implemented a translator from ELVM IR to C++14 constexpr [here](https://github.com/shinh/elvm/pull/15).

## Author
**Keiichi Watanabe** (udon.watanabe [at] gmail.com)

## Links
* [8cc](https://github.com/rui314/8cc) ([@rui314](https://github.com/rui314))
- A very cool C compiler. constexpr-8cc is a C++14's constexpr port of 8cc.
* [ELVM](https://github.com/shinh/elvm) ([@shinh](https://github.com/shinh))
- ELVM(EsoLang Virtual Machine) is a parody project of LLVM, but dedicated to Esoteric Languages. constexpr-8cc is built on ELVM infrastructure.
* [8cc.vim](https://github.com/rhysd/8cc.vim) ([@rhysd](https://github.com/rhysd)), [8cc.tex](https://github.com/hak7a3/8cc.tex) ([@hak7a3](https://github.com/hak7a3))
- constexpr-8cc is influenced by these projects.
* [Compile-time Brainf\*ck compiler](https://github.com/bolero-MURAKAMI/Sprout/blob/master/example/brainfuck/x86_compile.cpp) ([@bolero-MURAKAMI](https://github.com/bolero-MURAKAMI))
- I got several ideas from this program.

* [TMP-8cc](https://github.com/keiichiw/TMP-8cc): Another Compile-time C Compiler
- Another compile-time C compiler I created, which is implemented in **C++ Template Metaprogramming**
- This is generated by [ELVM's C++ Template Metaprogramming backend](https://github.com/shinh/elvm/pull/39).
- Since `TMP` neads huge amount of memories, `TMP-8cc` unfortunately **does not work** on real machines.
* [My blog post (Japanese)](http://kw-udon.hatenablog.com/entry/2016/12/03/201722)