Skip to content

Instantly share code, notes, and snippets.

@iwillspeak
Last active July 30, 2023 08:40
Show Gist options
  • Save iwillspeak/1fed07333f7187c25735e90d73b82468 to your computer and use it in GitHub Desktop.
Save iwillspeak/1fed07333f7187c25735e90d73b82468 to your computer and use it in GitHub Desktop.
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) }
}
@iwillspeak
Copy link
Author

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

@re-masashi
Copy link

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

Previously llvm-sys was called llvm_sys this error seems ot have happened for that reason.

@iwillspeak
Copy link
Author

This is old code. Previously I think rust normalised crate names when converting them to crate identifiers. Characters such as - in names became _ in the identifier.

As I say. Old code.

@Toni-Graphics
Copy link

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

Then when i try cargo build i get this error:

error[E0433]: failed to resolve: use of undeclared crate or module `llvm_sys`
 --> src\main.rs:7:5
  |
7 | use llvm_sys::prelude::*;
  |     ^^^^^^^^ use of undeclared crate or module `llvm_sys`

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