Skip to content

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) }
}
@jeudine

This comment has been minimized.

Copy link

@jeudine jeudine commented Aug 13, 2021

Hi,
I tried to compile your project (cargo build) with llvm-sys = "100" and I got the following error:

error[E0463]: can't find crate for `llvm_sys`
 --> main.rs:3:1
  |
3 | extern crate llvm_sys;
  | ^^^^^^^^^^^^^^^^^^^^^^ can't find crate

Do you know why I got this error and how to fix it?

EDIT:

Apparently, there is only an error with the latest stable release (1.54) but it works with 1.53

@iwillspeak

This comment has been minimized.

Copy link
Owner Author

@iwillspeak iwillspeak commented Aug 13, 2021

Not sure i'm afraid. I haven't built this code in quite some time. In my more recent code I
reference the llvm-10 package like this:

llvm-10 = { package = "llvm-sys", version = "100", optional = true }

https://github.com/iwillspeak/ullage/blob/464d73f28df781a543f2f6a7faec634fae1572c5/Cargo.toml#L19

And then import it like this:

#[cfg(feature = "llvm-10")] use llvm_10 as llvm_sys;

https://github.com/iwillspeak/ullage/blob/464d73f28df781a543f2f6a7faec634fae1572c5/src/low_loader.rs#L26

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment