Cranelift Documentation
A fast, reliable code generator focused on WebAssembly and written in Rust.
On this page
What is Cranelift?
Cranelift is an optimizing compiler backend developed by the Bytecode Alliance, written in Rust. Unlike traditional compiler backends such as LLVM that focus primarily on ahead-of-time compilation, Cranelift specifically targets just-in-time compilation with an explicit goal of achieving short compile times.
The project started in 2016 (formerly known as Cretonne) and has evolved into a robust, secure, and relatively simple compiler framework that converts target-independent intermediate representations into executable machine code. Cranelift currently supports multiple instruction set architectures including x86-64, AArch64, RISC-V, and IBM z/Architecture.
Quick Info
- Project: Cranelift
- Organization: Bytecode Alliance
- Language: Rust
- Focus: Just-in-Time (JIT) compilation
- Architectures: x86-64, AArch64, RISC-V, IBM z/Architecture
- GitHub: bytecodealliance/wasmtime/cranelift
Key Features
Fast Compilation
Optimized for short compilation times, making it ideal for just-in-time compilation scenarios.
Multiple ISA Support
Supports x86-64, AArch64, RISC-V, and IBM z/Architecture with a unified backend structure.
SIMD Support
Comprehensive support for vectorized operations across supported architectures.
Security-Focused
Built with security considerations from the ground up, essential for WebAssembly use cases.
CLIF IR
A target-independent intermediate representation designed for efficient compilation.
ISLE DSL
Instruction Selection Language for simplified backend development and maintenance.
Cranelift vs. LLVM
Feature | Cranelift | LLVM |
---|---|---|
Primary Focus | JIT compilation speed | Thorough optimization |
Implementation Language | Rust | C++ |
Code Size | Smaller (~100K LOC) | Larger (~1M+ LOC) |
Compilation Speed | Faster | Slower |
Code Quality | Good | Excellent |
Memory Usage | Lower | Higher |
Target Architecture Support | 4 primary targets | Many targets |
Supported Architectures
Cranelift supports the following target architectures:
x86-64
Full support for x86-64 architecture with a focus on modern instruction set extensions like AVX and SSE.
AArch64
Support for ARM 64-bit architecture with NEON SIMD operations and other ARMv8 features.
RISC-V
Support for the open RISC-V instruction set architecture, including RV64GC features.
IBM z/Architecture
Support for s390x mainframe architecture with vector facility.
Getting Started
To use Cranelift in your Rust project, add the appropriate crates to your Cargo.toml
:
[dependencies]
cranelift = "0.100.0"
cranelift-module = "0.100.0"
cranelift-jit = "0.100.0"
Here's a simple example of using Cranelift to generate a function that adds two integers:
use cranelift::prelude::*;
use cranelift_module::{Linkage, Module};
use cranelift_jit::{JITBuilder, JITModule};
// Create JIT instance
let mut builder = JITBuilder::new(cranelift_module::default_libcall_names());
let mut module = JITModule::new(builder);
let mut ctx = module.make_context();
// Define the function signature
let mut sig = module.make_signature();
sig.params.push(AbiParam::new(types::I32));
sig.params.push(AbiParam::new(types::I32));
sig.returns.push(AbiParam::new(types::I32));
// Create the function and build it
let func_id = module.declare_function("add", Linkage::Export, &sig).unwrap();
ctx.func.signature = sig;
let mut func = Function::with_name_signature(ExternalName::user(0, 0), sig);
let mut builder_ctx = FunctionBuilderContext::new();
let mut builder = FunctionBuilder::new(&mut func, &mut builder_ctx);
// Build the function body
let block0 = builder.create_block();
builder.append_block_params_for_function_params(block0);
builder.switch_to_block(block0);
let param0 = builder.block_params(block0)[0];
let param1 = builder.block_params(block0)[1];
let sum = builder.ins().iadd(param0, param1);
builder.ins().return_(&[sum]);
builder.finalize();
// Finalize and execute
module.define_function(func_id, &ctx).unwrap();
module.finalize_definitions().unwrap();
// Get and call the JIT-compiled function
let code = module.get_finalized_function(func_id);
let add = unsafe { std::mem::transmute::<_, fn(i32, i32) -> i32>(code) };
let result = add(5, 6);
assert_eq!(result, 11);
Important Note
The std::mem::transmute
function used in this example is unsafe. In production code, ensure you're managing memory safely and following Rust's safety guidelines.
Quick Start Steps
Add dependencies
Include Cranelift crates in your Cargo.toml file
Create a JIT compiler
Initialize the JIT module and context
Define function signature
Create the function type with parameters and return types
Build the function
Use the function builder to construct the function body
Compile and execute
Finalize the function and call it
Architecture
Cranelift uses a multi-phase compilation pipeline that balances compilation speed with code quality. The design prioritizes modularity, allowing different parts of the pipeline to be reused or replaced as needed.
Compilation Pipeline
Performance
Cranelift is designed with performance in mind, particularly focusing on compilation speed over absolute code quality. This makes it especially suitable for JIT compilation scenarios where compilation time is part of the end-user experience.
Compilation Time Comparison
Cranelift vs. LLVM (lower is better)
Key Performance Characteristics
- Fast compilation times - 3-5x faster than LLVM for many workloads
- Lower memory footprint - Uses significantly less memory during compilation
- Good but not optimal code quality - Generated code performs well but prioritizes compilation speed over maximum optimization
- Predictable latency - More consistent compilation times across different code patterns
Examples
Explore these examples to understand how to use Cranelift in different scenarios.
Community
Cranelift is developed as part of the Bytecode Alliance, a nonprofit organization dedicated to creating secure new software foundations built on WebAssembly and WebAssembly System Interface (WASI).
GitHub Repository
Source code, issues, and pull requests
Zulip Chat
Real-time discussions with developers
Bytecode Alliance
Parent organization website
API Documentation
Detailed API reference on docs.rs
How to Contribute
Find an Issue
Look for issues labeled with "good first issue" or "help wanted"
Join the Discussion
Engage in Zulip chat to discuss your intended contributions
Submit a PR
Fork the repository, make changes, and submit a pull request
Review Process
Work with maintainers to refine your contribution
Frequently Asked Questions
What is the difference between Cranelift and LLVM?
Cranelift and LLVM have different design goals. LLVM prioritizes generating the most optimized code possible, often at the expense of compilation time. Cranelift, on the other hand, focuses on fast compilation times for just-in-time compilation scenarios, with good but not exhaustive optimizations.
Cranelift is also written in Rust (versus LLVM's C++), has a smaller codebase, and is designed with a focus on security and WebAssembly compilation use cases.
Which architectures does Cranelift support?
Cranelift currently supports:
- x86-64
- AArch64 (ARM 64-bit)
- RISC-V
- IBM z/Architecture (s390x)
Support for additional architectures is planned or in development.
How do I use Cranelift in my Rust project?
To use Cranelift in a Rust project, add the appropriate crates to your Cargo.toml:
[dependencies]
cranelift = "0.100.0"
cranelift-module = "0.100.0"
cranelift-jit = "0.100.0"
You can then use Cranelift to generate code at runtime. The cranelift-jit crate provides a simple API for JIT compilation.
Is Cranelift used in any production systems?
Yes, Cranelift is used in several production systems:
- Wasmtime - A standalone WebAssembly runtime
- Fastly's Compute@Edge - A serverless compute platform
- Firefox - Used for some WebAssembly compilation
- Various WebAssembly-based projects - Including blockchain systems and edge computing platforms
What is ISLE and how is it used in Cranelift?
ISLE (Instruction Selection/Lowering Expressions) is a domain-specific language (DSL) used in Cranelift for instruction selection during code generation. It allows Cranelift developers to write declarative rules for matching and transforming IR patterns into target-specific machine instructions.
ISLE makes it easier to develop and maintain different architecture backends by providing a concise, declarative way to specify instruction selection rules. This approach helps ensure correctness and reduces the complexity of backend code.