It’s a New Kind of Glue for LLVM IR Design & Execution
Inkglide offers lightweight, type-safe Swift wrappers for the LLVM C APIs, allowing for safe and performant access to LLVM. Inkglide relies heavily on Swift’s ownership semantics and noncopyable types to ensure safety and correctness, so it’s recommended to be familiar with these concepts in Swift before using this library.
Inkglide takes inspiration from multiple sources, including but limited to: Inkwell, Swifty-LLVM, LLVMSwift
See also: swift-llvm-bindings
- Swift 6.2
- LLVM 21
- Install LLVM 21
- Install pkg-config
- Create an
llvm.pcfile with the following template:
prefix=/path/to/llvm/installation
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
Name: LLVM
Description: LLVM Compiler Infrastructure
Version: 21
Libs: -L${libdir} -lLLVM
Cflags: -I${includedir}
-
Save this file to a
pkgconfigdirectory (e.g.,~/.pkgconfig/or/usr/local/lib/pkgconfig/) -
Add the pkgconfig directory to your environment:
export PKG_CONFIG_PATH=/path/to/pkgconfig:$PKG_CONFIG_PATH- Build and run:
swift build -c release
swift test -c release- macOS only: If using Homebrew's LLVM, you may need to set the library path for Z3 (an LLVM dependency):
export DYLD_LIBRARY_PATH="/opt/homebrew/opt/z3/lib:$DYLD_LIBRARY_PATH"Inkwell's example written with Inkglide:
import Inkglide
typealias SumFunc = @convention(c) (UInt64, UInt64, UInt64) -> UInt64
struct CodeGen: ~Copyable {
let context: Context
var module: Module
var builder: Builder
mutating func emitIR() {
let int64Type = self.context.int64Type()
let functionType = int64Type.functionType([int64Type, int64Type, int64Type], isVariadic: false)
let function = module.addFunction(name: "sum", type: functionType)
let basicBlock = self.context.appendBasicBlock(named: "entry", in: function)
self.builder.positionAtEnd(of: basicBlock)
let i = function.parameter(at: 0)!.intValue!
let j = function.parameter(at: 1)!.intValue!
let k = function.parameter(at: 2)!.intValue!
var sum = self.builder.buildIntAdd(i, j, name: "sum")
sum = self.builder.buildIntAdd(sum, k, name: "sum")
_ = self.builder.buildReturn(sum)
}
}
func main() throws {
let context = Context()
let module = Module(name: "sum", in: context)
let builder = Builder(in: context)
var codeGen = CodeGen(context: context, module: module, builder: builder)
codeGen.emitIR()
try Target.initializeNative()
var jit = try OrcJIT()
try jit.add(module: codeGen.module)
let sum = try jit.getFunction(named: "sum", as: SumFunc.self)
let i: UInt64 = 1
let j: UInt64 = 2
let k: UInt64 = 3
print("\(i) + \(j) + \(k) = \(sum(i, j, k))")
assert(sum(i, j, k) == i + j + k)
}