Installing LLVM on Windows, Raspbian & macOS

I had no idea about LLVM(Low-Level Virtual Machine) until the day I installed Emscripten for learning asm.js and WebAssembly. Emscripten Compiler Frontend (emcc) uses Clang to convert C/C++ files to LLVM bitcode, and Fastcomp (Emscripten’s Compiler Core — an LLVM backend) to compile the bitcode to JavaScript.

Installing LLVM on Different Platforms

Windows

Get the pre-built binaries from LLVM download page.

After installing Clang for Windows, follow the Getting Started tutorial to compile a C file to LLVM bitcode file:

clang -O3 -emit-llvm hello.c -c -o hello.bc

If you don’t have a hex editor installed, you can view the bc file with wasmcodeexplorer online.

wasm code explorer

LLVM bitcode reminds me of the Java bytecode. We can use lli to run .bc files directly.

According to the tutorial, run the program as follows:

lli hello.bc

However, where is lli? There is no pre-built binary available for download online except the source code. Therefore, we can download the LLVM source code and build it ourselves. The lli project is located at llvm-<version>\tools\lli.

Build the source code with CMake:

mkdir llvm-<version>\build
cd build
cmake ..
cmake --build .

Once the build is done, we can find lli.exe under llvm-<version>\build\bin\Debug\.

Raspbian

Install Clang:

sudo apt-get install clang

Choose a Clang version:

sudo apt-get install clang-<version number>

Install LLVM

sudo apt-get install llvm

Can we run the bc file built with Clang for Windows on Raspbian? I got the following error message:

lli: hello.bc: error: Invalid type for value

Not like Java bytecode, we cannot run one copy of LLVM bitcode directly on all platforms. But, we can compile the bc file to native code with Clang:

clang hello.bc -o hello

llvm clang raspbian

MacOS

Use Homebrew to Install LLVM:

brew install LLVM

Export the path to ~/.bashrc:

export PATH=/usr/local/opt/llvm/bin:$PATH

Compile hello.bc file on macOS:

llvm clang macos

Emscripten vs. LLVM

The backend of Emscripten is called Fastcomp, which is Implemented as an LLVM backend. Its role is to convert the LLVM Intermediate Representation (IR) created by Clang (from C/C++) into JavaScript.

Assume we have a C/C++ library built with Clang, can we convert it directly to JavaScript file with Emscripten? I do hope so, but the fact is no.

G:\llvm>emcc hello.bc -o hello.js

error: Invalid type for value

error: Invalid type for value

Traceback (most recent call last):

  File "E:\Program Files\Emscripten\emscripten\1.35.0\\emcc", line 1309, in <module>

    final = shared.Building.llvm_opt(final, link_opts, DEFAULT_FINAL)

  File "E:\Program Files\Emscripten\emscripten\1.35.0\tools\shared.py", line 1471, in llvm_opt

    assert os.path.exists(target), 'Failed to run llvm optimizations: ' + output

AssertionError: Failed to run llvm optimizations:

Here is the reason:

The backend is still too new to be in the upstream LLVM repository. As such, builds from Linux distributions will not contain Fastcomp, and Emscripten will report an error if you try to use them.

We can compare the bc files that generated by emcc and Clang.

compare bc file

Because Emscripten has the gene of LLVM, Clang can compile the bc file built with emcc:

emcc hello.c -o hello.bc
clang hello.bc -o hello.exe
> hello.exe
hello world