21
Use LLVM by JavaScript/TypeScript
As a developer, have you ever wanted to implement your own compiler in the past?
Fortunately, in 2021, implementing a compiler is no longer a difficult task because of LLVM Website.
LLVM is a set of compiler infrastructure projects, a compiler framework. Both Rust and Swift use LLVM as their compiler backend.
Everyone can implement their own compiler based on LLVM.
But... LLVM is written in C++, which means that if you want to use LLVM, you must also use C++. Not everyone likes C++.
So I developed a library called llvm-bindings to allow you to use LLVM by JavaScript. Of course, there is no problem using LLVM through TypeScript.
First, you need to install CMake and LLVM before llvm-bindings.
Install CMake and LLVM on macOS
brew install cmake llvm
Install CMake and LLVM on Ubuntu
sudo apt-get install cmake
sudo bash -c "$(wget -O - https://apt.llvm.org/llvm.sh)"
After making sure that CMake and LLVM are installed correctly on your system, you can install llvm-bindings
through npm.
npm install llvm-bindings
We will write all our code in a file called
demo.js
First, import llvm-bindings
const llvm = require('llvm-bindings');
Then, new a Context
, a Module
and a IR Builder
const context = new llvm.LLVMContext();
const mod = new llvm.Module('demo', context);
const builder = new llvm.IRBuilder(context);
We call this module
mod
because Node.js does not allow variables calledmodule
to be declared in the top level.
Then, build objects related to function signatures
const returnType = builder.getInt32Ty();
const paramTypes = [builder.getInt32Ty(), builder.getInt32Ty()];
const functionType = llvm.FunctionType.get(returnType, paramTypes, false);
const func = llvm.Function.Create(functionType, llvm.Function.LinkageTypes.ExternalLinkage, 'add', mod);
Then, build the basic blocks and instructions within the function
const entryBB = llvm.BasicBlock.Create(context, 'entry', func);
builder.SetInsertPoint(entryBB);
const a = func.getArg(0);
const b = func.getArg(1);
const result = builder.CreateAdd(a, b);
builder.CreateRet(result);
Finally, verify the function and the module, and print the LLVM IR of the entire module in text form
if (llvm.verifyFunction(func)) {
console.error('Verifying function failed');
return;
}
if (llvm.verifyModule(mod)) {
console.error('Verifying module failed');
return;
}
mod.print();
Now you have implemented a basic example of using LLVM through JavaScript, by executing node demo.js
, you can see:
llvm-bindings
provides developers with the ability to use LLVM through JavaScript/TypeScript. Friends who need to use llvm can try llvm-bindings.
llvm-bindings
is currently under development on demand. Maybe the LLVM API you need has not been added yet. You can submit an issue to request a new API. I will add it within one day of receiving the issue.
const llvm = require('llvm-bindings');
const context = new llvm.LLVMContext();
const mod = new llvm.Module('demo', context);
const builder = new llvm.IRBuilder(context);
const returnType = builder.getInt32Ty();
const paramTypes = [builder.getInt32Ty(), builder.getInt32Ty()];
const functionType = llvm.FunctionType.get(returnType, paramTypes, false);
const func = llvm.Function.Create(functionType, llvm.Function.LinkageTypes.ExternalLinkage, 'add', mod);
const entryBB = llvm.BasicBlock.Create(context, 'entry', func);
builder.SetInsertPoint(entryBB);
const a = func.getArg(0);
const b = func.getArg(1);
const result = builder.CreateAdd(a, b);
builder.CreateRet(result);
if (llvm.verifyFunction(func)) {
console.error('verifying the function failed');
return;
}
if (llvm.verifyModule(mod)) {
console.error('verifying the module failed');
return;
}
mod.print();
main();
Currently llvm-bindings
only supports macOS and Ubuntu systems, and Windows is not yet supported.
21