diff --git a/src/module.rs b/src/module.rs index c91c3e3923f..91b8ec99aa1 100644 --- a/src/module.rs +++ b/src/module.rs @@ -1,6 +1,7 @@ //! A `Module` represets a single code compilation unit. use llvm_sys::analysis::{LLVMVerifyModule, LLVMVerifierFailureAction}; +#[allow(deprecated)] use llvm_sys::bit_reader::{LLVMParseBitcode, LLVMParseBitcodeInContext}; use llvm_sys::bit_writer::{LLVMWriteBitcodeToFile, LLVMWriteBitcodeToMemoryBuffer}; use llvm_sys::core::{LLVMAddFunction, LLVMAddGlobal, LLVMDumpModule, LLVMGetNamedFunction, LLVMGetTypeByName, LLVMSetDataLayout, LLVMSetTarget, LLVMCloneModule, LLVMDisposeModule, LLVMGetTarget, LLVMModuleCreateWithName, LLVMGetModuleContext, LLVMGetFirstFunction, LLVMGetLastFunction, LLVMAddGlobalInAddressSpace, LLVMPrintModuleToString, LLVMGetNamedMetadataNumOperands, LLVMAddNamedMetadataOperand, LLVMGetNamedMetadataOperands, LLVMGetFirstGlobal, LLVMGetLastGlobal, LLVMGetNamedGlobal, LLVMPrintModuleToFile, LLVMSetModuleInlineAsm}; @@ -1065,6 +1066,7 @@ impl Module { // LLVM has a newer version of this function w/o the error result since 3.8 but this deprecated function // hasen't yet been removed even in the unreleased LLVM 7. Seems fine to use instead of switching to their // error diagnostics handler + #[allow(deprecated)] let success = unsafe { LLVMParseBitcode(buffer.memory_buffer, &mut module, &mut err_string) }; @@ -1101,6 +1103,7 @@ impl Module { // LLVM has a newer version of this function w/o the error result since 3.8 but this deprecated function // hasen't yet been removed even in the unreleased LLVM 7. Seems fine to use instead of switching to their // error diagnostics handler + #[allow(deprecated)] let success = unsafe { LLVMParseBitcodeInContext(*context.context, buffer.memory_buffer, &mut module, &mut err_string) }; diff --git a/src/types/array_type.rs b/src/types/array_type.rs index eb9b474a1c1..c6cf86a6064 100644 --- a/src/types/array_type.rs +++ b/src/types/array_type.rs @@ -1,4 +1,4 @@ -use llvm_sys::core::{LLVMConstArray, LLVMConstNull, LLVMGetArrayLength}; +use llvm_sys::core::{LLVMConstArray, LLVMGetArrayLength}; use llvm_sys::prelude::{LLVMTypeRef, LLVMValueRef}; use AddressSpace; @@ -6,7 +6,7 @@ use context::ContextRef; use support::LLVMString; use types::traits::AsTypeRef; use types::{Type, BasicTypeEnum, PointerType, FunctionType}; -use values::{AsValueRef, ArrayValue, PointerValue, IntValue}; +use values::{AsValueRef, ArrayValue, IntValue}; /// An `ArrayType` is the type of contiguous constants or variables. #[derive(Debug, PartialEq, Eq, Clone, Copy)] @@ -158,7 +158,7 @@ impl ArrayType { /// let context = Context::create(); /// let f32_type = context.f32_type(); /// let f32_array_type = f32_type.array_type(3); - /// let f32_array_val = f32_array_type.const_null(); + /// let f32_array_val = f32_array_type.const_zero(); /// let f32_array_array = f32_array_type.const_array(&[f32_array_val, f32_array_val]); /// /// assert!(f32_array_array.is_const()); @@ -174,7 +174,7 @@ impl ArrayType { ArrayValue::new(value) } - /// Creates a `PointerValue` representing a constant value of zero (null pointer) pointing to this `ArrayType`. + /// Creates a null `ArrayValue` of this `ArrayType`. /// It will be automatically assigned this `ArrayType`'s `Context`. /// /// # Example @@ -185,24 +185,24 @@ impl ArrayType { /// /// // Global Context /// let f32_type = FloatType::f32_type(); - /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::Generic); - /// let f32_ptr_ptr_value = f32_ptr_type.const_null_ptr(); + /// let f32_array_type = f32_type.array_type(7); + /// let f32_array_null = f32_array_type.const_null(); /// - /// assert!(f32_ptr_ptr_value.is_null()); + /// assert!(f32_array_null.is_null()); /// /// // Custom Context /// let context = Context::create(); /// let f32_type = context.f32_type(); - /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::Generic); - /// let f32_ptr_ptr_value = f32_ptr_type.const_null_ptr(); + /// let f32_array_type = f32_type.array_type(7); + /// let f32_array_null = f32_array_type.const_null(); /// - /// assert!(f32_ptr_ptr_value.is_null()); + /// assert!(f32_array_null.is_null()); /// ``` - pub fn const_null_ptr(&self) -> PointerValue { - self.array_type.const_null_ptr() + pub fn const_null(&self) -> ArrayValue { + ArrayValue::new(self.array_type.const_null()) } - /// Creates a constant null (zero) value of this `ArrayType`. + /// Creates a constant zero value of this `ArrayType`. /// /// # Example /// @@ -212,16 +212,10 @@ impl ArrayType { /// let context = Context::create(); /// let i8_type = context.i8_type(); /// let i8_array_type = i8_type.array_type(3); - /// let i8_array_zero = i8_array_type.const_null(); - /// - /// assert!(i8_array_zero.is_null()); + /// let i8_array_zero = i8_array_type.const_zero(); /// ``` - pub fn const_null(&self) -> ArrayValue { - let null = unsafe { - LLVMConstNull(self.as_type_ref()) - }; - - ArrayValue::new(null) + pub fn const_zero(&self) -> ArrayValue { + ArrayValue::new(self.array_type.const_zero()) } /// Gets the length of this `ArrayType`. @@ -249,7 +243,7 @@ impl ArrayType { } // See Type::print_to_stderr note on 5.0+ status - /// Prints the definition of an `IntType` to stderr. Not available in newer LLVM versions. + /// Prints the definition of an `ArrayType` to stderr. Not available in newer LLVM versions. #[cfg(not(any(feature = "llvm3-6", feature = "llvm5-0")))] pub fn print_to_stderr(&self) { self.array_type.print_to_stderr() @@ -287,7 +281,7 @@ impl ArrayType { /// assert_eq!(i8_array_type.get_element_type().into_int_type(), i8_type); /// ``` pub fn get_element_type(&self) -> BasicTypeEnum { - self.array_type.get_element_type() + self.array_type.get_element_type().to_basic_type_enum() } } diff --git a/src/types/enums.rs b/src/types/enums.rs index 1d8687bad2a..423c02f95bf 100644 --- a/src/types/enums.rs +++ b/src/types/enums.rs @@ -65,6 +65,10 @@ impl AnyTypeEnum { LLVMTypeKind::LLVMTokenTypeKind => panic!("FIXME: Unsupported type: Token"), } } + + pub(crate) fn to_basic_type_enum(&self) -> BasicTypeEnum { + BasicTypeEnum::new(self.as_type_ref()) + } } impl BasicTypeEnum { @@ -85,13 +89,13 @@ impl BasicTypeEnum { LLVMTypeKind::LLVMPointerTypeKind => BasicTypeEnum::PointerType(PointerType::new(type_)), LLVMTypeKind::LLVMArrayTypeKind => BasicTypeEnum::ArrayType(ArrayType::new(type_)), LLVMTypeKind::LLVMVectorTypeKind => BasicTypeEnum::VectorType(VectorType::new(type_)), - LLVMTypeKind::LLVMMetadataTypeKind => unreachable!("Unsupported type: Metadata"), - LLVMTypeKind::LLVMX86_MMXTypeKind => unreachable!("Unsupported type: MMX"), - LLVMTypeKind::LLVMLabelTypeKind => unreachable!("Unsupported type: Label"), - LLVMTypeKind::LLVMVoidTypeKind => unreachable!("Unsupported type: VoidType"), - LLVMTypeKind::LLVMFunctionTypeKind => unreachable!("Unsupported type: FunctionType"), + LLVMTypeKind::LLVMMetadataTypeKind => unreachable!("Unsupported basic type: Metadata"), + LLVMTypeKind::LLVMX86_MMXTypeKind => unreachable!("Unsupported basic type: MMX"), + LLVMTypeKind::LLVMLabelTypeKind => unreachable!("Unsupported basic type: Label"), + LLVMTypeKind::LLVMVoidTypeKind => unreachable!("Unsupported basic type: VoidType"), + LLVMTypeKind::LLVMFunctionTypeKind => unreachable!("Unsupported basic type: FunctionType"), #[cfg(not(any(feature = "llvm3-6", feature = "llvm3-7")))] - LLVMTypeKind::LLVMTokenTypeKind => panic!("FIXME: Unsupported type: Token"), + LLVMTypeKind::LLVMTokenTypeKind => unreachable!("Unsupported basic type: Token"), } } } diff --git a/src/types/float_type.rs b/src/types/float_type.rs index 7f2123cd8c2..ef58b9236bc 100644 --- a/src/types/float_type.rs +++ b/src/types/float_type.rs @@ -1,4 +1,4 @@ -use llvm_sys::core::{LLVMConstReal, LLVMConstNull, LLVMHalfType, LLVMFloatType, LLVMDoubleType, LLVMFP128Type, LLVMPPCFP128Type, LLVMConstRealOfStringAndSize, LLVMX86FP80Type, LLVMConstArray}; +use llvm_sys::core::{LLVMConstReal, LLVMHalfType, LLVMFloatType, LLVMDoubleType, LLVMFP128Type, LLVMPPCFP128Type, LLVMConstRealOfStringAndSize, LLVMX86FP80Type, LLVMConstArray}; use llvm_sys::execution_engine::LLVMCreateGenericValueOfFloat; use llvm_sys::prelude::{LLVMTypeRef, LLVMValueRef}; @@ -7,7 +7,7 @@ use context::ContextRef; use support::LLVMString; use types::traits::AsTypeRef; use types::{Type, PointerType, FunctionType, BasicTypeEnum, ArrayType, VectorType}; -use values::{AsValueRef, ArrayValue, FloatValue, GenericValue, PointerValue, IntValue}; +use values::{AsValueRef, ArrayValue, FloatValue, GenericValue, IntValue}; /// A `FloatType` is the type of a floating point constant or variable. #[derive(Debug, PartialEq, Eq, Clone, Copy)] @@ -138,7 +138,7 @@ impl FloatType { FloatValue::new(value) } - /// Creates a `PointerValue` representing a constant value of zero (null pointer) pointing to this `FloatType`. + /// Creates a constant null value of this `FloatType`. /// It will be automatically assigned this `FloatType`'s `Context`. /// /// # Example @@ -148,18 +148,18 @@ impl FloatType { /// /// // Global Context /// let f32_type = FloatType::f32_type(); - /// let f32_value = f32_type.const_null_ptr(); + /// let f32_value = f32_type.const_null(); /// /// // Custom Context /// let context = Context::create(); /// let f32_type = context.f32_type(); - /// let f32_value = f32_type.const_null_ptr(); + /// let f32_value = f32_type.const_null(); /// ``` - pub fn const_null_ptr(&self) -> PointerValue { - self.float_type.const_null_ptr() + pub fn const_null(&self) -> FloatValue { + FloatValue::new(self.float_type.const_null()) } - /// Creates a constant null (zero) value of this `FloatType`. + /// Creates a constant zero value of this `FloatType`. /// /// # Example /// @@ -168,17 +168,12 @@ impl FloatType { /// /// let context = Context::create(); /// let f32_type = context.f32_type(); - /// let f32_zero = f32_type.const_null(); + /// let f32_zero = f32_type.const_zero(); /// - /// assert!(f32_zero.is_null()); /// assert_eq!(f32_zero.print_to_string().to_string(), "f32 0"); /// ``` - pub fn const_null(&self) -> FloatValue { - let null = unsafe { - LLVMConstNull(self.as_type_ref()) - }; - - FloatValue::new(null) + pub fn const_zero(&self) -> FloatValue { + FloatValue::new(self.float_type.const_zero()) } // REVIEW: Always true -> const fn? diff --git a/src/types/fn_type.rs b/src/types/fn_type.rs index 845f71e3686..dafa48a8dcb 100644 --- a/src/types/fn_type.rs +++ b/src/types/fn_type.rs @@ -4,11 +4,13 @@ use llvm_sys::prelude::LLVMTypeRef; use std::fmt; use std::mem::forget; +use AddressSpace; use context::ContextRef; use support::LLVMString; use types::traits::AsTypeRef; -use types::{Type, BasicTypeEnum}; -// use values::FunctionValue; +use types::{PointerType, Type, BasicTypeEnum}; + +// REVIEW: Add a get_return_type() -> Option? #[derive(PartialEq, Eq, Clone, Copy)] pub struct FunctionType { @@ -24,6 +26,10 @@ impl FunctionType { } } + pub fn ptr_type(&self, address_space: AddressSpace) -> PointerType { + self.fn_type.ptr_type(address_space) + } + pub fn is_var_arg(&self) -> bool { unsafe { LLVMIsFunctionVarArg(self.as_type_ref()) != 0 diff --git a/src/types/int_type.rs b/src/types/int_type.rs index 313c933b8c7..6080862b552 100644 --- a/src/types/int_type.rs +++ b/src/types/int_type.rs @@ -1,4 +1,4 @@ -use llvm_sys::core::{LLVMInt1Type, LLVMInt8Type, LLVMInt16Type, LLVMInt32Type, LLVMInt64Type, LLVMConstInt, LLVMConstNull, LLVMConstAllOnes, LLVMIntType, LLVMGetIntTypeWidth, LLVMConstIntOfStringAndSize, LLVMConstIntOfArbitraryPrecision, LLVMConstArray}; +use llvm_sys::core::{LLVMInt1Type, LLVMInt8Type, LLVMInt16Type, LLVMInt32Type, LLVMInt64Type, LLVMConstInt, LLVMConstAllOnes, LLVMIntType, LLVMGetIntTypeWidth, LLVMConstIntOfStringAndSize, LLVMConstIntOfArbitraryPrecision, LLVMConstArray}; use llvm_sys::execution_engine::LLVMCreateGenericValueOfInt; use llvm_sys::prelude::{LLVMTypeRef, LLVMValueRef}; @@ -7,7 +7,7 @@ use context::ContextRef; use support::LLVMString; use types::traits::AsTypeRef; use types::{Type, ArrayType, BasicTypeEnum, VectorType, PointerType, FunctionType}; -use values::{AsValueRef, ArrayValue, GenericValue, IntValue, PointerValue}; +use values::{AsValueRef, ArrayValue, GenericValue, IntValue}; /// An `IntType` is the type of an integer constant or variable. #[derive(Debug, PartialEq, Eq, Clone, Copy)] @@ -280,7 +280,7 @@ impl IntType { IntValue::new(value) } - /// Creates a `PointerValue` representing a constant value of zero (null pointer) pointing to this `IntType`. It will be automatically assigned this `IntType`'s `Context`. + /// Creates a constant null value of this `IntType`. /// /// # Example /// ``` @@ -289,18 +289,18 @@ impl IntType { /// /// // Global Context /// let i32_type = IntType::i32_type(); - /// let i32_value = i32_type.const_null_ptr(); + /// let i32_value = i32_type.const_null(); /// /// // Custom Context /// let context = Context::create(); /// let i32_type = context.i32_type(); - /// let i32_value = i32_type.const_null_ptr(); + /// let i32_value = i32_type.const_null(); /// ``` - pub fn const_null_ptr(&self) -> PointerValue { - self.int_type.const_null_ptr() + pub fn const_null(&self) -> IntValue { + IntValue::new(self.int_type.const_null()) } - /// Creates a constant null (zero) value of this `IntType`. + /// Creates a constant zero value of this `IntType`. /// /// # Example /// @@ -309,17 +309,12 @@ impl IntType { /// /// let context = Context::create(); /// let i8_type = context.i8_type(); - /// let i8_zero = i8_type.const_null(); + /// let i8_zero = i8_type.const_zero(); /// - /// 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()) - }; - - IntValue::new(null) + pub fn const_zero(&self) -> IntValue { + IntValue::new(self.int_type.const_zero()) } /// Creates a `FunctionType` with this `IntType` for its return type. diff --git a/src/types/mod.rs b/src/types/mod.rs index 1dadece18d5..74e0f8075b3 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -12,6 +12,7 @@ mod struct_type; mod traits; #[deny(missing_docs)] mod vec_type; +#[deny(missing_docs)] mod void_type; pub use types::array_type::ArrayType; @@ -28,8 +29,7 @@ pub(crate) use types::traits::AsTypeRef; #[cfg(not(feature = "llvm3-6"))] use llvm_sys::core::LLVMDumpType; -use llvm_sys::core::{LLVMAlignOf, LLVMGetTypeContext, LLVMFunctionType, LLVMArrayType, LLVMGetTypeKind, LLVMGetUndef, LLVMPointerType, LLVMPrintTypeToString, LLVMTypeIsSized, LLVMSizeOf, LLVMVectorType, LLVMConstPointerNull, LLVMGetElementType}; -use llvm_sys::LLVMTypeKind; +use llvm_sys::core::{LLVMAlignOf, LLVMGetTypeContext, LLVMFunctionType, LLVMArrayType, LLVMGetUndef, LLVMPointerType, LLVMPrintTypeToString, LLVMTypeIsSized, LLVMSizeOf, LLVMVectorType, LLVMConstPointerNull, LLVMGetElementType, LLVMConstNull}; use llvm_sys::prelude::{LLVMTypeRef, LLVMValueRef}; use std::fmt; @@ -38,11 +38,10 @@ use std::rc::Rc; use AddressSpace; use context::{Context, ContextRef}; use support::LLVMString; -use values::{IntValue, PointerValue}; +use values::IntValue; // Worth noting that types seem to be singletons. At the very least, primitives are. // Though this is likely only true per thread since LLVM claims to not be very thread-safe. -// REVIEW: Maybe move this into its own module? #[derive(PartialEq, Eq, Clone, Copy)] struct Type { type_: LLVMTypeRef, @@ -68,12 +67,18 @@ impl Type { } } - fn const_null_ptr(&self) -> PointerValue { - let ptr_type = unsafe { + // Even though the LLVM fuction has the word "Pointer", it doesn't seem to create + // a pointer at all, just a null value of the current type... + fn const_null(&self) -> LLVMValueRef { + unsafe { LLVMConstPointerNull(self.type_) - }; + } + } - PointerValue::new(ptr_type) + fn const_zero(&self) -> LLVMValueRef { + unsafe { + LLVMConstNull(self.type_) + } } fn ptr_type(&self, address_space: AddressSpace) -> PointerType { @@ -118,13 +123,6 @@ impl Type { } } - // NOTE: AnyType - pub(crate) fn get_kind(&self) -> LLVMTypeKind { - unsafe { - LLVMGetTypeKind(self.type_) - } - } - fn get_alignment(&self) -> IntValue { let val = unsafe { LLVMAlignOf(self.type_) @@ -177,12 +175,12 @@ impl Type { LLVMString::new(c_string_ptr) } - pub fn get_element_type(&self) -> BasicTypeEnum { + pub fn get_element_type(&self) -> AnyTypeEnum { let ptr = unsafe { LLVMGetElementType(self.type_) }; - BasicTypeEnum::new(ptr) + AnyTypeEnum::new(ptr) } } diff --git a/src/types/ptr_type.rs b/src/types/ptr_type.rs index 97aa71018a6..0729b49cd0d 100644 --- a/src/types/ptr_type.rs +++ b/src/types/ptr_type.rs @@ -1,11 +1,11 @@ -use llvm_sys::core::{LLVMGetPointerAddressSpace, LLVMConstNull, LLVMConstArray}; +use llvm_sys::core::{LLVMGetPointerAddressSpace, LLVMConstArray}; use llvm_sys::prelude::{LLVMTypeRef, LLVMValueRef}; use AddressSpace; use context::ContextRef; use support::LLVMString; use types::traits::AsTypeRef; -use types::{Type, BasicTypeEnum, ArrayType, FunctionType, VectorType}; +use types::{AnyTypeEnum, Type, BasicTypeEnum, ArrayType, FunctionType, VectorType}; use values::{AsValueRef, ArrayValue, PointerValue, IntValue}; /// A `PointerType` is the type of a pointer constant or variable. @@ -183,31 +183,32 @@ impl PointerType { self.ptr_type.print_to_stderr() } - /// Creates a `PointerValue` representing a constant value of zero (null pointer) pointing to this `PointerType`. + /// Creates a null `PointerValue` of this `PointerType`. /// It will be automatically assigned this `PointerType`'s `Context`. /// /// # Example /// ``` + /// use inkwell::AddressSpace; /// use inkwell::context::Context; /// use inkwell::types::FloatType; /// /// // Global Context /// let f32_type = FloatType::f32_type(); - /// let f32_array_type = f32_type.array_type(3); - /// let f32_array_ptr_value = f32_array_type.const_null_ptr(); + /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::Generic); + /// let f32_ptr_null = f32_ptr_type.const_null(); /// - /// assert!(f32_array_ptr_value.is_null()); + /// assert!(f32_ptr_null.is_null()); /// /// // Custom Context /// let context = Context::create(); /// let f32_type = context.f32_type(); - /// let f32_array_type = f32_type.array_type(3); - /// let f32_array_ptr_value = f32_array_type.const_null_ptr(); + /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::Generic); + /// let f32_ptr_null = f32_ptr_type.const_null(); /// - /// assert!(f32_array_ptr_value.is_null()); + /// assert!(f32_ptr_null.is_null()); /// ``` - pub fn const_null_ptr(&self) -> PointerValue { - self.ptr_type.const_null_ptr() + pub fn const_null(&self) -> PointerValue { + PointerValue::new(self.ptr_type.const_null()) } /// Creates a constant null (zero) value of this `PointerType`. @@ -215,22 +216,16 @@ impl PointerType { /// # Example /// /// ```no_run - /// use inkwell::context::Context; /// use inkwell::AddressSpace; + /// use inkwell::context::Context; /// /// let context = Context::create(); /// let f32_type = context.f32_type(); /// let f32_ptr_type = f32_type.ptr_type(AddressSpace::Generic); - /// let f32_ptr_zero = f32_ptr_type.const_null(); - /// - /// assert!(f32_ptr_zero.is_null()); + /// let f32_ptr_zero = f32_ptr_type.const_zero(); /// ``` - pub fn const_null(&self) -> PointerValue { - let null = unsafe { - LLVMConstNull(self.as_type_ref()) - }; - - PointerValue::new(null) + pub fn const_zero(&self) -> PointerValue { + PointerValue::new(self.ptr_type.const_zero()) } /// Creates an undefined instance of a `PointerType`. @@ -286,7 +281,7 @@ impl PointerType { /// /// assert_eq!(f32_ptr_type.get_element_type().into_float_type(), f32_type); /// ``` - pub fn get_element_type(&self) -> BasicTypeEnum { + pub fn get_element_type(&self) -> AnyTypeEnum { self.ptr_type.get_element_type() } diff --git a/src/types/struct_type.rs b/src/types/struct_type.rs index 32ad62d87ea..6ba9d54d910 100644 --- a/src/types/struct_type.rs +++ b/src/types/struct_type.rs @@ -1,4 +1,4 @@ -use llvm_sys::core::{LLVMConstNamedStruct, LLVMConstStruct, LLVMConstNull, LLVMStructType, LLVMCountStructElementTypes, LLVMGetStructElementTypes, LLVMGetStructName, LLVMIsPackedStruct, LLVMIsOpaqueStruct, LLVMStructSetBody, LLVMConstArray}; +use llvm_sys::core::{LLVMConstNamedStruct, LLVMConstStruct, LLVMStructType, LLVMCountStructElementTypes, LLVMGetStructElementTypes, LLVMGetStructName, LLVMIsPackedStruct, LLVMIsOpaqueStruct, LLVMStructSetBody, LLVMConstArray}; #[cfg(not(feature = "llvm3-6"))] use llvm_sys::core::LLVMStructGetTypeAtIndex; use llvm_sys::prelude::{LLVMTypeRef, LLVMValueRef}; @@ -11,7 +11,7 @@ use context::ContextRef; use support::LLVMString; use types::traits::AsTypeRef; use types::{Type, BasicType, BasicTypeEnum, ArrayType, PointerType, FunctionType, VectorType}; -use values::{ArrayValue, BasicValueEnum, StructValue, PointerValue, IntValue, AsValueRef}; +use values::{ArrayValue, BasicValueEnum, StructValue, IntValue, AsValueRef}; #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub struct StructType { @@ -72,16 +72,12 @@ impl StructType { StructValue::new(value) } - pub fn const_null_ptr(&self) -> PointerValue { - self.struct_type.const_null_ptr() - } - pub fn const_null(&self) -> StructValue { - let null = unsafe { - LLVMConstNull(self.as_type_ref()) - }; + StructValue::new(self.struct_type.const_null()) + } - StructValue::new(null) + pub fn const_zero(&self) -> StructValue { + StructValue::new(self.struct_type.const_zero()) } // REVIEW: Can be false if opaque. To make a const fn, we'd have to have diff --git a/src/types/vec_type.rs b/src/types/vec_type.rs index a97baa56105..a962f0c62f2 100644 --- a/src/types/vec_type.rs +++ b/src/types/vec_type.rs @@ -1,11 +1,11 @@ -use llvm_sys::core::{LLVMConstVector, LLVMConstNull, LLVMGetVectorSize, LLVMConstArray}; +use llvm_sys::core::{LLVMConstVector, LLVMGetVectorSize, LLVMConstArray}; use llvm_sys::prelude::{LLVMTypeRef, LLVMValueRef}; use AddressSpace; use context::ContextRef; use support::LLVMString; use types::{ArrayType, BasicTypeEnum, Type, traits::AsTypeRef, FunctionType, PointerType}; -use values::{AsValueRef, ArrayValue, BasicValue, PointerValue, VectorValue, IntValue}; +use values::{AsValueRef, ArrayValue, BasicValue, VectorValue, IntValue}; /// A `VectorType` is the type of a multiple value SIMD constant or variable. #[derive(Debug, PartialEq, Eq, Clone, Copy)] @@ -133,7 +133,7 @@ impl VectorType { VectorValue::new(vec_value) } - /// Creates a `PointerValue` representing a constant value of zero (null pointer) pointing to this `VectorType`. + /// Creates a null `VectorValue` of this `VectorType`. /// It will be automatically assigned this `VectorType`'s `Context`. /// /// # Example @@ -144,23 +144,23 @@ impl VectorType { /// // Global Context /// let f32_type = FloatType::f32_type(); /// let f32_vec_type = f32_type.vec_type(7); - /// let f32_vec_ptr_value = f32_vec_type.const_null_ptr(); + /// let f32_vec_null = f32_vec_type.const_null(); /// - /// assert!(f32_vec_ptr_value.is_null()); + /// assert!(f32_vec_null.is_null()); /// /// // Custom Context /// let context = Context::create(); /// let f32_type = context.f32_type(); /// let f32_vec_type = f32_type.vec_type(7); - /// let f32_vec_ptr_value = f32_vec_type.const_null_ptr(); + /// let f32_vec_null = f32_vec_type.const_null(); /// - /// assert!(f32_vec_ptr_value.is_null()); + /// assert!(f32_vec_null.is_null()); /// ``` - pub fn const_null_ptr(&self) -> PointerValue { - self.vec_type.const_null_ptr() + pub fn const_null(&self) -> VectorValue { + VectorValue::new(self.vec_type.const_null()) } - /// Creates a constant null (zero) value of this `VectorType`. + /// Creates a constant zero value of this `VectorType`. /// /// # Example /// @@ -170,16 +170,10 @@ impl VectorType { /// let context = Context::create(); /// let f32_type = context.f32_type(); /// let f32_vec_type = f32_type.vec_type(7); - /// let f32_vec_zero = f32_vec_type.const_null(); - /// - /// assert!(f32_vec_zero.is_null()); + /// let f32_vec_zero = f32_vec_type.const_zero(); /// ``` - pub fn const_null(&self) -> VectorValue { - let null = unsafe { - LLVMConstNull(self.as_type_ref()) - }; - - VectorValue::new(null) + pub fn const_zero(&self) -> VectorValue { + VectorValue::new(self.vec_type.const_zero()) } /// Prints the definition of a `VectorType` to a `LLVMString`. @@ -228,7 +222,8 @@ impl VectorType { /// assert_eq!(f32_vector_type.get_element_type().into_float_type(), f32_type); /// ``` pub fn get_element_type(&self) -> BasicTypeEnum { - self.vec_type.get_element_type() + self.vec_type.get_element_type().to_basic_type_enum() + } /// Creates a `VectorType` with this `VectorType` for its element type. diff --git a/src/types/void_type.rs b/src/types/void_type.rs index 53b7d5bdda6..f6f64c7fadb 100644 --- a/src/types/void_type.rs +++ b/src/types/void_type.rs @@ -6,8 +6,9 @@ use context::ContextRef; use support::LLVMString; use types::traits::AsTypeRef; use types::{Type, BasicTypeEnum, FunctionType, PointerType}; -use values::PointerValue; +/// A `VoidType` is a special type with no possible direct instances. It's particularly +/// useful as a pointer element type or a function return type. #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub struct VoidType { void_type: Type, @@ -23,18 +24,69 @@ impl VoidType { } // REVIEW: Always false -> const fn? + /// Gets whether or not this `VectorType` is sized or not. This may always + /// be false and as such this function may be removed in the future. + /// + /// # Example + /// + /// ```no_run + /// use inkwell::context::Context; + /// + /// let context = Context::create(); + /// let void_type = context.void_type(); + /// + /// assert!(void_type.is_sized()); + /// ``` pub fn is_sized(&self) -> bool { self.void_type.is_sized() } + /// Gets a reference to the `Context` this `VoidType` was created in. + /// + /// # Example + /// + /// ```no_run + /// use inkwell::context::Context; + /// + /// let context = Context::create(); + /// let void_type = context.void_type(); + /// + /// assert_eq!(*void_type.get_context(), context); + /// ``` pub fn get_context(&self) -> ContextRef { self.void_type.get_context() } + /// Creates a `PointerType` with this `VoidType` for its element type. + /// + /// # Example + /// + /// ```no_run + /// use inkwell::context::Context; + /// use inkwell::AddressSpace; + /// + /// let context = Context::create(); + /// let void_type = context.void_type(); + /// let void_ptr_type = void_type.ptr_type(AddressSpace::Generic); + /// + /// assert_eq!(void_ptr_type.get_element_type().into_void_type(), void_type); + /// ``` pub fn ptr_type(&self, address_space: AddressSpace) -> PointerType { self.void_type.ptr_type(address_space) } + /// Creates a `FunctionType` with this `VoidType` for its return type. + /// This means the function does not return. + /// + /// # Example + /// + /// ```no_run + /// use inkwell::context::Context; + /// + /// let context = Context::create(); + /// let void_type = context.void_type(); + /// let fn_type = void_type.fn_type(&[], false); + /// ``` pub fn fn_type(&self, param_types: &[BasicTypeEnum], is_var_args: bool) -> FunctionType { self.void_type.fn_type(param_types, is_var_args) } @@ -59,19 +111,17 @@ impl VoidType { VoidType::new(void_type) } + /// Prints the definition of a `VoidType` to a `LLVMString`. pub fn print_to_string(&self) -> LLVMString { self.void_type.print_to_string() } // See Type::print_to_stderr note on 5.0+ status + /// Prints the definition of a `VoidType` to stderr. Not available in newer LLVM versions. #[cfg(not(any(feature = "llvm3-6", feature = "llvm5-0")))] pub fn print_to_stderr(&self) { self.void_type.print_to_stderr() } - - pub fn const_null_ptr(&self) -> PointerValue { - self.void_type.const_null_ptr() - } } impl AsTypeRef for VoidType { diff --git a/src/values/ptr_value.rs b/src/values/ptr_value.rs index 7669d4f619a..9df153b722d 100644 --- a/src/values/ptr_value.rs +++ b/src/values/ptr_value.rs @@ -41,6 +41,24 @@ impl PointerValue { self.ptr_value.is_undef() } + /// Determines whether or not a `PointerValue` is a constant. + /// + /// # Example + /// + /// ```no_run + /// use inkwell::AddressSpace; + /// use inkwell::context::Context; + /// + /// let context = Context::create(); + /// let void_type = context.void_type(); + /// let void_ptr_null = void_type.ptr_type(AddressSpace::Generic).const_null(); + /// + /// assert!(void_ptr_null.is_const()); + /// ``` + pub fn is_const(&self) -> bool { + self.ptr_value.is_const() + } + pub fn print_to_string(&self) -> LLVMString { self.ptr_value.print_to_string() } diff --git a/src/values/vec_value.rs b/src/values/vec_value.rs index d1d5292bab6..9b3f6d8a841 100644 --- a/src/values/vec_value.rs +++ b/src/values/vec_value.rs @@ -22,6 +22,24 @@ impl VectorValue { } } + /// Determines whether or not a `VectorValue` is a constant. + /// + /// # Example + /// + /// ```no_run + /// use inkwell::context::Context; + /// + /// let context = Context::create(); + /// let i8_type = context.i8_type(); + /// let i8_vec_type = i8_type.vec_type(3); + /// let i8_vec_null = i8_vec_type.const_null(); + /// + /// assert!(i8_vec_null.is_const()); + /// ``` + pub fn is_const(&self) -> bool { + self.vec_value.is_const() + } + pub fn is_constant_vector(&self) -> bool { unsafe { !LLVMIsAConstantVector(self.as_value_ref()).is_null() diff --git a/tests/all/test_types.rs b/tests/all/test_types.rs index f649d55f7ba..c807afdcb00 100644 --- a/tests/all/test_types.rs +++ b/tests/all/test_types.rs @@ -238,7 +238,6 @@ fn test_sized_types() { #[test] fn test_const_null() { let context = Context::create(); - let void_type = context.void_type(); let bool_type = context.bool_type(); let i8_type = context.i8_type(); let i16_type = context.i16_type(); @@ -270,40 +269,39 @@ fn test_const_null() { 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()); - assert!(i16_type.const_null_ptr().is_null()); - assert!(i32_type.const_null_ptr().is_null()); - assert!(i64_type.const_null_ptr().is_null()); - assert!(i128_type.const_null_ptr().is_null()); - assert!(f16_type.const_null_ptr().is_null()); - assert!(f32_type.const_null_ptr().is_null()); - assert!(f64_type.const_null_ptr().is_null()); - assert!(f80_type.const_null_ptr().is_null()); - assert!(f128_type.const_null_ptr().is_null()); - assert!(ppc_f128_type.const_null_ptr().is_null()); - assert!(struct_type.const_null_ptr().is_null()); - assert!(ptr_type.const_null_ptr().is_null()); - assert!(vec_type.const_null_ptr().is_null()); - assert!(array_type.const_null_ptr().is_null()); - - let bool_zero = bool_type.const_null(); - let i8_zero = i8_type.const_null(); - let i16_zero = i16_type.const_null(); - let i32_zero = i32_type.const_null(); - let i64_zero = i64_type.const_null(); - let i128_zero = i128_type.const_null(); - let f16_zero = f16_type.const_null(); - let f32_zero = f32_type.const_null(); - let f64_zero = f64_type.const_null(); - let f80_zero = f80_type.const_null(); - let f128_zero = f128_type.const_null(); - let ppc_f128_zero = ppc_f128_type.const_null(); - let struct_zero = struct_type.const_null(); - let ptr_zero = ptr_type.const_null(); - let vec_zero = vec_type.const_null(); - let array_zero = array_type.const_null(); + assert!(bool_type.const_null().is_null()); + assert!(i8_type.const_null().is_null()); + assert!(i16_type.const_null().is_null()); + assert!(i32_type.const_null().is_null()); + assert!(i64_type.const_null().is_null()); + assert!(i128_type.const_null().is_null()); + assert!(f16_type.const_null().is_null()); + assert!(f32_type.const_null().is_null()); + assert!(f64_type.const_null().is_null()); + assert!(f80_type.const_null().is_null()); + assert!(f128_type.const_null().is_null()); + assert!(ppc_f128_type.const_null().is_null()); + assert!(struct_type.const_null().is_null()); + assert!(ptr_type.const_null().is_null()); + assert!(vec_type.const_null().is_null()); + assert!(array_type.const_null().is_null()); + + let bool_zero = bool_type.const_zero(); + let i8_zero = i8_type.const_zero(); + let i16_zero = i16_type.const_zero(); + let i32_zero = i32_type.const_zero(); + let i64_zero = i64_type.const_zero(); + let i128_zero = i128_type.const_zero(); + let f16_zero = f16_type.const_zero(); + let f32_zero = f32_type.const_zero(); + let f64_zero = f64_type.const_zero(); + let f80_zero = f80_type.const_zero(); + let f128_zero = f128_type.const_zero(); + let ppc_f128_zero = ppc_f128_type.const_zero(); + let struct_zero = struct_type.const_zero(); + let ptr_zero = ptr_type.const_zero(); + let vec_zero = vec_type.const_zero(); + let array_zero = array_type.const_zero(); assert_eq!(*bool_zero.print_to_string(), *CString::new("i1 false").unwrap()); assert!(bool_zero.is_null()); @@ -367,4 +365,17 @@ fn test_ptr_type() { assert_eq!(ptr_type.get_address_space(), AddressSpace::Generic); assert_eq!(ptr_type.get_element_type().into_int_type(), i8_type); + + // Void ptr: + let void_type = context.void_type(); + let void_ptr_type = void_type.ptr_type(AddressSpace::Generic); + + assert_eq!(void_ptr_type.get_element_type().into_void_type(), void_type); + + // Fn ptr: + let fn_type = void_type.fn_type(&[], false); + let fn_ptr_type = fn_type.ptr_type(AddressSpace::Generic); + + assert_eq!(fn_ptr_type.get_element_type().into_function_type(), fn_type); + assert_eq!(*fn_ptr_type.get_context(), context); } diff --git a/tests/all/test_values.rs b/tests/all/test_values.rs index ecda365d03a..a558cccd345 100644 --- a/tests/all/test_values.rs +++ b/tests/all/test_values.rs @@ -115,7 +115,7 @@ fn test_set_get_name() { let f32_val = f32_type.const_float(0.0); let f64_val = f64_type.const_float(0.0); let f128_val = f128_type.const_float(0.0); - let ptr_val = bool_type.const_null_ptr(); + let ptr_val = bool_type.ptr_type(AddressSpace::Generic).const_null(); let array_val = f64_type.const_array(&[f64_val]); let struct_val = context.const_struct(&[i8_val.into(), f128_val.into()], false); let vec_val = VectorType::const_vector(&[i8_val]); @@ -257,7 +257,7 @@ fn test_undef() { let f32_val = f32_type.const_float(0.0); let f64_val = f64_type.const_float(0.0); let f128_val = f128_type.const_float(0.0); - let ptr_val = bool_type.const_null_ptr(); + let ptr_val = bool_type.ptr_type(AddressSpace::Generic).const_null(); let array_val = f64_type.const_array(&[f64_val]); let struct_val = context.const_struct(&[i8_val.into(), f128_val.into()], false); let vec_val = VectorType::const_vector(&[i8_val]); @@ -1068,7 +1068,20 @@ fn test_consts() { let array_val = i8_type.const_array(&[i8_val]); let arbitrary_precision_int = i64_type.const_int_arbitrary_precision(&[1, 2]); + assert!(bool_val.is_const()); + assert!(i8_val.is_const()); + assert!(i16_val.is_const()); + assert!(i32_val.is_const()); + assert!(i64_val.is_const()); + assert!(i128_val.is_const()); + assert!(f16_val.is_const()); + assert!(f32_val.is_const()); + assert!(f64_val.is_const()); + assert!(f128_val.is_const()); + assert!(ppc_f128_val.is_const()); + assert!(vec_val.is_const()); assert!(array_val.is_const()); + assert!(arbitrary_precision_int.is_const()); assert_eq!(*arbitrary_precision_int.print_to_string(), *CString::new("i64 1").unwrap());