🌐
LLVM
llvm.org › docs › tutorial › MyFirstLanguageFrontend › index.html
My First Language Frontend with LLVM Tutorial — LLVM 23.0.0git documentation
Chapter #7: Extending the Language: Mutable Variables - This chapter talks about adding user-defined local variables along with an assignment operator. This shows how easy it is to construct SSA form in LLVM: LLVM does not require your front-end to construct SSA form in order to use it!
🌐
GitHub
github.com › learn-llvm › awesome-llvm
GitHub - learn-llvm/awesome-llvm: A curated list of awesome LLVM (including Clang, etc) related resources. · GitHub
llvm/Polygeist - C/C++ frontend for MLIR · j2kun/mlir-tutorial - a series of articles on the MLIR framework for building compilers · Lewuathe/mlir-hello - minimal Hello-World example of MLIR · melior - The rustic MLIR bindings in Rust; see also introduction blog post ·
Starred by 717 users
Forked by 54 users
Languages   Python 76.7% | Shell 22.1% | Vim Script 1.2%
🌐
LLVM
llvm.org › docs › tutorial
LLVM Tutorial: Table of Contents — LLVM 23.0.0git documentation
This is the “Kaleidoscope” Language tutorial, showing how to implement a simple language using LLVM components in C++.
🌐
LLVM
llvm.org › docs › GettingStarted.html
Getting Started with the LLVM System — LLVM 23.0.0git documentation
Build configuration for llvm user defined options. Checks compiler version and linker flags. ... Toolchain configuration for Android NDK, iOS systems and non-Windows hosts to target MSVC. Some simple examples showing how to use LLVM as a compiler for a custom language - including lowering, optimization, and code generation.
🌐
mcyoung
mcyoung.xyz › 2023 › 08 › 01 › llvm-ir
A Gentle Introduction to LLVM IR · mcyoung
Although you could represent this operation with a chain of brs, a separate switch instruction makes it easier for LLVM to generate jump tables. unreachable, which we saw before, is a special terminator that does not trigger control flow per se, but which can terminate a block because reaching it is undefined behavior; it is equivalent to e.g. std::unreachable() in C++. ... The unreachable instruction provides a good example of why LLVM uses a basic block CFG: a naive dead code elimination (DCE) optimization pass can be implemented as follows:
🌐
LLVM
llvm.org › docs › LangRef.html
LLVM Language Reference Manual — LLVM 23.0.0git documentation
May 12, 2026 - Reserved words in LLVM are very similar to reserved words in other languages. There are keywords for different opcodes (’add’, ‘bitcast’, ‘ret’, etc…), for primitive type names (’void’, ‘i32’, etc…), and others. These reserved words cannot conflict with variable names, because none of them start with a prefix character ('%' or '@'). Here is an example of LLVM code to multiply the integer variable ‘%X’ by 8:
🌐
GitHub
github.com › shining1984 › llvm-examples
GitHub - shining1984/llvm-examples: The repo is to keep some examples of the LLVM. Some of them are moved from llvm/examples, and others are writen by myself. · GitHub
This example is moved from the llvm3.5 release version. I just wrote a make file for it, let it can be run on the outside of the llvm. Before you run this example, you must make sure you have install llvm on your computer. If you use the source code to install llvm, please don't forget to use the command "make install" after you build llvm.
Starred by 7 users
Forked by 2 users
Languages   C++ 87.1% | Makefile 12.9%
🌐
LLVM
llvm.org › docs › WritingAnLLVMBackend.html
Writing an LLVM Backend — LLVM 23.0.0git documentation
To write a compiler backend for LLVM that converts the LLVM IR to code for a specified target (machine or other language), follow these steps: Create a subclass of the TargetMachine class that describes characteristics of your target machine. Copy existing examples of specific TargetMachine class and header files; for example, start with SparcTargetMachine.cpp and SparcTargetMachine.h, but change the file names for your target.
Find elsewhere
🌐
Tomassetti
tomassetti.me › home › a tutorial on how to write a compiler using llvm
A tutorial on how to write a compiler using LLVM - Strumenta
October 28, 2020 - The LLVM API provides the methods to create and invoke functions defined within the module. It is possible to invoke external functions implemented in a library such as the standard C library function printf. To call the printf function from the IR it is required to provide the function definition and provide the parameters required. The RPG code below implements the algorithm to compute the Fibonacci’s number taken from an example provided by Franco Lombardo available in the Jariko GitHub repository.
🌐
Mukulrathi
mukulrathi.com › blog › a complete guide to llvm for programming language creators
A Complete Guide to LLVM for Programming Language Creators
December 24, 2020 - It is of the form phi type [val1, ... In the example above, we set %iftmp to 1 if we’ve come from the then block, and %mult if we’ve come from the else block. Phi nodes must be at the start of a block, and include one entry for each predecessor. Taking another step back, the overall structure of a function in LLVM IR is as ...
🌐
GitHub
github.com › nsumner › llvm-demo
GitHub - nsumner/llvm-demo: A simple example of how LLVM can be used to gather static or dynamic facts about a program.
A simple example of how LLVM can be used to gather static or dynamic facts about a program. - nsumner/llvm-demo
Starred by 73 users
Forked by 23 users
Languages   C++ 83.2% | CMake 16.2% | C 0.6% | C++ 83.2% | CMake 16.2% | C 0.6%
🌐
LLVM
llvm.org › doxygen › examples.html
LLVM: Examples
Here is a list of all examples: /home/buildbot/as-worker-4/publish-doxygen-docs/llvm-project/llvm/include/llvm/ADT/ilist_node.h · /home/buildbot/as-worker-4/publish-doxygen-docs/llvm-project/llvm/include/llvm/Transforms/Utils/Local.h ·
🌐
GitHub
github.com › michelou › llvm-examples
GitHub - michelou/llvm-examples: Running and building LLVM on Windows · GitHub
C:\opt\cmake\ ( 106 MB) C:\opt\ConEmu\ ( 26 MB) C:\opt\doxygen\ ( 118 MB) C:\opt\Git\ ( 358 MB) C:\opt\LLVM-8.0.1\ (1.1 GB) C:\opt\LLVM-9.0.1\ (1.3 GB) C:\opt\LLVM-10.0.1\ (1.5 resp 2.6 GB) C:\opt\LLVM-11.1.0\ (1.5 resp 3.0 GB) C:\opt\LLVM-12.0.1\ (1.5 resp 3.7 GB) C:\opt\LLVM-14.0.6\ (2.1 resp 3.1 GB) C:\opt\LLVM-15.0.7\ (3.1 GB) C:\opt\LLVM-16.0.6\ (2.5 GB) C:\opt\msys64\ (2.85 GB) C:\opt\ninja-1.11.1\ ( 0.5 MB) C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\ (2.98 GB) C:\opt\Python-3.11.1\ ( 61 MB)
Starred by 45 users
Forked by 2 users
Languages   C++ 99.6% | C 0.4%
🌐
Cornell Computer Science
cs.cornell.edu › ~asampson › blog › llvm.html
Adrian Sampson: LLVM for Grad Students
August 3, 2015 - I encourage you to reach for LLVM by default before hacking any of these tools unless you have a really good reason: ... source-level transformation (from simple stuff like sed to more complete tools involving AST parsing and serialization) ... Even if a compiler doesn’t seem like a perfect match for your task, it can often get you 90% of the way there far easier than, say, a source-to-source translation. Here are some nifty examples of research projects that used LLVM to do things that are not all that compilery:
🌐
LLVM
llvm.org › docs › ProgrammersManual.html
LLVM Programmer’s Manual — LLVM 23.0.0git documentation
StringRef is small and pervasive enough in LLVM that it should always be passed by value. The Twine (doxygen) class is an efficient way for APIs to accept concatenated strings. For example, a common LLVM paradigm is to name one instruction based on the name of another instruction with a suffix, for example:
🌐
Reddit
reddit.com › r/programming › a complete guide to llvm for programming language creators (diagrams + code)
r/programming on Reddit: A Complete Guide to LLVM for Programming Language Creators (diagrams + code)
December 24, 2020 - Note how the names of the blocks (entry, for.cond, for.body, if.then, if.end, for.inc, for.end, return) and the names of the variables (e.g., idxprom, arrayidx, inc, cmp, retval) already give a good idea of what a given value represents. In contrast, here's an example with discarded value names: https://llvm.godbolt.org/z/GrG4cx (without -fno-discard-value-names we only get numerical identifiers).
🌐
Wikipedia
en.wikipedia.org › wiki › LLVM
LLVM - Wikipedia
3 weeks ago - The type system consists of basic types such as integer or floating-point numbers and five derived types: pointers, arrays, vectors, structures, and functions. A type construct in a concrete language can be represented by combining these basic types in LLVM. For example, a class in C++ can ...
Top answer
1 of 2
6

So, I've digged through the KaleidoscopeJIT and retrieved the most important pieces. First of all note that I'm using llvm-4.0. I've had lots of issues by not realizing how really incompatible 4.0 and lower versions are.

The code works with C++11. I'm using clang++-4.0 with following compilation flags:

llvm-config-4.0 --cxxflags --ldflags --system-libs --libs core engine

And now the entire code:

#include <string>
#include <vector>
#include <iostream>
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/IRBuilder.h"
#include "llvm/IR/Verifier.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/RTDyldMemoryManager.h"
#include "llvm/ExecutionEngine/RuntimeDyld.h"
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
#include "llvm/ExecutionEngine/Orc/CompileUtils.h"
#include "llvm/ExecutionEngine/Orc/IRCompileLayer.h"
#include "llvm/ExecutionEngine/Orc/LambdaResolver.h"
#include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h"
#include "llvm/ExecutionEngine/JITSymbol.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Mangler.h"
#include "llvm/Support/DynamicLibrary.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/TargetSelect.h"

using namespace llvm;
typedef orc::ObjectLinkingLayer<> ObjLayerT;
typedef orc::IRCompileLayer<ObjLayerT> CompileLayerT;

static LLVMContext Context;
static auto MyModule = make_unique<Module>("my compiler", Context);

Function *createFunc(IRBuilder<> &Builder, std::string Name) {
    std::vector<Type*> Integers(2, Builder.getInt32Ty());
    auto *funcType = FunctionType::get(Builder.getInt32Ty(), Integers, false);
    auto *fooFunc = Function::Create(funcType, Function::ExternalLinkage, Name, MyModule.get());
    return fooFunc;
};

void updateBody(Function *fooFunc, IRBuilder<> &Builder) {
    auto *entry = BasicBlock::Create(Context, "entry", fooFunc);
    Builder.SetInsertPoint(entry);
    auto args = fooFunc->arg_begin();
    Value *arg1 = &(*args);
    args = std::next(args);
    Value *arg2 = &(*args);
    auto *sum = Builder.CreateAdd(arg1, arg2, "tmp");
    Builder.CreateRet(sum);
};

int main(int argc, char* argv[]) {
    // Prepare the module
    static IRBuilder<> Builder(Context);
    auto *fooFunc = createFunc(Builder, "sum");
    updateBody(fooFunc, Builder);
    verifyFunction(*fooFunc);

    // Initilaze native target
    InitializeNativeTarget();
    InitializeNativeTargetAsmPrinter();
    InitializeNativeTargetAsmParser();

    // Prepare jit layer
    ObjLayerT ObjectLayer;
    std::unique_ptr<TargetMachine> TM(EngineBuilder().selectTarget());
    DataLayout DL(TM->createDataLayout());
    CompileLayerT CompileLayer(ObjectLayer, orc::SimpleCompiler(*TM));
    auto Resolver = orc::createLambdaResolver(
        & {
            if (auto Sym = CompileLayer.findSymbol(Name, false))
                return Sym;
            return JITSymbol(nullptr);
        },
         { return nullptr; }
    );

    // Add MyModule to the jit layer
    std::vector<std::unique_ptr<Module>> Modules;
    Modules.push_back(std::move(MyModule));
    CompileLayer.addModuleSet(
        std::move(Modules),
        make_unique<SectionMemoryManager>(),
        std::move(Resolver)
    );

    // Retrieve the foo symbol
    std::string MangledName;
    raw_string_ostream MangledNameStream(MangledName);
    Mangler::getNameWithPrefix(MangledNameStream, "sum", DL);
    auto Sym = CompileLayer.findSymbol(MangledNameStream.str(), true);

    // Cast to function
    auto func = (int(*)(int, int))Sym.getAddress();

    // Try it
    std::cout << func(5, 7) << std::endl;

    return 0;
}

I'm not sure if all includes are needed but anyway it works like a charm. Although I'm looking forward for any comment on how to improve it. :)

2 of 2
0

Using the provided KaleidoscopeJIT.h this is pretty straightforward (I'm using LLVM 4.0.0 in this example):

// Your existing includes here.
#include "llvm/Support/TargetSelect.h" // For InitializeNativeTarget() etc.
#include "KaleidoscopeJIT.h" 

int main() {
    // Your existing main body here.

    InitializeNativeTarget();
    InitializeNativeTargetAsmPrinter();
    InitializeNativeTargetAsmParser();

    orc::KaleidoscopeJIT jit;
    MyModule->setDataLayout(jit.getTargetMachine().createDataLayout());
    auto moduleHandle = jit.addModule(std::move(MyModule)); // JIT-compile MyModule.
    auto symbol = jit.findSymbol("sum"); // Get the compiled sum function.
    auto sumFunc = (int(*)(int, int)) symbol.getAddress(); // Cast it.
    auto result = sumFunc(42, 42); // Call it.
    assert(result == 84); // Voilà.
}
🌐
Anoopsarkar
anoopsarkar.github.io › compilers-class › llvm-practice.html
LLVM Practice - SFU Compilers class
In the llvm-practice directory of the compiler-class-hw repository you can find two example C++ programs: globalscalar.cc and globalarray.cc for global scalar variables and global array variables respectively.
🌐
GitHub
github.com › banach-space › llvm-tutor
GitHub - banach-space/llvm-tutor: A collection of out-of-tree LLVM passes for teaching and learning · GitHub
The HelloWorld pass from HelloWorld.cpp is a self-contained reference example. The corresponding CMakeLists.txt implements the minimum set-up for an out-of-source pass. For every function defined in the input module, HelloWorld prints its name and the number of arguments that it takes. You can build it like this: export LLVM_DIR=<installation/dir/of/llvm/22> mkdir build cd build cmake -DLT_LLVM_INSTALL_DIR=$LLVM_DIR <source/dir/llvm/tutor>/HelloWorld/ make
Starred by 3.4K users
Forked by 447 users
Languages   C++ 52.3% | LLVM 33.3% | CMake 4.9% | C 4.5% | Shell 3.7% | Python 1.3%