1#[deny(missing_docs)]
4mod array_type;
5mod enums;
6#[deny(missing_docs)]
7mod float_type;
8#[deny(missing_docs)]
9mod fn_type;
10#[deny(missing_docs)]
11mod int_type;
12#[deny(missing_docs)]
13mod metadata_type;
14#[deny(missing_docs)]
15mod ptr_type;
16#[deny(missing_docs)]
17mod scalable_vec_type;
18#[deny(missing_docs)]
19mod struct_type;
20#[deny(missing_docs)]
21mod traits;
22#[deny(missing_docs)]
23mod vec_type;
24#[deny(missing_docs)]
25mod void_type;
26
27pub use crate::types::array_type::ArrayType;
28pub use crate::types::enums::{AnyTypeEnum, BasicMetadataTypeEnum, BasicTypeEnum};
29pub use crate::types::float_type::FloatType;
30pub use crate::types::fn_type::FunctionType;
31pub use crate::types::int_type::{IntType, StringRadix};
32pub use crate::types::metadata_type::MetadataType;
33pub use crate::types::ptr_type::PointerType;
34pub use crate::types::scalable_vec_type::ScalableVectorType;
35pub use crate::types::struct_type::FieldTypesIter;
36pub use crate::types::struct_type::StructType;
37pub use crate::types::traits::{AnyType, AsTypeRef, BasicType, FloatMathType, IntMathType, PointerMathType};
38pub use crate::types::vec_type::VectorType;
39pub use crate::types::void_type::VoidType;
40
41#[llvm_versions(12..)]
42use llvm_sys::core::LLVMScalableVectorType;
43
44#[llvm_versions(12..)]
45use llvm_sys::core::LLVMGetPoison;
46
47#[allow(deprecated)]
48use llvm_sys::core::LLVMArrayType;
49use llvm_sys::core::{
50 LLVMAlignOf, LLVMConstNull, LLVMConstPointerNull, LLVMFunctionType, LLVMGetElementType, LLVMGetTypeContext,
51 LLVMGetTypeKind, LLVMGetUndef, LLVMPointerType, LLVMPrintTypeToString, LLVMSizeOf, LLVMTypeIsSized, LLVMVectorType,
52};
53use llvm_sys::prelude::{LLVMTypeRef, LLVMValueRef};
54use llvm_sys::LLVMTypeKind;
55#[cfg(feature = "experimental")]
56use static_alloc::Bump;
57
58use std::fmt;
59use std::marker::PhantomData;
60
61use crate::context::ContextRef;
62use crate::support::LLVMString;
63use crate::values::IntValue;
64use crate::AddressSpace;
65
66#[derive(PartialEq, Eq, Clone, Copy)]
69struct Type<'ctx> {
70 ty: LLVMTypeRef,
71 _marker: PhantomData<&'ctx ()>,
72}
73
74impl<'ctx> Type<'ctx> {
75 unsafe fn new(ty: LLVMTypeRef) -> Self {
76 assert!(!ty.is_null());
77
78 Type {
79 ty,
80 _marker: PhantomData,
81 }
82 }
83
84 fn const_zero(self) -> LLVMValueRef {
85 unsafe {
86 match LLVMGetTypeKind(self.ty) {
87 LLVMTypeKind::LLVMMetadataTypeKind => LLVMConstPointerNull(self.ty),
88 _ => LLVMConstNull(self.ty),
89 }
90 }
91 }
92
93 fn ptr_type(self, address_space: AddressSpace) -> PointerType<'ctx> {
94 unsafe { PointerType::new(LLVMPointerType(self.ty, address_space.0)) }
95 }
96
97 fn vec_type(self, size: u32) -> VectorType<'ctx> {
98 assert!(size != 0, "Vectors of size zero are not allowed.");
99 unsafe { VectorType::new(LLVMVectorType(self.ty, size)) }
102 }
103
104 #[llvm_versions(12..)]
105 fn scalable_vec_type(self, size: u32) -> ScalableVectorType<'ctx> {
106 assert!(size != 0, "Vectors of size zero are not allowed.");
107 unsafe { ScalableVectorType::new(LLVMScalableVectorType(self.ty, size)) }
110 }
111
112 #[cfg(not(feature = "experimental"))]
113 fn fn_type(self, param_types: &[BasicMetadataTypeEnum<'ctx>], is_var_args: bool) -> FunctionType<'ctx> {
114 let mut param_types: Vec<LLVMTypeRef> = param_types.iter().map(|val| val.as_type_ref()).collect();
115 unsafe {
116 FunctionType::new(LLVMFunctionType(
117 self.ty,
118 param_types.as_mut_ptr(),
119 param_types.len() as u32,
120 is_var_args as i32,
121 ))
122 }
123 }
124
125 #[cfg(feature = "experimental")]
126 fn fn_type(self, param_types: &[BasicMetadataTypeEnum<'ctx>], is_var_args: bool) -> FunctionType<'ctx> {
127 let pool: Bump<[usize; 16]> = Bump::uninit();
128 let mut pool_start = None;
129
130 for (i, param_type) in param_types.iter().enumerate() {
131 let addr = pool.leak(param_type.as_type_ref()).expect("Found more than 16 params");
132
133 if i == 0 {
134 pool_start = Some(addr as *mut _);
135 }
136 }
137
138 unsafe {
139 FunctionType::new(LLVMFunctionType(
140 self.ty,
141 pool_start.unwrap_or(std::ptr::null_mut()),
142 param_types.len() as u32,
143 is_var_args as i32,
144 ))
145 }
146 }
147
148 #[allow(deprecated)]
149 fn array_type(self, size: u32) -> ArrayType<'ctx> {
150 unsafe { ArrayType::new(LLVMArrayType(self.ty, size)) }
151 }
152
153 fn get_undef(self) -> LLVMValueRef {
154 unsafe { LLVMGetUndef(self.ty) }
155 }
156
157 #[llvm_versions(12..)]
158 fn get_poison(&self) -> LLVMValueRef {
159 unsafe { LLVMGetPoison(self.ty) }
160 }
161
162 fn get_alignment(self) -> IntValue<'ctx> {
163 unsafe { IntValue::new(LLVMAlignOf(self.ty)) }
164 }
165
166 fn get_context(self) -> ContextRef<'ctx> {
167 unsafe { ContextRef::new(LLVMGetTypeContext(self.ty)) }
168 }
169
170 fn is_sized(self) -> bool {
174 unsafe { LLVMTypeIsSized(self.ty) == 1 }
175 }
176
177 fn size_of(self) -> Option<IntValue<'ctx>> {
178 if !self.is_sized() {
179 return None;
180 }
181
182 unsafe { Some(IntValue::new(LLVMSizeOf(self.ty))) }
183 }
184
185 fn print_to_string(self) -> LLVMString {
186 unsafe { LLVMString::new(LLVMPrintTypeToString(self.ty)) }
187 }
188
189 pub fn get_element_type(self) -> AnyTypeEnum<'ctx> {
190 unsafe { AnyTypeEnum::new(LLVMGetElementType(self.ty)) }
191 }
192}
193
194impl fmt::Debug for Type<'_> {
195 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
196 let llvm_type = self.print_to_string();
197
198 f.debug_struct("Type")
199 .field("address", &self.ty)
200 .field("llvm_type", &llvm_type)
201 .finish()
202 }
203}