llvm_wrap/
lib.rs

1//! A safer wrapper for the LLVM C API bindings in Rust, based on `llvm-sys`
2//!
3//! ## Notes on Safety
4//!
5//! Although there are no `unsafe` blocks needed to use this library, it does ignore some of Rust's
6//! constraints on memory management. Mainly, immutable references can still be modified in order
7//! to make certain programs more simple.
8//!
9//! To make things simple, `LLVMBuilder` and `LLVMModule` are disposed automatically when they leave
10//! scope. Values and types are always created in the default global context provided by LLVM.
11//!
12//! If necessary, it is possible to use the `inner` function to access the wrapped value, or
13//! `into_inner` to destroy the wrapper without disposing the contained value. Most types can also
14//! dereference into their C equivalents. This crate is still in development and many features are
15//! not fully supported, so use this if you need to use unsupported LLVM functions. Use `into_c`
16//! and `from_c` to make strings easier to work with when dealing directly with the C API.
17//!
18//! ## Setup
19//!
20//! This crate relies heavily on `llvm-sys` and requires the same setup. Before using this crate,
21//! be sure to install a version of LLVM 5 and add `LLVM_SYS_50_PREFIX=/path/to/llvm` to your `PATH`
22//! environment variable.
23//!
24//! [LLVM Documentation] | [LLVM Language Reference] | [Rust Bindings]
25//!
26//! ## Example
27//!
28//! ```
29//! # extern crate llvm_wrap as llvm;
30//! # use llvm::*;
31//! # use llvm::types::*;
32//! # fn main() {
33//! // Create a module
34//! let module = create_module("add");
35//! // Create a builder
36//! let builder = create_builder();
37//!
38//! // Get an `i32 (i32, i32)` type
39//! let ty = ty_i32().function(vec![ty_i32(); 2], false);
40//! // Create the add function
41//! let def = module.add_function("add", ty);
42//! // Add an entry block
43//! let entry = def.append_basic_block("entry");
44//! // Move the builder to the end of the block
45//! builder.position_at_end(entry);
46//! // Add and name the two parameters
47//! let result = builder.build_int_add(
48//!     def.param(0).name("a"),
49//!     def.param(1).name("b"),
50//! );
51//! // Return and name the result
52//! builder.build_ret(result.name("tmp"));
53//!
54//! // Dump the contents of the module
55//! module.dump();
56//! # }
57//! ```
58//!
59//! ## Output
60//!
61//! ```text
62//! ; ModuleID = 'add'
63//! source_filename = "add"
64//!
65//! define i32 @add(i32 %a, i32 %b) {
66//! entry:
67//!   %tmp = add i32 %a, %b
68//!   ret i32 %tmp
69//! }
70//! ```
71//!
72//! [LLVM Documentation]: http://releases.llvm.org/5.0.0/docs/index.html
73//! [LLVM Language Reference]: http://releases.llvm.org/5.0.0/docs/LangRef.html
74//! [Rust Bindings]: http://rustdoc.taricorp.net/llvm-sys/llvm_sys
75
76#![deny(missing_docs)]
77
78extern crate llvm_sys;
79
80use llvm_sys::prelude::*;
81use llvm_sys::core::*;
82use llvm_sys::*;
83
84use std::ffi::{CStr, CString};
85use std::ops::Deref;
86use std::fmt::{self, Debug, Display};
87
88mod context;
89mod module;
90mod builder;
91mod ty;
92mod bb;
93mod val;
94mod cc;
95mod link;
96
97pub mod iter;
98pub mod target;
99pub mod types;
100
101/// Provides functions for using the C API
102pub mod c_api {
103    use super::*;
104
105    /// Returns the global `LLVMContextRef`
106    pub unsafe fn context() -> LLVMContextRef {
107        LLVMGetGlobalContext()
108    }
109
110    /// Create a wrapper for a type
111    pub unsafe fn ty(ty: LLVMTypeRef) -> Type {
112        Type {
113            ty,
114        }
115    }
116
117    /// Create a wrapper for a value
118    pub unsafe fn value(value: LLVMValueRef) -> Value {
119        Value {
120            value,
121        }
122    }
123
124    /// Converts a `String` into a `CString`
125    ///
126    /// This function will also work with other, similar inputs like `&str` literals or
127    /// `String` references. Use the `as_ptr` method to pass a pointer to a C function.
128    pub fn into_c<S: AsRef<str>>(string: S) -> CString {
129        CString::new(string.as_ref()).expect("invalid name")
130    }
131
132    /// Converts a `*const i8` into a `String`, if possible
133    ///
134    /// Returns `Some` if the pointer isn't null and points to a valid, non-empty string and
135    /// returns `None` otherwise.
136    pub fn from_c(string: *const i8) -> Option<String> {
137        if !string.is_null() {
138            unsafe {
139                if let Ok(string) = CStr::from_ptr(string).to_str() {
140                    if !string.is_empty() {
141                        return Some(string.to_string());
142                    }
143                }
144            }
145        }
146        None
147    }
148
149    #[doc(inline)]
150    pub use llvm_sys::prelude::{
151        LLVMValueRef,
152        LLVMTypeRef,
153        LLVMContextRef,
154        LLVMBuilderRef,
155        LLVMModuleRef,
156        LLVMBasicBlockRef
157    };
158
159    #[doc(inline)]
160    pub use llvm_sys::core as llvm_core;
161}
162
163#[doc(inline)]
164pub use context::*;
165#[doc(inline)]
166pub use module::Module;
167#[doc(inline)]
168pub use builder::Builder;
169#[doc(inline)]
170pub use ty::Type;
171#[doc(inline)]
172pub use bb::BasicBlock;
173#[doc(inline)]
174pub use val::Value;
175#[doc(inline)]
176pub use cc::CallConv;
177#[doc(inline)]
178pub use link::Linkage;
179
180/// Converts a `Vec<Value>` into a `Vec<LLVMValueRef>`
181fn val_vec(vals: &Vec<Value>) -> Vec<LLVMValueRef> {
182    vals.iter().map(|i| i.value).collect()
183}
184
185/// Converts a `Vec<Type>` into a `Vec<LLVMTypeRef>`
186fn ty_vec(types: &Vec<Type>) -> Vec<LLVMTypeRef> {
187    types.iter().map(|i| i.ty).collect()
188}