Create a gist now

Instantly share code, notes, and snippets.

Embed
What would you like to do?
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