Ecosyste.ms: Awesome

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

Awesome Lists | Featured Topics | Projects

https://github.com/redraiment/brainfuck

Brainfuck Compiler and Interpreter with LLVM in C
https://github.com/redraiment/brainfuck

brainfuck c compiler interpreter llvm llvm-frontend

Last synced: about 1 month ago
JSON representation

Brainfuck Compiler and Interpreter with LLVM in C

Awesome Lists containing this project

README

        

# Brainfuck Interpreters and Compilers

[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)

This is my learning project to practice building compiler and interpreter with LLVM C API.

The project is too complext for someone, who just want to implement a simple interpreter for Brainfuck. This [snippet](https://gist.github.com/redraiment/87413e5edc5c33458812492b5358ed61) is a better alternative, which implements the interpreter with one C file only.

# About the Project

There are so many LLVM tutorials in C++, however, I'd like to build a compiler and interpreter with LLVM in C. Therefore, I created this project to build a compiler and JIT interpreter for [Brainfuck](https://en.wikipedia.org/wiki/Brainfuck). Brainfuck language is simple enough, and it designed for implementing the smallest possible compiler.

# Roadmap

* [x] ~~Generating Makefile with [GNU Autoconf](https://www.gnu.org/software/autoconf/).~~
* [x] Generating Makefile with [CMake](https://cmake.org/).
* [x] Building project with [GNU Make](https://www.gnu.org/software/make/).
* [x] Parsing Command line options with [getopt](https://www.gnu.org/software/libc/manual/html_node/Getopt.html).
* [x] Lexical analysis with [flex](https://github.com/westes/flex).
* [x] Syntax analysis with [bison](https://www.gnu.org/software/bison/).
* [x] Creating LLVM IR file with [LLVM C API](https://llvm.org/doxygen/group__LLVMC.html).
* [x] Creating native object file with [LLVM C API](https://llvm.org/doxygen/group__LLVMC.html).
* [x] Creating executable file with linker.
* [x] Running script file with [LLVM MCJIT](https://llvm.org/doxygen/group__LLVMCExecutionEngine.html).
* [x] Deploying with [docker](https://hub.docker.com/).
* [x] Linking with [lld](https://lld.llvm.org/).
* [x] Static linking with [musl](https://musl.libc.org/).
* [x] Embedding C runtime library.

# Getting Started

The program can only working on Linux for now.

## Download pre-build binary file (Recommended)

```sh
wget https://github.com/redraiment/brainfuck/releases/download/v0.5.0/brainfuck-0.5.0-x86_64.gz
gunzip brainfuck-0.5.0.x86_64.gz
sudo mv brainfuck-0.5.0.x86_64 /usr/local/bin/brainfuck
brainfuck -v
```

You can see below version information if the above command run success.

```
brainfuck v0.5.0

Home page: .
E-mail bug reports to: .
```

Example for creating executable file and run it then:

```sh
brainfuck hello-world.bf
./hello-world
```

You can find the `hello-world.bf` in [test](https://github.com/redraiment/brainfuck/tree/main/test) folder.

## Install with Source Code

An example on Ubuntu:

```sh
sudo apt install --no-install-recommends -y flex bison clang-15 lld-15 liblld-15-dev llvm-15 llvm-15-dev llvm-15-tools zlib1g-dev libtinfo-dev binutils-dev musl-dev xxd make cmake
git clone --depth=1 https://github.com/redraiment/brainfuck.git
cd brainfuck
cmake 'Unix Makefiles' -B build .
cmake --build build
```

# Usage

```sh
brainfuck [OPTIONS]
```

It will create an executable file default.

## Options

* `-c/--compile`: only run preprocess, compile and assemble steps, then emit native object (`.o`) to output file. By default, the object file name for a source file is made by replacing the extension with `.o`.
* `-r/--representation`: emit LLVM representation (`.ll`) to standard output.
* `-s/--script`: run source file as Brainfuck script.
* `-m/--enable-single-line-comment`: enable single line comment command `#`. It's useful used with Shebang.
* `-o/--output `: write output to file. This applies to whatever sort of output is being produced, whether it be an executable file, an object file, an IR file. If `-o` is not specified, the default executable file name for a source file is made by removing the extension.
* `-h/--help`: show this help and exit.
* `-v/--version`: show version and exit.

## Examples

1. Creating an executable file: `brainfuck helloworld.bf`
2. Running a file as scripting: `brainfuck -s helloworld.bf`
3. Using with Shebang: `#!/usr/local/bin/brainfuck -ms`
4. Creating native object file: `brainfuck -c helloworld.bf`
5. Creating LLVM representation file: `brainfuck -p helloworld.bf`

# Language Specification

Here are some key behaviors:

* Memory size: 30,000 bytes, and initialized to zero.
* Data pointer initialized to point to the leftmost byte of the array.
* Two streams of bytes for input and output.
* End-of-file behavior: setting the cell to 0.
* Use "\n" for end-of-line.

## Commands

| Character | Meaning |
| -- | -- |
| `>` | Increment the data pointer (to point to the next cell to the right). |
| `<` | Decrement the data pointer (to point to the next cell to the left). |
| `+` | Increment (increase by one) the byte at the data pointer. |
| `-` | Decrement (decrease by one) the byte at the data pointer. |
| `.` | Output the byte at the data pointer. |
| `,` | Accept one byte of input, storing its value in the byte at the data pointer. |
| `[` | If the byte at the data pointer is zero, then instead of moving the instruction pointer forward to the next command, jump it forward to the command after the matching `]` command. |
| `]` | If the byte at the data pointer is nonzero, then instead of moving the instruction pointer forward to the next command, jump it back to the command after the matching `[` command. |
| `#` | Single line comment. **Disabled default**. |
| others | Comments |

**HINT**: Single line comment command (`#`) is an extra command to ignore the text until end-of-line. It was added to avoid command of shebang conflict with Brainfuck commands. For example, there is `-` in `#!/bin/brainfuck -s`, which is backward command of Brainfuck.

## Snippets

Here some Brainfuck snippets for testing.

### Hello World

From [Wikipedia](https://en.wikipedia.org/wiki/Brainfuck#Hello_World!). It will write "Hello world" to standard output.

```brainfuck
++++++++++
[>+++++++>++++++++++>+++>+<<<<-]
>++.>+.+++++++..+++.>++.<<+++++++++++++++.
>.+++.------.--------.>+.>.
```

### cat

It will read data from standard input and write to standard output directly, until end of file.

```brainfuck
,[.,]
```

### wc

from [brainfuck.org](http://brainfuck.org/wc.b). the standard (line and) word (and character) count utility.

```brainfuck
>>>+>>>>>+>>+>>+[<<],[
-[-[-[-[-[-[-[-[<+>-[>+<-[>-<-[-[-[<++[<++++++>-]<
[>>[-<]<[>]<-]>>[<+>-[<->[-]]]]]]]]]]]]]]]]
<[-<<[-]+>]<<[>>>>>>+<<<<<<-]>[>]>>>>>>>+>[
<+[
>+++++++++<-[>-<-]++>[<+++++++>-[<->-]+[+>>>>>>]]
<[>+<-]>[>>>>>++>[-]]+<
]>[-<<<<<<]>>>>
],
]+<++>>>[[+++++>>>>>>]<+>+[[<++++++++>-]<.<<<<<]>>>>>>>>]
```

# Contributing

If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". Don't forget to give the project a star! Thanks again!

1. Fork the Project
1. Create your Feature Branch (git checkout -b feature/AmazingFeature)
1. Commit your Changes (git commit -m 'Add some AmazingFeature')
1. Push to the Branch (git push origin feature/AmazingFeature)
1. Open a Pull Request

# License

Distrubuted under the GPLv3 License. See `LICENSE` for more information.

# Contact

* Zhang, Zepeng - [@redraiment](https://twitter.com/redraiment) - [[email protected]](mailto:[email protected])

# Acknowledgments

* [Wikipedia](https://en.wikipedia.org/)
* [brainfuck.org](http://brainfuck.org/)
* [LLVM.org](https://llvm.org/)
* [CMake](https://cmake.org/)
* [GNU](https://www.gnu.org/)
* ~~[GNU Autoconf](https://www.gnu.org/software/autoconf/)~~
* [GNU Make](https://www.gnu.org/software/make/)
* [GNU getopt](https://www.gnu.org/software/libc/manual/html_node/Getopt.html)
* [GNU bison](https://www.gnu.org/software/bison/).
* [flex](https://github.com/westes/flex).
* [Docker](https://www.docker.com/).