diff --git a/src/attributes.rs b/src/attributes.rs index 67c4bead79a..397a14158d4 100644 --- a/src/attributes.rs +++ b/src/attributes.rs @@ -1,15 +1,20 @@ //! `Attribute`s are optional modifiers to functions, function parameters, and return types. -use llvm_sys::core::{ - LLVMGetEnumAttributeKind, LLVMGetEnumAttributeKindForName, LLVMGetEnumAttributeValue, LLVMGetLastEnumAttributeKind, - LLVMGetStringAttributeKind, LLVMGetStringAttributeValue, LLVMIsEnumAttribute, LLVMIsStringAttribute, -}; #[llvm_versions(12..)] use llvm_sys::core::{LLVMGetTypeAttributeValue, LLVMIsTypeAttribute}; use llvm_sys::prelude::LLVMAttributeRef; +use llvm_sys::{ + LLVMOpaqueAttributeRef, + core::{ + LLVMGetEnumAttributeKind, LLVMGetEnumAttributeKindForName, LLVMGetEnumAttributeValue, + LLVMGetLastEnumAttributeKind, LLVMGetStringAttributeKind, LLVMGetStringAttributeValue, LLVMIsEnumAttribute, + LLVMIsStringAttribute, + }, +}; -use std::ffi::CStr; +use std::{ffi::CStr, ptr::NonNull}; +use crate::support::assert_niche; #[llvm_versions(12..)] use crate::types::AnyTypeEnum; @@ -17,17 +22,19 @@ use crate::types::AnyTypeEnum; // REVIEW: Should Attributes have a 'ctx lifetime? /// Functions, function parameters, and return types can have `Attribute`s to indicate /// how they should be treated by optimizations and code generation. +#[repr(transparent)] #[derive(Clone, Copy)] pub struct Attribute { - pub(crate) attribute: LLVMAttributeRef, + pub(crate) attribute: NonNull, } +const _: () = assert_niche::(); impl std::fmt::Debug for Attribute { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { if self.is_string() { return f .debug_struct("Attribute::String") - .field("ptr", &self.attribute) + .field("ptr", &self.as_mut_ptr()) .field("kind_id", &self.get_string_kind_id()) .field("value", &self.get_string_value()) .finish(); @@ -36,7 +43,7 @@ impl std::fmt::Debug for Attribute { if self.is_enum() { return f .debug_struct("Attribute::Enum") - .field("ptr", &self.attribute) + .field("ptr", &self.as_mut_ptr()) .field("kind_id", &self.get_enum_kind_id()) .field("value", &self.get_enum_value()) .finish(); @@ -45,7 +52,7 @@ impl std::fmt::Debug for Attribute { if self.is_type() { return f .debug_struct("Attribute::Type") - .field("ptr", &self.attribute) + .field("ptr", &self.as_mut_ptr()) .field("kind_id", &self.get_enum_kind_id()) .field("value", &self.get_type_value()) .finish(); @@ -84,16 +91,22 @@ impl PartialEq for Attribute { } impl Attribute { - /// Creates a new `Attribute` from a raw pointer. + /// Creates a new [Attribute] from a raw pointer. + /// + /// # Safety + /// + /// `attribute` must be non-null and point to a valid value. pub unsafe fn new(attribute: LLVMAttributeRef) -> Self { debug_assert!(!attribute.is_null()); - Attribute { attribute } + Attribute { + attribute: unsafe { NonNull::new_unchecked(attribute) }, + } } /// Acquires the underlying raw pointer belonging to this `Attribute` type. pub fn as_mut_ptr(&self) -> LLVMAttributeRef { - self.attribute + self.attribute.as_ptr() } /// Determines whether or not an `Attribute` is an enum. This method will @@ -111,7 +124,7 @@ impl Attribute { /// assert!(enum_attribute.is_enum()); /// ``` pub fn is_enum(self) -> bool { - unsafe { LLVMIsEnumAttribute(self.attribute) == 1 } + unsafe { LLVMIsEnumAttribute(self.as_mut_ptr()) == 1 } } /// Determines whether or not an `Attribute` is a string. This method will @@ -129,7 +142,7 @@ impl Attribute { /// assert!(string_attribute.is_string()); /// ``` pub fn is_string(self) -> bool { - unsafe { LLVMIsStringAttribute(self.attribute) == 1 } + unsafe { LLVMIsStringAttribute(self.as_mut_ptr()) == 1 } } /// Determines whether or not an `Attribute` is a type attribute. This method will @@ -153,7 +166,7 @@ impl Attribute { /// ``` #[llvm_versions(12..)] pub fn is_type(self) -> bool { - unsafe { LLVMIsTypeAttribute(self.attribute) == 1 } + unsafe { LLVMIsTypeAttribute(self.as_mut_ptr()) == 1 } } // private function to make code elsewhere easier @@ -196,7 +209,7 @@ impl Attribute { pub fn get_enum_kind_id(self) -> u32 { assert!(self.get_enum_kind_id_is_valid()); // FIXME: SubTypes - unsafe { LLVMGetEnumAttributeKind(self.attribute) } + unsafe { LLVMGetEnumAttributeKind(self.as_mut_ptr()) } } /// Gets the kind id associated with an enum `Attribute`. @@ -233,7 +246,7 @@ impl Attribute { pub fn get_enum_kind_id(self) -> u32 { assert!(self.get_enum_kind_id_is_valid()); // FIXME: SubTypes - unsafe { LLVMGetEnumAttributeKind(self.attribute) } + unsafe { LLVMGetEnumAttributeKind(self.as_mut_ptr()) } } #[cfg(feature = "llvm11-0")] @@ -274,7 +287,7 @@ impl Attribute { pub fn get_enum_value(self) -> u64 { assert!(self.is_enum()); // FIXME: SubTypes - unsafe { LLVMGetEnumAttributeValue(self.attribute) } + unsafe { LLVMGetEnumAttributeValue(self.as_mut_ptr()) } } /// Gets the string kind id associated with a string attribute. @@ -294,7 +307,7 @@ impl Attribute { assert!(self.is_string()); // FIXME: SubTypes let mut length = 0; - let cstr_ptr = unsafe { LLVMGetStringAttributeKind(self.attribute, &mut length) }; + let cstr_ptr = unsafe { LLVMGetStringAttributeKind(self.as_mut_ptr(), &mut length) }; unsafe { CStr::from_ptr(cstr_ptr) } } @@ -315,7 +328,7 @@ impl Attribute { assert!(self.is_string()); // FIXME: SubTypes let mut length = 0; - let cstr_ptr = unsafe { LLVMGetStringAttributeValue(self.attribute, &mut length) }; + let cstr_ptr = unsafe { LLVMGetStringAttributeValue(self.as_mut_ptr(), &mut length) }; unsafe { CStr::from_ptr(cstr_ptr) } } @@ -345,7 +358,7 @@ impl Attribute { pub fn get_type_value(&self) -> AnyTypeEnum<'_> { assert!(self.is_type()); // FIXME: SubTypes - unsafe { AnyTypeEnum::new(LLVMGetTypeAttributeValue(self.attribute)) } + unsafe { AnyTypeEnum::new(LLVMGetTypeAttributeValue(self.as_mut_ptr())) } } // private function to make code elsewhere easier diff --git a/src/basic_block.rs b/src/basic_block.rs index 85d6a9995e2..1b4778604c9 100644 --- a/src/basic_block.rs +++ b/src/basic_block.rs @@ -1,5 +1,6 @@ //! A `BasicBlock` is a container of instructions. +use llvm_sys::LLVMBasicBlock; use llvm_sys::core::{ LLVMBasicBlockAsValue, LLVMBlockAddress, LLVMDeleteBasicBlock, LLVMGetBasicBlockName, LLVMGetBasicBlockParent, LLVMGetBasicBlockTerminator, LLVMGetFirstInstruction, LLVMGetFirstUse, LLVMGetLastInstruction, @@ -10,12 +11,13 @@ use llvm_sys::core::{ use llvm_sys::prelude::{LLVMBasicBlockRef, LLVMValueRef}; use crate::context::ContextRef; -use crate::support::to_c_str; +use crate::support::{assert_niche, to_c_str}; use crate::values::{AsValueRef, BasicValueUse, FunctionValue, InstructionValue, PointerValue}; use std::ffi::CStr; use std::fmt; use std::marker::PhantomData; +use std::ptr::NonNull; /// A `BasicBlock` is a container of instructions. /// @@ -24,11 +26,13 @@ use std::marker::PhantomData; /// A well formed `BasicBlock` is a list of non terminating instructions followed by a single terminating /// instruction. `BasicBlock`s are allowed to be malformed prior to running validation because it may be useful /// when constructing or modifying a program. +#[repr(transparent)] #[derive(PartialEq, Eq, Clone, Copy, Hash)] pub struct BasicBlock<'ctx> { - pub(crate) basic_block: LLVMBasicBlockRef, + pub(crate) basic_block: NonNull, _marker: PhantomData<&'ctx ()>, } +const _: () = assert_niche::(); impl<'ctx> BasicBlock<'ctx> { /// Create a basic block from an [LLVMBasicBlockRef]. @@ -46,7 +50,7 @@ impl<'ctx> BasicBlock<'ctx> { assert!(!LLVMIsABasicBlock(basic_block as LLVMValueRef).is_null()); Some(BasicBlock { - basic_block, + basic_block: NonNull::new_unchecked(basic_block), _marker: PhantomData, }) } @@ -54,7 +58,7 @@ impl<'ctx> BasicBlock<'ctx> { /// Acquires the underlying raw pointer belonging to this `BasicBlock` type. pub fn as_mut_ptr(&self) -> LLVMBasicBlockRef { - self.basic_block + self.basic_block.as_ptr() } /// Obtains the `FunctionValue` that this `BasicBlock` belongs to, if any. @@ -80,7 +84,7 @@ impl<'ctx> BasicBlock<'ctx> { /// assert!(basic_block.get_parent().is_none()); /// ``` pub fn get_parent(self) -> Option> { - unsafe { FunctionValue::new(LLVMGetBasicBlockParent(self.basic_block)) } + unsafe { FunctionValue::new(LLVMGetBasicBlockParent(self.as_mut_ptr())) } } /// Gets the `BasicBlock` preceding the current one, in its own scope, if any. @@ -112,7 +116,7 @@ impl<'ctx> BasicBlock<'ctx> { pub fn get_previous_basic_block(self) -> Option> { self.get_parent()?; - unsafe { BasicBlock::new(LLVMGetPreviousBasicBlock(self.basic_block)) } + unsafe { BasicBlock::new(LLVMGetPreviousBasicBlock(self.as_mut_ptr())) } } /// Gets the `BasicBlock` succeeding the current one, in its own scope, if any. @@ -145,7 +149,7 @@ impl<'ctx> BasicBlock<'ctx> { pub fn get_next_basic_block(self) -> Option> { self.get_parent()?; - unsafe { BasicBlock::new(LLVMGetNextBasicBlock(self.basic_block)) } + unsafe { BasicBlock::new(LLVMGetNextBasicBlock(self.as_mut_ptr())) } } /// Prepends one `BasicBlock` before another. @@ -178,7 +182,7 @@ impl<'ctx> BasicBlock<'ctx> { return Err(()); } - unsafe { LLVMMoveBasicBlockBefore(self.basic_block, basic_block.basic_block) } + unsafe { LLVMMoveBasicBlockBefore(self.as_mut_ptr(), basic_block.as_mut_ptr()) } Ok(()) } @@ -213,7 +217,7 @@ impl<'ctx> BasicBlock<'ctx> { return Err(()); } - unsafe { LLVMMoveBasicBlockAfter(self.basic_block, basic_block.basic_block) } + unsafe { LLVMMoveBasicBlockAfter(self.as_mut_ptr(), basic_block.as_mut_ptr()) } Ok(()) } @@ -241,7 +245,7 @@ impl<'ctx> BasicBlock<'ctx> { /// assert_eq!(basic_block.get_first_instruction().unwrap().get_opcode(), InstructionOpcode::Return); /// ``` pub fn get_first_instruction(self) -> Option> { - let value = unsafe { LLVMGetFirstInstruction(self.basic_block) }; + let value = unsafe { LLVMGetFirstInstruction(self.as_mut_ptr()) }; if value.is_null() { return None; @@ -273,7 +277,7 @@ impl<'ctx> BasicBlock<'ctx> { /// assert_eq!(basic_block.get_last_instruction().unwrap().get_opcode(), InstructionOpcode::Return); /// ``` pub fn get_last_instruction(self) -> Option> { - let value = unsafe { LLVMGetLastInstruction(self.basic_block) }; + let value = unsafe { LLVMGetLastInstruction(self.as_mut_ptr()) }; if value.is_null() { return None; @@ -347,7 +351,7 @@ impl<'ctx> BasicBlock<'ctx> { // TODOC: Every BB must have a terminating instruction or else it is invalid // REVIEW: Unclear how this differs from get_last_instruction pub fn get_terminator(self) -> Option> { - let value = unsafe { LLVMGetBasicBlockTerminator(self.basic_block) }; + let value = unsafe { LLVMGetBasicBlockTerminator(self.as_mut_ptr()) }; if value.is_null() { return None; @@ -393,7 +397,7 @@ impl<'ctx> BasicBlock<'ctx> { return Err(()); } - unsafe { LLVMRemoveBasicBlockFromParent(self.basic_block) } + unsafe { LLVMRemoveBasicBlockFromParent(self.as_mut_ptr()) } Ok(()) } @@ -426,7 +430,7 @@ impl<'ctx> BasicBlock<'ctx> { return Err(()); } - LLVMDeleteBasicBlock(self.basic_block); + LLVMDeleteBasicBlock(self.as_mut_ptr()); Ok(()) } @@ -450,7 +454,7 @@ impl<'ctx> BasicBlock<'ctx> { /// assert_eq!(context, basic_block.get_context()); /// ``` pub fn get_context(self) -> ContextRef<'ctx> { - unsafe { ContextRef::new(LLVMGetTypeContext(LLVMTypeOf(LLVMBasicBlockAsValue(self.basic_block)))) } + unsafe { ContextRef::new(LLVMGetTypeContext(LLVMTypeOf(LLVMBasicBlockAsValue(self.as_mut_ptr())))) } } /// Gets the name of a `BasicBlock`. @@ -471,7 +475,7 @@ impl<'ctx> BasicBlock<'ctx> { /// assert_eq!(bb.get_name().to_str(), Ok("entry")); /// ``` pub fn get_name(&self) -> &CStr { - let ptr = unsafe { LLVMGetBasicBlockName(self.basic_block) }; + let ptr = unsafe { LLVMGetBasicBlockName(self.as_mut_ptr()) }; unsafe { CStr::from_ptr(ptr) } } @@ -482,7 +486,7 @@ impl<'ctx> BasicBlock<'ctx> { unsafe { LLVMSetValueName2( - LLVMBasicBlockAsValue(self.basic_block), + LLVMBasicBlockAsValue(self.as_mut_ptr()), c_string.as_ptr(), c_string.to_bytes().len(), ) @@ -513,8 +517,8 @@ impl<'ctx> BasicBlock<'ctx> { /// assert_eq!(branch_inst.get_operand(0).unwrap().unwrap_block(), bb2); /// ``` pub fn replace_all_uses_with(self, other: &BasicBlock<'ctx>) { - let value = unsafe { LLVMBasicBlockAsValue(self.basic_block) }; - let other = unsafe { LLVMBasicBlockAsValue(other.basic_block) }; + let value = unsafe { LLVMBasicBlockAsValue(self.as_mut_ptr()) }; + let other = unsafe { LLVMBasicBlockAsValue(other.as_mut_ptr()) }; // LLVM may infinite-loop when they aren't distinct, which is UB in C++. if value != other { @@ -549,7 +553,7 @@ impl<'ctx> BasicBlock<'ctx> { /// assert!(bb1.get_first_use().is_some()); /// ``` pub fn get_first_use(self) -> Option> { - let use_ = unsafe { LLVMGetFirstUse(LLVMBasicBlockAsValue(self.basic_block)) }; + let use_ = unsafe { LLVMGetFirstUse(LLVMBasicBlockAsValue(self.as_mut_ptr())) }; if use_.is_null() { return None; @@ -586,7 +590,7 @@ impl<'ctx> BasicBlock<'ctx> { // Taking the address of the entry block is illegal. self.get_previous_basic_block()?; - let value = PointerValue::new(LLVMBlockAddress(parent.as_value_ref(), self.basic_block)); + let value = PointerValue::new(LLVMBlockAddress(parent.as_value_ref(), self.as_mut_ptr())); if value.is_null() { return None; @@ -599,12 +603,12 @@ impl<'ctx> BasicBlock<'ctx> { impl fmt::Debug for BasicBlock<'_> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let llvm_value = unsafe { CStr::from_ptr(LLVMPrintValueToString(self.basic_block as LLVMValueRef)) }; - let llvm_type = unsafe { CStr::from_ptr(LLVMPrintTypeToString(LLVMTypeOf(self.basic_block as LLVMValueRef))) }; - let is_const = unsafe { LLVMIsConstant(self.basic_block as LLVMValueRef) == 1 }; + let llvm_value = unsafe { CStr::from_ptr(LLVMPrintValueToString(self.as_mut_ptr() as LLVMValueRef)) }; + let llvm_type = unsafe { CStr::from_ptr(LLVMPrintTypeToString(LLVMTypeOf(self.as_mut_ptr() as LLVMValueRef))) }; + let is_const = unsafe { LLVMIsConstant(self.as_mut_ptr() as LLVMValueRef) == 1 }; f.debug_struct("BasicBlock") - .field("address", &self.basic_block) + .field("address", &self.as_mut_ptr()) .field("is_const", &is_const) .field("llvm_value", &llvm_value) .field("llvm_type", &llvm_type) diff --git a/src/builder.rs b/src/builder.rs index a91f132a852..2cfeb1a63b5 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -1,5 +1,6 @@ //! A `Builder` enables you to build instructions. +use llvm_sys::LLVMBuilder; #[llvm_versions(18..)] use llvm_sys::core::LLVMBuildCallWithOperandBundles; use llvm_sys::core::{ @@ -50,7 +51,7 @@ use thiserror::Error; use crate::basic_block::BasicBlock; use crate::debug_info::DILocation; -use crate::support::to_c_str; +use crate::support::{assert_niche, to_c_str}; #[llvm_versions(15..)] use crate::types::FunctionType; use crate::types::{AsTypeRef, BasicType, FloatMathType, IntMathType, PointerMathType, PointerType}; @@ -69,6 +70,7 @@ use crate::{AtomicOrdering, AtomicRMWBinOp, FloatPredicate, IntPredicate}; use std::cell::Cell; use std::marker::PhantomData; +use std::ptr::NonNull; #[derive(Debug, PartialEq, Clone, Copy)] enum PositionState { @@ -118,28 +120,34 @@ pub enum BuilderError { /// Those methods all may return `BuilderError::UnsetPosition` if a `position_*` method has not yet been called, in addition /// to any other possibility. pub struct Builder<'ctx> { - builder: LLVMBuilderRef, + builder: NonNull, positioned: Cell, _marker: PhantomData<&'ctx ()>, } +const _: () = assert_niche::(); #[allow(unused)] // only used in documentation use crate::context::Context; impl<'ctx> Builder<'ctx> { + /// Create a new [Builder] from an [LLVMBuilderRef]. + /// + /// # Safety + /// + /// `builder` must be non-null and point to a valid value. pub unsafe fn new(builder: LLVMBuilderRef) -> Self { debug_assert!(!builder.is_null()); Builder { positioned: Cell::from(PositionState::NotSet), - builder, + builder: unsafe { NonNull::new_unchecked(builder) }, _marker: PhantomData, } } /// Acquires the underlying raw pointer belonging to this `Builder` type. pub fn as_mut_ptr(&self) -> LLVMBuilderRef { - self.builder + self.builder.as_ptr() } // REVIEW: Would probably make this API a bit simpler by taking Into> @@ -172,8 +180,8 @@ impl<'ctx> Builder<'ctx> { } let value = unsafe { value.map_or_else( - || LLVMBuildRetVoid(self.builder), - |value| LLVMBuildRet(self.builder, value.as_value_ref()), + || LLVMBuildRetVoid(self.as_mut_ptr()), + |value| LLVMBuildRet(self.as_mut_ptr(), value.as_value_ref()), ) }; @@ -211,7 +219,7 @@ impl<'ctx> Builder<'ctx> { return Err(BuilderError::UnsetPosition); } let mut args: Vec = values.iter().map(|val| val.as_value_ref()).collect(); - let value = unsafe { LLVMBuildAggregateRet(self.builder, args.as_mut_ptr(), args.len() as u32) }; + let value = unsafe { LLVMBuildAggregateRet(self.as_mut_ptr(), args.as_mut_ptr(), args.len() as u32) }; unsafe { Ok(InstructionValue::new(value)) } } @@ -271,7 +279,7 @@ impl<'ctx> Builder<'ctx> { #[allow(deprecated)] let value = unsafe { LLVMBuildCall( - self.builder, + self.builder.as_ptr(), fn_val_ref, args.as_mut_ptr(), args.len() as u32, @@ -476,7 +484,7 @@ impl<'ctx> Builder<'ctx> { let value = unsafe { LLVMBuildCall2( - self.builder, + self.as_mut_ptr(), fn_ty_ref, fn_val_ref, args.as_mut_ptr(), @@ -517,7 +525,7 @@ impl<'ctx> Builder<'ctx> { let value = unsafe { LLVMBuildCallWithOperandBundles( - self.builder, + self.as_mut_ptr(), fn_ty_ref, fn_val_ref, args.as_mut_ptr(), @@ -640,12 +648,12 @@ impl<'ctx> Builder<'ctx> { #[allow(deprecated)] let value = unsafe { LLVMBuildInvoke( - self.builder, + self.builder.as_ptr(), fn_val_ref, args.as_mut_ptr(), args.len() as u32, - then_block.basic_block, - catch_block.basic_block, + then_block.basic_block.as_ptr(), + catch_block.basic_block.as_ptr(), c_string.as_ptr(), ) }; @@ -818,13 +826,13 @@ impl<'ctx> Builder<'ctx> { let value = unsafe { LLVMBuildInvoke2( - self.builder, + self.as_mut_ptr(), fn_ty_ref, fn_val_ref, args.as_mut_ptr(), args.len() as u32, - then_block.basic_block, - catch_block.basic_block, + then_block.as_mut_ptr(), + catch_block.as_mut_ptr(), c_string.as_ptr(), ) }; @@ -1002,7 +1010,7 @@ impl<'ctx> Builder<'ctx> { let value = unsafe { LLVMBuildLandingPad( - self.builder, + self.as_mut_ptr(), exception_type.as_type_ref(), personality_function.as_value_ref(), num_clauses, @@ -1101,7 +1109,7 @@ impl<'ctx> Builder<'ctx> { if self.positioned.get() != PositionState::Set { return Err(BuilderError::UnsetPosition); } - let val = unsafe { LLVMBuildResume(self.builder, value.as_value_ref()) }; + let val = unsafe { LLVMBuildResume(self.as_mut_ptr(), value.as_value_ref()) }; unsafe { Ok(InstructionValue::new(val)) } } @@ -1126,7 +1134,7 @@ impl<'ctx> Builder<'ctx> { #[cfg(not(feature = "llvm16-0"))] #[allow(deprecated)] let value = LLVMBuildGEP( - self.builder, + self.builder.as_ptr(), ptr.as_value_ref(), index_values.as_mut_ptr(), index_values.len() as u32, @@ -1134,7 +1142,7 @@ impl<'ctx> Builder<'ctx> { ); #[cfg(feature = "llvm16-0")] let value = LLVMBuildGEP2( - self.builder, + self.builder.as_ptr(), ptr.get_type().get_element_type().as_type_ref(), ptr.as_value_ref(), index_values.as_mut_ptr(), @@ -1165,7 +1173,7 @@ impl<'ctx> Builder<'ctx> { let mut index_values: Vec = ordered_indexes.iter().map(|val| val.as_value_ref()).collect(); let value = LLVMBuildGEP2( - self.builder, + self.as_mut_ptr(), pointee_ty.as_type_ref(), ptr.as_value_ref(), index_values.as_mut_ptr(), @@ -1198,7 +1206,7 @@ impl<'ctx> Builder<'ctx> { #[cfg(not(feature = "llvm16-0"))] #[allow(deprecated)] let value = LLVMBuildInBoundsGEP( - self.builder, + self.builder.as_ptr(), ptr.as_value_ref(), index_values.as_mut_ptr(), index_values.len() as u32, @@ -1206,7 +1214,7 @@ impl<'ctx> Builder<'ctx> { ); #[cfg(feature = "llvm16-0")] let value = LLVMBuildInBoundsGEP2( - self.builder, + self.builder.as_ptr(), ptr.get_type().get_element_type().as_type_ref(), ptr.as_value_ref(), index_values.as_mut_ptr(), @@ -1238,7 +1246,7 @@ impl<'ctx> Builder<'ctx> { let mut index_values: Vec = ordered_indexes.iter().map(|val| val.as_value_ref()).collect(); let value = LLVMBuildInBoundsGEP2( - self.builder, + self.as_mut_ptr(), pointee_ty.as_type_ref(), ptr.as_value_ref(), index_values.as_mut_ptr(), @@ -1313,11 +1321,11 @@ impl<'ctx> Builder<'ctx> { #[cfg(not(feature = "llvm16-0"))] #[allow(deprecated)] - let value = unsafe { LLVMBuildStructGEP(self.builder, ptr.as_value_ref(), index, c_string.as_ptr()) }; + let value = unsafe { LLVMBuildStructGEP(self.builder.as_ptr(), ptr.as_value_ref(), index, c_string.as_ptr()) }; #[cfg(feature = "llvm16-0")] let value = unsafe { LLVMBuildStructGEP2( - self.builder, + self.builder.as_ptr(), ptr.get_type().get_element_type().as_type_ref(), ptr.as_value_ref(), index, @@ -1391,7 +1399,7 @@ impl<'ctx> Builder<'ctx> { let value = unsafe { LLVMBuildStructGEP2( - self.builder, + self.as_mut_ptr(), pointee_ty.as_type_ref(), ptr.as_value_ref(), index, @@ -1445,7 +1453,7 @@ impl<'ctx> Builder<'ctx> { #[allow(deprecated)] let value = unsafe { LLVMBuildPtrDiff( - self.builder, + self.builder.as_ptr(), lhs_ptr.as_value_ref(), rhs_ptr.as_value_ref(), c_string.as_ptr(), @@ -1459,7 +1467,7 @@ impl<'ctx> Builder<'ctx> { unsafe { LLVMBuildPtrDiff2( - self.builder, + self.builder.as_ptr(), lhs_ptr.get_type().get_element_type().as_type_ref(), lhs_ptr.as_value_ref(), rhs_ptr.as_value_ref(), @@ -1514,7 +1522,7 @@ impl<'ctx> Builder<'ctx> { let value = unsafe { LLVMBuildPtrDiff2( - self.builder, + self.as_mut_ptr(), pointee_ty.as_type_ref(), lhs_ptr.as_value_ref(), rhs_ptr.as_value_ref(), @@ -1535,7 +1543,7 @@ impl<'ctx> Builder<'ctx> { return Err(BuilderError::UnsetPosition); } let c_string = to_c_str(name); - let value = unsafe { LLVMBuildPhi(self.builder, type_.as_type_ref(), c_string.as_ptr()) }; + let value = unsafe { LLVMBuildPhi(self.as_mut_ptr(), type_.as_type_ref(), c_string.as_ptr()) }; unsafe { Ok(PhiValue::new(value)) } } @@ -1576,7 +1584,7 @@ impl<'ctx> Builder<'ctx> { if self.positioned.get() != PositionState::Set { return Err(BuilderError::UnsetPosition); } - let value = unsafe { LLVMBuildStore(self.builder, value.as_value_ref(), ptr.as_value_ref()) }; + let value = unsafe { LLVMBuildStore(self.as_mut_ptr(), value.as_value_ref(), ptr.as_value_ref()) }; unsafe { Ok(InstructionValue::new(value)) } } @@ -1618,11 +1626,11 @@ impl<'ctx> Builder<'ctx> { #[cfg(not(feature = "llvm16-0"))] #[allow(deprecated)] - let value = unsafe { LLVMBuildLoad(self.builder, ptr.as_value_ref(), c_string.as_ptr()) }; + let value = unsafe { LLVMBuildLoad(self.builder.as_ptr(), ptr.as_value_ref(), c_string.as_ptr()) }; #[cfg(feature = "llvm16-0")] let value = unsafe { LLVMBuildLoad2( - self.builder, + self.builder.as_ptr(), ptr.get_type().get_element_type().as_type_ref(), ptr.as_value_ref(), c_string.as_ptr(), @@ -1674,7 +1682,7 @@ impl<'ctx> Builder<'ctx> { let value = unsafe { LLVMBuildLoad2( - self.builder, + self.as_mut_ptr(), pointee_ty.as_type_ref(), ptr.as_value_ref(), c_string.as_ptr(), @@ -1690,7 +1698,7 @@ impl<'ctx> Builder<'ctx> { return Err(BuilderError::UnsetPosition); } let c_string = to_c_str(name); - let value = unsafe { LLVMBuildAlloca(self.builder, ty.as_type_ref(), c_string.as_ptr()) }; + let value = unsafe { LLVMBuildAlloca(self.as_mut_ptr(), ty.as_type_ref(), c_string.as_ptr()) }; unsafe { Ok(PointerValue::new(value)) } } @@ -1706,8 +1714,14 @@ impl<'ctx> Builder<'ctx> { return Err(BuilderError::UnsetPosition); } let c_string = to_c_str(name); - let value = - unsafe { LLVMBuildArrayAlloca(self.builder, ty.as_type_ref(), size.as_value_ref(), c_string.as_ptr()) }; + let value = unsafe { + LLVMBuildArrayAlloca( + self.as_mut_ptr(), + ty.as_type_ref(), + size.as_value_ref(), + c_string.as_ptr(), + ) + }; unsafe { Ok(PointerValue::new(value)) } } @@ -1747,7 +1761,7 @@ impl<'ctx> Builder<'ctx> { let value = unsafe { LLVMBuildMemCpy( - self.builder, + self.as_mut_ptr(), dest.as_value_ref(), dest_align_bytes, src.as_value_ref(), @@ -1794,7 +1808,7 @@ impl<'ctx> Builder<'ctx> { let value = unsafe { LLVMBuildMemMove( - self.builder, + self.as_mut_ptr(), dest.as_value_ref(), dest_align_bytes, src.as_value_ref(), @@ -1834,7 +1848,7 @@ impl<'ctx> Builder<'ctx> { let value = unsafe { LLVMBuildMemSet( - self.builder, + self.as_mut_ptr(), dest.as_value_ref(), val.as_value_ref(), size.as_value_ref(), @@ -1858,7 +1872,7 @@ impl<'ctx> Builder<'ctx> { let c_string = to_c_str(name); - let value = unsafe { LLVMBuildMalloc(self.builder, ty.as_type_ref(), c_string.as_ptr()) }; + let value = unsafe { LLVMBuildMalloc(self.as_mut_ptr(), ty.as_type_ref(), c_string.as_ptr()) }; unsafe { Ok(PointerValue::new(value)) } } @@ -1881,8 +1895,14 @@ impl<'ctx> Builder<'ctx> { let c_string = to_c_str(name); - let value = - unsafe { LLVMBuildArrayMalloc(self.builder, ty.as_type_ref(), size.as_value_ref(), c_string.as_ptr()) }; + let value = unsafe { + LLVMBuildArrayMalloc( + self.as_mut_ptr(), + ty.as_type_ref(), + size.as_value_ref(), + c_string.as_ptr(), + ) + }; unsafe { Ok(PointerValue::new(value)) } } @@ -1892,7 +1912,12 @@ impl<'ctx> Builder<'ctx> { if self.positioned.get() != PositionState::Set { return Err(BuilderError::UnsetPosition); } - unsafe { Ok(InstructionValue::new(LLVMBuildFree(self.builder, ptr.as_value_ref()))) } + unsafe { + Ok(InstructionValue::new(LLVMBuildFree( + self.as_mut_ptr(), + ptr.as_value_ref(), + ))) + } } pub fn insert_instruction(&self, instruction: &InstructionValue<'ctx>, name: Option<&str>) { @@ -1900,16 +1925,18 @@ impl<'ctx> Builder<'ctx> { Some(name) => { let c_string = to_c_str(name); - unsafe { LLVMInsertIntoBuilderWithName(self.builder, instruction.as_value_ref(), c_string.as_ptr()) } + unsafe { + LLVMInsertIntoBuilderWithName(self.as_mut_ptr(), instruction.as_value_ref(), c_string.as_ptr()) + } }, None => unsafe { - LLVMInsertIntoBuilder(self.builder, instruction.as_value_ref()); + LLVMInsertIntoBuilder(self.as_mut_ptr(), instruction.as_value_ref()); }, } } pub fn get_insert_block(&self) -> Option> { - unsafe { BasicBlock::new(LLVMGetInsertBlock(self.builder)) } + unsafe { BasicBlock::new(LLVMGetInsertBlock(self.as_mut_ptr())) } } // TODO: Possibly make this generic over sign via struct metadata or subtypes @@ -1920,7 +1947,14 @@ impl<'ctx> Builder<'ctx> { return Err(BuilderError::UnsetPosition); } let c_string = to_c_str(name); - let value = unsafe { LLVMBuildUDiv(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) }; + let value = unsafe { + LLVMBuildUDiv( + self.as_mut_ptr(), + lhs.as_value_ref(), + rhs.as_value_ref(), + c_string.as_ptr(), + ) + }; unsafe { Ok(T::new(value)) } } @@ -1932,7 +1966,14 @@ impl<'ctx> Builder<'ctx> { return Err(BuilderError::UnsetPosition); } let c_string = to_c_str(name); - let value = unsafe { LLVMBuildSDiv(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) }; + let value = unsafe { + LLVMBuildSDiv( + self.as_mut_ptr(), + lhs.as_value_ref(), + rhs.as_value_ref(), + c_string.as_ptr(), + ) + }; unsafe { Ok(T::new(value)) } } @@ -1949,8 +1990,14 @@ impl<'ctx> Builder<'ctx> { return Err(BuilderError::UnsetPosition); } let c_string = to_c_str(name); - let value = - unsafe { LLVMBuildExactSDiv(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) }; + let value = unsafe { + LLVMBuildExactSDiv( + self.as_mut_ptr(), + lhs.as_value_ref(), + rhs.as_value_ref(), + c_string.as_ptr(), + ) + }; unsafe { Ok(T::new(value)) } } @@ -1962,7 +2009,14 @@ impl<'ctx> Builder<'ctx> { return Err(BuilderError::UnsetPosition); } let c_string = to_c_str(name); - let value = unsafe { LLVMBuildURem(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) }; + let value = unsafe { + LLVMBuildURem( + self.as_mut_ptr(), + lhs.as_value_ref(), + rhs.as_value_ref(), + c_string.as_ptr(), + ) + }; unsafe { Ok(T::new(value)) } } @@ -1974,7 +2028,14 @@ impl<'ctx> Builder<'ctx> { return Err(BuilderError::UnsetPosition); } let c_string = to_c_str(name); - let value = unsafe { LLVMBuildSRem(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) }; + let value = unsafe { + LLVMBuildSRem( + self.as_mut_ptr(), + lhs.as_value_ref(), + rhs.as_value_ref(), + c_string.as_ptr(), + ) + }; unsafe { Ok(T::new(value)) } } @@ -1991,7 +2052,7 @@ impl<'ctx> Builder<'ctx> { let c_string = to_c_str(name); let value = unsafe { LLVMBuildSExt( - self.builder, + self.as_mut_ptr(), int_value.as_value_ref(), int_type.as_type_ref(), c_string.as_ptr(), @@ -2014,7 +2075,7 @@ impl<'ctx> Builder<'ctx> { let c_string = to_c_str(name); let value = unsafe { LLVMBuildAddrSpaceCast( - self.builder, + self.as_mut_ptr(), ptr_val.as_value_ref(), ptr_type.as_type_ref(), c_string.as_ptr(), @@ -2061,7 +2122,14 @@ impl<'ctx> Builder<'ctx> { return Err(BuilderError::UnsetPosition); } let c_string = to_c_str(name); - let value = unsafe { LLVMBuildBitCast(self.builder, val.as_value_ref(), ty.as_type_ref(), c_string.as_ptr()) }; + let value = unsafe { + LLVMBuildBitCast( + self.as_mut_ptr(), + val.as_value_ref(), + ty.as_type_ref(), + c_string.as_ptr(), + ) + }; unsafe { Ok(BasicValueEnum::new(value)) } } @@ -2078,7 +2146,7 @@ impl<'ctx> Builder<'ctx> { let c_string = to_c_str(name); let value = unsafe { LLVMBuildSExtOrBitCast( - self.builder, + self.as_mut_ptr(), int_value.as_value_ref(), int_type.as_type_ref(), c_string.as_ptr(), @@ -2100,7 +2168,7 @@ impl<'ctx> Builder<'ctx> { let c_string = to_c_str(name); let value = unsafe { LLVMBuildZExt( - self.builder, + self.as_mut_ptr(), int_value.as_value_ref(), int_type.as_type_ref(), c_string.as_ptr(), @@ -2122,7 +2190,7 @@ impl<'ctx> Builder<'ctx> { let c_string = to_c_str(name); let value = unsafe { LLVMBuildZExtOrBitCast( - self.builder, + self.as_mut_ptr(), int_value.as_value_ref(), int_type.as_type_ref(), c_string.as_ptr(), @@ -2145,7 +2213,7 @@ impl<'ctx> Builder<'ctx> { let value = unsafe { LLVMBuildTrunc( - self.builder, + self.as_mut_ptr(), int_value.as_value_ref(), int_type.as_type_ref(), c_string.as_ptr(), @@ -2168,7 +2236,7 @@ impl<'ctx> Builder<'ctx> { let value = unsafe { LLVMBuildTruncOrBitCast( - self.builder, + self.as_mut_ptr(), int_value.as_value_ref(), int_type.as_type_ref(), c_string.as_ptr(), @@ -2183,7 +2251,14 @@ impl<'ctx> Builder<'ctx> { return Err(BuilderError::UnsetPosition); } let c_string = to_c_str(name); - let value = unsafe { LLVMBuildFRem(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) }; + let value = unsafe { + LLVMBuildFRem( + self.as_mut_ptr(), + lhs.as_value_ref(), + rhs.as_value_ref(), + c_string.as_ptr(), + ) + }; unsafe { Ok(T::new(value)) } } @@ -2202,7 +2277,7 @@ impl<'ctx> Builder<'ctx> { let c_string = to_c_str(name); let value = unsafe { LLVMBuildFPToUI( - self.builder, + self.as_mut_ptr(), float.as_value_ref(), int_type.as_type_ref(), c_string.as_ptr(), @@ -2225,7 +2300,7 @@ impl<'ctx> Builder<'ctx> { let c_string = to_c_str(name); let value = unsafe { LLVMBuildFPToSI( - self.builder, + self.as_mut_ptr(), float.as_value_ref(), int_type.as_type_ref(), c_string.as_ptr(), @@ -2249,7 +2324,7 @@ impl<'ctx> Builder<'ctx> { let c_string = to_c_str(name); let value = unsafe { LLVMBuildUIToFP( - self.builder, + self.as_mut_ptr(), int.as_value_ref(), float_type.as_type_ref(), c_string.as_ptr(), @@ -2272,7 +2347,7 @@ impl<'ctx> Builder<'ctx> { let c_string = to_c_str(name); let value = unsafe { LLVMBuildSIToFP( - self.builder, + self.as_mut_ptr(), int.as_value_ref(), float_type.as_type_ref(), c_string.as_ptr(), @@ -2294,7 +2369,7 @@ impl<'ctx> Builder<'ctx> { let c_string = to_c_str(name); let value = unsafe { LLVMBuildFPTrunc( - self.builder, + self.as_mut_ptr(), float.as_value_ref(), float_type.as_type_ref(), c_string.as_ptr(), @@ -2316,7 +2391,7 @@ impl<'ctx> Builder<'ctx> { let c_string = to_c_str(name); let value = unsafe { LLVMBuildFPExt( - self.builder, + self.as_mut_ptr(), float.as_value_ref(), float_type.as_type_ref(), c_string.as_ptr(), @@ -2338,7 +2413,7 @@ impl<'ctx> Builder<'ctx> { let c_string = to_c_str(name); let value = unsafe { LLVMBuildFPCast( - self.builder, + self.as_mut_ptr(), float.as_value_ref(), float_type.as_type_ref(), c_string.as_ptr(), @@ -2361,7 +2436,7 @@ impl<'ctx> Builder<'ctx> { let c_string = to_c_str(name); let value = unsafe { LLVMBuildIntCast( - self.builder, + self.as_mut_ptr(), int.as_value_ref(), int_type.as_type_ref(), c_string.as_ptr(), @@ -2385,7 +2460,7 @@ impl<'ctx> Builder<'ctx> { let c_string = to_c_str(name); let value = unsafe { LLVMBuildIntCast2( - self.builder, + self.as_mut_ptr(), int.as_value_ref(), int_type.as_type_ref(), is_signed.into(), @@ -2401,7 +2476,14 @@ impl<'ctx> Builder<'ctx> { return Err(BuilderError::UnsetPosition); } let c_string = to_c_str(name); - let value = unsafe { LLVMBuildFDiv(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) }; + let value = unsafe { + LLVMBuildFDiv( + self.as_mut_ptr(), + lhs.as_value_ref(), + rhs.as_value_ref(), + c_string.as_ptr(), + ) + }; unsafe { Ok(T::new(value)) } } @@ -2412,7 +2494,14 @@ impl<'ctx> Builder<'ctx> { return Err(BuilderError::UnsetPosition); } let c_string = to_c_str(name); - let value = unsafe { LLVMBuildAdd(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) }; + let value = unsafe { + LLVMBuildAdd( + self.as_mut_ptr(), + lhs.as_value_ref(), + rhs.as_value_ref(), + c_string.as_ptr(), + ) + }; unsafe { Ok(T::new(value)) } } @@ -2421,7 +2510,14 @@ impl<'ctx> Builder<'ctx> { // SubType: (&self, lhs: &IntValue, rhs: &IntValue, name: &str) -> IntValue { pub fn build_int_nsw_add>(&self, lhs: T, rhs: T, name: &str) -> Result { let c_string = to_c_str(name); - let value = unsafe { LLVMBuildNSWAdd(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) }; + let value = unsafe { + LLVMBuildNSWAdd( + self.as_mut_ptr(), + lhs.as_value_ref(), + rhs.as_value_ref(), + c_string.as_ptr(), + ) + }; unsafe { Ok(T::new(value)) } } @@ -2433,7 +2529,14 @@ impl<'ctx> Builder<'ctx> { return Err(BuilderError::UnsetPosition); } let c_string = to_c_str(name); - let value = unsafe { LLVMBuildNUWAdd(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) }; + let value = unsafe { + LLVMBuildNUWAdd( + self.as_mut_ptr(), + lhs.as_value_ref(), + rhs.as_value_ref(), + c_string.as_ptr(), + ) + }; unsafe { Ok(T::new(value)) } } @@ -2444,7 +2547,14 @@ impl<'ctx> Builder<'ctx> { return Err(BuilderError::UnsetPosition); } let c_string = to_c_str(name); - let value = unsafe { LLVMBuildFAdd(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) }; + let value = unsafe { + LLVMBuildFAdd( + self.as_mut_ptr(), + lhs.as_value_ref(), + rhs.as_value_ref(), + c_string.as_ptr(), + ) + }; unsafe { Ok(T::new(value)) } } @@ -2455,7 +2565,14 @@ impl<'ctx> Builder<'ctx> { return Err(BuilderError::UnsetPosition); } let c_string = to_c_str(name); - let value = unsafe { LLVMBuildXor(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) }; + let value = unsafe { + LLVMBuildXor( + self.as_mut_ptr(), + lhs.as_value_ref(), + rhs.as_value_ref(), + c_string.as_ptr(), + ) + }; unsafe { Ok(T::new(value)) } } @@ -2466,7 +2583,14 @@ impl<'ctx> Builder<'ctx> { return Err(BuilderError::UnsetPosition); } let c_string = to_c_str(name); - let value = unsafe { LLVMBuildAnd(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) }; + let value = unsafe { + LLVMBuildAnd( + self.as_mut_ptr(), + lhs.as_value_ref(), + rhs.as_value_ref(), + c_string.as_ptr(), + ) + }; unsafe { Ok(T::new(value)) } } @@ -2477,7 +2601,14 @@ impl<'ctx> Builder<'ctx> { return Err(BuilderError::UnsetPosition); } let c_string = to_c_str(name); - let value = unsafe { LLVMBuildOr(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) }; + let value = unsafe { + LLVMBuildOr( + self.as_mut_ptr(), + lhs.as_value_ref(), + rhs.as_value_ref(), + c_string.as_ptr(), + ) + }; unsafe { Ok(T::new(value)) } } @@ -2530,7 +2661,14 @@ impl<'ctx> Builder<'ctx> { return Err(BuilderError::UnsetPosition); } let c_string = to_c_str(name); - let value = unsafe { LLVMBuildShl(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) }; + let value = unsafe { + LLVMBuildShl( + self.as_mut_ptr(), + lhs.as_value_ref(), + rhs.as_value_ref(), + c_string.as_ptr(), + ) + }; unsafe { Ok(T::new(value)) } } @@ -2612,9 +2750,19 @@ impl<'ctx> Builder<'ctx> { let c_string = to_c_str(name); let value = unsafe { if sign_extend { - LLVMBuildAShr(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) + LLVMBuildAShr( + self.as_mut_ptr(), + lhs.as_value_ref(), + rhs.as_value_ref(), + c_string.as_ptr(), + ) } else { - LLVMBuildLShr(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) + LLVMBuildLShr( + self.as_mut_ptr(), + lhs.as_value_ref(), + rhs.as_value_ref(), + c_string.as_ptr(), + ) } }; @@ -2627,7 +2775,14 @@ impl<'ctx> Builder<'ctx> { return Err(BuilderError::UnsetPosition); } let c_string = to_c_str(name); - let value = unsafe { LLVMBuildSub(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) }; + let value = unsafe { + LLVMBuildSub( + self.as_mut_ptr(), + lhs.as_value_ref(), + rhs.as_value_ref(), + c_string.as_ptr(), + ) + }; unsafe { Ok(T::new(value)) } } @@ -2638,7 +2793,14 @@ impl<'ctx> Builder<'ctx> { return Err(BuilderError::UnsetPosition); } let c_string = to_c_str(name); - let value = unsafe { LLVMBuildNSWSub(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) }; + let value = unsafe { + LLVMBuildNSWSub( + self.as_mut_ptr(), + lhs.as_value_ref(), + rhs.as_value_ref(), + c_string.as_ptr(), + ) + }; unsafe { Ok(T::new(value)) } } @@ -2650,7 +2812,14 @@ impl<'ctx> Builder<'ctx> { return Err(BuilderError::UnsetPosition); } let c_string = to_c_str(name); - let value = unsafe { LLVMBuildNUWSub(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) }; + let value = unsafe { + LLVMBuildNUWSub( + self.as_mut_ptr(), + lhs.as_value_ref(), + rhs.as_value_ref(), + c_string.as_ptr(), + ) + }; unsafe { Ok(T::new(value)) } } @@ -2661,7 +2830,14 @@ impl<'ctx> Builder<'ctx> { return Err(BuilderError::UnsetPosition); } let c_string = to_c_str(name); - let value = unsafe { LLVMBuildFSub(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) }; + let value = unsafe { + LLVMBuildFSub( + self.as_mut_ptr(), + lhs.as_value_ref(), + rhs.as_value_ref(), + c_string.as_ptr(), + ) + }; unsafe { Ok(T::new(value)) } } @@ -2672,7 +2848,14 @@ impl<'ctx> Builder<'ctx> { return Err(BuilderError::UnsetPosition); } let c_string = to_c_str(name); - let value = unsafe { LLVMBuildMul(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) }; + let value = unsafe { + LLVMBuildMul( + self.as_mut_ptr(), + lhs.as_value_ref(), + rhs.as_value_ref(), + c_string.as_ptr(), + ) + }; unsafe { Ok(T::new(value)) } } @@ -2684,7 +2867,14 @@ impl<'ctx> Builder<'ctx> { return Err(BuilderError::UnsetPosition); } let c_string = to_c_str(name); - let value = unsafe { LLVMBuildNSWMul(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) }; + let value = unsafe { + LLVMBuildNSWMul( + self.as_mut_ptr(), + lhs.as_value_ref(), + rhs.as_value_ref(), + c_string.as_ptr(), + ) + }; unsafe { Ok(T::new(value)) } } @@ -2696,7 +2886,14 @@ impl<'ctx> Builder<'ctx> { return Err(BuilderError::UnsetPosition); } let c_string = to_c_str(name); - let value = unsafe { LLVMBuildNUWMul(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) }; + let value = unsafe { + LLVMBuildNUWMul( + self.as_mut_ptr(), + lhs.as_value_ref(), + rhs.as_value_ref(), + c_string.as_ptr(), + ) + }; unsafe { Ok(T::new(value)) } } @@ -2707,7 +2904,14 @@ impl<'ctx> Builder<'ctx> { return Err(BuilderError::UnsetPosition); } let c_string = to_c_str(name); - let value = unsafe { LLVMBuildFMul(self.builder, lhs.as_value_ref(), rhs.as_value_ref(), c_string.as_ptr()) }; + let value = unsafe { + LLVMBuildFMul( + self.as_mut_ptr(), + lhs.as_value_ref(), + rhs.as_value_ref(), + c_string.as_ptr(), + ) + }; unsafe { Ok(T::new(value)) } } @@ -2725,7 +2929,7 @@ impl<'ctx> Builder<'ctx> { let c_string = to_c_str(name); let value = unsafe { LLVMBuildBinOp( - self.builder, + self.as_mut_ptr(), op.into(), lhs.as_value_ref(), rhs.as_value_ref(), @@ -2749,7 +2953,7 @@ impl<'ctx> Builder<'ctx> { let c_string = to_c_str(name); let value = unsafe { LLVMBuildCast( - self.builder, + self.as_mut_ptr(), op.into(), from_value.as_value_ref(), to_type.as_type_ref(), @@ -2771,8 +2975,14 @@ impl<'ctx> Builder<'ctx> { return Err(BuilderError::UnsetPosition); } let c_string = to_c_str(name); - let value = - unsafe { LLVMBuildPointerCast(self.builder, from.as_value_ref(), to.as_type_ref(), c_string.as_ptr()) }; + let value = unsafe { + LLVMBuildPointerCast( + self.as_mut_ptr(), + from.as_value_ref(), + to.as_type_ref(), + c_string.as_ptr(), + ) + }; unsafe { Ok(T::new(value)) } } @@ -2794,7 +3004,7 @@ impl<'ctx> Builder<'ctx> { let c_string = to_c_str(name); let value = unsafe { LLVMBuildICmp( - self.builder, + self.as_mut_ptr(), op.into(), lhs.as_value_ref(), rhs.as_value_ref(), @@ -2822,7 +3032,7 @@ impl<'ctx> Builder<'ctx> { let value = unsafe { LLVMBuildFCmp( - self.builder, + self.as_mut_ptr(), op.into(), lhs.as_value_ref(), rhs.as_value_ref(), @@ -2840,7 +3050,7 @@ impl<'ctx> Builder<'ctx> { if self.positioned.get() != PositionState::Set { return Err(BuilderError::UnsetPosition); } - let value = unsafe { LLVMBuildBr(self.builder, destination_block.basic_block) }; + let value = unsafe { LLVMBuildBr(self.as_mut_ptr(), destination_block.as_mut_ptr()) }; unsafe { Ok(InstructionValue::new(value)) } } @@ -2856,10 +3066,10 @@ impl<'ctx> Builder<'ctx> { } let value = unsafe { LLVMBuildCondBr( - self.builder, + self.as_mut_ptr(), comparison.as_value_ref(), - then_block.basic_block, - else_block.basic_block, + then_block.as_mut_ptr(), + else_block.as_mut_ptr(), ) }; @@ -2874,10 +3084,11 @@ impl<'ctx> Builder<'ctx> { if self.positioned.get() != PositionState::Set { return Err(BuilderError::UnsetPosition); } - let value = unsafe { LLVMBuildIndirectBr(self.builder, address.as_value_ref(), destinations.len() as u32) }; + let value = + unsafe { LLVMBuildIndirectBr(self.as_mut_ptr(), address.as_value_ref(), destinations.len() as u32) }; for destination in destinations { - unsafe { LLVMAddDestination(value, destination.basic_block) } + unsafe { LLVMAddDestination(value, destination.as_mut_ptr()) } } unsafe { Ok(InstructionValue::new(value)) } @@ -2889,7 +3100,7 @@ impl<'ctx> Builder<'ctx> { return Err(BuilderError::UnsetPosition); } let c_string = to_c_str(name); - let value = unsafe { LLVMBuildNeg(self.builder, value.as_value_ref(), c_string.as_ptr()) }; + let value = unsafe { LLVMBuildNeg(self.as_mut_ptr(), value.as_value_ref(), c_string.as_ptr()) }; unsafe { Ok(T::new(value)) } } @@ -2901,7 +3112,7 @@ impl<'ctx> Builder<'ctx> { return Err(BuilderError::UnsetPosition); } let c_string = to_c_str(name); - let value = unsafe { LLVMBuildNSWNeg(self.builder, value.as_value_ref(), c_string.as_ptr()) }; + let value = unsafe { LLVMBuildNSWNeg(self.as_mut_ptr(), value.as_value_ref(), c_string.as_ptr()) }; unsafe { Ok(T::new(value)) } } @@ -2913,7 +3124,7 @@ impl<'ctx> Builder<'ctx> { return Err(BuilderError::UnsetPosition); } let c_string = to_c_str(name); - let value = unsafe { LLVMBuildNUWNeg(self.builder, value.as_value_ref(), c_string.as_ptr()) }; + let value = unsafe { LLVMBuildNUWNeg(self.builder.as_ptr(), value.as_value_ref(), c_string.as_ptr()) }; unsafe { Ok(T::new(value)) } } @@ -2924,7 +3135,7 @@ impl<'ctx> Builder<'ctx> { return Err(BuilderError::UnsetPosition); } let c_string = to_c_str(name); - let value = unsafe { LLVMBuildNeg(self.builder, value.as_value_ref(), c_string.as_ptr()) }; + let value = unsafe { LLVMBuildNeg(self.as_mut_ptr(), value.as_value_ref(), c_string.as_ptr()) }; unsafe { LLVMSetNUW(value, true.into()); } @@ -2938,7 +3149,7 @@ impl<'ctx> Builder<'ctx> { return Err(BuilderError::UnsetPosition); } let c_string = to_c_str(name); - let value = unsafe { LLVMBuildFNeg(self.builder, value.as_value_ref(), c_string.as_ptr()) }; + let value = unsafe { LLVMBuildFNeg(self.as_mut_ptr(), value.as_value_ref(), c_string.as_ptr()) }; unsafe { Ok(T::new(value)) } } @@ -2949,7 +3160,7 @@ impl<'ctx> Builder<'ctx> { return Err(BuilderError::UnsetPosition); } let c_string = to_c_str(name); - let value = unsafe { LLVMBuildNot(self.builder, value.as_value_ref(), c_string.as_ptr()) }; + let value = unsafe { LLVMBuildNot(self.as_mut_ptr(), value.as_value_ref(), c_string.as_ptr()) }; unsafe { Ok(T::new(value)) } } @@ -2962,7 +3173,7 @@ impl<'ctx> Builder<'ctx> { pub fn position_at(&self, basic_block: BasicBlock<'ctx>, instruction: &InstructionValue<'ctx>) { self.positioned.set(PositionState::Set); - unsafe { LLVMPositionBuilder(self.builder, basic_block.basic_block, instruction.as_value_ref()) } + unsafe { LLVMPositionBuilder(self.as_mut_ptr(), basic_block.as_mut_ptr(), instruction.as_value_ref()) } } /// Set the position of the builder to before an instruction. @@ -2971,7 +3182,7 @@ impl<'ctx> Builder<'ctx> { pub fn position_before(&self, instruction: &InstructionValue<'ctx>) { self.positioned.set(PositionState::Set); - unsafe { LLVMPositionBuilderBefore(self.builder, instruction.as_value_ref()) } + unsafe { LLVMPositionBuilderBefore(self.as_mut_ptr(), instruction.as_value_ref()) } } /// Set the position of the builder to the end of a basic block. @@ -2981,7 +3192,7 @@ impl<'ctx> Builder<'ctx> { self.positioned.set(PositionState::Set); unsafe { - LLVMPositionBuilderAtEnd(self.builder, basic_block.basic_block); + LLVMPositionBuilderAtEnd(self.as_mut_ptr(), basic_block.as_mut_ptr()); } } @@ -3051,7 +3262,7 @@ impl<'ctx> Builder<'ctx> { let c_string = to_c_str(name); - let value = unsafe { LLVMBuildExtractValue(self.builder, agg.as_value_ref(), index, c_string.as_ptr()) }; + let value = unsafe { LLVMBuildExtractValue(self.as_mut_ptr(), agg.as_value_ref(), index, c_string.as_ptr()) }; unsafe { Ok(BasicValueEnum::new(value)) } } @@ -3124,7 +3335,7 @@ impl<'ctx> Builder<'ctx> { let value = unsafe { LLVMBuildInsertValue( - self.builder, + self.as_mut_ptr(), agg.as_value_ref(), value.as_value_ref(), index, @@ -3172,7 +3383,7 @@ impl<'ctx> Builder<'ctx> { let value = unsafe { LLVMBuildExtractElement( - self.builder, + self.as_mut_ptr(), vector.as_value_ref(), index.as_value_ref(), c_string.as_ptr(), @@ -3221,7 +3432,7 @@ impl<'ctx> Builder<'ctx> { let value = unsafe { LLVMBuildInsertElement( - self.builder, + self.as_mut_ptr(), vector.as_value_ref(), element.as_value_ref(), index.as_value_ref(), @@ -3236,7 +3447,7 @@ impl<'ctx> Builder<'ctx> { if self.positioned.get() != PositionState::Set { return Err(BuilderError::UnsetPosition); } - let val = unsafe { LLVMBuildUnreachable(self.builder) }; + let val = unsafe { LLVMBuildUnreachable(self.as_mut_ptr()) }; unsafe { Ok(InstructionValue::new(val)) } } @@ -3264,7 +3475,7 @@ impl<'ctx> Builder<'ctx> { let val = unsafe { LLVMBuildFence( - self.builder, + self.as_mut_ptr(), atomic_ordering.into(), is_single_thread as i32, c_string.as_ptr(), @@ -3285,7 +3496,7 @@ impl<'ctx> Builder<'ctx> { return Err(BuilderError::UnsetPosition); } let c_string = to_c_str(name); - let val = unsafe { LLVMBuildIsNull(self.builder, ptr.as_value_ref(), c_string.as_ptr()) }; + let val = unsafe { LLVMBuildIsNull(self.as_mut_ptr(), ptr.as_value_ref(), c_string.as_ptr()) }; unsafe { Ok(<::PtrConvType as IntMathType>::ValueType::new(val)) } } @@ -3301,7 +3512,7 @@ impl<'ctx> Builder<'ctx> { return Err(BuilderError::UnsetPosition); } let c_string = to_c_str(name); - let val = unsafe { LLVMBuildIsNotNull(self.builder, ptr.as_value_ref(), c_string.as_ptr()) }; + let val = unsafe { LLVMBuildIsNotNull(self.as_mut_ptr(), ptr.as_value_ref(), c_string.as_ptr()) }; unsafe { Ok(<::PtrConvType as IntMathType>::ValueType::new(val)) } } @@ -3321,7 +3532,7 @@ impl<'ctx> Builder<'ctx> { let value = unsafe { LLVMBuildIntToPtr( - self.builder, + self.as_mut_ptr(), int.as_value_ref(), ptr_type.as_type_ref(), c_string.as_ptr(), @@ -3346,7 +3557,7 @@ impl<'ctx> Builder<'ctx> { let value = unsafe { LLVMBuildPtrToInt( - self.builder, + self.as_mut_ptr(), ptr.as_value_ref(), int_type.as_type_ref(), c_string.as_ptr(), @@ -3358,7 +3569,7 @@ impl<'ctx> Builder<'ctx> { pub fn clear_insertion_position(&self) { self.positioned.set(PositionState::NotSet); - unsafe { LLVMClearInsertionPosition(self.builder) } + unsafe { LLVMClearInsertionPosition(self.as_mut_ptr()) } } // REVIEW: Returning InstructionValue is the safe move here; but if the value means something @@ -3375,15 +3586,15 @@ impl<'ctx> Builder<'ctx> { } let switch_value = unsafe { LLVMBuildSwitch( - self.builder, + self.as_mut_ptr(), value.as_value_ref(), - else_block.basic_block, + else_block.as_mut_ptr(), cases.len() as u32, ) }; for &(value, basic_block) in cases { - unsafe { LLVMAddCase(switch_value, value.as_value_ref(), basic_block.basic_block) } + unsafe { LLVMAddCase(switch_value, value.as_value_ref(), basic_block.as_mut_ptr()) } } unsafe { Ok(InstructionValue::new(switch_value)) } @@ -3403,7 +3614,7 @@ impl<'ctx> Builder<'ctx> { let c_string = to_c_str(name); let value = unsafe { LLVMBuildSelect( - self.builder, + self.as_mut_ptr(), condition.as_value_ref(), then.as_value_ref(), else_.as_value_ref(), @@ -3422,7 +3633,7 @@ impl<'ctx> Builder<'ctx> { } let c_string_value = to_c_str(value); let c_string_name = to_c_str(name); - let value = LLVMBuildGlobalString(self.builder, c_string_value.as_ptr(), c_string_name.as_ptr()); + let value = LLVMBuildGlobalString(self.as_mut_ptr(), c_string_value.as_ptr(), c_string_name.as_ptr()); Ok(GlobalValue::new(value)) } @@ -3436,7 +3647,8 @@ impl<'ctx> Builder<'ctx> { } let c_string_value = to_c_str(value); let c_string_name = to_c_str(name); - let value = unsafe { LLVMBuildGlobalStringPtr(self.builder, c_string_value.as_ptr(), c_string_name.as_ptr()) }; + let value = + unsafe { LLVMBuildGlobalStringPtr(self.as_mut_ptr(), c_string_value.as_ptr(), c_string_name.as_ptr()) }; unsafe { Ok(GlobalValue::new(value)) } } @@ -3455,7 +3667,7 @@ impl<'ctx> Builder<'ctx> { let c_string = to_c_str(name); let value = unsafe { LLVMBuildShuffleVector( - self.builder, + self.as_mut_ptr(), left.as_value_ref(), right.as_value_ref(), mask.as_value_ref(), @@ -3482,7 +3694,7 @@ impl<'ctx> Builder<'ctx> { let value = unsafe { LLVMBuildVAArg( - self.builder, + self.as_mut_ptr(), list.as_value_ref(), type_.as_type_ref(), c_string.as_ptr(), @@ -3557,7 +3769,7 @@ impl<'ctx> Builder<'ctx> { let val = unsafe { LLVMBuildAtomicRMW( - self.builder, + self.as_mut_ptr(), op.into(), ptr.as_value_ref(), value.as_value_ref(), @@ -3646,7 +3858,7 @@ impl<'ctx> Builder<'ctx> { let val = unsafe { LLVMBuildAtomicCmpXchg( - self.builder, + self.as_mut_ptr(), ptr.as_value_ref(), cmp.as_value_ref(), new.as_value_ref(), @@ -3663,7 +3875,7 @@ impl<'ctx> Builder<'ctx> { pub fn set_current_debug_location(&self, location: DILocation<'ctx>) { use llvm_sys::core::LLVMSetCurrentDebugLocation2; unsafe { - LLVMSetCurrentDebugLocation2(self.builder, location.metadata_ref); + LLVMSetCurrentDebugLocation2(self.as_mut_ptr(), location.as_mut_ptr()); } } @@ -3671,12 +3883,9 @@ impl<'ctx> Builder<'ctx> { /// if available. pub fn get_current_debug_location(&self) -> Option> { use llvm_sys::core::LLVMGetCurrentDebugLocation2; - let metadata_ref = unsafe { LLVMGetCurrentDebugLocation2(self.builder) }; - if metadata_ref.is_null() { - return None; - } + let metadata_ref = unsafe { LLVMGetCurrentDebugLocation2(self.as_mut_ptr()) }; Some(DILocation { - metadata_ref, + metadata_ref: NonNull::new(metadata_ref)?, _marker: PhantomData, }) } @@ -3686,7 +3895,7 @@ impl<'ctx> Builder<'ctx> { pub fn unset_current_debug_location(&self) { use llvm_sys::core::LLVMSetCurrentDebugLocation2; unsafe { - LLVMSetCurrentDebugLocation2(self.builder, std::ptr::null_mut()); + LLVMSetCurrentDebugLocation2(self.as_mut_ptr(), std::ptr::null_mut()); } } } @@ -3703,7 +3912,7 @@ fn is_alignment_ok(align: u32) -> bool { impl Drop for Builder<'_> { fn drop(&mut self) { unsafe { - LLVMDisposeBuilder(self.builder); + LLVMDisposeBuilder(self.as_mut_ptr()); } } } diff --git a/src/comdat.rs b/src/comdat.rs index 385a255af94..a8f6cc12938 100644 --- a/src/comdat.rs +++ b/src/comdat.rs @@ -2,9 +2,14 @@ // https://llvm.org/doxygen/IR_2Comdat_8h_source.html // https://stackoverflow.com/questions/1834597/what-is-the-comdat-section-used-for +use std::ptr::NonNull; + +use llvm_sys::LLVMComdat; use llvm_sys::comdat::{LLVMComdatSelectionKind, LLVMGetComdatSelectionKind, LLVMSetComdatSelectionKind}; use llvm_sys::prelude::LLVMComdatRef; +use crate::support::assert_niche; + #[llvm_enum(LLVMComdatSelectionKind)] #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] /// Determines how linker conflicts are to be resolved. @@ -27,31 +32,37 @@ pub enum ComdatSelectionKind { } /// A `Comdat` determines how to resolve duplicate sections when linking. +#[repr(transparent)] #[derive(Debug, PartialEq, Eq, Copy, Clone)] -pub struct Comdat(pub(crate) LLVMComdatRef); +pub struct Comdat(pub(crate) NonNull); +const _: () = assert_niche::(); impl Comdat { - /// Creates a new `Comdat` type from a raw pointer. + /// Creates a new [Comdat] type from an [LLVMComdatRef]. + /// + /// # Safety + /// + /// `comdat` must be non-null and point to a valid value. pub unsafe fn new(comdat: LLVMComdatRef) -> Self { debug_assert!(!comdat.is_null()); - Comdat(comdat) + Comdat(unsafe { NonNull::new_unchecked(comdat) }) } /// Acquires the underlying raw pointer belonging to this `Comdat` type. pub fn as_mut_ptr(&self) -> LLVMComdatRef { - self.0 + self.0.as_ptr() } /// Gets what kind of `Comdat` this is. pub fn get_selection_kind(self) -> ComdatSelectionKind { - let kind_ptr = unsafe { LLVMGetComdatSelectionKind(self.0) }; + let kind_ptr = unsafe { LLVMGetComdatSelectionKind(self.as_mut_ptr()) }; ComdatSelectionKind::new(kind_ptr) } /// Sets what kind of `Comdat` this should be. pub fn set_selection_kind(self, kind: ComdatSelectionKind) { - unsafe { LLVMSetComdatSelectionKind(self.0, kind.into()) } + unsafe { LLVMSetComdatSelectionKind(self.as_mut_ptr(), kind.into()) } } } diff --git a/src/context.rs b/src/context.rs index 1467be35e50..9f5b1f0d912 100644 --- a/src/context.rs +++ b/src/context.rs @@ -1,7 +1,9 @@ //! A `Context` is an opaque owner and manager of core global data. use crate::InlineAsmDialect; +use crate::support::assert_niche; use libc::c_void; +use llvm_sys::LLVMContext; #[cfg(all(any(feature = "llvm15-0", feature = "llvm16-0"), feature = "typed-pointers"))] use llvm_sys::core::LLVMContextSetOpaquePointers; #[llvm_versions(12..)] @@ -37,6 +39,7 @@ use llvm_sys::ir_reader::LLVMParseIRInContext2; use llvm_sys::prelude::{LLVMContextRef, LLVMDiagnosticInfoRef, LLVMMetadataRef, LLVMTypeRef, LLVMValueRef}; use llvm_sys::target::{LLVMIntPtrTypeForASInContext, LLVMIntPtrTypeInContext}; use std::cell::LazyCell; +use std::ptr::NonNull; use std::sync::{LazyLock, Mutex, MutexGuard}; use crate::AddressSpace; @@ -87,10 +90,17 @@ thread_local! { const LLVM_MAX_INT_BITS: u32 = 1 << 23; /// This struct allows us to share method impls across Context and ContextRef types +#[repr(transparent)] #[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub(crate) struct ContextImpl(pub(crate) LLVMContextRef); +pub(crate) struct ContextImpl(pub(crate) NonNull); +const _: () = assert_niche::(); impl ContextImpl { + /// Create a new [ContextImpl] from an [LLVMContextRef]. + /// + /// # Safety + /// + /// `context` must be non-null and point to a valid value. pub(crate) unsafe fn new(context: LLVMContextRef) -> Self { assert!(!context.is_null()); @@ -99,17 +109,21 @@ impl ContextImpl { LLVMContextSetOpaquePointers(context, 0) }; - ContextImpl(context) + ContextImpl(unsafe { NonNull::new_unchecked(context) }) + } + + pub fn as_mut_ptr(&self) -> LLVMContextRef { + self.0.as_ptr() } fn create_builder<'ctx>(&self) -> Builder<'ctx> { - unsafe { Builder::new(LLVMCreateBuilderInContext(self.0)) } + unsafe { Builder::new(LLVMCreateBuilderInContext(self.as_mut_ptr())) } } fn create_module<'ctx>(&self, name: &str) -> Module<'ctx> { let c_string = to_c_str(name); - unsafe { Module::new(LLVMModuleCreateWithNameInContext(c_string.as_ptr(), self.0)) } + unsafe { Module::new(LLVMModuleCreateWithNameInContext(c_string.as_ptr(), self.as_mut_ptr())) } } fn create_module_from_ir<'ctx>(&self, memory_buffer: MemoryBuffer) -> Result, LLVMString> { @@ -117,9 +131,11 @@ impl ContextImpl { let mut err_str = ptr::null_mut(); #[cfg(not(feature = "llvm22-1"))] - let code = unsafe { LLVMParseIRInContext(self.0, memory_buffer.memory_buffer, &mut module, &mut err_str) }; + let code = + unsafe { LLVMParseIRInContext(self.as_mut_ptr(), memory_buffer.as_mut_ptr(), &mut module, &mut err_str) }; #[cfg(feature = "llvm22-1")] - let code = unsafe { LLVMParseIRInContext2(self.0, memory_buffer.memory_buffer, &mut module, &mut err_str) }; + let code = + unsafe { LLVMParseIRInContext2(self.as_mut_ptr(), memory_buffer.as_mut_ptr(), &mut module, &mut err_str) }; forget(memory_buffer); @@ -163,27 +179,27 @@ impl ContextImpl { } fn void_type<'ctx>(&self) -> VoidType<'ctx> { - unsafe { VoidType::new(LLVMVoidTypeInContext(self.0)) } + unsafe { VoidType::new(LLVMVoidTypeInContext(self.as_mut_ptr())) } } fn bool_type<'ctx>(&self) -> IntType<'ctx> { - unsafe { IntType::new(LLVMInt1TypeInContext(self.0)) } + unsafe { IntType::new(LLVMInt1TypeInContext(self.as_mut_ptr())) } } fn i8_type<'ctx>(&self) -> IntType<'ctx> { - unsafe { IntType::new(LLVMInt8TypeInContext(self.0)) } + unsafe { IntType::new(LLVMInt8TypeInContext(self.as_mut_ptr())) } } fn i16_type<'ctx>(&self) -> IntType<'ctx> { - unsafe { IntType::new(LLVMInt16TypeInContext(self.0)) } + unsafe { IntType::new(LLVMInt16TypeInContext(self.as_mut_ptr())) } } fn i32_type<'ctx>(&self) -> IntType<'ctx> { - unsafe { IntType::new(LLVMInt32TypeInContext(self.0)) } + unsafe { IntType::new(LLVMInt32TypeInContext(self.as_mut_ptr())) } } fn i64_type<'ctx>(&self) -> IntType<'ctx> { - unsafe { IntType::new(LLVMInt64TypeInContext(self.0)) } + unsafe { IntType::new(LLVMInt64TypeInContext(self.as_mut_ptr())) } } // TODO: Call LLVMInt128TypeInContext in applicable versions @@ -195,29 +211,29 @@ impl ContextImpl { let width = bits.get(); if width <= LLVM_MAX_INT_BITS { - unsafe { Ok(IntType::new(LLVMIntTypeInContext(self.0, width))) } + unsafe { Ok(IntType::new(LLVMIntTypeInContext(self.as_mut_ptr(), width))) } } else { Err("LLVM only supports integers with bit widths between 1 and 8388608 (inclusive)") } } fn metadata_type<'ctx>(&self) -> MetadataType<'ctx> { - unsafe { MetadataType::new(LLVMMetadataTypeInContext(self.0)) } + unsafe { MetadataType::new(LLVMMetadataTypeInContext(self.as_mut_ptr())) } } fn ptr_sized_int_type<'ctx>(&self, target_data: &TargetData, address_space: Option) -> IntType<'ctx> { let int_type_ptr = match address_space { Some(address_space) => unsafe { - LLVMIntPtrTypeForASInContext(self.0, target_data.target_data, address_space.0) + LLVMIntPtrTypeForASInContext(self.as_mut_ptr(), target_data.target_data.as_ptr(), address_space.0) }, - None => unsafe { LLVMIntPtrTypeInContext(self.0, target_data.target_data) }, + None => unsafe { LLVMIntPtrTypeInContext(self.as_mut_ptr(), target_data.target_data.as_ptr()) }, }; unsafe { IntType::new(int_type_ptr) } } fn f16_type<'ctx>(&self) -> FloatType<'ctx> { - unsafe { FloatType::new(LLVMHalfTypeInContext(self.0)) } + unsafe { FloatType::new(LLVMHalfTypeInContext(self.as_mut_ptr())) } } #[cfg(any( @@ -235,39 +251,39 @@ impl ContextImpl { feature = "llvm22-1", ))] fn bf16_type<'ctx>(&self) -> FloatType<'ctx> { - unsafe { FloatType::new(LLVMBFloatTypeInContext(self.0)) } + unsafe { FloatType::new(LLVMBFloatTypeInContext(self.as_mut_ptr())) } } fn f32_type<'ctx>(&self) -> FloatType<'ctx> { - unsafe { FloatType::new(LLVMFloatTypeInContext(self.0)) } + unsafe { FloatType::new(LLVMFloatTypeInContext(self.as_mut_ptr())) } } fn f64_type<'ctx>(&self) -> FloatType<'ctx> { - unsafe { FloatType::new(LLVMDoubleTypeInContext(self.0)) } + unsafe { FloatType::new(LLVMDoubleTypeInContext(self.as_mut_ptr())) } } fn x86_f80_type<'ctx>(&self) -> FloatType<'ctx> { - unsafe { FloatType::new(LLVMX86FP80TypeInContext(self.0)) } + unsafe { FloatType::new(LLVMX86FP80TypeInContext(self.as_mut_ptr())) } } fn f128_type<'ctx>(&self) -> FloatType<'ctx> { - unsafe { FloatType::new(LLVMFP128TypeInContext(self.0)) } + unsafe { FloatType::new(LLVMFP128TypeInContext(self.as_mut_ptr())) } } fn ppc_f128_type<'ctx>(&self) -> FloatType<'ctx> { - unsafe { FloatType::new(LLVMPPCFP128TypeInContext(self.0)) } + unsafe { FloatType::new(LLVMPPCFP128TypeInContext(self.as_mut_ptr())) } } #[cfg(not(feature = "typed-pointers"))] fn ptr_type<'ctx>(&self, address_space: AddressSpace) -> PointerType<'ctx> { - unsafe { PointerType::new(LLVMPointerTypeInContext(self.0, address_space.0)) } + unsafe { PointerType::new(LLVMPointerTypeInContext(self.as_mut_ptr(), address_space.0)) } } fn struct_type<'ctx>(&self, field_types: &[BasicTypeEnum], packed: bool) -> StructType<'ctx> { let mut field_types: Vec = field_types.iter().map(|val| val.as_type_ref()).collect(); unsafe { StructType::new(LLVMStructTypeInContext( - self.0, + self.as_mut_ptr(), field_types.as_mut_ptr(), field_types.len() as u32, packed as i32, @@ -278,14 +294,14 @@ impl ContextImpl { fn opaque_struct_type<'ctx>(&self, name: &str) -> StructType<'ctx> { let c_string = to_c_str(name); - unsafe { StructType::new(LLVMStructCreateNamed(self.0, c_string.as_ptr())) } + unsafe { StructType::new(LLVMStructCreateNamed(self.as_mut_ptr(), c_string.as_ptr())) } } #[llvm_versions(12..)] fn get_struct_type<'ctx>(&self, name: &str) -> Option> { let c_string = to_c_str(name); - let ty = unsafe { LLVMGetTypeByName2(self.0, c_string.as_ptr()) }; + let ty = unsafe { LLVMGetTypeByName2(self.as_mut_ptr(), c_string.as_ptr()) }; if ty.is_null() { return None; } @@ -297,7 +313,7 @@ impl ContextImpl { let mut args: Vec = values.iter().map(|val| val.as_value_ref()).collect(); unsafe { StructValue::new(LLVMConstStructInContext( - self.0, + self.as_mut_ptr(), args.as_mut_ptr(), args.len() as u32, packed as i32, @@ -310,7 +326,7 @@ impl ContextImpl { unsafe { BasicBlock::new(LLVMAppendBasicBlockInContext( - self.0, + self.as_mut_ptr(), function.as_value_ref(), c_string.as_ptr(), )) @@ -334,8 +350,8 @@ impl ContextImpl { unsafe { BasicBlock::new(LLVMInsertBasicBlockInContext( - self.0, - basic_block.basic_block, + self.as_mut_ptr(), + basic_block.as_mut_ptr(), c_string.as_ptr(), )) .expect("Prepending basic block should never fail") @@ -349,8 +365,8 @@ impl ContextImpl { .collect(); unsafe { - let metadata = LLVMMDNodeInContext2(self.0, tuple_values.as_mut_ptr(), tuple_values.len()); - MetadataValue::new(LLVMMetadataAsValue(self.0, metadata)) + let metadata = LLVMMDNodeInContext2(self.as_mut_ptr(), tuple_values.as_mut_ptr(), tuple_values.len()); + MetadataValue::new(LLVMMetadataAsValue(self.as_mut_ptr(), metadata)) } } @@ -358,23 +374,29 @@ impl ContextImpl { let c_string = to_c_str(string); unsafe { - let metadata = LLVMMDStringInContext2(self.0, c_string.as_ptr(), c_string.count_bytes()); - MetadataValue::new(LLVMMetadataAsValue(self.0, metadata)) + let metadata = LLVMMDStringInContext2(self.as_mut_ptr(), c_string.as_ptr(), c_string.count_bytes()); + MetadataValue::new(LLVMMetadataAsValue(self.as_mut_ptr(), metadata)) } } fn get_kind_id(&self, key: &str) -> u32 { - unsafe { LLVMGetMDKindIDInContext(self.0, key.as_ptr() as *const ::libc::c_char, key.len() as u32) } + unsafe { + LLVMGetMDKindIDInContext( + self.as_mut_ptr(), + key.as_ptr() as *const ::libc::c_char, + key.len() as u32, + ) + } } fn create_enum_attribute(&self, kind_id: u32, val: u64) -> Attribute { - unsafe { Attribute::new(LLVMCreateEnumAttribute(self.0, kind_id, val)) } + unsafe { Attribute::new(LLVMCreateEnumAttribute(self.as_mut_ptr(), kind_id, val)) } } fn create_string_attribute(&self, key: &str, val: &str) -> Attribute { unsafe { Attribute::new(LLVMCreateStringAttribute( - self.0, + self.as_mut_ptr(), key.as_ptr() as *const _, key.len() as u32, val.as_ptr() as *const _, @@ -385,14 +407,20 @@ impl ContextImpl { #[llvm_versions(12..)] fn create_type_attribute(&self, kind_id: u32, type_ref: AnyTypeEnum) -> Attribute { - unsafe { Attribute::new(LLVMCreateTypeAttribute(self.0, kind_id, type_ref.as_type_ref())) } + unsafe { + Attribute::new(LLVMCreateTypeAttribute( + self.as_mut_ptr(), + kind_id, + type_ref.as_type_ref(), + )) + } } #[llvm_versions(..19)] fn const_string<'ctx>(&self, string: &[u8], null_terminated: bool) -> ArrayValue<'ctx> { unsafe { ArrayValue::new(LLVMConstStringInContext( - self.0, + self.as_mut_ptr(), string.as_ptr() as *const ::libc::c_char, string.len() as u32, !null_terminated as i32, @@ -404,7 +432,7 @@ impl ContextImpl { fn const_string<'ctx>(&self, string: &[u8], null_terminated: bool) -> ArrayValue<'ctx> { unsafe { ArrayValue::new(LLVMConstStringInContext2( - self.0, + self.as_mut_ptr(), string.as_ptr() as *const ::libc::c_char, string.len(), !null_terminated as i32, @@ -417,7 +445,7 @@ impl ContextImpl { handler: extern "C" fn(LLVMDiagnosticInfoRef, *mut c_void), void_ptr: *mut c_void, ) { - unsafe { LLVMContextSetDiagnosticHandler(self.0, Some(handler), void_ptr) } + unsafe { LLVMContextSetDiagnosticHandler(self.as_mut_ptr(), Some(handler), void_ptr) } } } @@ -437,10 +465,12 @@ impl PartialEq> for Context { /// /// A `Context` is not thread safe and cannot be shared across threads. Multiple `Context`s /// can, however, execute on different threads simultaneously according to the LLVM docs. +#[repr(transparent)] #[derive(Debug, PartialEq, Eq)] pub struct Context { pub(crate) context: ContextImpl, } +const _: () = assert_niche::(); unsafe impl Send for Context {} @@ -450,7 +480,7 @@ impl Context { /// This function is exposed only for interoperability with other LLVM IR libraries. /// It's not intended to be used by most users. pub fn raw(&self) -> LLVMContextRef { - self.context.0 + self.context.as_mut_ptr() } /// Creates a new `Context` from [`LLVMContextRef`]. @@ -1352,17 +1382,19 @@ impl Context { impl Drop for Context { fn drop(&mut self) { unsafe { - LLVMContextDispose(self.context.0); + LLVMContextDispose(self.context.as_mut_ptr()); } } } /// A `ContextRef` is a smart pointer allowing borrowed access to a type's `Context`. +#[repr(transparent)] #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub struct ContextRef<'ctx> { pub(crate) context: ContextImpl, _marker: PhantomData<&'ctx Context>, } +const _: () = assert_niche::(); impl<'ctx> ContextRef<'ctx> { /// Get raw [`LLVMContextRef`]. @@ -1370,7 +1402,7 @@ impl<'ctx> ContextRef<'ctx> { /// This function is exposed only for interoperability with other LLVM IR libraries. /// It's not intended to be used by most users. pub fn raw(&self) -> LLVMContextRef { - self.context.0 + self.context.as_mut_ptr() } /// Creates a new `ContextRef` from [`LLVMContextRef`]. @@ -2226,13 +2258,13 @@ pub unsafe trait AsContextRef<'ctx> { unsafe impl<'ctx> AsContextRef<'ctx> for &'ctx Context { /// Acquires the underlying raw pointer belonging to this `Context` type. fn as_ctx_ref(&self) -> LLVMContextRef { - self.context.0 + self.context.as_mut_ptr() } } unsafe impl<'ctx> AsContextRef<'ctx> for ContextRef<'ctx> { /// Acquires the underlying raw pointer belonging to this `ContextRef` type. fn as_ctx_ref(&self) -> LLVMContextRef { - self.context.0 + self.context.as_mut_ptr() } } diff --git a/src/data_layout.rs b/src/data_layout.rs index c6ad87e2a6c..f016155ce0f 100644 --- a/src/data_layout.rs +++ b/src/data_layout.rs @@ -1,5 +1,5 @@ -use std::ffi::CStr; use std::fmt; +use std::{ffi::CStr, ptr::NonNull}; use crate::support::{LLVMString, LLVMStringOrRaw}; @@ -23,7 +23,7 @@ impl DataLayout { debug_assert!(!data_layout.is_null()); DataLayout { - data_layout: LLVMStringOrRaw::Borrowed(data_layout), + data_layout: LLVMStringOrRaw::Borrowed(unsafe { NonNull::new_unchecked(data_layout.cast_mut()) }), } } @@ -33,8 +33,8 @@ impl DataLayout { pub fn as_ptr(&self) -> *const ::libc::c_char { match self.data_layout { - LLVMStringOrRaw::Owned(ref llvm_string) => llvm_string.ptr, - LLVMStringOrRaw::Borrowed(ptr) => ptr, + LLVMStringOrRaw::Owned(ref llvm_string) => llvm_string.ptr.as_ptr(), + LLVMStringOrRaw::Borrowed(ptr) => ptr.as_ptr().cast_const(), } } } diff --git a/src/debug_info.rs b/src/debug_info.rs index 8435f0e10e0..90922e07550 100644 --- a/src/debug_info.rs +++ b/src/debug_info.rs @@ -105,9 +105,11 @@ use crate::basic_block::BasicBlock; use crate::context::{AsContextRef, Context}; pub use crate::debug_info::flags::{DIFlags, DIFlagsConstants}; use crate::module::Module; +use crate::support::assert_niche; use crate::values::{AsValueRef, BasicValueEnum, InstructionValue, MetadataValue, PointerValue}; use llvm_sys::core::LLVMMetadataAsValue; +use llvm_sys::{LLVMOpaqueDIBuilder, LLVMOpaqueMetadata}; use llvm_sys::debuginfo::LLVMDIBuilderCreateTypedef; pub use llvm_sys::debuginfo::LLVMDWARFTypeEncoding; @@ -149,6 +151,7 @@ use llvm_sys::prelude::{LLVMDIBuilderRef, LLVMMetadataRef}; use std::convert::TryInto; use std::marker::PhantomData; use std::ops::Range; +use std::ptr::NonNull; /// Gets the version of debug metadata produced by the current LLVM version. pub fn debug_metadata_version() -> libc::c_uint { @@ -158,25 +161,29 @@ pub fn debug_metadata_version() -> libc::c_uint { /// A builder object to create debug info metadata. Used along with `Builder` while producing /// IR. Created by `Module::create_debug_info_builder`. See `debug_info` module level /// documentation for more. +#[repr(transparent)] #[derive(Debug, PartialEq, Eq)] pub struct DebugInfoBuilder<'ctx> { - pub(crate) builder: LLVMDIBuilderRef, + pub(crate) builder: NonNull, _marker: PhantomData<&'ctx Context>, } +const _: () = assert_niche::(); /// Any kind of debug information scope (i.e. visibility of a source code symbol). Scopes are /// created by special `DebugInfoBuilder` methods (eg `create_lexical_block`) and can be turned /// into a `DIScope` with the `AsDIScope::as_debug_info_scope` trait method. +#[repr(transparent)] #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub struct DIScope<'ctx> { - metadata_ref: LLVMMetadataRef, + metadata_ref: NonNull, _marker: PhantomData<&'ctx Context>, } +const _: () = assert_niche::(); impl DIScope<'_> { /// Acquires the underlying raw pointer belonging to this `DIScope` type. pub fn as_mut_ptr(&self) -> LLVMMetadataRef { - self.metadata_ref + self.metadata_ref.as_ptr() } } @@ -236,14 +243,14 @@ impl<'ctx> DebugInfoBuilder<'ctx> { ) -> (Self, DICompileUnit<'ctx>) { let builder = unsafe { if allow_unresolved { - LLVMCreateDIBuilder(module.module.get()) + LLVMCreateDIBuilder(module.as_mut_ptr()) } else { - LLVMCreateDIBuilderDisallowUnresolved(module.module.get()) + LLVMCreateDIBuilderDisallowUnresolved(module.as_mut_ptr()) } }; let builder = DebugInfoBuilder { - builder, + builder: unsafe { NonNull::new_unchecked(builder) }, _marker: PhantomData, }; @@ -298,7 +305,7 @@ impl<'ctx> DebugInfoBuilder<'ctx> { /// Acquires the underlying raw pointer belonging to this `DebugInfoBuilder` type. pub fn as_mut_ptr(&self) -> LLVMDIBuilderRef { - self.builder + self.builder.as_ptr() } /// A DICompileUnit provides an anchor for all debugging information generated during this instance of compilation. @@ -360,9 +367,9 @@ impl<'ctx> DebugInfoBuilder<'ctx> { ) -> DICompileUnit<'ctx> { let metadata_ref = unsafe { LLVMDIBuilderCreateCompileUnit( - self.builder, + self.as_mut_ptr(), language.into(), - file.metadata_ref, + file.as_mut_ptr(), producer.as_ptr() as _, producer.len(), is_optimized as _, @@ -381,10 +388,11 @@ impl<'ctx> DebugInfoBuilder<'ctx> { sdk.len(), ) }; + debug_assert!(!metadata_ref.is_null(), "metadata_ref must not be null."); DICompileUnit { file, - metadata_ref, + metadata_ref: unsafe { NonNull::new_unchecked(metadata_ref) }, _marker: PhantomData, } } @@ -422,15 +430,15 @@ impl<'ctx> DebugInfoBuilder<'ctx> { let metadata_ref = unsafe { LLVMDIBuilderCreateFunction( - self.builder, - scope.metadata_ref, + self.as_mut_ptr(), + scope.as_mut_ptr(), name.as_ptr() as _, name.len(), linkage_name.as_ptr() as _, linkage_name.len(), - file.metadata_ref, + file.as_mut_ptr(), line_no, - ditype.metadata_ref, + ditype.as_mut_ptr(), is_local_to_unit as _, is_definition as _, scope_line as libc::c_uint, @@ -438,8 +446,9 @@ impl<'ctx> DebugInfoBuilder<'ctx> { is_optimized as _, ) }; + debug_assert!(!metadata_ref.is_null(), "metadata_ref must not be null."); DISubprogram { - metadata_ref, + metadata_ref: unsafe { NonNull::new_unchecked(metadata_ref) }, _marker: PhantomData, } } @@ -454,15 +463,16 @@ impl<'ctx> DebugInfoBuilder<'ctx> { ) -> DILexicalBlock<'ctx> { let metadata_ref = unsafe { LLVMDIBuilderCreateLexicalBlock( - self.builder, - parent_scope.metadata_ref, - file.metadata_ref, + self.as_mut_ptr(), + parent_scope.as_mut_ptr(), + file.as_mut_ptr(), line as libc::c_uint, column as libc::c_uint, ) }; + debug_assert!(!metadata_ref.is_null(), "metadata_ref must not be null."); DILexicalBlock { - metadata_ref, + metadata_ref: unsafe { NonNull::new_unchecked(metadata_ref) }, _marker: PhantomData, } } @@ -471,15 +481,16 @@ impl<'ctx> DebugInfoBuilder<'ctx> { pub fn create_file(&self, filename: &str, directory: &str) -> DIFile<'ctx> { let metadata_ref = unsafe { LLVMDIBuilderCreateFile( - self.builder, + self.as_mut_ptr(), filename.as_ptr() as _, filename.len(), directory.as_ptr() as _, directory.len(), ) }; + debug_assert!(!metadata_ref.is_null(), "metadata_ref must not be null."); DIFile { - metadata_ref, + metadata_ref: unsafe { NonNull::new_unchecked(metadata_ref) }, _marker: PhantomData, } } @@ -498,12 +509,13 @@ impl<'ctx> DebugInfoBuilder<'ctx> { context.as_ctx_ref(), line, column, - scope.metadata_ref, - inlined_at.map(|l| l.metadata_ref).unwrap_or(std::ptr::null_mut()), + scope.as_mut_ptr(), + inlined_at.map(|l| l.as_mut_ptr()).unwrap_or(std::ptr::null_mut()), ) }; + debug_assert!(!metadata_ref.is_null(), "metadata_ref must not be null."); DILocation { - metadata_ref, + metadata_ref: unsafe { NonNull::new_unchecked(metadata_ref) }, _marker: PhantomData, } } @@ -524,7 +536,7 @@ impl<'ctx> DebugInfoBuilder<'ctx> { } let metadata_ref = unsafe { LLVMDIBuilderCreateBasicType( - self.builder, + self.as_mut_ptr(), name.as_ptr() as _, name.len(), size_in_bits, @@ -532,8 +544,9 @@ impl<'ctx> DebugInfoBuilder<'ctx> { flags, ) }; + debug_assert!(!metadata_ref.is_null(), "metadata_ref must not be null."); Ok(DIBasicType { - metadata_ref, + metadata_ref: unsafe { NonNull::new_unchecked(metadata_ref) }, _marker: PhantomData, }) } @@ -550,18 +563,19 @@ impl<'ctx> DebugInfoBuilder<'ctx> { ) -> DIDerivedType<'ctx> { let metadata_ref = unsafe { LLVMDIBuilderCreateTypedef( - self.builder, - ditype.metadata_ref, + self.as_mut_ptr(), + ditype.as_mut_ptr(), name.as_ptr() as _, name.len(), - file.metadata_ref, + file.as_mut_ptr(), line_no, - scope.metadata_ref, + scope.as_mut_ptr(), align_in_bits, ) }; + debug_assert!(!metadata_ref.is_null(), "metadata_ref must not be null."); DIDerivedType { - metadata_ref, + metadata_ref: unsafe { NonNull::new_unchecked(metadata_ref) }, _marker: PhantomData, } } @@ -580,14 +594,14 @@ impl<'ctx> DebugInfoBuilder<'ctx> { runtime_language: u32, unique_id: &str, ) -> DICompositeType<'ctx> { - let mut elements: Vec = elements.iter().map(|dt| dt.metadata_ref).collect(); + let mut elements: Vec = elements.iter().map(|dt| dt.as_mut_ptr()).collect(); let metadata_ref = unsafe { LLVMDIBuilderCreateUnionType( - self.builder, - scope.metadata_ref, + self.as_mut_ptr(), + scope.as_mut_ptr(), name.as_ptr() as _, name.len(), - file.metadata_ref, + file.as_mut_ptr(), line_no, size_in_bits, align_in_bits, @@ -599,8 +613,9 @@ impl<'ctx> DebugInfoBuilder<'ctx> { unique_id.len(), ) }; + debug_assert!(!metadata_ref.is_null(), "metadata_ref must not be null."); DICompositeType { - metadata_ref, + metadata_ref: unsafe { NonNull::new_unchecked(metadata_ref) }, _marker: PhantomData, } } @@ -620,21 +635,22 @@ impl<'ctx> DebugInfoBuilder<'ctx> { ) -> DIDerivedType<'ctx> { let metadata_ref = unsafe { LLVMDIBuilderCreateMemberType( - self.builder, - scope.metadata_ref, + self.as_mut_ptr(), + scope.as_mut_ptr(), name.as_ptr() as _, name.len(), - file.metadata_ref, + file.as_mut_ptr(), line_no, size_in_bits, align_in_bits, offset_in_bits, flags, - ty.metadata_ref, + ty.as_mut_ptr(), ) }; + debug_assert!(!metadata_ref.is_null(), "metadata_ref must not be null."); DIDerivedType { - metadata_ref, + metadata_ref: unsafe { NonNull::new_unchecked(metadata_ref) }, _marker: PhantomData, } } @@ -655,16 +671,16 @@ impl<'ctx> DebugInfoBuilder<'ctx> { vtable_holder: Option>, unique_id: &str, ) -> DICompositeType<'ctx> { - let mut elements: Vec = elements.iter().map(|dt| dt.metadata_ref).collect(); - let derived_from = derived_from.map_or(std::ptr::null_mut(), |dt| dt.metadata_ref); - let vtable_holder = vtable_holder.map_or(std::ptr::null_mut(), |dt| dt.metadata_ref); + let mut elements: Vec = elements.iter().map(|dt| dt.as_mut_ptr()).collect(); + let derived_from = derived_from.map_or(std::ptr::null_mut(), |dt| dt.as_mut_ptr()); + let vtable_holder = vtable_holder.map_or(std::ptr::null_mut(), |dt| dt.as_mut_ptr()); let metadata_ref = unsafe { LLVMDIBuilderCreateStructType( - self.builder, - scope.metadata_ref, + self.as_mut_ptr(), + scope.as_mut_ptr(), name.as_ptr() as _, name.len(), - file.metadata_ref, + file.as_mut_ptr(), line_no, size_in_bits, align_in_bits, @@ -678,8 +694,9 @@ impl<'ctx> DebugInfoBuilder<'ctx> { unique_id.len(), ) }; + debug_assert!(!metadata_ref.is_null(), "metadata_ref must not be null."); DICompositeType { - metadata_ref, + metadata_ref: unsafe { NonNull::new_unchecked(metadata_ref) }, _marker: PhantomData, } } @@ -692,24 +709,25 @@ impl<'ctx> DebugInfoBuilder<'ctx> { parameter_types: &[DIType<'ctx>], flags: DIFlags, ) -> DISubroutineType<'ctx> { - let mut p = vec![return_type.map_or(std::ptr::null_mut(), |t| t.metadata_ref)]; + let mut p = vec![return_type.map_or(std::ptr::null_mut(), |t| t.as_mut_ptr())]; p.append( &mut parameter_types .iter() - .map(|t| t.metadata_ref) + .map(|t| t.as_mut_ptr()) .collect::>(), ); let metadata_ref = unsafe { LLVMDIBuilderCreateSubroutineType( - self.builder, - file.metadata_ref, + self.as_mut_ptr(), + file.as_mut_ptr(), p.as_mut_ptr(), p.len().try_into().unwrap(), flags, ) }; + debug_assert!(!metadata_ref.is_null(), "metadata_ref must not be null."); DISubroutineType { - metadata_ref, + metadata_ref: unsafe { NonNull::new_unchecked(metadata_ref) }, _marker: PhantomData, } } @@ -725,8 +743,8 @@ impl<'ctx> DebugInfoBuilder<'ctx> { ) -> DIDerivedType<'ctx> { let metadata_ref = unsafe { LLVMDIBuilderCreatePointerType( - self.builder, - pointee.metadata_ref, + self.as_mut_ptr(), + pointee.as_mut_ptr(), size_in_bits, align_in_bits, address_space.0, @@ -734,19 +752,19 @@ impl<'ctx> DebugInfoBuilder<'ctx> { name.len(), ) }; - + debug_assert!(!metadata_ref.is_null(), "metadata_ref must not be null"); DIDerivedType { - metadata_ref, + metadata_ref: unsafe { NonNull::new_unchecked(metadata_ref) }, _marker: PhantomData, } } /// Creates a pointer type pub fn create_reference_type(&self, pointee: DIType<'ctx>, tag: u32) -> DIDerivedType<'ctx> { - let metadata_ref = unsafe { LLVMDIBuilderCreateReferenceType(self.builder, tag, pointee.metadata_ref) }; - + let metadata_ref = unsafe { LLVMDIBuilderCreateReferenceType(self.as_mut_ptr(), tag, pointee.as_mut_ptr()) }; + debug_assert!(!metadata_ref.is_null(), "metadata_ref must not be null."); DIDerivedType { - metadata_ref, + metadata_ref: unsafe { NonNull::new_unchecked(metadata_ref) }, _marker: PhantomData, } } @@ -766,22 +784,22 @@ impl<'ctx> DebugInfoBuilder<'ctx> { let lower = range.start; let upper = range.end; let subscript_size = upper - lower; - unsafe { LLVMDIBuilderGetOrCreateSubrange(self.builder, lower, subscript_size) } + unsafe { LLVMDIBuilderGetOrCreateSubrange(self.as_mut_ptr(), lower, subscript_size) } }) .collect::>(); let metadata_ref = unsafe { LLVMDIBuilderCreateArrayType( - self.builder, + self.as_mut_ptr(), size_in_bits, align_in_bits, - inner_type.metadata_ref, + inner_type.as_mut_ptr(), subscripts.as_mut_ptr(), subscripts.len().try_into().unwrap(), ) }; - + debug_assert!(!metadata_ref.is_null(), "metadata_ref must not be null."); DICompositeType { - metadata_ref, + metadata_ref: unsafe { NonNull::new_unchecked(metadata_ref) }, _marker: PhantomData, } } @@ -798,25 +816,25 @@ impl<'ctx> DebugInfoBuilder<'ctx> { elements: &[DIEnumerator<'ctx>], inner_type: DIType<'ctx>, ) -> DICompositeType<'ctx> { - let mut elements: Vec = elements.iter().map(|dt| dt.metadata_ref).collect(); + let mut elements: Vec = elements.iter().map(|dt| dt.as_mut_ptr()).collect(); let metadata_ref = unsafe { LLVMDIBuilderCreateEnumerationType( - self.builder, - scope.metadata_ref, + self.as_mut_ptr(), + scope.as_mut_ptr(), name.as_ptr() as _, name.len(), - file.metadata_ref, + file.as_mut_ptr(), line_no, size_in_bits, align_in_bits, elements.as_mut_ptr(), elements.len().try_into().unwrap(), - inner_type.metadata_ref, + inner_type.as_mut_ptr(), ) }; - + debug_assert!(!metadata_ref.is_null(), "metadata_ref must not be null."); DICompositeType { - metadata_ref, + metadata_ref: unsafe { NonNull::new_unchecked(metadata_ref) }, _marker: PhantomData, } } @@ -824,11 +842,17 @@ impl<'ctx> DebugInfoBuilder<'ctx> { /// Create an enumerator pub fn create_enumerator(&self, name: &str, value: i64, is_unsigned: bool) -> DIEnumerator<'ctx> { let metadata_ref = unsafe { - LLVMDIBuilderCreateEnumerator(self.builder, name.as_ptr() as _, name.len(), value, is_unsigned as i32) + LLVMDIBuilderCreateEnumerator( + self.as_mut_ptr(), + name.as_ptr() as _, + name.len(), + value, + is_unsigned as i32, + ) }; - + debug_assert!(!metadata_ref.is_null(), "metadata_ref must not be null."); DIEnumerator { - metadata_ref, + metadata_ref: unsafe { NonNull::new_unchecked(metadata_ref) }, _marker: PhantomData, } } @@ -846,36 +870,37 @@ impl<'ctx> DebugInfoBuilder<'ctx> { declaration: Option, align_in_bits: u32, ) -> DIGlobalVariableExpression<'ctx> { - let expression_ptr = expression.map_or(std::ptr::null_mut(), |dt| dt.metadata_ref); - let decl_ptr = declaration.map_or(std::ptr::null_mut(), |dt| dt.metadata_ref); + let expression_ptr = expression.map_or(std::ptr::null_mut(), |dt| dt.as_mut_ptr()); + let decl_ptr = declaration.map_or(std::ptr::null_mut(), |dt| dt.as_mut_ptr()); let metadata_ref = unsafe { LLVMDIBuilderCreateGlobalVariableExpression( - self.builder, - scope.metadata_ref, + self.as_mut_ptr(), + scope.as_mut_ptr(), name.as_ptr() as _, name.len(), linkage.as_ptr() as _, linkage.len(), - file.metadata_ref, + file.as_mut_ptr(), line_no, - ty.metadata_ref, + ty.as_mut_ptr(), local_to_unit as _, expression_ptr, decl_ptr, align_in_bits, ) }; + debug_assert!(!metadata_ref.is_null(), "metadata_ref must not be null."); DIGlobalVariableExpression { - metadata_ref, + metadata_ref: unsafe { NonNull::new_unchecked(metadata_ref) }, _marker: PhantomData, } } pub fn create_constant_expression(&self, value: i64) -> DIExpression<'ctx> { - let metadata_ref = unsafe { LLVMDIBuilderCreateConstantValueExpression(self.builder, value as _) }; - + let metadata_ref = unsafe { LLVMDIBuilderCreateConstantValueExpression(self.as_mut_ptr(), value as _) }; + debug_assert!(!metadata_ref.is_null(), "metadata_ref must not be null."); DIExpression { - metadata_ref, + metadata_ref: unsafe { NonNull::new_unchecked(metadata_ref) }, _marker: PhantomData, } } @@ -894,20 +919,21 @@ impl<'ctx> DebugInfoBuilder<'ctx> { ) -> DILocalVariable<'ctx> { let metadata_ref = unsafe { LLVMDIBuilderCreateParameterVariable( - self.builder, - scope.metadata_ref, + self.as_mut_ptr(), + scope.as_mut_ptr(), name.as_ptr() as _, name.len(), arg_no, - file.metadata_ref, + file.as_mut_ptr(), line_no, - ty.metadata_ref, + ty.as_mut_ptr(), always_preserve as _, flags, ) }; + debug_assert!(!metadata_ref.is_null(), "metadata_ref must not be null."); DILocalVariable { - metadata_ref, + metadata_ref: unsafe { NonNull::new_unchecked(metadata_ref) }, _marker: PhantomData, } } @@ -926,20 +952,21 @@ impl<'ctx> DebugInfoBuilder<'ctx> { ) -> DILocalVariable<'ctx> { let metadata_ref = unsafe { LLVMDIBuilderCreateAutoVariable( - self.builder, - scope.metadata_ref, + self.as_mut_ptr(), + scope.as_mut_ptr(), name.as_ptr() as _, name.len(), - file.metadata_ref, + file.as_mut_ptr(), line_no, - ty.metadata_ref, + ty.as_mut_ptr(), always_preserve as _, flags, align_in_bits, ) }; + debug_assert!(!metadata_ref.is_null(), "metadata_ref must not be null."); DILocalVariable { - metadata_ref, + metadata_ref: unsafe { NonNull::new_unchecked(metadata_ref) }, _marker: PhantomData, } } @@ -947,15 +974,16 @@ impl<'ctx> DebugInfoBuilder<'ctx> { pub fn create_namespace(&self, scope: DIScope<'ctx>, name: &str, export_symbols: bool) -> DINamespace<'ctx> { let metadata_ref = unsafe { LLVMDIBuilderCreateNameSpace( - self.builder, - scope.metadata_ref, + self.as_mut_ptr(), + scope.as_mut_ptr(), name.as_ptr() as _, name.len(), export_symbols as _, ) }; + debug_assert!(!metadata_ref.is_null(), "metadata_ref must not be null."); DINamespace { - metadata_ref, + metadata_ref: unsafe { NonNull::new_unchecked(metadata_ref) }, _marker: PhantomData, } } @@ -971,11 +999,11 @@ impl<'ctx> DebugInfoBuilder<'ctx> { ) -> InstructionValue<'ctx> { let value_ref = unsafe { LLVMDIBuilderInsertDeclareBefore( - self.builder, + self.as_mut_ptr(), storage.as_value_ref(), - var_info.map(|v| v.metadata_ref).unwrap_or(std::ptr::null_mut()), - expr.unwrap_or_else(|| self.create_expression(vec![])).metadata_ref, - debug_loc.metadata_ref, + var_info.map(|v| v.as_mut_ptr()).unwrap_or(std::ptr::null_mut()), + expr.unwrap_or_else(|| self.create_expression(vec![])).as_mut_ptr(), + debug_loc.as_mut_ptr(), instruction.as_value_ref(), ) }; @@ -1015,12 +1043,12 @@ impl<'ctx> DebugInfoBuilder<'ctx> { ) -> InstructionValue<'ctx> { let value_ref = unsafe { LLVMDIBuilderInsertDeclareAtEnd( - self.builder, + self.as_mut_ptr(), storage.as_value_ref(), - var_info.map(|v| v.metadata_ref).unwrap_or(std::ptr::null_mut()), - expr.unwrap_or_else(|| self.create_expression(vec![])).metadata_ref, - debug_loc.metadata_ref, - block.basic_block, + var_info.map(|v| v.as_mut_ptr()).unwrap_or(std::ptr::null_mut()), + expr.unwrap_or_else(|| self.create_expression(vec![])).as_mut_ptr(), + debug_loc.as_mut_ptr(), + block.as_mut_ptr(), ) }; @@ -1052,13 +1080,14 @@ impl<'ctx> DebugInfoBuilder<'ctx> { pub fn create_expression(&self, mut address_operations: Vec) -> DIExpression<'ctx> { let metadata_ref = unsafe { LLVMDIBuilderCreateExpression( - self.builder, + self.as_mut_ptr(), address_operations.as_mut_ptr() as *mut _, address_operations.len(), ) }; + debug_assert!(!metadata_ref.is_null(), "metadata_ref must not be null."); DIExpression { - metadata_ref, + metadata_ref: unsafe { NonNull::new_unchecked(metadata_ref) }, _marker: PhantomData, } } @@ -1074,11 +1103,11 @@ impl<'ctx> DebugInfoBuilder<'ctx> { ) -> InstructionValue<'ctx> { let value_ref = unsafe { LLVMDIBuilderInsertDbgValueBefore( - self.builder, + self.as_mut_ptr(), value.as_value_ref(), - var_info.metadata_ref, - expr.unwrap_or_else(|| self.create_expression(vec![])).metadata_ref, - debug_loc.metadata_ref, + var_info.as_mut_ptr(), + expr.unwrap_or_else(|| self.create_expression(vec![])).as_mut_ptr(), + debug_loc.as_mut_ptr(), instruction.as_value_ref(), ) }; @@ -1113,8 +1142,9 @@ impl<'ctx> DebugInfoBuilder<'ctx> { pub unsafe fn create_placeholder_derived_type(&self, context: impl AsContextRef<'ctx>) -> DIDerivedType<'ctx> { unsafe { let metadata_ref = LLVMTemporaryMDNode(context.as_ctx_ref(), std::ptr::null_mut(), 0); + debug_assert!(!metadata_ref.is_null(), "metadata_ref must not be null."); DIDerivedType { - metadata_ref, + metadata_ref: NonNull::new_unchecked(metadata_ref), _marker: PhantomData, } } @@ -1131,7 +1161,7 @@ impl<'ctx> DebugInfoBuilder<'ctx> { other: DIDerivedType<'ctx>, ) { unsafe { - LLVMMetadataReplaceAllUsesWith(placeholder.metadata_ref, other.metadata_ref); + LLVMMetadataReplaceAllUsesWith(placeholder.as_mut_ptr(), other.as_mut_ptr()); } } @@ -1140,23 +1170,25 @@ impl<'ctx> DebugInfoBuilder<'ctx> { /// /// Call before any kind of code generation (including verification). Can be called more than once. pub fn finalize(&self) { - unsafe { LLVMDIBuilderFinalize(self.builder) }; + unsafe { LLVMDIBuilderFinalize(self.as_mut_ptr()) }; } } impl Drop for DebugInfoBuilder<'_> { fn drop(&mut self) { self.finalize(); - unsafe { LLVMDisposeDIBuilder(self.builder) } + unsafe { LLVMDisposeDIBuilder(self.as_mut_ptr()) } } } /// Source file scope for debug info +#[repr(transparent)] #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct DIFile<'ctx> { - pub(crate) metadata_ref: LLVMMetadataRef, + pub(crate) metadata_ref: NonNull, _marker: PhantomData<&'ctx Context>, } +const _: () = assert_niche::(); impl<'ctx> AsDIScope<'ctx> for DIFile<'ctx> { fn as_debug_info_scope(self) -> DIScope<'ctx> { @@ -1170,7 +1202,7 @@ impl<'ctx> AsDIScope<'ctx> for DIFile<'ctx> { impl DIFile<'_> { /// Acquires the underlying raw pointer belonging to this `DIFile` type. pub fn as_mut_ptr(&self) -> LLVMMetadataRef { - self.metadata_ref + self.metadata_ref.as_ptr() } } @@ -1178,9 +1210,10 @@ impl DIFile<'_> { #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct DICompileUnit<'ctx> { file: DIFile<'ctx>, - pub(crate) metadata_ref: LLVMMetadataRef, + pub(crate) metadata_ref: NonNull, _marker: PhantomData<&'ctx Context>, } +const _: () = assert_niche::(); impl<'ctx> DICompileUnit<'ctx> { pub fn get_file(&self) -> DIFile<'ctx> { @@ -1189,7 +1222,7 @@ impl<'ctx> DICompileUnit<'ctx> { /// Acquires the underlying raw pointer belonging to this `DICompileUnit` type. pub fn as_mut_ptr(&self) -> LLVMMetadataRef { - self.metadata_ref + self.metadata_ref.as_ptr() } } @@ -1203,16 +1236,18 @@ impl<'ctx> AsDIScope<'ctx> for DICompileUnit<'ctx> { } /// Namespace scope for debug info +#[repr(transparent)] #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct DINamespace<'ctx> { - pub(crate) metadata_ref: LLVMMetadataRef, + pub(crate) metadata_ref: NonNull, _marker: PhantomData<&'ctx Context>, } +const _: () = assert_niche::(); impl DINamespace<'_> { /// Acquires the underlying raw pointer belonging to this `DINamespace` type. pub fn as_mut_ptr(&self) -> LLVMMetadataRef { - self.metadata_ref + self.metadata_ref.as_ptr() } } @@ -1226,11 +1261,13 @@ impl<'ctx> AsDIScope<'ctx> for DINamespace<'ctx> { } /// Function body scope for debug info +#[repr(transparent)] #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct DISubprogram<'ctx> { - pub(crate) metadata_ref: LLVMMetadataRef, + pub(crate) metadata_ref: NonNull, pub(crate) _marker: PhantomData<&'ctx Context>, } +const _: () = assert_niche::(); impl<'ctx> AsDIScope<'ctx> for DISubprogram<'ctx> { fn as_debug_info_scope(self) -> DIScope<'ctx> { @@ -1244,33 +1281,35 @@ impl<'ctx> AsDIScope<'ctx> for DISubprogram<'ctx> { impl DISubprogram<'_> { /// Acquires the underlying raw pointer belonging to this `DISubprogram` type. pub fn as_mut_ptr(&self) -> LLVMMetadataRef { - self.metadata_ref + self.metadata_ref.as_ptr() } } /// Any kind of debug info type +#[repr(transparent)] #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct DIType<'ctx> { - pub(crate) metadata_ref: LLVMMetadataRef, + pub(crate) metadata_ref: NonNull, _marker: PhantomData<&'ctx Context>, } +const _: () = assert_niche::(); impl DIType<'_> { pub fn get_size_in_bits(&self) -> u64 { - unsafe { LLVMDITypeGetSizeInBits(self.metadata_ref) } + unsafe { LLVMDITypeGetSizeInBits(self.as_mut_ptr()) } } pub fn get_align_in_bits(&self) -> u32 { - unsafe { LLVMDITypeGetAlignInBits(self.metadata_ref) } + unsafe { LLVMDITypeGetAlignInBits(self.as_mut_ptr()) } } pub fn get_offset_in_bits(&self) -> u64 { - unsafe { LLVMDITypeGetOffsetInBits(self.metadata_ref) } + unsafe { LLVMDITypeGetOffsetInBits(self.as_mut_ptr()) } } /// Acquires the underlying raw pointer belonging to this `DIType` type. pub fn as_mut_ptr(&self) -> LLVMMetadataRef { - self.metadata_ref + self.metadata_ref.as_ptr() } } @@ -1284,11 +1323,13 @@ impl<'ctx> AsDIScope<'ctx> for DIType<'ctx> { } /// A wrapper around a single type, such as a typedef or member type. +#[repr(transparent)] #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct DIDerivedType<'ctx> { - pub(crate) metadata_ref: LLVMMetadataRef, + pub(crate) metadata_ref: NonNull, _marker: PhantomData<&'ctx Context>, } +const _: () = assert_niche::(); impl<'ctx> DIDerivedType<'ctx> { pub fn as_type(&self) -> DIType<'ctx> { @@ -1301,7 +1342,7 @@ impl<'ctx> DIDerivedType<'ctx> { impl DIDerivedType<'_> { pub fn as_mut_ptr(&self) -> LLVMMetadataRef { - self.metadata_ref + self.metadata_ref.as_ptr() } } @@ -1315,11 +1356,13 @@ impl<'ctx> AsDIScope<'ctx> for DIDerivedType<'ctx> { } /// A primitive debug info type created by `create_basic_type` method of `DebugInfoBuilder` +#[repr(transparent)] #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct DIBasicType<'ctx> { - pub(crate) metadata_ref: LLVMMetadataRef, + pub(crate) metadata_ref: NonNull, _marker: PhantomData<&'ctx Context>, } +const _: () = assert_niche::(); impl<'ctx> DIBasicType<'ctx> { pub fn as_type(&self) -> DIType<'ctx> { @@ -1331,7 +1374,7 @@ impl<'ctx> DIBasicType<'ctx> { /// Acquires the underlying raw pointer belonging to this `DIBasicType` type. pub fn as_mut_ptr(&self) -> LLVMMetadataRef { - self.metadata_ref + self.metadata_ref.as_ptr() } } @@ -1344,11 +1387,13 @@ impl<'ctx> AsDIScope<'ctx> for DIBasicType<'ctx> { } } /// A wrapper around an array of types, such as a union or struct. +#[repr(transparent)] #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct DICompositeType<'ctx> { - pub(crate) metadata_ref: LLVMMetadataRef, + pub(crate) metadata_ref: NonNull, _marker: PhantomData<&'ctx Context>, } +const _: () = assert_niche::(); impl<'ctx> DICompositeType<'ctx> { pub fn as_type(&self) -> DIType<'ctx> { @@ -1360,7 +1405,7 @@ impl<'ctx> DICompositeType<'ctx> { /// Acquires the underlying raw pointer belonging to this `DICompositeType` type. pub fn as_mut_ptr(&self) -> LLVMMetadataRef { - self.metadata_ref + self.metadata_ref.as_ptr() } } @@ -1374,18 +1419,28 @@ impl<'ctx> AsDIScope<'ctx> for DICompositeType<'ctx> { } /// Metadata representing the type of a function +#[repr(transparent)] #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct DISubroutineType<'ctx> { - pub(crate) metadata_ref: LLVMMetadataRef, + pub(crate) metadata_ref: NonNull, _marker: PhantomData<&'ctx Context>, } +const _: () = assert_niche::(); + +impl<'ctx> DISubroutineType<'ctx> { + pub fn as_mut_ptr(&self) -> LLVMMetadataRef { + self.metadata_ref.as_ptr() + } +} /// Lexical block scope for debug info +#[repr(transparent)] #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct DILexicalBlock<'ctx> { - pub(crate) metadata_ref: LLVMMetadataRef, + pub(crate) metadata_ref: NonNull, _marker: PhantomData<&'ctx Context>, } +const _: () = assert_niche::(); impl<'ctx> AsDIScope<'ctx> for DILexicalBlock<'ctx> { fn as_debug_info_scope(self) -> DIScope<'ctx> { @@ -1399,7 +1454,7 @@ impl<'ctx> AsDIScope<'ctx> for DILexicalBlock<'ctx> { impl DILexicalBlock<'_> { /// Acquires the underlying raw pointer belonging to this `DILexicalBlock` type. pub fn as_mut_ptr(&self) -> LLVMMetadataRef { - self.metadata_ref + self.metadata_ref.as_ptr() } } @@ -1411,62 +1466,68 @@ impl DILexicalBlock<'_> { /// /// Created by `create_debug_location` of `DebugInfoBuilder` and consumed by /// `set_current_debug_location` of `Builder`. +#[repr(transparent)] #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct DILocation<'ctx> { - pub(crate) metadata_ref: LLVMMetadataRef, + pub(crate) metadata_ref: NonNull, pub(crate) _marker: PhantomData<&'ctx Context>, } +const _: () = assert_niche::(); impl<'ctx> DILocation<'ctx> { pub fn get_line(&self) -> u32 { - unsafe { LLVMDILocationGetLine(self.metadata_ref) } + unsafe { LLVMDILocationGetLine(self.as_mut_ptr()) } } pub fn get_column(&self) -> u32 { - unsafe { LLVMDILocationGetColumn(self.metadata_ref) } + unsafe { LLVMDILocationGetColumn(self.as_mut_ptr()) } } pub fn get_scope(&self) -> DIScope<'ctx> { DIScope { - metadata_ref: unsafe { LLVMDILocationGetScope(self.metadata_ref) }, + metadata_ref: unsafe { NonNull::new_unchecked(LLVMDILocationGetScope(self.as_mut_ptr())) }, _marker: PhantomData, } } /// Acquires the underlying raw pointer belonging to this `DILocation` type. pub fn as_mut_ptr(&self) -> LLVMMetadataRef { - self.metadata_ref + self.metadata_ref.as_ptr() } } /// Metadata representing a variable inside a scope +#[repr(transparent)] #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct DILocalVariable<'ctx> { - pub(crate) metadata_ref: LLVMMetadataRef, + pub(crate) metadata_ref: NonNull, _marker: PhantomData<&'ctx Context>, } +const _: () = assert_niche::(); impl DILocalVariable<'_> { /// Acquires the underlying raw pointer belonging to this `DILocalVariable` type. pub fn as_mut_ptr(&self) -> LLVMMetadataRef { - self.metadata_ref + self.metadata_ref.as_ptr() } } +#[repr(transparent)] #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct DIGlobalVariableExpression<'ctx> { - pub(crate) metadata_ref: LLVMMetadataRef, + pub(crate) metadata_ref: NonNull, _marker: PhantomData<&'ctx Context>, } +const _: () = assert_niche::(); impl<'ctx> DIGlobalVariableExpression<'ctx> { pub fn as_metadata_value(&self, context: impl AsContextRef<'ctx>) -> MetadataValue<'ctx> { - unsafe { MetadataValue::new(LLVMMetadataAsValue(context.as_ctx_ref(), self.metadata_ref)) } + unsafe { MetadataValue::new(LLVMMetadataAsValue(context.as_ctx_ref(), self.as_mut_ptr())) } } /// Acquires the underlying raw pointer belonging to this `DIGlobalVariableExpression` type. pub fn as_mut_ptr(&self) -> LLVMMetadataRef { - self.metadata_ref + self.metadata_ref.as_ptr() } } @@ -1475,29 +1536,33 @@ impl<'ctx> DIGlobalVariableExpression<'ctx> { /// # Remarks /// /// See also the [LLVM language reference](https://llvm.org/docs/LangRef.html#diexpression). +#[repr(transparent)] #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct DIExpression<'ctx> { - pub(crate) metadata_ref: LLVMMetadataRef, + pub(crate) metadata_ref: NonNull, _marker: PhantomData<&'ctx Context>, } +const _: () = assert_niche::(); impl DIExpression<'_> { /// Acquires the underlying raw pointer belonging to this `DIExpression` type. pub fn as_mut_ptr(&self) -> LLVMMetadataRef { - self.metadata_ref + self.metadata_ref.as_ptr() } } +#[repr(transparent)] #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct DIEnumerator<'ctx> { - pub(crate) metadata_ref: LLVMMetadataRef, + pub(crate) metadata_ref: NonNull, _marker: PhantomData<&'ctx Context>, } +const _: () = assert_niche::(); impl<'ctx> DIEnumerator<'ctx> { /// Acquires the underlying raw pointer belonging to this `DIEnumerator` type. pub fn as_mut_ptr(&self) -> LLVMMetadataRef { - self.metadata_ref + self.metadata_ref.as_ptr() } pub fn as_type(&self) -> DIType<'ctx> { diff --git a/src/execution_engine.rs b/src/execution_engine.rs index 5120e39dbf4..9172876c622 100644 --- a/src/execution_engine.rs +++ b/src/execution_engine.rs @@ -17,6 +17,7 @@ use std::fmt::{self, Debug, Display, Formatter}; use std::marker::PhantomData; use std::mem::{MaybeUninit, forget, size_of, transmute_copy}; use std::ops::Deref; +use std::ptr::NonNull; use std::rc::Rc; static EE_INNER_PANIC: &str = "ExecutionEngineInner should exist until Drop"; @@ -201,7 +202,7 @@ impl<'ctx> ExecutionEngine<'ctx> { /// assert!(ee.add_module(&module).is_err()); /// ``` pub fn add_module(&self, module: &Module<'ctx>) -> Result<(), ()> { - unsafe { LLVMAddModule(self.execution_engine_inner(), module.module.get()) } + unsafe { LLVMAddModule(self.execution_engine_inner(), module.as_mut_ptr()) } if module.owned_by_ee.borrow().is_some() { return Err(()); @@ -227,7 +228,7 @@ impl<'ctx> ExecutionEngine<'ctx> { let code = unsafe { LLVMRemoveModule( self.execution_engine_inner(), - module.module.get(), + module.as_mut_ptr(), new_module.as_mut_ptr(), &mut err_string, ) @@ -241,7 +242,7 @@ impl<'ctx> ExecutionEngine<'ctx> { let new_module = unsafe { new_module.assume_init() }; - module.module.set(new_module); + module.module.set(unsafe { NonNull::new_unchecked(new_module) }); *module.owned_by_ee.borrow_mut() = None; Ok(()) @@ -387,7 +388,7 @@ impl<'ctx> ExecutionEngine<'ctx> { args: &[&GenericValue<'ctx>], ) -> GenericValue<'ctx> { unsafe { - let mut args: Vec = args.iter().map(|val| val.generic_value).collect(); + let mut args: Vec = args.iter().map(|val| val.generic_value.as_ptr()).collect(); let value = LLVMRunFunction( self.execution_engine_inner(), @@ -461,6 +462,7 @@ impl Clone for ExecutionEngine<'_> { } /// A smart pointer which wraps the `Drop` logic for `LLVMExecutionEngineRef`. +#[repr(transparent)] #[derive(Debug, Clone, PartialEq, Eq)] struct ExecEngineInner<'ctx>(Rc, PhantomData<&'ctx Context>); @@ -620,7 +622,7 @@ pub mod experimental { impl Orc { pub fn create(target_machine: TargetMachine) -> Self { - let stack_ref = unsafe { LLVMOrcCreateInstance(target_machine.target_machine) }; + let stack_ref = unsafe { LLVMOrcCreateInstance(target_machine.target_machine.as_ptr()) }; Orc(stack_ref) } diff --git a/src/intrinsics.rs b/src/intrinsics.rs index 479601809ab..e2eaa420e84 100644 --- a/src/intrinsics.rs +++ b/src/intrinsics.rs @@ -99,7 +99,7 @@ impl Intrinsic { unsafe { FunctionValue::new(LLVMGetIntrinsicDeclaration( - module.module.get(), + module.as_mut_ptr(), self.id, param_types.as_mut_ptr(), param_types.len(), diff --git a/src/memory_buffer.rs b/src/memory_buffer.rs index 04a31aeb40e..ee2bf266e4a 100644 --- a/src/memory_buffer.rs +++ b/src/memory_buffer.rs @@ -1,3 +1,4 @@ +use llvm_sys::LLVMMemoryBuffer; use llvm_sys::core::{ LLVMCreateMemoryBufferWithContentsOfFile, LLVMCreateMemoryBufferWithMemoryRange, LLVMCreateMemoryBufferWithMemoryRangeCopy, LLVMCreateMemoryBufferWithSTDIN, LLVMDisposeMemoryBuffer, @@ -8,18 +9,20 @@ use llvm_sys::prelude::LLVMMemoryBufferRef; use crate::context::Context; use crate::object_file::BinaryFile; -use crate::support::{LLVMString, to_c_str}; +use crate::support::{LLVMString, assert_niche, to_c_str}; use std::marker::PhantomData; use std::path::Path; -use std::ptr; +use std::ptr::{self, NonNull}; use std::slice; +#[repr(transparent)] #[derive(Debug)] pub struct MemoryBuffer<'a> { - pub(crate) memory_buffer: LLVMMemoryBufferRef, + pub(crate) memory_buffer: NonNull, _phantom: PhantomData<&'a [u8]>, } +const _: () = assert_niche::(); // The backing memory is owned and managed by LLVM, such that it is valid throughout the buffer's // lifetime, hence 'static. @@ -95,13 +98,13 @@ impl<'a> MemoryBuffer<'a> { assert!(!memory_buffer.is_null()); Self { - memory_buffer, + memory_buffer: unsafe { NonNull::new_unchecked(memory_buffer) }, _phantom: PhantomData, } } pub fn as_mut_ptr(&self) -> LLVMMemoryBufferRef { - self.memory_buffer + self.memory_buffer.as_ptr() } /// Create a memory buffer from a byte slice with a trailing nul byte. @@ -134,7 +137,7 @@ impl<'a> MemoryBuffer<'a> { /// Gets a byte slice of this [`MemoryBuffer`], containing the trailing nul byte. pub fn as_slice(&self) -> &[u8] { unsafe { - let start = LLVMGetBufferStart(self.memory_buffer); + let start = LLVMGetBufferStart(self.as_mut_ptr()); // SAFETY: from LLVM `MemoryBuffer.h`: // "this interface guarantees you can read one character past the end of the file, @@ -148,7 +151,7 @@ impl<'a> MemoryBuffer<'a> { /// Gets the byte size of this `MemoryBuffer`, counting the trailing nul byte. pub fn get_size(&self) -> usize { // buffer size does not include the trailing nul byte, hence incremented. - unsafe { LLVMGetBufferSize(self.memory_buffer) + 1 } + unsafe { LLVMGetBufferSize(self.as_mut_ptr()) + 1 } } /// Convert this [`MemoryBuffer`] and optional [`Context`] into a [`BinaryFile`]. @@ -160,7 +163,7 @@ impl<'a> MemoryBuffer<'a> { let context = context.map_or(ptr::null_mut(), |c| c.raw()); let mut err_string = ptr::null_mut(); - let binary_file = unsafe { LLVMCreateBinary(self.memory_buffer, context, &mut err_string) }; + let binary_file = unsafe { LLVMCreateBinary(self.as_mut_ptr(), context, &mut err_string) }; if binary_file.is_null() { unsafe { @@ -175,7 +178,7 @@ impl<'a> MemoryBuffer<'a> { impl<'a> Drop for MemoryBuffer<'a> { fn drop(&mut self) { unsafe { - LLVMDisposeMemoryBuffer(self.memory_buffer); + LLVMDisposeMemoryBuffer(self.as_mut_ptr()); } } } diff --git a/src/memory_manager.rs b/src/memory_manager.rs index 8634f946c9a..de9c3fecd3a 100644 --- a/src/memory_manager.rs +++ b/src/memory_manager.rs @@ -1,5 +1,7 @@ use llvm_sys::prelude::LLVMBool; +use crate::support::assert_niche; + /// A trait for user-defined memory management in MCJIT. /// /// Implementors can override how LLVM's MCJIT engine allocates memory for code @@ -86,10 +88,12 @@ pub trait McjitMemoryManager: std::fmt::Debug { /// Holds a boxed `McjitMemoryManager` and passes it to LLVM as an opaque pointer. /// /// LLVM calls into the adapter using the extern "C" function pointers defined below. +#[repr(transparent)] #[derive(Debug)] pub struct MemoryManagerAdapter { pub memory_manager: Box, } +const _: () = assert_niche::(); // ------ Extern "C" Adapters ------ diff --git a/src/module.rs b/src/module.rs index 89051cdcb3a..239dc0a7d08 100644 --- a/src/module.rs +++ b/src/module.rs @@ -1,6 +1,5 @@ //! A `Module` represents a single code compilation unit. -use llvm_sys::LLVMLinkage; use llvm_sys::analysis::{LLVMVerifierFailureAction, LLVMVerifyModule}; #[allow(deprecated)] use llvm_sys::bit_reader::LLVMParseBitcodeInContext; @@ -26,6 +25,7 @@ use llvm_sys::execution_engine::{ use llvm_sys::prelude::{LLVMModuleRef, LLVMValueRef}; #[llvm_versions(13..)] use llvm_sys::transforms::pass_builder::LLVMRunPasses; +use llvm_sys::{LLVMLinkage, LLVMModule}; use llvm_sys::LLVMModuleFlagBehavior; @@ -35,7 +35,7 @@ use std::fs::File; use std::marker::PhantomData; use std::mem::{MaybeUninit, forget}; use std::path::Path; -use std::ptr; +use std::ptr::{self, NonNull}; use std::rc::Rc; use crate::comdat::Comdat; @@ -171,7 +171,7 @@ pub enum Linkage { #[derive(Debug, PartialEq, Eq)] pub struct Module<'ctx> { data_layout: RefCell>, - pub(crate) module: Cell, + pub(crate) module: Cell>, pub(crate) owned_by_ee: RefCell>>, _marker: PhantomData<&'ctx Context>, } @@ -186,7 +186,7 @@ impl<'ctx> Module<'ctx> { debug_assert!(!module.is_null()); Module { - module: Cell::new(module), + module: Cell::new(unsafe { NonNull::new_unchecked(module) }), owned_by_ee: RefCell::new(None), data_layout: RefCell::new(Some(Module::get_borrowed_data_layout(module))), _marker: PhantomData, @@ -195,7 +195,7 @@ impl<'ctx> Module<'ctx> { /// Acquires the underlying raw pointer belonging to this `Module` type. pub fn as_mut_ptr(&self) -> LLVMModuleRef { - self.module.get() + self.module.get().as_ptr() } /// Creates a function given its `name` and `ty`, adds it to the `Module` @@ -222,7 +222,7 @@ impl<'ctx> Module<'ctx> { pub fn add_function(&self, name: &str, ty: FunctionType<'ctx>, linkage: Option) -> FunctionValue<'ctx> { let c_string = to_c_str(name); let fn_value = unsafe { - FunctionValue::new(LLVMAddFunction(self.module.get(), c_string.as_ptr(), ty.as_type_ref())) + FunctionValue::new(LLVMAddFunction(self.as_mut_ptr(), c_string.as_ptr(), ty.as_type_ref())) .expect("add_function should always succeed in adding a new function") }; @@ -246,7 +246,7 @@ impl<'ctx> Module<'ctx> { /// assert_eq!(local_module.get_context(), local_context); /// ``` pub fn get_context(&self) -> ContextRef<'ctx> { - unsafe { ContextRef::new(LLVMGetModuleContext(self.module.get())) } + unsafe { ContextRef::new(LLVMGetModuleContext(self.as_mut_ptr())) } } /// Gets the first `FunctionValue` defined in this `Module`. @@ -268,7 +268,7 @@ impl<'ctx> Module<'ctx> { /// assert_eq!(fn_value, module.get_first_function().unwrap()); /// ``` pub fn get_first_function(&self) -> Option> { - unsafe { FunctionValue::new(LLVMGetFirstFunction(self.module.get())) } + unsafe { FunctionValue::new(LLVMGetFirstFunction(self.as_mut_ptr())) } } /// Gets the last `FunctionValue` defined in this `Module`. @@ -290,7 +290,7 @@ impl<'ctx> Module<'ctx> { /// assert_eq!(fn_value, module.get_last_function().unwrap()); /// ``` pub fn get_last_function(&self) -> Option> { - unsafe { FunctionValue::new(LLVMGetLastFunction(self.module.get())) } + unsafe { FunctionValue::new(LLVMGetLastFunction(self.as_mut_ptr())) } } /// Gets a `FunctionValue` defined in this `Module` by its name. @@ -314,7 +314,7 @@ impl<'ctx> Module<'ctx> { pub fn get_function(&self, name: &str) -> Option> { let c_string = to_c_str(name); - unsafe { FunctionValue::new(LLVMGetNamedFunction(self.module.get(), c_string.as_ptr())) } + unsafe { FunctionValue::new(LLVMGetNamedFunction(self.as_mut_ptr(), c_string.as_ptr())) } } /// An iterator over the functions in this `Module`. @@ -364,7 +364,7 @@ impl<'ctx> Module<'ctx> { pub fn get_struct_type(&self, name: &str) -> Option> { let c_string = to_c_str(name); - let struct_type = unsafe { LLVMGetTypeByName(self.module.get(), c_string.as_ptr()) }; + let struct_type = unsafe { LLVMGetTypeByName(self.as_mut_ptr(), c_string.as_ptr()) }; if struct_type.is_null() { return None; @@ -414,7 +414,7 @@ impl<'ctx> Module<'ctx> { /// assert_eq!(module.get_triple(), triple); /// ``` pub fn set_triple(&self, triple: &TargetTriple) { - unsafe { LLVMSetTarget(self.module.get(), triple.as_ptr()) } + unsafe { LLVMSetTarget(self.as_mut_ptr(), triple.as_ptr()) } } /// Gets the `TargetTriple` assigned to this `Module`. If none has been @@ -439,7 +439,7 @@ impl<'ctx> Module<'ctx> { /// ``` pub fn get_triple(&self) -> TargetTriple { // REVIEW: This isn't an owned LLVMString, is it? If so, need to deallocate. - let target_str = unsafe { LLVMGetTarget(self.module.get()) }; + let target_str = unsafe { LLVMGetTarget(self.as_mut_ptr()) }; unsafe { TargetTriple::new(LLVMString::create_from_c_str(CStr::from_ptr(target_str))) } } @@ -479,7 +479,7 @@ impl<'ctx> Module<'ctx> { let mut err_string: *mut ::libc::c_char = ::core::ptr::null_mut(); let code = unsafe { // Takes ownership of module - LLVMCreateExecutionEngineForModule(execution_engine.as_mut_ptr(), self.module.get(), &mut err_string) + LLVMCreateExecutionEngineForModule(execution_engine.as_mut_ptr(), self.as_mut_ptr(), &mut err_string) }; if code == 1 { @@ -531,7 +531,7 @@ impl<'ctx> Module<'ctx> { let code = unsafe { // Takes ownership of module - LLVMCreateInterpreterForModule(execution_engine.as_mut_ptr(), self.module.get(), &mut err_string) + LLVMCreateInterpreterForModule(execution_engine.as_mut_ptr(), self.as_mut_ptr(), &mut err_string) }; if code == 1 { @@ -589,7 +589,7 @@ impl<'ctx> Module<'ctx> { // Takes ownership of module LLVMCreateJITCompilerForModule( execution_engine.as_mut_ptr(), - self.module.get(), + self.as_mut_ptr(), opt_level as u32, &mut err_string, ) @@ -716,7 +716,7 @@ impl<'ctx> Module<'ctx> { let code = unsafe { llvm_sys::execution_engine::LLVMCreateMCJITCompilerForModule( execution_engine.as_mut_ptr(), - self.module.get(), + self.as_mut_ptr(), &mut options, std::mem::size_of::(), &mut err_string, @@ -766,12 +766,12 @@ impl<'ctx> Module<'ctx> { let value = unsafe { match address_space { Some(address_space) => LLVMAddGlobalInAddressSpace( - self.module.get(), + self.as_mut_ptr(), type_.as_type_ref(), c_string.as_ptr(), address_space.0, ), - None => LLVMAddGlobal(self.module.get(), type_.as_type_ref(), c_string.as_ptr()), + None => LLVMAddGlobal(self.as_mut_ptr(), type_.as_type_ref(), c_string.as_ptr()), } }; @@ -804,7 +804,7 @@ impl<'ctx> Module<'ctx> { .expect("Did not find a valid Unicode path string"); let c_string = to_c_str(path_str); - unsafe { LLVMWriteBitcodeToFile(self.module.get(), c_string.as_ptr()) == 0 } + unsafe { LLVMWriteBitcodeToFile(self.as_mut_ptr(), c_string.as_ptr()) == 0 } } /// `write_bitcode_to_path` should be preferred over this method, as it does not work on all operating systems. @@ -820,7 +820,7 @@ impl<'ctx> Module<'ctx> { // Also, should_close should maybe be hardcoded to true? unsafe { LLVMWriteBitcodeToFD( - self.module.get(), + self.as_mut_ptr(), file.as_raw_fd(), // should_close: Rust will close the // File itself, so `should_close` can @@ -853,7 +853,7 @@ impl<'ctx> Module<'ctx> { /// let buffer = module.write_bitcode_to_memory(); /// ``` pub fn write_bitcode_to_memory(&self) -> MemoryBuffer<'static> { - let memory_buffer = unsafe { LLVMWriteBitcodeToMemoryBuffer(self.module.get()) }; + let memory_buffer = unsafe { LLVMWriteBitcodeToMemoryBuffer(self.as_mut_ptr()) }; unsafe { MemoryBuffer::new(memory_buffer) } } @@ -869,7 +869,7 @@ impl<'ctx> Module<'ctx> { let action = LLVMVerifierFailureAction::LLVMReturnStatusAction; - let code = unsafe { LLVMVerifyModule(self.module.get(), action, &mut err_str) }; + let code = unsafe { LLVMVerifyModule(self.as_mut_ptr(), action, &mut err_str) }; if code == 1 && !err_str.is_null() { return unsafe { Err(LLVMString::new(err_str)) }; @@ -942,22 +942,22 @@ impl<'ctx> Module<'ctx> { /// ``` pub fn set_data_layout(&self, data_layout: &DataLayout) { unsafe { - LLVMSetDataLayout(self.module.get(), data_layout.as_ptr()); + LLVMSetDataLayout(self.as_mut_ptr(), data_layout.as_ptr()); } - *self.data_layout.borrow_mut() = Some(Module::get_borrowed_data_layout(self.module.get())); + *self.data_layout.borrow_mut() = Some(Module::get_borrowed_data_layout(self.as_mut_ptr())); } /// Prints the content of the `Module` to stderr. pub fn print_to_stderr(&self) { unsafe { - LLVMDumpModule(self.module.get()); + LLVMDumpModule(self.as_mut_ptr()); } } /// Prints the content of the `Module` to an `LLVMString`. pub fn print_to_string(&self) -> LLVMString { - unsafe { LLVMString::new(LLVMPrintModuleToString(self.module.get())) } + unsafe { LLVMString::new(LLVMPrintModuleToString(self.as_mut_ptr())) } } /// Prints the content of the `Module` to a file. @@ -970,7 +970,7 @@ impl<'ctx> Module<'ctx> { let mut err_string: *mut ::libc::c_char = ::core::ptr::null_mut(); let return_code = unsafe { LLVMPrintModuleToFile( - self.module.get(), + self.as_mut_ptr(), path.as_ptr() as *const ::libc::c_char, &mut err_string, ) @@ -997,7 +997,7 @@ impl<'ctx> Module<'ctx> { /// Sets the inline assembly for the `Module`. pub fn set_inline_assembly(&self, asm: &str) { - unsafe { LLVMSetModuleInlineAsm2(self.module.get(), asm.as_ptr() as *const ::libc::c_char, asm.len()) } + unsafe { LLVMSetModuleInlineAsm2(self.as_mut_ptr(), asm.as_ptr() as *const ::libc::c_char, asm.len()) } } // REVIEW: Should module take ownership of metadata? @@ -1047,7 +1047,7 @@ impl<'ctx> Module<'ctx> { let c_string = to_c_str(key); unsafe { - LLVMAddNamedMetadataOperand(self.module.get(), c_string.as_ptr(), metadata.as_value_ref()); + LLVMAddNamedMetadataOperand(self.as_mut_ptr(), c_string.as_ptr(), metadata.as_value_ref()); } Ok(()) @@ -1093,7 +1093,7 @@ impl<'ctx> Module<'ctx> { pub fn get_global_metadata_size(&self, key: &str) -> u32 { let c_string = to_c_str(key); - unsafe { LLVMGetNamedMetadataNumOperands(self.module.get(), c_string.as_ptr()) } + unsafe { LLVMGetNamedMetadataNumOperands(self.as_mut_ptr(), c_string.as_ptr()) } } // SubTypes: -> Vec> @@ -1141,7 +1141,7 @@ impl<'ctx> Module<'ctx> { let ptr = vec.as_mut_ptr(); unsafe { - LLVMGetNamedMetadataOperands(self.module.get(), c_string.as_ptr(), ptr); + LLVMGetNamedMetadataOperands(self.as_mut_ptr(), c_string.as_ptr(), ptr); vec.set_len(count); }; @@ -1168,7 +1168,7 @@ impl<'ctx> Module<'ctx> { /// assert_eq!(module.get_first_global().unwrap(), global); /// ``` pub fn get_first_global(&self) -> Option> { - let value = unsafe { LLVMGetFirstGlobal(self.module.get()) }; + let value = unsafe { LLVMGetFirstGlobal(self.as_mut_ptr()) }; if value.is_null() { return None; @@ -1196,7 +1196,7 @@ impl<'ctx> Module<'ctx> { /// assert_eq!(module.get_last_global().unwrap(), global); /// ``` pub fn get_last_global(&self) -> Option> { - let value = unsafe { LLVMGetLastGlobal(self.module.get()) }; + let value = unsafe { LLVMGetLastGlobal(self.as_mut_ptr()) }; if value.is_null() { return None; @@ -1225,7 +1225,7 @@ impl<'ctx> Module<'ctx> { /// ``` pub fn get_global(&self, name: &str) -> Option> { let c_string = to_c_str(name); - let value = unsafe { LLVMGetNamedGlobal(self.module.get(), c_string.as_ptr()) }; + let value = unsafe { LLVMGetNamedGlobal(self.as_mut_ptr(), c_string.as_ptr()) }; if value.is_null() { return None; @@ -1271,7 +1271,7 @@ impl<'ctx> Module<'ctx> { let success = unsafe { LLVMParseBitcodeInContext( context.as_ctx_ref(), - buffer.memory_buffer, + buffer.as_mut_ptr(), module.as_mut_ptr(), &mut err_string, ) @@ -1327,7 +1327,7 @@ impl<'ctx> Module<'ctx> { /// ``` pub fn get_name(&self) -> &CStr { let mut length = 0; - let cstr_ptr = unsafe { LLVMGetModuleIdentifier(self.module.get(), &mut length) }; + let cstr_ptr = unsafe { LLVMGetModuleIdentifier(self.as_mut_ptr(), &mut length) }; unsafe { CStr::from_ptr(cstr_ptr) } } @@ -1347,7 +1347,7 @@ impl<'ctx> Module<'ctx> { /// assert_eq!(module.get_name().to_str(), Ok("my_module2")); /// ``` pub fn set_name(&self, name: &str) { - unsafe { LLVMSetModuleIdentifier(self.module.get(), name.as_ptr() as *const ::libc::c_char, name.len()) } + unsafe { LLVMSetModuleIdentifier(self.as_mut_ptr(), name.as_ptr() as *const ::libc::c_char, name.len()) } } /// Gets the source file name. It defaults to the module identifier but is separate from it. @@ -1371,7 +1371,7 @@ impl<'ctx> Module<'ctx> { use llvm_sys::core::LLVMGetSourceFileName; let mut len = 0; - let ptr = unsafe { LLVMGetSourceFileName(self.module.get(), &mut len) }; + let ptr = unsafe { LLVMGetSourceFileName(self.as_mut_ptr(), &mut len) }; unsafe { CStr::from_ptr(ptr) } } @@ -1398,7 +1398,7 @@ impl<'ctx> Module<'ctx> { unsafe { LLVMSetSourceFileName( - self.module.get(), + self.as_mut_ptr(), file_name.as_ptr() as *const ::libc::c_char, file_name.len(), ) @@ -1437,7 +1437,7 @@ impl<'ctx> Module<'ctx> { // Here we assign an error handler to extract the error message, if any, for us. context.set_diagnostic_handler(get_error_str_diagnostic_handler, char_ptr_ptr); - let code = unsafe { LLVMLinkModules2(self.module.get(), other.module.get()) }; + let code = unsafe { LLVMLinkModules2(self.as_mut_ptr(), other.as_mut_ptr()) }; forget(other); @@ -1456,7 +1456,7 @@ impl<'ctx> Module<'ctx> { use llvm_sys::comdat::LLVMGetOrInsertComdat; let c_string = to_c_str(name); - let comdat_ptr = unsafe { LLVMGetOrInsertComdat(self.module.get(), c_string.as_ptr()) }; + let comdat_ptr = unsafe { LLVMGetOrInsertComdat(self.as_mut_ptr(), c_string.as_ptr()) }; unsafe { Comdat::new(comdat_ptr) } } @@ -1468,13 +1468,13 @@ impl<'ctx> Module<'ctx> { pub fn get_flag(&self, key: &str) -> Option> { use llvm_sys::core::LLVMMetadataAsValue; - let flag = unsafe { LLVMGetModuleFlag(self.module.get(), key.as_ptr() as *const ::libc::c_char, key.len()) }; + let flag = unsafe { LLVMGetModuleFlag(self.as_mut_ptr(), key.as_ptr() as *const ::libc::c_char, key.len()) }; if flag.is_null() { return None; } - let flag_value = unsafe { LLVMMetadataAsValue(LLVMGetModuleContext(self.module.get()), flag) }; + let flag_value = unsafe { LLVMMetadataAsValue(LLVMGetModuleContext(self.as_mut_ptr()), flag) }; unsafe { Some(MetadataValue::new(flag_value)) } } @@ -1486,7 +1486,7 @@ impl<'ctx> Module<'ctx> { unsafe { LLVMAddModuleFlag( - self.module.get(), + self.as_mut_ptr(), behavior.into(), key.as_ptr() as *mut ::libc::c_char, key.len(), @@ -1505,7 +1505,7 @@ impl<'ctx> Module<'ctx> { unsafe { LLVMAddModuleFlag( - self.module.get(), + self.as_mut_ptr(), behavior.into(), key.as_ptr() as *mut ::libc::c_char, key.len(), @@ -1516,12 +1516,12 @@ impl<'ctx> Module<'ctx> { /// Strips and debug info from the module, if it exists. pub fn strip_debug_info(&self) -> bool { - unsafe { LLVMStripModuleDebugInfo(self.module.get()) == 1 } + unsafe { LLVMStripModuleDebugInfo(self.as_mut_ptr()) == 1 } } /// Gets the version of debug metadata contained in this `Module`. pub fn get_debug_metadata_version(&self) -> libc::c_uint { - unsafe { LLVMGetModuleDebugMetadataVersion(self.module.get()) } + unsafe { LLVMGetModuleDebugMetadataVersion(self.as_mut_ptr()) } } /// Creates a `DebugInfoBuilder` for this `Module`. @@ -1638,9 +1638,9 @@ impl<'ctx> Module<'ctx> { ) -> Result<(), LLVMString> { unsafe { let error = LLVMRunPasses( - self.module.get(), + self.as_mut_ptr(), to_c_str(passes).as_ptr(), - machine.target_machine, + machine.target_machine.as_ptr(), options.options_ref, ); if error.is_null() { @@ -1664,7 +1664,7 @@ impl Clone for Module<'_> { verify.unwrap_err() ); - unsafe { Module::new(LLVMCloneModule(self.module.get())) } + unsafe { Module::new(LLVMCloneModule(self.as_mut_ptr())) } } } @@ -1674,7 +1674,7 @@ impl Drop for Module<'_> { fn drop(&mut self) { if self.owned_by_ee.borrow_mut().take().is_none() { unsafe { - LLVMDisposeModule(self.module.get()); + LLVMDisposeModule(self.as_mut_ptr()); } } diff --git a/src/object_file.rs b/src/object_file.rs index 84b722fbb0f..1ac828046d0 100644 --- a/src/object_file.rs +++ b/src/object_file.rs @@ -6,35 +6,39 @@ use llvm_sys::object::{ LLVMGetSectionSize, LLVMGetSymbolAddress, LLVMGetSymbolName, LLVMGetSymbolSize, LLVMIsRelocationIteratorAtEnd, LLVMMoveToContainingSection, LLVMMoveToNextRelocation, LLVMMoveToNextSection, LLVMMoveToNextSymbol, LLVMObjectFileCopySectionIterator, LLVMObjectFileCopySymbolIterator, LLVMObjectFileIsSectionIteratorAtEnd, - LLVMObjectFileIsSymbolIteratorAtEnd, LLVMRelocationIteratorRef, LLVMSectionIteratorRef, LLVMSymbolIteratorRef, + LLVMObjectFileIsSymbolIteratorAtEnd, LLVMOpaqueBinary, LLVMOpaqueRelocationIterator, LLVMOpaqueSectionIterator, + LLVMOpaqueSymbolIterator, LLVMRelocationIteratorRef, LLVMSectionIteratorRef, LLVMSymbolIteratorRef, }; pub use llvm_sys::object::LLVMBinaryType; use std::ffi::CStr; use std::marker::PhantomData; +use std::ptr::NonNull; use crate::memory_buffer::MemoryBuffer; -use crate::support::LLVMString; +use crate::support::{LLVMString, assert_niche}; +#[repr(transparent)] #[derive(Debug)] pub struct BinaryFile<'a> { - binary_file: LLVMBinaryRef, + binary_file: NonNull, _phantom: PhantomData<&'a ()>, } +const _: () = assert_niche::(); impl<'a> BinaryFile<'a> { pub unsafe fn new(binary_file: LLVMBinaryRef) -> Self { assert!(!binary_file.is_null()); Self { - binary_file, + binary_file: unsafe { NonNull::new_unchecked(binary_file) }, _phantom: PhantomData, } } pub fn as_mut_ptr(&self) -> LLVMBinaryRef { - self.binary_file + self.binary_file.as_ptr() } pub fn get_binary_type(&self) -> LLVMBinaryType { @@ -43,46 +47,47 @@ impl<'a> BinaryFile<'a> { // the backing buffer must outlive 'a, hence never dangling pub fn get_memory_buffer(&self) -> MemoryBuffer<'a> { - unsafe { MemoryBuffer::new(LLVMBinaryCopyMemoryBuffer(self.binary_file)) } + unsafe { MemoryBuffer::new(LLVMBinaryCopyMemoryBuffer(self.as_mut_ptr())) } } pub fn get_sections(&self) -> Option> { - let section_iterator = unsafe { LLVMObjectFileCopySectionIterator(self.binary_file) }; + let section_iterator = unsafe { LLVMObjectFileCopySectionIterator(self.as_mut_ptr()) }; if section_iterator.is_null() { return None; } - Some(unsafe { Sections::new(section_iterator, self.binary_file) }) + Some(unsafe { Sections::new(section_iterator, self.as_mut_ptr()) }) } pub fn get_symbols(&self) -> Option> { - let symbol_iterator = unsafe { LLVMObjectFileCopySymbolIterator(self.binary_file) }; + let symbol_iterator = unsafe { LLVMObjectFileCopySymbolIterator(self.as_mut_ptr()) }; if symbol_iterator.is_null() { return None; } - Some(unsafe { Symbols::new(symbol_iterator, self.binary_file) }) + Some(unsafe { Symbols::new(symbol_iterator, self.as_mut_ptr()) }) } } impl<'a> Drop for BinaryFile<'a> { fn drop(&mut self) { unsafe { - LLVMDisposeBinary(self.binary_file); + LLVMDisposeBinary(self.as_mut_ptr()); } } } #[derive(Debug)] pub struct Sections<'a> { - section_iterator: LLVMSectionIteratorRef, - binary_file: LLVMBinaryRef, + section_iterator: NonNull, + binary_file: NonNull, at_start: bool, at_end: bool, _phantom: PhantomData<&'a ()>, } +const _: () = assert_niche::(); impl<'a> Sections<'a> { pub unsafe fn new(section_iterator: LLVMSectionIteratorRef, binary_file: LLVMBinaryRef) -> Self { @@ -90,8 +95,8 @@ impl<'a> Sections<'a> { assert!(!binary_file.is_null()); Sections { - section_iterator, - binary_file, + section_iterator: unsafe { NonNull::new_unchecked(section_iterator) }, + binary_file: unsafe { NonNull::new_unchecked(binary_file) }, at_start: true, at_end: false, _phantom: PhantomData, @@ -99,7 +104,7 @@ impl<'a> Sections<'a> { } pub fn as_mut_ptr(&self) -> (LLVMSectionIteratorRef, LLVMBinaryRef) { - (self.section_iterator, self.binary_file) + (self.section_iterator.as_ptr(), self.binary_file.as_ptr()) } // Here we cannot use the `Iterator`` trait since `Section` depends on the lifetime of self to @@ -115,17 +120,19 @@ impl<'a> Sections<'a> { if !self.at_start { unsafe { - LLVMMoveToNextSection(self.section_iterator); + LLVMMoveToNextSection(self.section_iterator.as_ptr()); } } self.at_start = false; - self.at_end = unsafe { LLVMObjectFileIsSectionIteratorAtEnd(self.binary_file, self.section_iterator) == 1 }; + self.at_end = unsafe { + LLVMObjectFileIsSectionIteratorAtEnd(self.binary_file.as_ptr(), self.section_iterator.as_ptr()) == 1 + }; if self.at_end { return None; } - let section = unsafe { Section::new(self.section_iterator, self.binary_file) }; + let section = unsafe { Section::new(self.section_iterator.as_ptr(), self.binary_file.as_ptr()) }; Some(section) } @@ -134,23 +141,24 @@ impl<'a> Sections<'a> { self.at_start = true; self.at_end = false; unsafe { - LLVMMoveToContainingSection(self.section_iterator, symbol.symbol); + LLVMMoveToContainingSection(self.section_iterator.as_ptr(), symbol.symbol.as_ptr()); } } } impl<'a> Drop for Sections<'a> { fn drop(&mut self) { - unsafe { LLVMDisposeSectionIterator(self.section_iterator) } + unsafe { LLVMDisposeSectionIterator(self.section_iterator.as_ptr()) } } } #[derive(Debug)] pub struct Section<'a> { - section: LLVMSectionIteratorRef, - binary_file: LLVMBinaryRef, + section: NonNull, + binary_file: NonNull, _phantom: PhantomData<&'a ()>, } +const _: () = assert_niche::
(); impl<'a> Section<'a> { pub unsafe fn new(section: LLVMSectionIteratorRef, binary_file: LLVMBinaryRef) -> Self { @@ -158,18 +166,18 @@ impl<'a> Section<'a> { assert!(!binary_file.is_null()); Self { - section, - binary_file, + section: unsafe { NonNull::new_unchecked(section) }, + binary_file: unsafe { NonNull::new_unchecked(binary_file) }, _phantom: PhantomData, } } pub unsafe fn as_mut_ptr(&self) -> (LLVMSectionIteratorRef, LLVMBinaryRef) { - (self.section, self.binary_file) + (self.section.as_ptr(), self.binary_file.as_ptr()) } pub fn get_name(&self) -> Option<&CStr> { - let name = unsafe { LLVMGetSectionName(self.section) }; + let name = unsafe { LLVMGetSectionName(self.section.as_ptr()) }; if !name.is_null() { Some(unsafe { CStr::from_ptr(name) }) } else { @@ -178,42 +186,43 @@ impl<'a> Section<'a> { } pub fn get_size(&self) -> u64 { - unsafe { LLVMGetSectionSize(self.section) } + unsafe { LLVMGetSectionSize(self.section.as_ptr()) } } pub fn get_contents(&self) -> &[u8] { unsafe { std::slice::from_raw_parts( - LLVMGetSectionContents(self.section) as *const u8, + LLVMGetSectionContents(self.section.as_ptr()) as *const u8, self.get_size() as usize, ) } } pub fn get_address(&self) -> u64 { - unsafe { LLVMGetSectionAddress(self.section) } + unsafe { LLVMGetSectionAddress(self.section.as_ptr()) } } pub fn contains_symbol(&self, symbol: &Symbol<'_>) -> bool { - unsafe { LLVMGetSectionContainsSymbol(self.section, symbol.symbol) == 1 } + unsafe { LLVMGetSectionContainsSymbol(self.section.as_ptr(), symbol.symbol.as_ptr()) == 1 } } pub fn get_relocations(&self) -> Relocations<'_> { - let relocation_iterator = unsafe { LLVMGetRelocations(self.section) }; + let relocation_iterator = unsafe { LLVMGetRelocations(self.section.as_ptr()) }; - unsafe { Relocations::new(relocation_iterator, self.section, self.binary_file) } + unsafe { Relocations::new(relocation_iterator, self.section.as_ptr(), self.binary_file.as_ptr()) } } } #[derive(Debug)] pub struct Relocations<'a> { - relocation_iterator: LLVMRelocationIteratorRef, - section_iterator: LLVMSectionIteratorRef, - binary_file: LLVMBinaryRef, + relocation_iterator: NonNull, + section_iterator: NonNull, + binary_file: NonNull, at_start: bool, at_end: bool, _phantom: PhantomData<&'a ()>, } +const _: () = assert_niche::(); impl<'a> Relocations<'a> { pub unsafe fn new( @@ -226,9 +235,9 @@ impl<'a> Relocations<'a> { assert!(!binary_file.is_null()); Self { - relocation_iterator, - section_iterator, - binary_file, + relocation_iterator: unsafe { NonNull::new_unchecked(relocation_iterator) }, + section_iterator: unsafe { NonNull::new_unchecked(section_iterator) }, + binary_file: unsafe { NonNull::new_unchecked(binary_file) }, at_start: true, at_end: false, _phantom: PhantomData, @@ -236,7 +245,11 @@ impl<'a> Relocations<'a> { } pub fn as_mut_ptr(&self) -> (LLVMRelocationIteratorRef, LLVMSectionIteratorRef, LLVMBinaryRef) { - (self.relocation_iterator, self.section_iterator, self.binary_file) + ( + self.relocation_iterator.as_ptr(), + self.section_iterator.as_ptr(), + self.binary_file.as_ptr(), + ) } pub fn next_relocation(&mut self) -> Option> { @@ -246,33 +259,36 @@ impl<'a> Relocations<'a> { if !self.at_start { unsafe { - LLVMMoveToNextRelocation(self.relocation_iterator); + LLVMMoveToNextRelocation(self.relocation_iterator.as_ptr()); } } self.at_start = false; - self.at_end = unsafe { LLVMIsRelocationIteratorAtEnd(self.section_iterator, self.relocation_iterator) == 1 }; + self.at_end = unsafe { + LLVMIsRelocationIteratorAtEnd(self.section_iterator.as_ptr(), self.relocation_iterator.as_ptr()) == 1 + }; if self.at_end { return None; } - let relocation = unsafe { Relocation::new(self.relocation_iterator, self.binary_file) }; + let relocation = unsafe { Relocation::new(self.relocation_iterator.as_ptr(), self.binary_file.as_ptr()) }; Some(relocation) } } impl<'a> Drop for Relocations<'a> { fn drop(&mut self) { - unsafe { LLVMDisposeRelocationIterator(self.relocation_iterator) } + unsafe { LLVMDisposeRelocationIterator(self.relocation_iterator.as_ptr()) } } } #[derive(Debug)] pub struct Relocation<'a> { - relocation: LLVMRelocationIteratorRef, - binary_file: LLVMBinaryRef, + relocation: NonNull, + binary_file: NonNull, _phantom: PhantomData<&'a ()>, } +const _: () = assert_niche::(); impl<'a> Relocation<'a> { pub unsafe fn new(relocation: LLVMRelocationIteratorRef, binary_file: LLVMBinaryRef) -> Self { @@ -280,33 +296,33 @@ impl<'a> Relocation<'a> { assert!(!binary_file.is_null()); Self { - relocation, - binary_file, + relocation: unsafe { NonNull::new_unchecked(relocation) }, + binary_file: unsafe { NonNull::new_unchecked(binary_file) }, _phantom: PhantomData, } } pub fn as_mut_ptr(&self) -> (LLVMRelocationIteratorRef, LLVMBinaryRef) { - (self.relocation, self.binary_file) + (self.relocation.as_ptr(), self.binary_file.as_ptr()) } pub fn get_offset(&self) -> u64 { - unsafe { LLVMGetRelocationOffset(self.relocation) } + unsafe { LLVMGetRelocationOffset(self.relocation.as_ptr()) } } pub fn get_type(&self) -> (u64, LLVMString) { - let type_int = unsafe { LLVMGetRelocationType(self.relocation) }; - let type_name = unsafe { LLVMString::new(LLVMGetRelocationTypeName(self.relocation)) }; + let type_int = unsafe { LLVMGetRelocationType(self.relocation.as_ptr()) }; + let type_name = unsafe { LLVMString::new(LLVMGetRelocationTypeName(self.relocation.as_ptr())) }; (type_int, type_name) } pub fn get_value(&self) -> LLVMString { - unsafe { LLVMString::new(LLVMGetRelocationValueString(self.relocation)) } + unsafe { LLVMString::new(LLVMGetRelocationValueString(self.relocation.as_ptr())) } } pub fn get_symbol(&self) -> Symbol<'_> { - let symbol = unsafe { LLVMGetRelocationSymbol(self.relocation) }; + let symbol = unsafe { LLVMGetRelocationSymbol(self.relocation.as_ptr()) }; unsafe { Symbol::new(symbol) } } @@ -314,12 +330,13 @@ impl<'a> Relocation<'a> { #[derive(Debug)] pub struct Symbols<'a> { - symbol_iterator: LLVMSymbolIteratorRef, - binary_file: LLVMBinaryRef, + symbol_iterator: NonNull, + binary_file: NonNull, at_start: bool, at_end: bool, _phantom: PhantomData<&'a ()>, } +const _: () = assert_niche::(); impl<'a> Symbols<'a> { pub unsafe fn new(symbol_iterator: LLVMSymbolIteratorRef, binary_file: LLVMBinaryRef) -> Self { @@ -327,8 +344,8 @@ impl<'a> Symbols<'a> { assert!(!binary_file.is_null()); Self { - symbol_iterator, - binary_file, + symbol_iterator: unsafe { NonNull::new_unchecked(symbol_iterator) }, + binary_file: unsafe { NonNull::new_unchecked(binary_file) }, at_start: true, at_end: false, _phantom: PhantomData, @@ -336,7 +353,7 @@ impl<'a> Symbols<'a> { } pub fn as_mut_ptr(&self) -> (LLVMSymbolIteratorRef, LLVMBinaryRef) { - (self.symbol_iterator, self.binary_file) + (self.symbol_iterator.as_ptr(), self.binary_file.as_ptr()) } pub fn next_symbol(&mut self) -> Option> { @@ -346,49 +363,52 @@ impl<'a> Symbols<'a> { if !self.at_start { unsafe { - LLVMMoveToNextSymbol(self.symbol_iterator); + LLVMMoveToNextSymbol(self.symbol_iterator.as_ptr()); } } self.at_start = false; - self.at_end = unsafe { LLVMObjectFileIsSymbolIteratorAtEnd(self.binary_file, self.symbol_iterator) == 1 }; + self.at_end = unsafe { + LLVMObjectFileIsSymbolIteratorAtEnd(self.binary_file.as_ptr(), self.symbol_iterator.as_ptr()) == 1 + }; if self.at_end { return None; } - let symbol = unsafe { Symbol::new(self.symbol_iterator) }; + let symbol = unsafe { Symbol::new(self.symbol_iterator.as_ptr()) }; Some(symbol) } } impl<'a> Drop for Symbols<'a> { fn drop(&mut self) { - unsafe { LLVMDisposeSymbolIterator(self.symbol_iterator) } + unsafe { LLVMDisposeSymbolIterator(self.symbol_iterator.as_ptr()) } } } #[derive(Debug)] pub struct Symbol<'a> { - symbol: LLVMSymbolIteratorRef, + symbol: NonNull, _phantom: PhantomData<&'a ()>, } +const _: () = assert_niche::(); impl<'a> Symbol<'a> { pub unsafe fn new(symbol: LLVMSymbolIteratorRef) -> Self { assert!(!symbol.is_null()); Self { - symbol, + symbol: unsafe { NonNull::new_unchecked(symbol) }, _phantom: PhantomData, } } pub fn as_mut_ptr(&self) -> LLVMSymbolIteratorRef { - self.symbol + self.symbol.as_ptr() } pub fn get_name(&self) -> Option<&CStr> { - let name = unsafe { LLVMGetSymbolName(self.symbol) }; + let name = unsafe { LLVMGetSymbolName(self.symbol.as_ptr()) }; if !name.is_null() { Some(unsafe { CStr::from_ptr(name) }) } else { @@ -397,10 +417,10 @@ impl<'a> Symbol<'a> { } pub fn get_size(&self) -> u64 { - unsafe { LLVMGetSymbolSize(self.symbol) } + unsafe { LLVMGetSymbolSize(self.symbol.as_ptr()) } } pub fn get_address(&self) -> u64 { - unsafe { LLVMGetSymbolAddress(self.symbol) } + unsafe { LLVMGetSymbolAddress(self.symbol.as_ptr()) } } } diff --git a/src/passes.rs b/src/passes.rs index dfc112872f3..b3a96c518b2 100644 --- a/src/passes.rs +++ b/src/passes.rs @@ -247,7 +247,7 @@ impl PassManagerSubType for Module<'_> { } unsafe fn run_in_pass_manager(&self, pass_manager: &PassManager) -> bool { - unsafe { LLVMRunPassManager(pass_manager.pass_manager, self.module.get()) == 1 } + unsafe { LLVMRunPassManager(pass_manager.pass_manager, self.as_mut_ptr()) == 1 } } } @@ -258,7 +258,7 @@ impl<'ctx> PassManagerSubType for FunctionValue<'ctx> { type Input = Module<'ctx>; unsafe fn create>(input: I) -> LLVMPassManagerRef { - unsafe { LLVMCreateFunctionPassManagerForModule(input.borrow().module.get()) } + unsafe { LLVMCreateFunctionPassManagerForModule(input.borrow().as_mut_ptr()) } } unsafe fn run_in_pass_manager(&self, pass_manager: &PassManager) -> bool { diff --git a/src/support/error_handling.rs b/src/support/error_handling.rs index 16352eb8e4b..9e49ca59c42 100644 --- a/src/support/error_handling.rs +++ b/src/support/error_handling.rs @@ -1,10 +1,14 @@ //! This module contains some supplemental functions for dealing with errors. +use std::ptr::NonNull; + use libc::c_void; -use llvm_sys::LLVMDiagnosticSeverity; use llvm_sys::core::{LLVMGetDiagInfoDescription, LLVMGetDiagInfoSeverity}; use llvm_sys::error_handling::{LLVMInstallFatalErrorHandler, LLVMResetFatalErrorHandler}; use llvm_sys::prelude::LLVMDiagnosticInfoRef; +use llvm_sys::{LLVMDiagnosticInfo, LLVMDiagnosticSeverity}; + +use crate::support::assert_niche; // REVIEW: Maybe it's possible to have a safe wrapper? If we can // wrap the provided function input ptr into a &CStr somehow @@ -28,17 +32,26 @@ pub fn reset_fatal_error_handler() { unsafe { LLVMResetFatalErrorHandler() } } +#[repr(transparent)] pub(crate) struct DiagnosticInfo { - diagnostic_info: LLVMDiagnosticInfoRef, + diagnostic_info: NonNull, } +const _: () = assert_niche::(); impl DiagnosticInfo { pub unsafe fn new(diagnostic_info: LLVMDiagnosticInfoRef) -> Self { - DiagnosticInfo { diagnostic_info } + debug_assert!(!diagnostic_info.is_null(), "diagnostic_info must be non-null."); + DiagnosticInfo { + diagnostic_info: unsafe { NonNull::new_unchecked(diagnostic_info) }, + } + } + + pub fn as_mut_ptr(&self) -> LLVMDiagnosticInfoRef { + self.diagnostic_info.as_ptr() } pub(crate) fn get_description(&self) -> *mut ::libc::c_char { - unsafe { LLVMGetDiagInfoDescription(self.diagnostic_info) } + unsafe { LLVMGetDiagInfoDescription(self.as_mut_ptr()) } } pub(crate) fn severity_is_error(&self) -> bool { @@ -46,7 +59,7 @@ impl DiagnosticInfo { } fn severity(&self) -> LLVMDiagnosticSeverity { - unsafe { LLVMGetDiagInfoSeverity(self.diagnostic_info) } + unsafe { LLVMGetDiagInfoSeverity(self.as_mut_ptr()) } } } diff --git a/src/support/mod.rs b/src/support/mod.rs index ea4a657ffbb..835e1783aac 100644 --- a/src/support/mod.rs +++ b/src/support/mod.rs @@ -14,12 +14,14 @@ use std::ffi::{CStr, CString}; use std::fmt::{self, Debug, Display, Formatter}; use std::ops::Deref; use std::path::Path; +use std::ptr::NonNull; /// An owned LLVM String. Also known as a LLVM Message #[derive(Eq)] pub struct LLVMString { - pub(crate) ptr: *const c_char, + pub(crate) ptr: NonNull, } +const _: () = assert_niche::(); unsafe impl Send for LLVMString {} unsafe impl Sync for LLVMString {} @@ -27,7 +29,9 @@ unsafe impl Sync for LLVMString {} impl LLVMString { pub(crate) unsafe fn new(ptr: *const c_char) -> Self { assert!(!ptr.is_null()); - LLVMString { ptr } + LLVMString { + ptr: unsafe { NonNull::new_unchecked(ptr.cast_mut()) }, + } } /// This is a convenience method for creating a Rust `String`, @@ -57,7 +61,7 @@ impl Deref for LLVMString { type Target = CStr; fn deref(&self) -> &Self::Target { - unsafe { CStr::from_ptr(self.ptr) } + unsafe { CStr::from_ptr(self.ptr.as_ptr()) } } } @@ -93,7 +97,7 @@ impl Error for LLVMString { impl Drop for LLVMString { fn drop(&mut self) { unsafe { - LLVMDisposeMessage(self.ptr as *mut _); + LLVMDisposeMessage(self.ptr.as_ptr()); } } } @@ -105,14 +109,14 @@ impl Drop for LLVMString { #[derive(Eq)] pub(crate) enum LLVMStringOrRaw { Owned(LLVMString), - Borrowed(*const c_char), + Borrowed(NonNull), } impl LLVMStringOrRaw { pub fn as_str(&self) -> &CStr { match self { LLVMStringOrRaw::Owned(llvm_string) => llvm_string.deref(), - LLVMStringOrRaw::Borrowed(ptr) => unsafe { CStr::from_ptr(*ptr) }, + LLVMStringOrRaw::Borrowed(ptr) => unsafe { CStr::from_ptr(ptr.as_ptr()) }, } } } @@ -233,6 +237,45 @@ pub(crate) fn to_c_str(mut s: &str) -> Cow<'_, CStr> { } } +/// Perform an assertion at compile time. +/// +/// # Example +/// +/// ```ignore +/// use inkwell::support::const_assert; +/// #[repr(transparent)] +/// struct Foo { +/// bar: &'static (), +/// } +/// const _: () = const_assert(size_of::() == size_of::<&'static ()>()); +/// ``` +#[track_caller] +#[inline(always)] +pub(crate) const fn const_assert(assertion: bool) { + if !assertion { + panic!("Assertion Failed"); + } +} + +/// Asserts that a type has at least one niche. Having a niche means that `size_of::() == size_of::>()`. +/// +/// # Example +/// +/// ```ignore +/// use std::ptr::NonNull; +/// use inkwell::support::assert_niche; +/// +/// struct Foo { +/// bar: NonNull, +/// } +/// const _: () = assert_niche::(); +/// ``` +#[track_caller] +#[inline(always)] +pub(crate) const fn assert_niche() { + const_assert(size_of::() == size_of::>() && align_of::() == align_of::>()); +} + #[test] fn test_to_c_str() { assert_eq!(to_c_str("my string"), Cow::::Owned(c"my string".to_owned())); diff --git a/src/targets.rs b/src/targets.rs index 8ca64d365b2..0dc41eb0e66 100644 --- a/src/targets.rs +++ b/src/targets.rs @@ -1,11 +1,10 @@ use llvm_sys::target::{ LLVMABIAlignmentOfType, LLVMABISizeOfType, LLVMByteOrder, LLVMByteOrdering, LLVMCallFrameAlignmentOfType, LLVMCopyStringRepOfTargetData, LLVMCreateTargetData, LLVMDisposeTargetData, LLVMElementAtOffset, - LLVMIntPtrTypeForASInContext, LLVMIntPtrTypeInContext, LLVMOffsetOfElement, LLVMPointerSize, LLVMPointerSizeForAS, - LLVMPreferredAlignmentOfGlobal, LLVMPreferredAlignmentOfType, LLVMSizeOfTypeInBits, LLVMStoreSizeOfType, - LLVMTargetDataRef, + LLVMIntPtrTypeForASInContext, LLVMIntPtrTypeInContext, LLVMOffsetOfElement, LLVMOpaqueTargetData, LLVMPointerSize, + LLVMPointerSizeForAS, LLVMPreferredAlignmentOfGlobal, LLVMPreferredAlignmentOfType, LLVMSizeOfTypeInBits, + LLVMStoreSizeOfType, LLVMTargetDataRef, }; -use llvm_sys::target_machine::LLVMCreateTargetDataLayout; use llvm_sys::target_machine::{ LLVMAddAnalysisPasses, LLVMCodeGenFileType, LLVMCodeModel, LLVMCreateTargetMachine, LLVMDisposeTargetMachine, LLVMGetDefaultTargetTriple, LLVMGetFirstTarget, LLVMGetNextTarget, LLVMGetTargetDescription, LLVMGetTargetFromName, @@ -14,11 +13,12 @@ use llvm_sys::target_machine::{ LLVMTargetHasAsmBackend, LLVMTargetHasJIT, LLVMTargetHasTargetMachine, LLVMTargetMachineEmitToFile, LLVMTargetMachineEmitToMemoryBuffer, LLVMTargetMachineRef, LLVMTargetRef, }; +use llvm_sys::target_machine::{LLVMCreateTargetDataLayout, LLVMOpaqueTargetMachine, LLVMTarget}; #[llvm_versions(18..)] use llvm_sys::target_machine::{ LLVMCreateTargetMachineOptions, LLVMCreateTargetMachineWithOptions, LLVMDisposeTargetMachineOptions, - LLVMTargetMachineOptionsRef, LLVMTargetMachineOptionsSetABI, LLVMTargetMachineOptionsSetCPU, - LLVMTargetMachineOptionsSetCodeGenOptLevel, LLVMTargetMachineOptionsSetCodeModel, + LLVMOpaqueTargetMachineOptions, LLVMTargetMachineOptionsRef, LLVMTargetMachineOptionsSetABI, + LLVMTargetMachineOptionsSetCPU, LLVMTargetMachineOptionsSetCodeGenOptLevel, LLVMTargetMachineOptionsSetCodeModel, LLVMTargetMachineOptionsSetFeatures, LLVMTargetMachineOptionsSetRelocMode, }; use std::sync::{LazyLock, RwLock}; @@ -29,7 +29,7 @@ use crate::memory_buffer::MemoryBuffer; use crate::module::Module; #[allow(deprecated)] use crate::passes::PassManager; -use crate::support::{LLVMString, to_c_str}; +use crate::support::{LLVMString, assert_niche, to_c_str}; use crate::types::{AnyType, AsTypeRef, IntType, StructType}; use crate::values::{AsValueRef, GlobalValue}; use crate::{AddressSpace, OptimizationLevel}; @@ -38,7 +38,7 @@ use std::default::Default; use std::ffi::CStr; use std::fmt; use std::path::Path; -use std::ptr; +use std::ptr::{self, NonNull}; #[derive(Default, Debug, PartialEq, Eq, Copy, Clone)] pub enum CodeModel { @@ -171,21 +171,25 @@ impl fmt::Display for TargetTriple { static TARGET_LOCK: LazyLock> = LazyLock::new(|| RwLock::new(())); // NOTE: Versions verified as target-complete: 3.6, 3.7, 3.8, 3.9, 4.0 +#[repr(transparent)] #[derive(Debug, Eq, PartialEq)] pub struct Target { - target: LLVMTargetRef, + target: NonNull, } +const _: () = assert_niche::(); impl Target { pub unsafe fn new(target: LLVMTargetRef) -> Self { assert!(!target.is_null()); - Target { target } + Target { + target: unsafe { NonNull::new_unchecked(target) }, + } } /// Acquires the underlying raw pointer belonging to this `Target` type. pub fn as_mut_ptr(&self) -> LLVMTargetRef { - self.target + self.target.as_ptr() } // REVIEW: Should this just initialize all? Is opt into each a good idea? @@ -912,7 +916,7 @@ impl Target { let target_machine = unsafe { LLVMCreateTargetMachine( - self.target, + self.target.as_ptr(), triple.as_ptr(), cpu.as_ptr(), features.as_ptr(), @@ -958,7 +962,7 @@ impl Target { triple: &TargetTriple, options: TargetMachineOptions, ) -> Option { - options.into_target_machine(self.target, triple) + options.into_target_machine(self.target.as_ptr(), triple) } pub fn get_first() -> Option { @@ -975,7 +979,7 @@ impl Target { } pub fn get_next(&self) -> Option { - let target = unsafe { LLVMGetNextTarget(self.target) }; + let target = unsafe { LLVMGetNextTarget(self.target.as_ptr()) }; if target.is_null() { return None; @@ -985,11 +989,11 @@ impl Target { } pub fn get_name(&self) -> &CStr { - unsafe { CStr::from_ptr(LLVMGetTargetName(self.target)) } + unsafe { CStr::from_ptr(LLVMGetTargetName(self.target.as_ptr())) } } pub fn get_description(&self) -> &CStr { - unsafe { CStr::from_ptr(LLVMGetTargetDescription(self.target)) } + unsafe { CStr::from_ptr(LLVMGetTargetDescription(self.target.as_ptr())) } } pub fn from_name(name: &str) -> Option { @@ -1030,41 +1034,45 @@ impl Target { } pub fn has_jit(&self) -> bool { - unsafe { LLVMTargetHasJIT(self.target) == 1 } + unsafe { LLVMTargetHasJIT(self.target.as_ptr()) == 1 } } pub fn has_target_machine(&self) -> bool { - unsafe { LLVMTargetHasTargetMachine(self.target) == 1 } + unsafe { LLVMTargetHasTargetMachine(self.target.as_ptr()) == 1 } } pub fn has_asm_backend(&self) -> bool { - unsafe { LLVMTargetHasAsmBackend(self.target) == 1 } + unsafe { LLVMTargetHasAsmBackend(self.target.as_ptr()) == 1 } } } +#[repr(transparent)] #[derive(Debug)] pub struct TargetMachine { - pub(crate) target_machine: LLVMTargetMachineRef, + pub(crate) target_machine: NonNull, } +const _: () = assert_niche::(); impl TargetMachine { pub unsafe fn new(target_machine: LLVMTargetMachineRef) -> Self { assert!(!target_machine.is_null()); - TargetMachine { target_machine } + TargetMachine { + target_machine: unsafe { NonNull::new_unchecked(target_machine) }, + } } /// Acquires the underlying raw pointer belonging to this `TargetMachine` type. pub fn as_mut_ptr(&self) -> LLVMTargetMachineRef { - self.target_machine + self.target_machine.as_ptr() } pub fn get_target(&self) -> Target { - unsafe { Target::new(LLVMGetTargetMachineTarget(self.target_machine)) } + unsafe { Target::new(LLVMGetTargetMachineTarget(self.target_machine.as_ptr())) } } pub fn get_triple(&self) -> TargetTriple { - let str = unsafe { LLVMString::new(LLVMGetTargetMachineTriple(self.target_machine)) }; + let str = unsafe { LLVMString::new(LLVMGetTargetMachineTriple(self.target_machine.as_ptr())) }; unsafe { TargetTriple::new(str) } } @@ -1117,26 +1125,26 @@ impl TargetMachine { } pub fn get_cpu(&self) -> LLVMString { - unsafe { LLVMString::new(LLVMGetTargetMachineCPU(self.target_machine)) } + unsafe { LLVMString::new(LLVMGetTargetMachineCPU(self.target_machine.as_ptr())) } } pub fn get_feature_string(&self) -> &CStr { - unsafe { CStr::from_ptr(LLVMGetTargetMachineFeatureString(self.target_machine)) } + unsafe { CStr::from_ptr(LLVMGetTargetMachineFeatureString(self.target_machine.as_ptr())) } } /// Create TargetData from this target machine pub fn get_target_data(&self) -> TargetData { - unsafe { TargetData::new(LLVMCreateTargetDataLayout(self.target_machine)) } + unsafe { TargetData::new(LLVMCreateTargetDataLayout(self.target_machine.as_ptr())) } } pub fn set_asm_verbosity(&self, verbosity: bool) { - unsafe { LLVMSetTargetMachineAsmVerbosity(self.target_machine, verbosity as i32) } + unsafe { LLVMSetTargetMachineAsmVerbosity(self.target_machine.as_ptr(), verbosity as i32) } } // TODO: Move to PassManager? #[allow(deprecated)] pub fn add_analysis_passes(&self, pass_manager: &PassManager) { - unsafe { LLVMAddAnalysisPasses(self.target_machine, pass_manager.pass_manager) } + unsafe { LLVMAddAnalysisPasses(self.target_machine.as_ptr(), pass_manager.pass_manager) } } /// Writes a `TargetMachine` to a `MemoryBuffer`. @@ -1181,11 +1189,11 @@ impl TargetMachine { let mut memory_buffer = ptr::null_mut(); let mut err_string: *mut ::libc::c_char = ::core::ptr::null_mut(); let return_code = unsafe { - let module_ptr = module.module.get(); + let module_ptr = module.as_mut_ptr(); let file_type_ptr = file_type.as_llvm_file_type(); LLVMTargetMachineEmitToMemoryBuffer( - self.target_machine, + self.target_machine.as_ptr(), module_ptr, file_type_ptr, &mut err_string, @@ -1245,12 +1253,12 @@ impl TargetMachine { let mut err_string: *mut ::libc::c_char = ::core::ptr::null_mut(); let return_code = unsafe { // REVIEW: Why does LLVM need a mutable ptr to path...? - let module_ptr = module.module.get(); + let module_ptr = module.as_mut_ptr(); let path_ptr = path_c_string.as_ptr() as *mut _; let file_type_ptr = file_type.as_llvm_file_type(); LLVMTargetMachineEmitToFile( - self.target_machine, + self.target_machine.as_ptr(), module_ptr, path_ptr, file_type_ptr, @@ -1270,7 +1278,7 @@ impl TargetMachine { impl Drop for TargetMachine { fn drop(&mut self) { - unsafe { LLVMDisposeTargetMachine(self.target_machine) } + unsafe { LLVMDisposeTargetMachine(self.target_machine.as_ptr()) } } } @@ -1280,21 +1288,25 @@ pub enum ByteOrdering { LittleEndian, } +#[repr(transparent)] #[derive(PartialEq, Eq, Debug)] pub struct TargetData { - pub(crate) target_data: LLVMTargetDataRef, + pub(crate) target_data: NonNull, } +const _: () = assert_niche::(); impl TargetData { pub unsafe fn new(target_data: LLVMTargetDataRef) -> TargetData { assert!(!target_data.is_null()); - TargetData { target_data } + TargetData { + target_data: unsafe { NonNull::new_unchecked(target_data) }, + } } /// Acquires the underlying raw pointer belonging to this `TargetData` type. pub fn as_mut_ptr(&self) -> LLVMTargetDataRef { - self.target_data + self.target_data.as_ptr() } /// Gets the `IntType` representing a bit width of a pointer. It will be assigned the referenced context. @@ -1322,21 +1334,21 @@ impl TargetData { ) -> IntType<'ctx> { let int_type_ptr = match address_space { Some(address_space) => unsafe { - LLVMIntPtrTypeForASInContext(context.as_ctx_ref(), self.target_data, address_space.0) + LLVMIntPtrTypeForASInContext(context.as_ctx_ref(), self.target_data.as_ptr(), address_space.0) }, - None => unsafe { LLVMIntPtrTypeInContext(context.as_ctx_ref(), self.target_data) }, + None => unsafe { LLVMIntPtrTypeInContext(context.as_ctx_ref(), self.target_data.as_ptr()) }, }; unsafe { IntType::new(int_type_ptr) } } pub fn get_data_layout(&self) -> DataLayout { - unsafe { DataLayout::new_owned(LLVMCopyStringRepOfTargetData(self.target_data)) } + unsafe { DataLayout::new_owned(LLVMCopyStringRepOfTargetData(self.target_data.as_ptr())) } } // REVIEW: Does this only work if Sized? pub fn get_bit_size(&self, type_: &dyn AnyType) -> u64 { - unsafe { LLVMSizeOfTypeInBits(self.target_data, type_.as_type_ref()) } + unsafe { LLVMSizeOfTypeInBits(self.target_data.as_ptr(), type_.as_type_ref()) } } // TODOC: This can fail on LLVM's side(exit?), but it doesn't seem like we have any way to check this in rust @@ -1347,7 +1359,7 @@ impl TargetData { } pub fn get_byte_ordering(&self) -> ByteOrdering { - let byte_ordering = unsafe { LLVMByteOrder(self.target_data) }; + let byte_ordering = unsafe { LLVMByteOrder(self.target_data.as_ptr()) }; match byte_ordering { LLVMByteOrdering::LLVMBigEndian => ByteOrdering::BigEndian, @@ -1357,37 +1369,37 @@ impl TargetData { pub fn get_pointer_byte_size(&self, address_space: Option) -> u32 { match address_space { - Some(address_space) => unsafe { LLVMPointerSizeForAS(self.target_data, address_space.0) }, - None => unsafe { LLVMPointerSize(self.target_data) }, + Some(address_space) => unsafe { LLVMPointerSizeForAS(self.target_data.as_ptr(), address_space.0) }, + None => unsafe { LLVMPointerSize(self.target_data.as_ptr()) }, } } pub fn get_store_size(&self, type_: &dyn AnyType) -> u64 { - unsafe { LLVMStoreSizeOfType(self.target_data, type_.as_type_ref()) } + unsafe { LLVMStoreSizeOfType(self.target_data.as_ptr(), type_.as_type_ref()) } } pub fn get_abi_size(&self, type_: &dyn AnyType) -> u64 { - unsafe { LLVMABISizeOfType(self.target_data, type_.as_type_ref()) } + unsafe { LLVMABISizeOfType(self.target_data.as_ptr(), type_.as_type_ref()) } } pub fn get_abi_alignment(&self, type_: &dyn AnyType) -> u32 { - unsafe { LLVMABIAlignmentOfType(self.target_data, type_.as_type_ref()) } + unsafe { LLVMABIAlignmentOfType(self.target_data.as_ptr(), type_.as_type_ref()) } } pub fn get_call_frame_alignment(&self, type_: &dyn AnyType) -> u32 { - unsafe { LLVMCallFrameAlignmentOfType(self.target_data, type_.as_type_ref()) } + unsafe { LLVMCallFrameAlignmentOfType(self.target_data.as_ptr(), type_.as_type_ref()) } } pub fn get_preferred_alignment(&self, type_: &dyn AnyType) -> u32 { - unsafe { LLVMPreferredAlignmentOfType(self.target_data, type_.as_type_ref()) } + unsafe { LLVMPreferredAlignmentOfType(self.target_data.as_ptr(), type_.as_type_ref()) } } pub fn get_preferred_alignment_of_global(&self, value: &GlobalValue) -> u32 { - unsafe { LLVMPreferredAlignmentOfGlobal(self.target_data, value.as_value_ref()) } + unsafe { LLVMPreferredAlignmentOfGlobal(self.target_data.as_ptr(), value.as_value_ref()) } } pub fn element_at_offset(&self, struct_type: &StructType, offset: u64) -> u32 { - unsafe { LLVMElementAtOffset(self.target_data, struct_type.as_type_ref(), offset) } + unsafe { LLVMElementAtOffset(self.target_data.as_ptr(), struct_type.as_type_ref(), offset) } } pub fn offset_of_element(&self, struct_type: &StructType, element: u32) -> Option { @@ -1397,7 +1409,7 @@ impl TargetData { unsafe { Some(LLVMOffsetOfElement( - self.target_data, + self.target_data.as_ptr(), struct_type.as_type_ref(), element, )) @@ -1407,7 +1419,7 @@ impl TargetData { impl Drop for TargetData { fn drop(&mut self) { - unsafe { LLVMDisposeTargetData(self.target_data) } + unsafe { LLVMDisposeTargetData(self.target_data.as_ptr()) } } } @@ -1418,7 +1430,7 @@ impl Drop for TargetData { /// and provides default values for unspecified settings. #[llvm_versions(18..)] #[derive(Default, Debug)] -pub struct TargetMachineOptions(Option); +pub struct TargetMachineOptions(Option>); #[llvm_versions(18..)] impl TargetMachineOptions { @@ -1481,7 +1493,11 @@ impl TargetMachineOptions { /// - The only way to access it is via this private method. /// - Disposal is taken care of automatically in `Drop::drop`. unsafe fn inner(&mut self) -> LLVMTargetMachineOptionsRef { - unsafe { *self.0.get_or_insert_with(|| LLVMCreateTargetMachineOptions()) } + unsafe { + self.0 + .get_or_insert_with(|| NonNull::new_unchecked(LLVMCreateTargetMachineOptions())) + .as_ptr() + } } } @@ -1489,7 +1505,7 @@ impl TargetMachineOptions { impl Drop for TargetMachineOptions { fn drop(&mut self) { if let Some(inner) = self.0 { - unsafe { LLVMDisposeTargetMachineOptions(inner) }; + unsafe { LLVMDisposeTargetMachineOptions(inner.as_ptr()) }; } } } diff --git a/src/types/array_type.rs b/src/types/array_type.rs index 8eb5a22e6da..1dd9adcb113 100644 --- a/src/types/array_type.rs +++ b/src/types/array_type.rs @@ -4,7 +4,7 @@ use llvm_sys::prelude::LLVMTypeRef; use crate::AddressSpace; use crate::context::ContextRef; -use crate::support::LLVMString; +use crate::support::{LLVMString, assert_niche}; use crate::types::enums::BasicMetadataTypeEnum; use crate::types::traits::AsTypeRef; use crate::types::{BasicTypeEnum, FunctionType, PointerType, Type}; @@ -13,10 +13,12 @@ use crate::values::{ArrayValue, IntValue}; use std::fmt::{self, Display}; /// An `ArrayType` is the type of contiguous constants or variables. +#[repr(transparent)] #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub struct ArrayType<'ctx> { array_type: Type<'ctx>, } +const _: () = assert_niche::(); impl<'ctx> ArrayType<'ctx> { /// Create `ArrayType` from [`LLVMTypeRef`] @@ -258,7 +260,7 @@ impl<'ctx> ArrayType<'ctx> { unsafe impl AsTypeRef for ArrayType<'_> { fn as_type_ref(&self) -> LLVMTypeRef { - self.array_type.ty + self.array_type.as_mut_ptr() } } diff --git a/src/types/float_type.rs b/src/types/float_type.rs index c74e56a008a..7e155e30fd4 100644 --- a/src/types/float_type.rs +++ b/src/types/float_type.rs @@ -4,7 +4,7 @@ use llvm_sys::prelude::LLVMTypeRef; use crate::AddressSpace; use crate::context::ContextRef; -use crate::support::LLVMString; +use crate::support::{LLVMString, assert_niche}; #[llvm_versions(12..)] use crate::types::ScalableVectorType; use crate::types::enums::BasicMetadataTypeEnum; @@ -15,10 +15,12 @@ use crate::values::{ArrayValue, FloatValue, GenericValue, IntValue}; use std::fmt::{self, Display}; /// A `FloatType` is the type of a floating point constant or variable. +#[repr(transparent)] #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub struct FloatType<'ctx> { float_type: Type<'ctx>, } +const _: () = assert_niche::(); impl<'ctx> FloatType<'ctx> { /// Create `FloatType` from [`LLVMTypeRef`] @@ -118,7 +120,7 @@ impl<'ctx> FloatType<'ctx> { /// let f32_value = f32_type.const_float(42.); /// ``` pub fn const_float(self, value: f64) -> FloatValue<'ctx> { - unsafe { FloatValue::new(LLVMConstReal(self.float_type.ty, value)) } + unsafe { FloatValue::new(LLVMConstReal(self.float_type.as_mut_ptr(), value)) } } // We could make this safe again by doing the validation for users. @@ -349,7 +351,7 @@ impl<'ctx> FloatType<'ctx> { unsafe impl AsTypeRef for FloatType<'_> { fn as_type_ref(&self) -> LLVMTypeRef { - self.float_type.ty + self.float_type.as_mut_ptr() } } diff --git a/src/types/fn_type.rs b/src/types/fn_type.rs index fee0beb3a95..025f5cb40f0 100644 --- a/src/types/fn_type.rs +++ b/src/types/fn_type.rs @@ -9,15 +9,17 @@ use std::mem::forget; use crate::AddressSpace; use crate::context::ContextRef; -use crate::support::LLVMString; +use crate::support::{LLVMString, assert_niche}; use crate::types::traits::AsTypeRef; use crate::types::{AnyType, BasicMetadataTypeEnum, BasicTypeEnum, PointerType, Type}; /// A `FunctionType` is the type of a function variable. +#[repr(transparent)] #[derive(PartialEq, Eq, Clone, Copy)] pub struct FunctionType<'ctx> { fn_type: Type<'ctx>, } +const _: () = assert_niche::(); impl<'ctx> FunctionType<'ctx> { /// Create `FunctionType` from [`LLVMTypeRef`] @@ -230,7 +232,7 @@ impl fmt::Debug for FunctionType<'_> { unsafe impl AsTypeRef for FunctionType<'_> { fn as_type_ref(&self) -> LLVMTypeRef { - self.fn_type.ty + self.fn_type.as_mut_ptr() } } diff --git a/src/types/int_type.rs b/src/types/int_type.rs index 4c0f08bb676..571848b6e2f 100644 --- a/src/types/int_type.rs +++ b/src/types/int_type.rs @@ -6,7 +6,7 @@ use llvm_sys::prelude::LLVMTypeRef; use crate::AddressSpace; use crate::context::ContextRef; -use crate::support::LLVMString; +use crate::support::{LLVMString, assert_niche}; #[llvm_versions(12..)] use crate::types::ScalableVectorType; use crate::types::traits::AsTypeRef; @@ -64,10 +64,12 @@ impl StringRadix { } /// An `IntType` is the type of an integer constant or variable. +#[repr(transparent)] #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub struct IntType<'ctx> { int_type: Type<'ctx>, } +const _: () = assert_niche::(); impl<'ctx> IntType<'ctx> { /// Create `IntType` from [`LLVMTypeRef`] @@ -414,7 +416,7 @@ impl<'ctx> IntType<'ctx> { unsafe impl AsTypeRef for IntType<'_> { fn as_type_ref(&self) -> LLVMTypeRef { - self.int_type.ty + self.int_type.as_mut_ptr() } } diff --git a/src/types/metadata_type.rs b/src/types/metadata_type.rs index 2b02fa17a5e..80372c75c04 100644 --- a/src/types/metadata_type.rs +++ b/src/types/metadata_type.rs @@ -1,7 +1,7 @@ use llvm_sys::prelude::LLVMTypeRef; use crate::context::ContextRef; -use crate::support::LLVMString; +use crate::support::{LLVMString, assert_niche}; use crate::types::enums::BasicMetadataTypeEnum; use crate::types::traits::AsTypeRef; use crate::types::{FunctionType, Type}; @@ -9,10 +9,12 @@ use crate::types::{FunctionType, Type}; use std::fmt::{self, Display}; /// A `MetadataType` is the type of a metadata. +#[repr(transparent)] #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub struct MetadataType<'ctx> { metadata_type: Type<'ctx>, } +const _: () = assert_niche::(); impl<'ctx> MetadataType<'ctx> { /// Create `MetadataType` from [`LLVMTypeRef`] @@ -68,7 +70,7 @@ impl<'ctx> MetadataType<'ctx> { unsafe impl AsTypeRef for MetadataType<'_> { fn as_type_ref(&self) -> LLVMTypeRef { - self.metadata_type.ty + self.metadata_type.as_mut_ptr() } } diff --git a/src/types/mod.rs b/src/types/mod.rs index c889fc324bf..0c7cc76d172 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -44,7 +44,6 @@ use llvm_sys::core::LLVMScalableVectorType; #[llvm_versions(12..)] use llvm_sys::core::LLVMGetPoison; -use llvm_sys::LLVMTypeKind; #[allow(deprecated)] use llvm_sys::core::LLVMArrayType; use llvm_sys::core::{ @@ -52,53 +51,61 @@ use llvm_sys::core::{ LLVMGetTypeKind, LLVMGetUndef, LLVMPointerType, LLVMPrintTypeToString, LLVMSizeOf, LLVMTypeIsSized, LLVMVectorType, }; use llvm_sys::prelude::{LLVMTypeRef, LLVMValueRef}; +use llvm_sys::{LLVMType, LLVMTypeKind}; #[cfg(feature = "experimental")] use static_alloc::Bump; use std::fmt; use std::marker::PhantomData; +use std::ptr::NonNull; use crate::AddressSpace; use crate::context::ContextRef; -use crate::support::LLVMString; +use crate::support::{LLVMString, assert_niche}; use crate::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. +#[repr(transparent)] #[derive(PartialEq, Eq, Clone, Copy)] struct Type<'ctx> { - ty: LLVMTypeRef, + ty: NonNull, _marker: PhantomData<&'ctx ()>, } +const _: () = assert_niche::(); impl<'ctx> Type<'ctx> { unsafe fn new(ty: LLVMTypeRef) -> Self { assert!(!ty.is_null()); Type { - ty, + ty: unsafe { NonNull::new_unchecked(ty) }, _marker: PhantomData, } } + pub(crate) fn as_mut_ptr(&self) -> LLVMTypeRef { + self.ty.as_ptr() + } + fn const_zero(self) -> LLVMValueRef { unsafe { - match LLVMGetTypeKind(self.ty) { - LLVMTypeKind::LLVMMetadataTypeKind => LLVMConstPointerNull(self.ty), - _ => LLVMConstNull(self.ty), + match LLVMGetTypeKind(self.as_mut_ptr()) { + LLVMTypeKind::LLVMMetadataTypeKind => LLVMConstPointerNull(self.as_mut_ptr()), + _ => LLVMConstNull(self.as_mut_ptr()), } } } fn ptr_type(self, address_space: AddressSpace) -> PointerType<'ctx> { - unsafe { PointerType::new(LLVMPointerType(self.ty, address_space.0)) } + unsafe { PointerType::new(LLVMPointerType(self.as_mut_ptr(), address_space.0)) } } fn vec_type(self, size: u32) -> VectorType<'ctx> { assert!(size != 0, "Vectors of size zero are not allowed."); // -- https://llvm.org/docs/LangRef.html#vector-type - unsafe { VectorType::new(LLVMVectorType(self.ty, size)) } + unsafe { VectorType::new(LLVMVectorType(self.as_mut_ptr(), size)) } } #[llvm_versions(12..)] @@ -106,7 +113,7 @@ impl<'ctx> Type<'ctx> { assert!(size != 0, "Vectors of size zero are not allowed."); // -- https://llvm.org/docs/LangRef.html#vector-type - unsafe { ScalableVectorType::new(LLVMScalableVectorType(self.ty, size)) } + unsafe { ScalableVectorType::new(LLVMScalableVectorType(self.as_mut_ptr(), size)) } } #[cfg(not(feature = "experimental"))] @@ -114,7 +121,7 @@ impl<'ctx> Type<'ctx> { let mut param_types: Vec = param_types.iter().map(|val| val.as_type_ref()).collect(); unsafe { FunctionType::new(LLVMFunctionType( - self.ty, + self.as_mut_ptr(), param_types.as_mut_ptr(), param_types.len() as u32, is_var_args as i32, @@ -137,7 +144,7 @@ impl<'ctx> Type<'ctx> { unsafe { FunctionType::new(LLVMFunctionType( - self.ty, + self.as_mut_ptr(), pool_start.unwrap_or(std::ptr::null_mut()), param_types.len() as u32, is_var_args as i32, @@ -147,31 +154,31 @@ impl<'ctx> Type<'ctx> { #[allow(deprecated)] fn array_type(self, size: u32) -> ArrayType<'ctx> { - unsafe { ArrayType::new(LLVMArrayType(self.ty, size)) } + unsafe { ArrayType::new(LLVMArrayType(self.as_mut_ptr(), size)) } } fn get_undef(self) -> LLVMValueRef { - unsafe { LLVMGetUndef(self.ty) } + unsafe { LLVMGetUndef(self.as_mut_ptr()) } } #[llvm_versions(12..)] fn get_poison(&self) -> LLVMValueRef { - unsafe { LLVMGetPoison(self.ty) } + unsafe { LLVMGetPoison(self.as_mut_ptr()) } } fn get_alignment(self) -> IntValue<'ctx> { - unsafe { IntValue::new(LLVMAlignOf(self.ty)) } + unsafe { IntValue::new(LLVMAlignOf(self.as_mut_ptr())) } } fn get_context(self) -> ContextRef<'ctx> { - unsafe { ContextRef::new(LLVMGetTypeContext(self.ty)) } + unsafe { ContextRef::new(LLVMGetTypeContext(self.as_mut_ptr())) } } // REVIEW: This should be known at compile time, maybe as a const fn? // On an enum or trait, this would not be known at compile time (unless // enum has only sized types for example) fn is_sized(self) -> bool { - unsafe { LLVMTypeIsSized(self.ty) == 1 } + unsafe { LLVMTypeIsSized(self.as_mut_ptr()) == 1 } } fn size_of(self) -> Option> { @@ -179,15 +186,15 @@ impl<'ctx> Type<'ctx> { return None; } - unsafe { Some(IntValue::new(LLVMSizeOf(self.ty))) } + unsafe { Some(IntValue::new(LLVMSizeOf(self.as_mut_ptr()))) } } fn print_to_string(self) -> LLVMString { - unsafe { LLVMString::new(LLVMPrintTypeToString(self.ty)) } + unsafe { LLVMString::new(LLVMPrintTypeToString(self.as_mut_ptr())) } } pub fn get_element_type(self) -> AnyTypeEnum<'ctx> { - unsafe { AnyTypeEnum::new(LLVMGetElementType(self.ty)) } + unsafe { AnyTypeEnum::new(LLVMGetElementType(self.as_mut_ptr())) } } } @@ -196,7 +203,7 @@ impl fmt::Debug for Type<'_> { let llvm_type = self.print_to_string(); f.debug_struct("Type") - .field("address", &self.ty) + .field("address", &self.as_mut_ptr()) .field("llvm_type", &llvm_type) .finish() } diff --git a/src/types/ptr_type.rs b/src/types/ptr_type.rs index 3a29b50d8c8..3d5c5b94a86 100644 --- a/src/types/ptr_type.rs +++ b/src/types/ptr_type.rs @@ -5,7 +5,7 @@ use llvm_sys::prelude::LLVMTypeRef; use crate::AddressSpace; use crate::context::ContextRef; -use crate::support::LLVMString; +use crate::support::{LLVMString, assert_niche}; #[cfg(feature = "typed-pointers")] use crate::types::AnyTypeEnum; #[llvm_versions(12..)] @@ -18,10 +18,12 @@ use crate::types::enums::BasicMetadataTypeEnum; use std::fmt::{self, Display}; /// A `PointerType` is the type of a pointer constant or variable. +#[repr(transparent)] #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub struct PointerType<'ctx> { ptr_type: Type<'ctx>, } +const _: () = assert_niche::(); impl<'ctx> PointerType<'ctx> { /// Create `PointerType` from [`LLVMTypeRef`] @@ -375,13 +377,13 @@ impl<'ctx> PointerType<'ctx> { /// Determine whether this pointer is opaque. #[llvm_versions(15..)] pub fn is_opaque(self) -> bool { - unsafe { LLVMPointerTypeIsOpaque(self.ptr_type.ty) != 0 } + unsafe { LLVMPointerTypeIsOpaque(self.ptr_type.as_mut_ptr()) != 0 } } } unsafe impl AsTypeRef for PointerType<'_> { fn as_type_ref(&self) -> LLVMTypeRef { - self.ptr_type.ty + self.ptr_type.as_mut_ptr() } } diff --git a/src/types/scalable_vec_type.rs b/src/types/scalable_vec_type.rs index 7232898f558..cfaf30127ca 100644 --- a/src/types/scalable_vec_type.rs +++ b/src/types/scalable_vec_type.rs @@ -3,7 +3,7 @@ use llvm_sys::prelude::LLVMTypeRef; use crate::AddressSpace; use crate::context::ContextRef; -use crate::support::LLVMString; +use crate::support::{LLVMString, assert_niche}; use crate::types::enums::BasicMetadataTypeEnum; use crate::types::{ArrayType, BasicTypeEnum, FunctionType, PointerType, Type, traits::AsTypeRef}; use crate::values::{ArrayValue, IntValue, ScalableVectorValue}; @@ -11,10 +11,12 @@ use crate::values::{ArrayValue, IntValue, ScalableVectorValue}; use std::fmt::{self, Display}; /// A `ScalableVectorType` is the type of a scalable multiple value SIMD constant or variable. +#[repr(transparent)] #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub struct ScalableVectorType<'ctx> { scalable_vec_type: Type<'ctx>, } +const _: () = assert_niche::(); impl<'ctx> ScalableVectorType<'ctx> { /// Create `ScalableVectorType` from [`LLVMTypeRef`] @@ -256,7 +258,7 @@ impl<'ctx> ScalableVectorType<'ctx> { unsafe impl AsTypeRef for ScalableVectorType<'_> { fn as_type_ref(&self) -> LLVMTypeRef { - self.scalable_vec_type.ty + self.scalable_vec_type.as_mut_ptr() } } diff --git a/src/types/struct_type.rs b/src/types/struct_type.rs index 43a2a596b2a..c21a424c475 100644 --- a/src/types/struct_type.rs +++ b/src/types/struct_type.rs @@ -10,17 +10,19 @@ use std::mem::forget; use crate::AddressSpace; use crate::context::ContextRef; -use crate::support::LLVMString; +use crate::support::{LLVMString, assert_niche}; use crate::types::enums::BasicMetadataTypeEnum; use crate::types::traits::AsTypeRef; use crate::types::{ArrayType, BasicTypeEnum, FunctionType, PointerType, Type}; use crate::values::{ArrayValue, AsValueRef, BasicValueEnum, IntValue, StructValue}; /// A `StructType` is the type of a heterogeneous container of types. +#[repr(transparent)] #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub struct StructType<'ctx> { struct_type: Type<'ctx>, } +const _: () = assert_niche::(); impl<'ctx> StructType<'ctx> { /// Create `StructType` from [`LLVMTypeRef`] @@ -436,7 +438,7 @@ impl<'ctx> StructType<'ctx> { unsafe impl AsTypeRef for StructType<'_> { fn as_type_ref(&self) -> LLVMTypeRef { - self.struct_type.ty + self.struct_type.as_mut_ptr() } } @@ -453,6 +455,7 @@ pub struct FieldTypesIter<'ctx> { i: u32, count: u32, } +const _: () = assert_niche::(); impl<'ctx> Iterator for FieldTypesIter<'ctx> { type Item = BasicTypeEnum<'ctx>; diff --git a/src/types/vec_type.rs b/src/types/vec_type.rs index ee4b33b290b..cdad643db0c 100644 --- a/src/types/vec_type.rs +++ b/src/types/vec_type.rs @@ -3,7 +3,7 @@ use llvm_sys::prelude::{LLVMTypeRef, LLVMValueRef}; use crate::AddressSpace; use crate::context::ContextRef; -use crate::support::LLVMString; +use crate::support::{LLVMString, assert_niche}; use crate::types::enums::BasicMetadataTypeEnum; use crate::types::{ArrayType, BasicTypeEnum, FunctionType, PointerType, Type, traits::AsTypeRef}; use crate::values::{ArrayValue, BasicValue, IntValue, VectorValue}; @@ -11,10 +11,12 @@ use crate::values::{ArrayValue, BasicValue, IntValue, VectorValue}; use std::fmt::{self, Display}; /// A `VectorType` is the type of a multiple value SIMD constant or variable. +#[repr(transparent)] #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub struct VectorType<'ctx> { vec_type: Type<'ctx>, } +const _: () = assert_niche::(); impl<'ctx> VectorType<'ctx> { /// Create `VectorType` from [`LLVMTypeRef`] @@ -284,7 +286,7 @@ impl<'ctx> VectorType<'ctx> { unsafe impl AsTypeRef for VectorType<'_> { fn as_type_ref(&self) -> LLVMTypeRef { - self.vec_type.ty + self.vec_type.as_mut_ptr() } } diff --git a/src/types/void_type.rs b/src/types/void_type.rs index 6efc86621cf..b7cf2d8db1d 100644 --- a/src/types/void_type.rs +++ b/src/types/void_type.rs @@ -1,7 +1,7 @@ use llvm_sys::prelude::LLVMTypeRef; use crate::context::ContextRef; -use crate::support::LLVMString; +use crate::support::{LLVMString, assert_niche}; use crate::types::enums::BasicMetadataTypeEnum; use crate::types::traits::AsTypeRef; use crate::types::{FunctionType, Type}; @@ -10,10 +10,12 @@ use std::fmt::{self, Display}; /// A `VoidType` is a special type with no possible direct instances. It's only /// useful as a function return type. +#[repr(transparent)] #[derive(Debug, PartialEq, Eq, Clone, Copy)] pub struct VoidType<'ctx> { void_type: Type<'ctx>, } +const _: () = assert_niche::(); impl<'ctx> VoidType<'ctx> { /// Create `VoidType` from [`LLVMTypeRef`] @@ -88,7 +90,7 @@ impl<'ctx> VoidType<'ctx> { unsafe impl AsTypeRef for VoidType<'_> { fn as_type_ref(&self) -> LLVMTypeRef { - self.void_type.ty + self.void_type.as_mut_ptr() } } diff --git a/src/values/array_value.rs b/src/values/array_value.rs index b65ecc105f5..c5d295749c7 100644 --- a/src/values/array_value.rs +++ b/src/values/array_value.rs @@ -9,15 +9,18 @@ use llvm_sys::prelude::LLVMValueRef; use std::ffi::CStr; use std::fmt::{self, Display}; +use crate::support::assert_niche; use crate::types::{ArrayType, AsTypeRef}; use crate::values::traits::{AnyValue, AsValueRef}; use crate::values::{InstructionValue, Value}; /// An `ArrayValue` is a block of contiguous constants or variables. +#[repr(transparent)] #[derive(PartialEq, Eq, Clone, Copy, Hash)] pub struct ArrayValue<'ctx> { array_value: Value<'ctx>, } +const _: () = assert_niche::(); impl<'ctx> ArrayValue<'ctx> { /// Get a value from an [LLVMValueRef]. @@ -191,7 +194,7 @@ impl<'ctx> ArrayValue<'ctx> { unsafe impl AsValueRef for ArrayValue<'_> { fn as_value_ref(&self) -> LLVMValueRef { - self.array_value.value + self.array_value.as_mut_ptr() } } diff --git a/src/values/basic_value_use.rs b/src/values/basic_value_use.rs index ce77b521638..f11c300aae6 100644 --- a/src/values/basic_value_use.rs +++ b/src/values/basic_value_use.rs @@ -1,9 +1,12 @@ +use llvm_sys::LLVMUse; use llvm_sys::core::{LLVMGetNextUse, LLVMGetUsedValue, LLVMGetUser, LLVMIsABasicBlock, LLVMValueAsBasicBlock}; use llvm_sys::prelude::LLVMUseRef; use std::marker::PhantomData; +use std::ptr::NonNull; use crate::basic_block::BasicBlock; +use crate::support::assert_niche; use crate::values::{AnyValueEnum, BasicValueEnum}; /// Either [BasicValueEnum] or [BasicBlock]. @@ -90,8 +93,10 @@ impl<'ctx> Operand<'ctx> { } /// A usage of a `BasicValue` in another value. +#[repr(transparent)] #[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub struct BasicValueUse<'ctx>(LLVMUseRef, PhantomData<&'ctx ()>); +pub struct BasicValueUse<'ctx>(NonNull, PhantomData<&'ctx ()>); +const _: () = assert_niche::(); impl<'ctx> BasicValueUse<'ctx> { /// Get a value from an [LLVMUseRef]. @@ -102,7 +107,12 @@ impl<'ctx> BasicValueUse<'ctx> { pub unsafe fn new(use_: LLVMUseRef) -> Self { debug_assert!(!use_.is_null()); - BasicValueUse(use_, PhantomData) + BasicValueUse(unsafe { NonNull::new_unchecked(use_) }, PhantomData) + } + + /// Get the inner [LLVMUseRef]. + pub fn as_mut_ptr(&self) -> LLVMUseRef { + self.0.as_ptr() } /// Gets the next use of a `BasicBlock`, `InstructionValue` or `BasicValue` if any. @@ -162,7 +172,7 @@ impl<'ctx> BasicValueUse<'ctx> { /// 1) In the store instruction /// 2) In the pointer bitcast pub fn get_next_use(self) -> Option { - let use_ = unsafe { LLVMGetNextUse(self.0) }; + let use_ = unsafe { LLVMGetNextUse(self.as_mut_ptr()) }; if use_.is_null() { return None; @@ -207,7 +217,7 @@ impl<'ctx> BasicValueUse<'ctx> { /// assert_eq!(store_operand_use1.get_user(), store_instruction); /// ``` pub fn get_user(self) -> AnyValueEnum<'ctx> { - unsafe { AnyValueEnum::new(LLVMGetUser(self.0)) } + unsafe { AnyValueEnum::new(LLVMGetUser(self.as_mut_ptr())) } } /// Gets the used value (a `BasicValueEnum` or `BasicBlock`) of this use. @@ -251,7 +261,7 @@ impl<'ctx> BasicValueUse<'ctx> { /// assert_eq!(bitcast_use_value, free_operand0); /// ``` pub fn get_used_value(self) -> Operand<'ctx> { - let used_value = unsafe { LLVMGetUsedValue(self.0) }; + let used_value = unsafe { LLVMGetUsedValue(self.as_mut_ptr()) }; let is_basic_block = unsafe { !LLVMIsABasicBlock(used_value).is_null() }; diff --git a/src/values/call_site_value.rs b/src/values/call_site_value.rs index 2ea137be71b..8b6207bc4db 100644 --- a/src/values/call_site_value.rs +++ b/src/values/call_site_value.rs @@ -11,6 +11,7 @@ use llvm_sys::core::{LLVMGetTailCallKind, LLVMSetTailCallKind}; use llvm_sys::prelude::LLVMValueRef; use crate::attributes::{Attribute, AttributeLoc}; +use crate::support::assert_niche; use crate::types::FunctionType; #[llvm_versions(18..)] use crate::values::operand_bundle::OperandBundleIter; @@ -104,8 +105,10 @@ impl<'ctx> ValueKind<'ctx> { /// A value resulting from a function call. It may have function attributes applied to it. /// /// This struct may be removed in the future in favor of an `InstructionValue` type. +#[repr(transparent)] #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub struct CallSiteValue<'ctx>(Value<'ctx>); +const _: () = assert_niche::(); impl<'ctx> CallSiteValue<'ctx> { /// Get a value from an [LLVMValueRef]. @@ -281,7 +284,7 @@ impl<'ctx> CallSiteValue<'ctx> { pub fn add_attribute(self, loc: AttributeLoc, attribute: Attribute) { use llvm_sys::core::LLVMAddCallSiteAttribute; - unsafe { LLVMAddCallSiteAttribute(self.as_value_ref(), loc.get_index(), attribute.attribute) } + unsafe { LLVMAddCallSiteAttribute(self.as_value_ref(), loc.get_index(), attribute.as_mut_ptr()) } } /// Gets the `FunctionValue` this `CallSiteValue` is based on. @@ -780,7 +783,7 @@ impl<'ctx> CallSiteValue<'ctx> { unsafe impl AsValueRef for CallSiteValue<'_> { fn as_value_ref(&self) -> LLVMValueRef { - self.0.value + self.0.as_mut_ptr() } } diff --git a/src/values/float_value.rs b/src/values/float_value.rs index b518d4df3f6..29fcae20c48 100644 --- a/src/values/float_value.rs +++ b/src/values/float_value.rs @@ -1,3 +1,4 @@ +use crate::support::assert_niche; #[llvm_versions(..=17)] use crate::types::IntType; #[llvm_versions(..=18)] @@ -24,10 +25,12 @@ use crate::{FloatPredicate, values::IntValue}; use super::AnyValue; +#[repr(transparent)] #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub struct FloatValue<'ctx> { float_value: Value<'ctx>, } +const _: () = assert_niche::(); impl<'ctx> FloatValue<'ctx> { /// Get a value from an [LLVMValueRef]. @@ -197,7 +200,7 @@ impl<'ctx> FloatValue<'ctx> { unsafe impl AsValueRef for FloatValue<'_> { fn as_value_ref(&self) -> LLVMValueRef { - self.float_value.value + self.float_value.as_mut_ptr() } } diff --git a/src/values/fn_value.rs b/src/values/fn_value.rs index 4e36f4db3eb..331086ad914 100644 --- a/src/values/fn_value.rs +++ b/src/values/fn_value.rs @@ -1,3 +1,4 @@ +use llvm_sys::LLVMValue; use llvm_sys::analysis::{LLVMVerifierFailureAction, LLVMVerifyFunction, LLVMViewFunctionCFG, LLVMViewFunctionCFGOnly}; use llvm_sys::core::LLVMAppendExistingBasicBlock; use llvm_sys::core::{ @@ -22,6 +23,7 @@ use std::ffi::CStr; use std::fmt::{self, Display}; use std::marker::PhantomData; use std::mem::forget; +use std::ptr::NonNull; use crate::attributes::{Attribute, AttributeLoc}; use crate::basic_block::BasicBlock; @@ -31,17 +33,19 @@ use crate::module::Linkage; use crate::passes::PassBuilderOptions; #[llvm_versions(20..)] use crate::support::LLVMString; -use crate::support::to_c_str; +use crate::support::{assert_niche, to_c_str}; #[llvm_versions(20..)] use crate::targets::TargetMachine; use crate::types::FunctionType; use crate::values::traits::{AnyValue, AsValueRef}; use crate::values::{BasicValueEnum, GlobalValue, Value}; +#[repr(transparent)] #[derive(PartialEq, Eq, Clone, Copy, Hash)] pub struct FunctionValue<'ctx> { fn_value: Value<'ctx>, } +const _: () = assert_niche::(); impl<'ctx> FunctionValue<'ctx> { /// Get a value from an [LLVMValueRef]. @@ -89,7 +93,7 @@ impl<'ctx> FunctionValue<'ctx> { LLVMVerifierFailureAction::LLVMReturnStatusAction }; - let code = unsafe { LLVMVerifyFunction(self.fn_value.value, action) }; + let code = unsafe { LLVMVerifyFunction(self.fn_value.as_mut_ptr(), action) }; code != 1 } @@ -138,7 +142,7 @@ impl<'ctx> FunctionValue<'ctx> { } pub fn count_params(self) -> u32 { - unsafe { LLVMCountParams(self.fn_value.value) } + unsafe { LLVMCountParams(self.fn_value.as_mut_ptr()) } } pub fn count_basic_blocks(self) -> u32 { @@ -193,7 +197,7 @@ impl<'ctx> FunctionValue<'ctx> { } pub fn get_last_basic_block(self) -> Option> { - unsafe { BasicBlock::new(LLVMGetLastBasicBlock(self.fn_value.value)) } + unsafe { BasicBlock::new(LLVMGetLastBasicBlock(self.fn_value.as_mut_ptr())) } } /// Gets the name of a `FunctionValue`. @@ -286,7 +290,7 @@ impl<'ctx> FunctionValue<'ctx> { /// fn_value.add_attribute(AttributeLoc::Return, enum_attribute); /// ``` pub fn add_attribute(self, loc: AttributeLoc, attribute: Attribute) { - unsafe { LLVMAddAttributeAtIndex(self.as_value_ref(), loc.get_index(), attribute.attribute) } + unsafe { LLVMAddAttributeAtIndex(self.as_value_ref(), loc.get_index(), attribute.as_mut_ptr()) } } /// Counts the number of `Attribute`s belonging to the specified location in this `FunctionValue`. @@ -499,21 +503,17 @@ impl<'ctx> FunctionValue<'ctx> { /// Set the debug info descriptor pub fn set_subprogram(self, subprogram: DISubprogram<'ctx>) { - unsafe { LLVMSetSubprogram(self.as_value_ref(), subprogram.metadata_ref) } + unsafe { LLVMSetSubprogram(self.as_value_ref(), subprogram.as_mut_ptr()) } } /// Get the debug info descriptor pub fn get_subprogram(self) -> Option> { let metadata_ref = unsafe { LLVMGetSubprogram(self.as_value_ref()) }; - if metadata_ref.is_null() { - None - } else { - Some(DISubprogram { - metadata_ref, - _marker: PhantomData, - }) - } + Some(DISubprogram { + metadata_ref: NonNull::new(metadata_ref)?, + _marker: PhantomData, + }) } /// Get the section to which this function belongs @@ -550,7 +550,7 @@ impl<'ctx> FunctionValue<'ctx> { let error = LLVMRunPassesOnFunction( self.as_value_ref(), to_c_str(passes).as_ptr(), - machine.target_machine, + machine.target_machine.as_ptr(), options.options_ref, ); if error.is_null() { @@ -565,7 +565,7 @@ impl<'ctx> FunctionValue<'ctx> { unsafe impl AsValueRef for FunctionValue<'_> { fn as_value_ref(&self) -> LLVMValueRef { - self.fn_value.value + self.fn_value.as_mut_ptr() } } @@ -580,7 +580,7 @@ impl fmt::Debug for FunctionValue<'_> { let llvm_value = self.print_to_string(); let llvm_type = self.get_type(); let name = self.get_name(); - let is_const = unsafe { LLVMIsConstant(self.fn_value.value) == 1 }; + let is_const = unsafe { LLVMIsConstant(self.fn_value.as_mut_ptr()) == 1 }; let is_null = self.is_null(); f.debug_struct("FunctionValue") @@ -595,6 +595,7 @@ impl fmt::Debug for FunctionValue<'_> { } /// Iterate over all `BasicBlock`s in a function. +#[repr(transparent)] #[derive(Debug)] pub struct BasicBlockIter<'ctx>(Option>); @@ -613,17 +614,18 @@ impl<'ctx> Iterator for BasicBlockIter<'ctx> { #[derive(Debug)] pub struct ParamValueIter<'ctx> { - param_iter_value: LLVMValueRef, + param_iter_value: NonNull, start: bool, _marker: PhantomData<&'ctx ()>, } +const _: () = assert_niche::(); impl<'ctx> Iterator for ParamValueIter<'ctx> { type Item = BasicValueEnum<'ctx>; fn next(&mut self) -> Option { if self.start { - let first_value = unsafe { LLVMGetFirstParam(self.param_iter_value) }; + let first_value = unsafe { LLVMGetFirstParam(self.param_iter_value.as_ptr()) }; if first_value.is_null() { return None; @@ -631,18 +633,18 @@ impl<'ctx> Iterator for ParamValueIter<'ctx> { self.start = false; - self.param_iter_value = first_value; + self.param_iter_value = unsafe { NonNull::new_unchecked(first_value) }; return unsafe { Some(Self::Item::new(first_value)) }; } - let next_value = unsafe { LLVMGetNextParam(self.param_iter_value) }; + let next_value = unsafe { LLVMGetNextParam(self.param_iter_value.as_ptr()) }; if next_value.is_null() { return None; } - self.param_iter_value = next_value; + self.param_iter_value = unsafe { NonNull::new_unchecked(next_value) }; unsafe { Some(Self::Item::new(next_value)) } } diff --git a/src/values/generic_value.rs b/src/values/generic_value.rs index 5973ed55219..70192a3a1a1 100644 --- a/src/values/generic_value.rs +++ b/src/values/generic_value.rs @@ -1,33 +1,38 @@ use libc::c_void; use llvm_sys::execution_engine::{ LLVMCreateGenericValueOfPointer, LLVMDisposeGenericValue, LLVMGenericValueIntWidth, LLVMGenericValueRef, - LLVMGenericValueToFloat, LLVMGenericValueToInt, LLVMGenericValueToPointer, + LLVMGenericValueToFloat, LLVMGenericValueToInt, LLVMGenericValueToPointer, LLVMOpaqueGenericValue, }; -use crate::types::{AsTypeRef, FloatType}; +use crate::{ + support::assert_niche, + types::{AsTypeRef, FloatType}, +}; -use std::marker::PhantomData; +use std::{marker::PhantomData, ptr::NonNull}; // SubTypes: GenericValue +#[repr(transparent)] #[derive(Debug)] pub struct GenericValue<'ctx> { - pub(crate) generic_value: LLVMGenericValueRef, + pub(crate) generic_value: NonNull, _phantom: PhantomData<&'ctx ()>, } +const _: () = assert_niche::(); impl<'ctx> GenericValue<'ctx> { pub(crate) unsafe fn new(generic_value: LLVMGenericValueRef) -> Self { assert!(!generic_value.is_null()); GenericValue { - generic_value, + generic_value: unsafe { NonNull::new_unchecked(generic_value) }, _phantom: PhantomData, } } // SubType: GenericValue only pub fn int_width(self) -> u32 { - unsafe { LLVMGenericValueIntWidth(self.generic_value) } + unsafe { LLVMGenericValueIntWidth(self.generic_value.as_ptr()) } } // SubType: create_generic_value() -> GenericValue @@ -42,23 +47,23 @@ impl<'ctx> GenericValue<'ctx> { // SubType: impl only for GenericValue pub fn as_int(self, is_signed: bool) -> u64 { - unsafe { LLVMGenericValueToInt(self.generic_value, is_signed as i32) } + unsafe { LLVMGenericValueToInt(self.generic_value.as_ptr(), is_signed as i32) } } // SubType: impl only for GenericValue pub fn as_float(self, float_type: &FloatType<'ctx>) -> f64 { - unsafe { LLVMGenericValueToFloat(float_type.as_type_ref(), self.generic_value) } + unsafe { LLVMGenericValueToFloat(float_type.as_type_ref(), self.generic_value.as_ptr()) } } // SubType: impl only for GenericValue // REVIEW: How safe is this really? pub unsafe fn into_pointer(self) -> *mut T { - unsafe { LLVMGenericValueToPointer(self.generic_value) as *mut T } + unsafe { LLVMGenericValueToPointer(self.generic_value.as_ptr()) as *mut T } } } impl Drop for GenericValue<'_> { fn drop(&mut self) { - unsafe { LLVMDisposeGenericValue(self.generic_value) } + unsafe { LLVMDisposeGenericValue(self.generic_value.as_ptr()) } } } diff --git a/src/values/global_value.rs b/src/values/global_value.rs index a4de40d2839..0afb86e52b8 100644 --- a/src/values/global_value.rs +++ b/src/values/global_value.rs @@ -19,6 +19,7 @@ use std::fmt::{self, Display}; use crate::comdat::Comdat; use crate::module::Linkage; +use crate::support::assert_niche; use crate::types::AnyTypeEnum; use crate::values::traits::AsValueRef; @@ -30,10 +31,12 @@ use super::AnyValue; // REVIEW: GlobalValues are always PointerValues. With SubTypes, we should // compress this into a PointerValue type +#[repr(transparent)] #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub struct GlobalValue<'ctx> { global_value: Value<'ctx>, } +const _: () = assert_niche::(); impl<'ctx> GlobalValue<'ctx> { /// Get a value from an [LLVMValueRef]. @@ -245,7 +248,7 @@ impl<'ctx> GlobalValue<'ctx> { pub fn set_comdat(self, comdat: Comdat) { use llvm_sys::comdat::LLVMSetComdat; - unsafe { LLVMSetComdat(self.as_value_ref(), comdat.0) } + unsafe { LLVMSetComdat(self.as_value_ref(), comdat.as_mut_ptr()) } } pub fn get_unnamed_address(self) -> UnnamedAddress { @@ -277,7 +280,7 @@ impl<'ctx> GlobalValue<'ctx> { unsafe impl AsValueRef for GlobalValue<'_> { fn as_value_ref(&self) -> LLVMValueRef { - self.global_value.value + self.global_value.as_mut_ptr() } } diff --git a/src/values/instruction_value.rs b/src/values/instruction_value.rs index 84d350ccf67..1bcb29c403d 100644 --- a/src/values/instruction_value.rs +++ b/src/values/instruction_value.rs @@ -11,10 +11,12 @@ use llvm_sys::core::{ }; use llvm_sys::prelude::LLVMValueRef; +use std::ptr::NonNull; use std::{ffi::CStr, fmt, fmt::Display}; use crate::AtomicRMWBinOp; use crate::debug_info::DILocation; +use crate::support::assert_niche; use crate::values::{BasicValue, BasicValueEnum, BasicValueUse, MetadataValue, Value}; use crate::{AtomicOrdering, FloatPredicate, IntPredicate}; use crate::{basic_block::BasicBlock, types::AnyTypeEnum}; @@ -155,10 +157,12 @@ pub enum InstructionOpcode { ZExt, } +#[repr(transparent)] #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub struct InstructionValue<'ctx> { instruction_value: Value<'ctx>, } +const _: () = assert_niche::(); impl<'ctx> InstructionValue<'ctx> { /// Get a value from an [LLVMValueRef]. @@ -1154,13 +1158,13 @@ impl<'ctx> InstructionValue<'ctx> { /// Determines whether or not this `Instruction` has any associated metadata. pub fn has_metadata(self) -> bool { - unsafe { LLVMHasMetadata(self.instruction_value.value) == 1 } + unsafe { LLVMHasMetadata(self.instruction_value.as_mut_ptr()) == 1 } } /// Gets the `MetadataValue` associated with this `Instruction` at a specific /// `kind_id`. pub fn get_metadata(self, kind_id: u32) -> Option> { - let metadata_value = unsafe { LLVMGetMetadata(self.instruction_value.value, kind_id) }; + let metadata_value = unsafe { LLVMGetMetadata(self.instruction_value.as_mut_ptr(), kind_id) }; if metadata_value.is_null() { return None; @@ -1177,7 +1181,7 @@ impl<'ctx> InstructionValue<'ctx> { } unsafe { - LLVMSetMetadata(self.instruction_value.value, kind_id, metadata.as_value_ref()); + LLVMSetMetadata(self.instruction_value.as_mut_ptr(), kind_id, metadata.as_value_ref()); } Ok(()) @@ -1187,20 +1191,16 @@ impl<'ctx> InstructionValue<'ctx> { pub fn get_debug_location(self) -> Option> { // https://github.com/llvm/llvm-project/blob/e83cc896e7c2378914a391f942c188d454b517d2/llvm/include/llvm/IR/Instruction.h#L513 let metadata_ref = unsafe { llvm_sys::debuginfo::LLVMInstructionGetDebugLoc(self.as_value_ref()) }; - if metadata_ref.is_null() { - None - } else { - Some(DILocation { - metadata_ref, - _marker: std::marker::PhantomData, - }) - } + Some(DILocation { + metadata_ref: NonNull::new(metadata_ref)?, + _marker: std::marker::PhantomData, + }) } /// Set the debug location for this instruction. pub fn set_debug_location(self, location: Option>) { // https://github.com/llvm/llvm-project/blob/e83cc896e7c2378914a391f942c188d454b517d2/llvm/include/llvm/IR/Instruction.h#L510 - let metadata_ref = location.map_or(std::ptr::null_mut(), |loc| loc.metadata_ref); + let metadata_ref = location.map_or(std::ptr::null_mut(), |loc| loc.as_mut_ptr()); unsafe { llvm_sys::debuginfo::LLVMInstructionSetDebugLoc(self.as_value_ref(), metadata_ref); } @@ -1209,7 +1209,7 @@ impl<'ctx> InstructionValue<'ctx> { unsafe impl AsValueRef for InstructionValue<'_> { fn as_value_ref(&self) -> LLVMValueRef { - self.instruction_value.value + self.instruction_value.as_mut_ptr() } } @@ -1226,6 +1226,7 @@ pub struct OperandIter<'ctx> { i: u32, count: u32, } +const _: () = assert_niche::(); impl<'ctx> Iterator for OperandIter<'ctx> { type Item = Option>; @@ -1248,6 +1249,7 @@ pub struct OperandUseIter<'ctx> { i: u32, count: u32, } +const _: () = assert_niche::(); impl<'ctx> Iterator for OperandUseIter<'ctx> { type Item = Option>; diff --git a/src/values/int_value.rs b/src/values/int_value.rs index 1e57980a2fd..01dd086f804 100644 --- a/src/values/int_value.rs +++ b/src/values/int_value.rs @@ -26,6 +26,7 @@ use std::convert::TryFrom; use std::ffi::CStr; use std::fmt::{self, Display}; +use crate::support::assert_niche; #[llvm_versions(..=17)] use crate::types::FloatType; use crate::types::{AsTypeRef, IntType, PointerType}; @@ -41,10 +42,12 @@ use crate::IntPredicate; use super::AnyValue; +#[repr(transparent)] #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub struct IntValue<'ctx> { int_value: Value<'ctx>, } +const _: () = assert_niche::(); impl<'ctx> IntValue<'ctx> { /// Get a value from an [LLVMValueRef]. @@ -409,7 +412,7 @@ impl<'ctx> IntValue<'ctx> { unsafe impl AsValueRef for IntValue<'_> { fn as_value_ref(&self) -> LLVMValueRef { - self.int_value.value + self.int_value.as_mut_ptr() } } diff --git a/src/values/metadata_value.rs b/src/values/metadata_value.rs index 836ba0f4a94..0302e32b324 100644 --- a/src/values/metadata_value.rs +++ b/src/values/metadata_value.rs @@ -6,6 +6,7 @@ use llvm_sys::prelude::LLVMValueRef; use llvm_sys::core::LLVMValueAsMetadata; use llvm_sys::prelude::LLVMMetadataRef; +use crate::support::assert_niche; use crate::values::traits::AsValueRef; use crate::values::{BasicMetadataValueEnum, Value}; @@ -38,10 +39,12 @@ pub const FIRST_CUSTOM_METADATA_KIND_ID: u32 = if cfg!(feature = "llvm11-0") { panic!("Unhandled LLVM version") }; +#[repr(transparent)] #[derive(PartialEq, Eq, Clone, Copy, Hash)] pub struct MetadataValue<'ctx> { metadata_value: Value<'ctx>, } +const _: () = assert_niche::(); impl<'ctx> MetadataValue<'ctx> { /// Get a value from an [LLVMValueRef]. @@ -130,7 +133,7 @@ impl<'ctx> MetadataValue<'ctx> { unsafe impl AsValueRef for MetadataValue<'_> { fn as_value_ref(&self) -> LLVMValueRef { - self.metadata_value.value + self.metadata_value.as_mut_ptr() } } diff --git a/src/values/mod.rs b/src/values/mod.rs index 4efeec12891..8bb09ca5140 100644 --- a/src/values/mod.rs +++ b/src/values/mod.rs @@ -59,7 +59,7 @@ pub use crate::values::instruction_value::FastMathFlags; #[llvm_versions(18..)] pub use crate::values::operand_bundle::OperandBundle; -use crate::support::{LLVMString, to_c_str}; +use crate::support::{LLVMString, assert_niche, to_c_str}; pub use crate::values::array_value::ArrayValue; pub use crate::values::basic_value_use::{BasicValueUse, Operand}; pub use crate::values::call_site_value::{CallSiteValue, ValueKind}; @@ -90,6 +90,7 @@ pub use crate::values::vec_value::VectorValue; #[llvm_versions(18..)] pub use llvm_sys::LLVMTailCallKind; +use llvm_sys::LLVMValue; use llvm_sys::core::{ LLVMDumpValue, LLVMGetFirstUse, LLVMGetSection, LLVMGetValueName2, LLVMIsAInstruction, LLVMIsConstant, LLVMIsNull, LLVMIsUndef, LLVMPrintTypeToString, LLVMPrintValueToString, LLVMReplaceAllUsesWith, LLVMSetSection, @@ -100,12 +101,15 @@ use llvm_sys::prelude::{LLVMTypeRef, LLVMValueRef}; use std::ffi::CStr; use std::fmt; use std::marker::PhantomData; +use std::ptr::NonNull; +#[repr(transparent)] #[derive(PartialEq, Eq, Clone, Copy, Hash)] struct Value<'ctx> { - value: LLVMValueRef, + value: NonNull, _marker: PhantomData<&'ctx ()>, } +const _: () = assert_niche::(); impl<'ctx> Value<'ctx> { pub(crate) unsafe fn new(value: LLVMValueRef) -> Self { @@ -115,13 +119,17 @@ impl<'ctx> Value<'ctx> { ); Value { - value, + value: unsafe { NonNull::new_unchecked(value) }, _marker: PhantomData, } } + pub fn as_mut_ptr(&self) -> LLVMValueRef { + self.value.as_ptr() + } + fn is_instruction(self) -> bool { - unsafe { !LLVMIsAInstruction(self.value).is_null() } + unsafe { !LLVMIsAInstruction(self.as_mut_ptr()).is_null() } } fn as_instruction(self) -> Option> { @@ -129,15 +137,15 @@ impl<'ctx> Value<'ctx> { return None; } - unsafe { Some(InstructionValue::new(self.value)) } + unsafe { Some(InstructionValue::new(self.as_mut_ptr())) } } fn is_null(self) -> bool { - unsafe { LLVMIsNull(self.value) == 1 } + unsafe { LLVMIsNull(self.as_mut_ptr()) == 1 } } fn is_const(self) -> bool { - unsafe { LLVMIsConstant(self.value) == 1 } + unsafe { LLVMIsConstant(self.as_mut_ptr()) == 1 } } // TODOC: According to https://stackoverflow.com/questions/21593752/llvm-how-to-pass-a-name-to-constantint @@ -149,7 +157,7 @@ impl<'ctx> Value<'ctx> { fn set_name(self, name: &str) { let c_string = to_c_str(name); - unsafe { LLVMSetValueName2(self.value, c_string.as_ptr(), c_string.to_bytes().len()) } + unsafe { LLVMSetValueName2(self.as_mut_ptr(), c_string.as_ptr(), c_string.to_bytes().len()) } } // get_name should *not* return a LLVMString, because it is not an owned value AFAICT @@ -158,39 +166,39 @@ impl<'ctx> Value<'ctx> { let ptr = unsafe { let mut len = 0; - LLVMGetValueName2(self.value, &mut len) + LLVMGetValueName2(self.as_mut_ptr(), &mut len) }; unsafe { CStr::from_ptr(ptr) } } fn is_undef(self) -> bool { - unsafe { LLVMIsUndef(self.value) == 1 } + unsafe { LLVMIsUndef(self.as_mut_ptr()) == 1 } } fn get_type(self) -> LLVMTypeRef { - unsafe { LLVMTypeOf(self.value) } + unsafe { LLVMTypeOf(self.as_mut_ptr()) } } fn print_to_string(self) -> LLVMString { - unsafe { LLVMString::new(LLVMPrintValueToString(self.value)) } + unsafe { LLVMString::new(LLVMPrintValueToString(self.as_mut_ptr())) } } fn print_to_stderr(self) { - unsafe { LLVMDumpValue(self.value) } + unsafe { LLVMDumpValue(self.as_mut_ptr()) } } // REVIEW: I think this is memory safe, though it may result in an IR error // if used incorrectly, which is OK. fn replace_all_uses_with(self, other: LLVMValueRef) { // LLVM may infinite-loop when they aren't distinct, which is UB in C++. - if self.value != other { - unsafe { LLVMReplaceAllUsesWith(self.value, other) } + if self.as_mut_ptr() != other { + unsafe { LLVMReplaceAllUsesWith(self.as_mut_ptr(), other) } } } pub fn get_first_use(self) -> Option> { - let use_ = unsafe { LLVMGetFirstUse(self.value) }; + let use_ = unsafe { LLVMGetFirstUse(self.as_mut_ptr()) }; if use_.is_null() { return None; @@ -201,7 +209,7 @@ impl<'ctx> Value<'ctx> { /// Gets the section of the global value pub fn get_section(&self) -> Option<&CStr> { - let ptr = unsafe { LLVMGetSection(self.value) }; + let ptr = unsafe { LLVMGetSection(self.as_mut_ptr()) }; if ptr.is_null() { return None; @@ -239,7 +247,7 @@ impl<'ctx> Value<'ctx> { unsafe { LLVMSetSection( - self.value, + self.as_mut_ptr(), // The as_ref call is important here so that we don't drop the cstr mid use c_string.as_ref().map(|s| s.as_ptr()).unwrap_or(std::ptr::null()), ) @@ -250,7 +258,7 @@ impl<'ctx> Value<'ctx> { impl fmt::Debug for Value<'_> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let llvm_value = self.print_to_string(); - let llvm_type = unsafe { CStr::from_ptr(LLVMPrintTypeToString(LLVMTypeOf(self.value))) }; + let llvm_type = unsafe { CStr::from_ptr(LLVMPrintTypeToString(LLVMTypeOf(self.as_mut_ptr()))) }; let name = self.get_name(); let is_const = self.is_const(); let is_null = self.is_null(); @@ -258,7 +266,7 @@ impl fmt::Debug for Value<'_> { f.debug_struct("Value") .field("name", &name) - .field("address", &self.value) + .field("address", &self.as_mut_ptr()) .field("is_const", &is_const) .field("is_null", &is_null) .field("is_undef", &is_undef) diff --git a/src/values/operand_bundle.rs b/src/values/operand_bundle.rs index d573b744c22..cca3bd6a721 100644 --- a/src/values/operand_bundle.rs +++ b/src/values/operand_bundle.rs @@ -1,21 +1,24 @@ use crate::context::Context; -use crate::support::to_c_str; +use crate::support::{assert_niche, to_c_str}; use crate::values::{AnyValueEnum, AsValueRef, BasicValueEnum, CallSiteValue}; +use llvm_sys::LLVMOpaqueOperandBundle; use llvm_sys::core::{ LLVMCreateOperandBundle, LLVMDisposeOperandBundle, LLVMGetNumOperandBundleArgs, LLVMGetNumOperandBundles, LLVMGetOperandBundleArgAtIndex, LLVMGetOperandBundleAtIndex, LLVMGetOperandBundleTag, }; use llvm_sys::prelude::{LLVMOperandBundleRef, LLVMValueRef}; -use std::cell::Cell; use std::ffi::CStr; use std::marker::PhantomData; +use std::ptr::NonNull; /// One of an instruction's operand bundles. +#[repr(transparent)] #[derive(Debug)] pub struct OperandBundle<'ctx> { - bundle: Cell, + bundle: NonNull, _marker: PhantomData<&'ctx Context>, } +const _: () = assert_niche::(); /// Iterator over an instruction's operand bundles. #[derive(Debug)] @@ -40,8 +43,9 @@ impl<'ctx> OperandBundle<'ctx> { /// /// The ref must be valid and represent an operand bundle. pub unsafe fn new(bundle: LLVMOperandBundleRef) -> Self { + debug_assert!(!bundle.is_null(), "bundle must be non-null."); Self { - bundle: Cell::new(bundle), + bundle: unsafe { NonNull::new_unchecked(bundle) }, _marker: PhantomData, } } @@ -76,7 +80,7 @@ impl<'ctx> OperandBundle<'ctx> { /// Acquire the underlying raw pointer belonging to this `OperandBundle` type. pub fn as_mut_ptr(&self) -> LLVMOperandBundleRef { - self.bundle.get() + self.bundle.as_ptr() } /// Get this operand bundle's tag. @@ -92,7 +96,7 @@ impl<'ctx> OperandBundle<'ctx> { pub fn get_tag(&self) -> Result<&str, std::str::Utf8Error> { unsafe { let mut size = 0usize; - let tag = LLVMGetOperandBundleTag(self.bundle.get(), &mut size as *mut usize); + let tag = LLVMGetOperandBundleTag(self.bundle.as_ptr(), &mut size as *mut usize); CStr::from_ptr(tag).to_str() } } diff --git a/src/values/phi_value.rs b/src/values/phi_value.rs index 03bf83dbc0e..97516d0b4b8 100644 --- a/src/values/phi_value.rs +++ b/src/values/phi_value.rs @@ -6,6 +6,7 @@ use std::ffi::CStr; use std::fmt::{self, Display}; use crate::basic_block::BasicBlock; +use crate::support::assert_niche; use crate::values::traits::AsValueRef; use crate::values::{BasicValue, BasicValueEnum, InstructionOpcode, InstructionValue, Value}; @@ -14,10 +15,12 @@ use super::AnyValue; // REVIEW: Metadata for phi values? /// A Phi Instruction returns a value based on which basic block branched into /// the Phi's containing basic block. +#[repr(transparent)] #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub struct PhiValue<'ctx> { phi_value: Value<'ctx>, } +const _: () = assert_niche::(); impl<'ctx> PhiValue<'ctx> { /// Get a value from an [LLVMValueRef]. @@ -39,7 +42,7 @@ impl<'ctx> PhiValue<'ctx> { let (mut values, mut basic_blocks): (Vec, Vec) = { incoming .iter() - .map(|&(v, bb)| (v.as_value_ref(), bb.basic_block)) + .map(|&(v, bb)| (v.as_value_ref(), bb.as_mut_ptr())) .unzip() }; @@ -126,7 +129,7 @@ impl<'ctx> PhiValue<'ctx> { unsafe impl AsValueRef for PhiValue<'_> { fn as_value_ref(&self) -> LLVMValueRef { - self.phi_value.value + self.phi_value.as_mut_ptr() } } @@ -155,6 +158,7 @@ pub struct IncomingIter<'ctx> { i: u32, count: u32, } +const _: () = assert_niche::(); impl<'ctx> Iterator for IncomingIter<'ctx> { type Item = (BasicValueEnum<'ctx>, BasicBlock<'ctx>); diff --git a/src/values/ptr_value.rs b/src/values/ptr_value.rs index c7e5442cef7..db82fae2f26 100644 --- a/src/values/ptr_value.rs +++ b/src/values/ptr_value.rs @@ -11,6 +11,7 @@ use std::convert::TryFrom; use std::ffi::CStr; use std::fmt::{self, Display}; +use crate::support::assert_niche; #[cfg(not(feature = "typed-pointers"))] use crate::types::BasicType; use crate::types::{AsTypeRef, IntType, PointerType}; @@ -18,10 +19,12 @@ use crate::values::{AsValueRef, InstructionValue, IntValue, Value}; use super::AnyValue; +#[repr(transparent)] #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub struct PointerValue<'ctx> { ptr_value: Value<'ctx>, } +const _: () = assert_niche::(); impl<'ctx> PointerValue<'ctx> { /// Get a value from an [LLVMValueRef]. @@ -208,7 +211,7 @@ impl<'ctx> PointerValue<'ctx> { unsafe impl AsValueRef for PointerValue<'_> { fn as_value_ref(&self) -> LLVMValueRef { - self.ptr_value.value + self.ptr_value.as_mut_ptr() } } diff --git a/src/values/scalable_vec_value.rs b/src/values/scalable_vec_value.rs index cd592c6dbaf..d39347623e5 100644 --- a/src/values/scalable_vec_value.rs +++ b/src/values/scalable_vec_value.rs @@ -8,16 +8,19 @@ use llvm_sys::prelude::LLVMValueRef; use std::ffi::CStr; use std::fmt::{self, Display}; +use crate::support::assert_niche; use crate::types::ScalableVectorType; use crate::values::traits::AsValueRef; use crate::values::{BasicValue, BasicValueEnum, InstructionValue, IntValue, Value}; use super::AnyValue; +#[repr(transparent)] #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub struct ScalableVectorValue<'ctx> { scalable_vec_value: Value<'ctx>, } +const _: () = assert_niche::(); impl<'ctx> ScalableVectorValue<'ctx> { /// Get a value from an [LLVMValueRef]. @@ -140,7 +143,7 @@ impl<'ctx> ScalableVectorValue<'ctx> { unsafe impl AsValueRef for ScalableVectorValue<'_> { fn as_value_ref(&self) -> LLVMValueRef { - self.scalable_vec_value.value + self.scalable_vec_value.as_mut_ptr() } } diff --git a/src/values/struct_value.rs b/src/values/struct_value.rs index b246c189e1a..f02e2763efe 100644 --- a/src/values/struct_value.rs +++ b/src/values/struct_value.rs @@ -5,16 +5,19 @@ use llvm_sys::prelude::LLVMValueRef; use std::ffi::CStr; use std::fmt::{self, Display}; +use crate::support::assert_niche; use crate::types::StructType; use crate::values::traits::AsValueRef; use crate::values::{BasicValue, InstructionValue, Value}; use super::{AnyValue, BasicValueEnum}; +#[repr(transparent)] #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub struct StructValue<'ctx> { struct_value: Value<'ctx>, } +const _: () = assert_niche::(); impl<'ctx> StructValue<'ctx> { /// Get a value from an [LLVMValueRef]. @@ -169,7 +172,7 @@ impl<'ctx> StructValue<'ctx> { unsafe impl AsValueRef for StructValue<'_> { fn as_value_ref(&self) -> LLVMValueRef { - self.struct_value.value + self.struct_value.as_mut_ptr() } } @@ -186,6 +189,7 @@ pub struct FieldValueIter<'ctx> { i: u32, count: u32, } +const _: () = assert_niche::(); impl<'ctx> Iterator for FieldValueIter<'ctx> { type Item = BasicValueEnum<'ctx>; diff --git a/src/values/vec_value.rs b/src/values/vec_value.rs index 011e3bc73e9..6af9f42bfbd 100644 --- a/src/values/vec_value.rs +++ b/src/values/vec_value.rs @@ -11,16 +11,19 @@ use llvm_sys::prelude::LLVMValueRef; use std::ffi::CStr; use std::fmt::{self, Display}; +use crate::support::assert_niche; use crate::types::VectorType; use crate::values::traits::AsValueRef; use crate::values::{BasicValue, BasicValueEnum, InstructionValue, IntValue, Value}; use super::AnyValue; +#[repr(transparent)] #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] pub struct VectorValue<'ctx> { vec_value: Value<'ctx>, } +const _: () = assert_niche::(); impl<'ctx> VectorValue<'ctx> { /// Get a value from an [LLVMValueRef]. @@ -147,7 +150,7 @@ impl<'ctx> VectorValue<'ctx> { unsafe impl AsValueRef for VectorValue<'_> { fn as_value_ref(&self) -> LLVMValueRef { - self.vec_value.value + self.vec_value.as_mut_ptr() } }