Skip to content

benmandrew/bf

Repository files navigation

Brainf*ck to LLVM IR Compiler Frontend

A compiler frontend for the Brainf*ck language that outputs code in LLVM Intermediate Representation (IR), which can then be compiled to any desired target architecture with clang.

You can interact with it online here, or in a self-hosted web interface accessed at http://localhost:8080 after running

$ docker compose up

The input validation and parsing functionality is formally verified to be memory safe for inputs up to thirteen commands long. Details are in MODELCHECKING.md.

alt

Dependencies

The project ships a Nix flake with a devShell providing every tool the build needs — cmake, LLVM/clang, check, expect, clang-format, cpplint, Doxygen, Graphviz, Python/Sphinx, shfmt, and shellcheck — pinned via flake.lock for reproducibility. This is what CI uses, and is the recommended way to build locally:

$ nix develop

Every command in this README can be run unmodified inside that shell.

Manual install (alternative to Nix)

Ubuntu/Debian

$ sudo apt-get install cmake llvm-dev check expect clang-format cpplint doxygen graphviz

MacOS (Homebrew)

$ brew install cmake llvm check expect clang-format cpplint doxygen graphviz

Building

$ cmake -B build
$ cmake --build build

After building, the bfc (compiler) and bfi (interpreter) executables will be in the build directory.

To compile a bf program to a binary executable:

# Generate LLVM IR
$ bfc test/res/helloworld.b > main.ll
# Compile IR to binary
$ clang main.ll -o main
$ ./main
Hello, World!

To execute a bf program with the interpreter:

$ bfi test/res/helloworld.b
Hello, World!

Formatting and Linting

$ cmake --build build --target fmt lint

Documentation

Code docs can be accessed online at benmandrew.com/docs/bf/, or built locally with

$ cmake --build build --target docs

Depends on Doxygen and Sphinx, both provided by the Nix devShell. The generated HTML site is written to build/docs/html/index.html.

Tests

$ cmake --build build --target tests

Fuzzing

You can fuzz test with AFL:

$ docker run -ti -v .:/src benmandrew/bf:fuzz

If there are crashes, the offending inputs will be located in build-fuzz/fuzz_output/default/crashes.

FAQ

Why does ASan fail with malloc: nano zone abandoned due to inability to reserve vm space.?

On MacOS, every ASan-built binary prints this error. This is not an issue with the program, and can be fixed by setting the environment variable MallocNanoZone=0. See google/sanitizers#1666.

Useful Links for Learning the LLVM Intermediate Representation

Compiling to the LLVM IR is a niche topic, and it is hard to find resources for learning. Here are a few useful ones I found:

  • Mapping High Level Constructs to LLVM IR (link)
  • A Complete Guide to LLVM for Programming Language Creators (link)
  • My First Language Frontend with LLVM Tutorial (link)

About

Brainf*ck to LLVM IR compiler frontend

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors