Create a gist now

Instantly share code, notes, and snippets.

Example of using LLVM from Rust

An Example of Using LLVM from Rust

This example compiles a simple function using the LLVM C API through the llvm-sys crate.

[root]
name = "low_down"
version = "0.1.0"
dependencies = [
"llvm-sys 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "bitflags"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "gcc"
version = "0.3.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libc"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "llvm-sys"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gcc 0.3.37 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)",
"semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "semver"
version = "0.1.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum bitflags 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4f67931368edf3a9a51d29886d245f1c3db2f1ef0dcc9e35ff70341b78c10d23"
"checksum gcc 0.3.37 (registry+https://github.com/rust-lang/crates.io-index)" = "41337e9dc80ebadf36b4f252bf7440f61bcf34f99caa170e50dcd0f9a0cdb5d8"
"checksum libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "044d1360593a78f5c8e5e710beccdc24ab71d1f01bc19a29bcacdba22e8475d8"
"checksum llvm-sys 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "53757e4a2a442608cd0c9d50b555695e299a459a94dc25970d60dc5bc5674449"
"checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac"
[package]
name = "low_down"
version = "0.1.0"
authors = ["Will Speak <will@willspeak.me>"]
[[bin]]
name = "low_down"
path = "main.rs"
[dependencies]
llvm-sys = "*"
//! Example of Using LLVM from Rust
extern crate llvm_sys;
use std::ffi::CStr;
use llvm_sys::prelude::*;
use llvm_sys::{core, target};
/// Initialise LLVM
///
/// Makes sure that the parts of LLVM we are going to use are
/// initialised before we do anything with them.
fn initialise_llvm() {
unsafe {
if target::LLVM_InitializeNativeTarget() != 0 {
panic!("Could not initialise target");
}
if target::LLVM_InitializeNativeAsmPrinter() != 0 {
panic!("Could not initialise ASM Printer");
}
}
}
/// Compile Module
///
/// Creates a new LLVM module and compiles a simple funciton in it.
fn compile() -> LLVMModuleRef {
// Create a module to compile the expression into
let mod_name = CStr::from_bytes_with_nul(b"hello\0").unwrap();
let module = unsafe { core::LLVMModuleCreateWithName(mod_name.as_ptr()) };
// Create a function type and add a function of that type to the module
let function_type = unsafe {
let int64 = core::LLVMInt64Type();
let mut param_types = [int64, int64];
core::LLVMFunctionType(int64, param_types.as_mut_ptr(), param_types.len() as u32, 0)
};
let function_name = CStr::from_bytes_with_nul(b"test\0").unwrap();
let function =
unsafe { core::LLVMAddFunction(module, function_name.as_ptr(), function_type) };
// Create a basic block and add it to the function
let block_name = CStr::from_bytes_with_nul(b"entry\0").unwrap();
let entry_block = unsafe { core::LLVMAppendBasicBlock(function, block_name.as_ptr()) };
// Create an LLVM instruction builder and position it at our new
// basic block
let builder = unsafe {
let b = core::LLVMCreateBuilder();
core::LLVMPositionBuilderAtEnd(b, entry_block);
b
};
// Fill in the body of the function.
unsafe {
let a = core::LLVMGetParam(function, 0);
let b = core::LLVMGetParam(function, 1);
let temp_name = CStr::from_bytes_with_nul(b"temp.1\0").unwrap();
let res = core::LLVMBuildAdd(builder, a, b, temp_name.as_ptr());
core::LLVMBuildRet(builder, res);
}
// Clean up the builder now that we are finished using it.
unsafe { core::LLVMDisposeBuilder(builder) }
module
}
fn main() {
initialise_llvm();
let module = compile();
// Dump the LLVM IR to stdout so we can see what we've created
unsafe { core::LLVMDumpModule(module) }
// Clean up the module after we're done with it.
unsafe { core::LLVMDisposeModule(module) }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment