Clause
← All documentation

Compilation

clau compiles Erlang/OTP 29 modules through LLVM to verified IR, bitcode or native objects. -o/--output links positional inputs (or one selected project target), their entry startup object and the runtime into an executable (linking); project builds link executable targets to their manifest outputs (projects). Emitted objects can also run through a C++ harness linked with the runtime (see the example below).

Accepted source subset

Named modules with exports and ordered function clauses. Heads and body matches accept variables, _, aliases, repeated names and patterns over atoms, arbitrary integers, finite floats, tuples, lists/strings, maps, bitstrings and ordinary tuple records. Bodies are sequences of matches, constructors, checked operators/guard BIFs, erlang:display/1 (printing), halt/0,1 (exit status), the raising error/1,2,3, exit/1, throw/1 and erlang:raise/3 (ABI), the other bridge builtins (erlang:function_exported/3) and funs of builtins, case/if, catch Expr, try ... of ... catch Class:Reason:Stack ... after with stack traces, maybe ... else ... end, list, binary and map comprehensions (patterns) and direct local or literal remote calls within the batch, including self, mutual and cross-module recursion on explicit process frames with proper tail calls (execution model); body recursion is bounded by the process stack (uncapped by default), not the native stack. Guards support the full admitted catalog. See patterns, guards and terms.

Function values fun F/A, fun M:F/A, anonymous and named funs with captured variables, calls of funs and dynamic calls (M:F(...), apply/2,3) run (funs). Rejected with diagnostics even in unused functions: receive, funs of builtins, processes and messaging. Accepted attributes: module, export, file, tuple and native record, export_record, import_record, type/spec forms, doc/moduledoc, author, vsn, copyright, deprecated, -compile with {no_auto_import, ...} or warning-only nowarn_* options (for example nowarn_deprecated_catch) and -import of erlang guard BIFs. Other attributes (on_load, parse transforms, other compile options, parameterized modules) are rejected. Sources starting with #! follow escript rules (implicit module and main/1 export, -mode accepted). Type/spec forms are analyzed but never change generated code. Syntax-only modes (--parse-check, --print-ast, --print-source, ...) accept the full grammar.

Run the compiled-module example

client:main/1 makes the example a program:

./build/debug/bin/clau -O2 -o build/demo examples/compile/answer.erl examples/compile/client.erl
./build/demo     # prints 42, -7 and {record,map,binary,list,integer,other}

The same modules also run through a C++ harness. From a Windows x64 Developer PowerShell with the built compiler:

$tool = './build/debug/bin/clau.exe'
& $tool -O0 --emit obj --artifact-dir build/example-aot examples/compile/answer.erl examples/compile/client.erl
cmake -S examples/compile -B build/example-native -G Ninja -DCMAKE_CXX_COMPILER=clang-cl -DCMAKE_BUILD_TYPE=Debug "-DGENERATED_DIR:PATH=$((Resolve-Path build/example-aot).Path)"
cmake --build build/example-native
./build/example-native/bin/Debug/compiled_modules.exe

It prints 42, -7, record, map, binary, list, integer, other, one per line. The harness registers modules explicitly, creates a context and decodes results; it is an example host, not a production entry point. On Unix use build/debug/bin/clau, clang++ and -DGENERATED_DIR="$PWD/build/example-aot" (native runs there are not yet validated).

Other actions on the same sources:

& $tool -O2 --emit llvm-ir --artifact-dir build/example-ir examples/compile/answer.erl examples/compile/client.erl
& $tool --print-types --verbose examples/compile/answer.erl examples/compile/client.erl
& $tool --print-ir --print-optimized-ir examples/compile/answer.erl examples/compile/client.erl
& $tool -O2 --no-type-specialization --verbose examples/compile/answer.erl examples/compile/client.erl

Source printing

--print-source (a frontend action, like --print-ast) prints each parsed module as Erlang source; --print-types prints the same text with type annotations. The printer (print_source, expression_source, type_source in printing.hpp; compiler/src/printing/source_*) is reusable:

Options

OptionBehavior
--emit obj|llvm-ir|llvm-bcPublish one artifact per module
--artifact-dir DIRArtifact root (requires --emit)
-o PATH / --output PATHLink an executable (linking); conflicts with --emit
--linker PATH, --runtime-library PATHClang driver and runtime archive for -o
--entry MODULE[:FUNCTION]Executable entry function/1; validated in every compiling mode and adds the clausev1_start startup artifact (executables)
--target-triple TRIPLETarget machine; --target is project target selection
-O0 / -O2 / -OsDefault generic code + LLVM O0 / bounded specialization + LLVM O2 / LLVM Os, no specialization, one section per symbol and linker dead-stripping of unreferenced code and data
--no-type-specializationDisable variants regardless of option order
--print-ir / --print-optimized-irVerified IR before/after LLVM passes, with Erlang source lines as comments
--print-typesEach module as Erlang source annotated with inferred types (semantic); stops before LLVM
--verbose[pp], [parse] and [comp] phase events on stderr
--impldebug n[,n...]Implementation-step debug output on stderr (e.g. 23: inference summaries)

Backend

LLVM SDK

Stable LLVM 23.1.x, minimum 23.1.1. LLVM is a host dependency: architecture, C++ standard library and Windows CRT must match the compiler tool. Project code keeps exceptions/RTTI; no exception may unwind through LLVM. The runtime never uses LLVM.

Reference Windows x64 setup (2026-09-29): host clang-cl 23.1.2 in C:/Program Files/LLVM/bin, SDK thirdparty/clang+llvm-23.1.2-x86_64-pc-windows-msvc, Visual Studio 18 x64 tools, Windows SDK 10.0.26100.0, Ninja, /MT, _ITERATOR_DEBUG_LEVEL=0. Automatic selection applies the /MT and iterator settings; an explicit LLVM_DIR does not, and the link probe then fails.

Historical macOS reference: Homebrew llvm 23.1.1_1 (arm64, shared libLLVM.23.1.dylib, assertions off) with AppleClang 21.

Other prerequisites: CMake ≥ 3.28, a C++23 compiler, Boost ≥ 1.90, toml++ 3.4.0 and the quality tools. OTP is needed only for opt-in audits and fixture regeneration.