Skip to content

Commit

Permalink
Finished docs for int_type.rs
Browse files Browse the repository at this point in the history
  • Loading branch information
TheDan64 committed Sep 16, 2018
1 parent 020c0c3 commit 9c7d5ec
Show file tree
Hide file tree
Showing 5 changed files with 216 additions and 6 deletions.
4 changes: 1 addition & 3 deletions src/module.rs
Expand Up @@ -1253,9 +1253,7 @@ impl Module {

// Newer LLVM versions don't use an out ptr anymore which was really straightforward...
// Here we assign an error handler to extract the error message, if any, for us.
unsafe {
context.set_diagnostic_handler(get_error_str_diagnostic_handler, char_ptr_ptr);
}
context.set_diagnostic_handler(get_error_str_diagnostic_handler, char_ptr_ptr);

let code = unsafe {
LLVMLinkModules2(self.module.get(), other.module.get())
Expand Down
200 changes: 197 additions & 3 deletions src/types/int_type.rs
@@ -1,3 +1,5 @@
//! This module contains functions for working with `IntType`s and generating values from them.

use llvm_sys::core::{LLVMInt1Type, LLVMInt8Type, LLVMInt16Type, LLVMInt32Type, LLVMInt64Type, LLVMConstInt, LLVMConstNull, LLVMConstAllOnes, LLVMIntType, LLVMGetIntTypeWidth, LLVMConstIntOfStringAndSize, LLVMConstIntOfArbitraryPrecision, LLVMConstArray};
use llvm_sys::execution_engine::LLVMCreateGenericValueOfInt;
use llvm_sys::prelude::{LLVMTypeRef, LLVMValueRef};
Expand All @@ -9,6 +11,7 @@ use types::traits::AsTypeRef;
use types::{Type, ArrayType, BasicTypeEnum, VectorType, PointerType, FunctionType};
use values::{AsValueRef, ArrayValue, GenericValue, IntValue, PointerValue};

/// An `IntType` is the type of an integer constant or variable.
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub struct IntType {
int_type: Type,
Expand Down Expand Up @@ -201,8 +204,33 @@ impl IntType {
IntValue::new(value)
}

// TODOC: LLVM will parse as best as it can, without any error for invalid input
// ie ("012", 2) => int 1
/// Create an `IntValue` from a string and radix. LLVM provides no error handling here,
/// so this may produce unexpected results and should not be relied upon for validation.
///
/// # Example
///
/// ```no_run
/// use inkwell::context::Context;
///
/// let context = Context::new();
/// let i8_type = context.i8_type();
/// let i8_val = i8_type.const_int_from_string("0121", 10);
///
/// assert_eq!(i8_val.print_to_string().to_string(), "i8 121");
///
/// let i8_val = i8_type.const_int_from_string("0121", 3);
///
/// assert_eq!(i8_val.print_to_string().to_string(), "i8 16");
///
/// // Unexpected outputs:
/// let i8_val = i8_type.const_int_from_string("0121", 2);
///
/// assert_eq!(i8_val.print_to_string().to_string(), "i8 3");
///
/// let i8_val = i8_type.const_int_from_string("ABCD", 2);
///
/// assert_eq!(i8_val.print_to_string().to_string(), "i8 -15");
/// ```
pub fn const_int_from_string(&self, slice: &str, radix: u8) -> IntValue {
let value = unsafe {
LLVMConstIntOfStringAndSize(self.as_type_ref(), slice.as_ptr() as *const i8, slice.len() as u32, radix)
Expand All @@ -211,6 +239,17 @@ impl IntType {
IntValue::new(value)
}

/// Create a constant `IntValue` of arbitrary precision.
///
/// # Example
///
/// ```no_run
/// use inkwell::context::Context;
///
/// let context = Context::create();
/// let i64_type = context.i64_type();
/// let i64_val = context.const_int_arbitrary_precision(&[1, 2]);
/// ```
pub fn const_int_arbitrary_precision(&self, words: &[u64]) -> IntValue {
let value = unsafe {
LLVMConstIntOfArbitraryPrecision(self.as_type_ref(), words.len() as u32, words.as_ptr())
Expand Down Expand Up @@ -263,6 +302,20 @@ impl IntType {
self.int_type.const_null_ptr()
}

/// Creates a constant null (zero) value of this `IntType`.
///
/// # Example
///
/// ```no_run
/// use inkwell::context::Context;
///
/// let context = Context::create();
/// let i8_type = context.i8_type();
/// let i8_zero = i8_type.const_null();
///
/// assert!(i8_zero.is_null());
/// assert_eq!(i8_zero.print_to_string().to_string(), "i8 0");
/// ```
pub fn const_null(&self) -> IntValue {
let null = unsafe {
LLVMConstNull(self.as_type_ref())
Expand All @@ -271,59 +324,185 @@ impl IntType {
IntValue::new(null)
}

/// Creates a `FunctionType` with this `IntType` for its return type.
///
/// # Example
///
/// ```no_run
/// use inkwell::context::Context;
///
/// let context = Context::create();
/// let i8_type = context.i8_type();
/// let fn_type = i8_type.fn_type(&[], false);
/// ```
pub fn fn_type(&self, param_types: &[BasicTypeEnum], is_var_args: bool) -> FunctionType {
self.int_type.fn_type(param_types, is_var_args)
}

/// Creates an `ArrayType` with this `IntType` for its element type.
///
/// # Example
///
/// ```no_run
/// use inkwell::context::Context;
///
/// let context = Context::create();
/// let i8_type = context.i8_type();
/// let i8_array_type = i8_type.array_type(3);
///
/// assert_eq!(i8_array_type.len(), 3);
/// assert_eq!(i8_array_type.get_element_type().into_int_type(), i8_type);
/// ```
pub fn array_type(&self, size: u32) -> ArrayType {
self.int_type.array_type(size)
}

/// Creates a `VectorType` with this `IntType` for its element type.
///
/// # Example
///
/// ```no_run
/// use inkwell::context::Context;
///
/// let context = Context::create();
/// let i8_type = context.i8_type();
/// let i8_vector_type = i8_type.vector_type(3);
///
/// assert_eq!(i8_vector_type.get_size(), 3);
/// assert_eq!(i8_vector_type.get_element_type().into_int_type(), i8_type);
/// ```
pub fn vec_type(&self, size: u32) -> VectorType {
self.int_type.vec_type(size)
}

/// Gets a reference to the `Context` this `IntType` was created in.
///
/// # Example
///
/// ```no_run
/// use inkwell::context::Context;
///
/// let context = Context::create();
/// let i8_type = context.i8_type();
///
/// assert_eq!(*i8_type.get_context(), context);
/// ```
pub fn get_context(&self) -> ContextRef {
self.int_type.get_context()
}

// REVIEW: Always true -> const fn?
// REVIEW: Always true -> const fn on trait?
/// Gets whether or not this `IntType` is sized or not. This is likely
/// always true and may be removed in the future.
///
/// # Example
///
/// ```no_run
/// use inkwell::context::Context;
///
/// let context = Context::create();
/// let i8_type = context.i8_type();
///
/// assert!(i8_type.is_sized());
/// ```
pub fn is_sized(&self) -> bool {
self.int_type.is_sized()
}

/// Gets the size of this `IntType`. Value may vary depending on the target machine.
///
/// # Example
///
/// ```no_run
/// use inkwell::context::Context;
///
/// let context = Context::create();
/// let i8_type = context.i8_type();
/// let i8_type_size = i8_type.size_of();
/// ```
pub fn size_of(&self) -> IntValue {
self.int_type.size_of()
}

/// Gets the aligment of this `IntType`. Value may vary depending on the target machine.
///
/// # Example
///
/// ```no_run
/// use inkwell::context::Context;
///
/// let context = Context::create();
/// let i8_type = context.i8_type();
/// let i8_type_alignment = i8_type.alignment_of();
/// ```
pub fn get_alignment(&self) -> IntValue {
self.int_type.get_alignment()
}

/// Creates a `PointerType` with this `IntType` for its element type.
///
/// # Example
///
/// ```no_run
/// use inkwell::context::Context;
/// use inkwell::AddressSpace;
///
/// let context = Context::create();
/// let i8_type = context.i8_type();
/// let i8_ptr_type = i8_type.ptr_type(AddressSpace::Generic);
///
/// assert_eq!(i8_ptr_type.get_element_type().into_int_type(), i8_type);
/// ```
pub fn ptr_type(&self, address_space: AddressSpace) -> PointerType {
self.int_type.ptr_type(address_space)
}

/// Gets the bit width of an `IntType`.
///
/// # Example
/// ```no_run
/// use inkwell::types::IntType;
///
/// let bool_type = IntType::bool_type();
///
/// assert_eq!(bool_type.get_bit_width(), 1);
/// ```
pub fn get_bit_width(&self) -> u32 {
unsafe {
LLVMGetIntTypeWidth(self.as_type_ref())
}
}

/// Prints the definition of an `IntType` to a `LLVMString`.
pub fn print_to_string(&self) -> LLVMString {
self.int_type.print_to_string()
}

// See Type::print_to_stderr note on 5.0+ status
/// Prints the definition of an `IntType` to stderr. Not available in newer LLVM versions.
#[cfg(not(any(feature = "llvm3-6", feature = "llvm5-0")))]
pub fn print_to_stderr(&self) {
self.int_type.print_to_stderr()
}

/// Creates an undefined instance of an `IntType`.
///
/// # Example
/// ```no_run
/// use inkwell::context::Context;
/// use inkwell::AddressSpace;
///
/// let context = Context::create();
/// let i8_type = context.i8_type();
/// let i8_undef = i8_type.get_undef();
///
/// assert!(i8_undef.is_undef());
/// ```
pub fn get_undef(&self) -> IntValue {
IntValue::new(self.int_type.get_undef())
}

/// Creates a `GenericValue` for use with `ExecutionEngine`s.
pub fn create_generic_value(&self, value: u64, is_signed: bool) -> GenericValue {
let value = unsafe {
LLVMCreateGenericValueOfInt(self.as_type_ref(), value, is_signed as i32)
Expand All @@ -332,6 +511,21 @@ impl IntType {
GenericValue::new(value)
}

/// Creates a constant `ArrayValue`.
///
/// # Example
/// ```no_run
/// use inkwell::context::Context;
/// use inkwell::AddressSpace;
///
/// let context = Context::create();
/// let i8_type = context.i8_type();
/// let i8_val = i8_type.const_int(0, false);
/// let i8_val2 = i8_type.const_int(2, false);
/// let i8_array = i8_type.const_array(&[i8_val, i8_val2]);
///
/// assert!(i8_array.is_const());
/// ```
pub fn const_array(&self, values: &[IntValue]) -> ArrayValue {
let mut values: Vec<LLVMValueRef> = values.iter()
.map(|val| val.as_value_ref())
Expand Down
1 change: 1 addition & 0 deletions src/types/mod.rs
Expand Up @@ -2,6 +2,7 @@ mod array_type;
mod enums;
mod float_type;
mod fn_type;
#[deny(missing_docs)]
mod int_type;
mod ptr_type;
mod struct_type;
Expand Down
14 changes: 14 additions & 0 deletions tests/all/test_types.rs
Expand Up @@ -256,6 +256,20 @@ fn test_const_null() {
let vec_type = f64_type.vec_type(42);
let array_type = f64_type.array_type(42);

bool_type.size_of();
f32_type.size_of();
struct_type.size_of();
ptr_type.size_of();
vec_type.size_of();
array_type.size_of();

bool_type.get_alignment();
f32_type.get_alignment();
struct_type.get_alignment();
ptr_type.get_alignment();
vec_type.get_alignment();
array_type.get_alignment();

assert!(void_type.const_null_ptr().is_null());
assert!(bool_type.const_null_ptr().is_null());
assert!(i8_type.const_null_ptr().is_null());
Expand Down
3 changes: 3 additions & 0 deletions tests/all/test_values.rs
Expand Up @@ -1043,6 +1043,9 @@ fn test_consts() {
let f128_val = f128_type.const_float(7.8);
let ppc_f128_val = ppc_f128_type.const_float(9.0);
let vec_val = VectorType::const_vector(&[i8_val]);
let arbitrary_precision_int = i64_type.const_int_arbitrary_precision(&[1, 2]);

assert_eq!(*arbitrary_precision_int.print_to_string(), *CString::new("i64 1").unwrap());

assert!(!vec_val.is_const_string());
assert!(!vec_val.is_constant_vector());
Expand Down

0 comments on commit 9c7d5ec

Please sign in to comment.