/rust/registry/src/index.crates.io-6f17d22bba15001f/inkwell-0.1.1/src/types/mod.rs
Line | Count | Source (jump to first uncovered line) |
1 | | //! A type is a classification which determines how data is used. |
2 | | |
3 | | #[deny(missing_docs)] |
4 | | mod array_type; |
5 | | mod enums; |
6 | | #[deny(missing_docs)] |
7 | | mod float_type; |
8 | | #[deny(missing_docs)] |
9 | | mod fn_type; |
10 | | #[deny(missing_docs)] |
11 | | mod int_type; |
12 | | #[deny(missing_docs)] |
13 | | mod metadata_type; |
14 | | #[deny(missing_docs)] |
15 | | mod ptr_type; |
16 | | #[deny(missing_docs)] |
17 | | mod struct_type; |
18 | | #[deny(missing_docs)] |
19 | | mod traits; |
20 | | #[deny(missing_docs)] |
21 | | mod vec_type; |
22 | | #[deny(missing_docs)] |
23 | | mod void_type; |
24 | | |
25 | | pub use crate::types::array_type::ArrayType; |
26 | | pub use crate::types::enums::{AnyTypeEnum, BasicMetadataTypeEnum, BasicTypeEnum}; |
27 | | pub use crate::types::float_type::FloatType; |
28 | | pub use crate::types::fn_type::FunctionType; |
29 | | pub use crate::types::int_type::{IntType, StringRadix}; |
30 | | pub use crate::types::metadata_type::MetadataType; |
31 | | pub use crate::types::ptr_type::PointerType; |
32 | | pub use crate::types::struct_type::StructType; |
33 | | pub use crate::types::traits::{AnyType, AsTypeRef, BasicType, FloatMathType, IntMathType, PointerMathType}; |
34 | | pub use crate::types::vec_type::VectorType; |
35 | | pub use crate::types::void_type::VoidType; |
36 | | |
37 | | use llvm_sys::core::{ |
38 | | LLVMAlignOf, LLVMArrayType, LLVMConstNull, LLVMConstPointerNull, LLVMFunctionType, LLVMGetElementType, |
39 | | LLVMGetTypeContext, LLVMGetTypeKind, LLVMGetUndef, LLVMPointerType, LLVMPrintTypeToString, LLVMSizeOf, |
40 | | LLVMTypeIsSized, LLVMVectorType, |
41 | | }; |
42 | | use llvm_sys::prelude::{LLVMTypeRef, LLVMValueRef}; |
43 | | use llvm_sys::LLVMTypeKind; |
44 | | #[cfg(feature = "experimental")] |
45 | | use static_alloc::Bump; |
46 | | |
47 | | use std::fmt; |
48 | | use std::marker::PhantomData; |
49 | | |
50 | | use crate::context::ContextRef; |
51 | | use crate::support::LLVMString; |
52 | | use crate::values::IntValue; |
53 | | use crate::AddressSpace; |
54 | | |
55 | | // Worth noting that types seem to be singletons. At the very least, primitives are. |
56 | | // Though this is likely only true per thread since LLVM claims to not be very thread-safe. |
57 | | #[derive(PartialEq, Eq, Clone, Copy)] |
58 | | struct Type<'ctx> { |
59 | | ty: LLVMTypeRef, |
60 | | _marker: PhantomData<&'ctx ()>, |
61 | | } |
62 | | |
63 | | impl<'ctx> Type<'ctx> { |
64 | 26.4M | unsafe fn new(ty: LLVMTypeRef) -> Self { |
65 | 26.4M | assert!(!ty.is_null()); |
66 | | |
67 | 26.4M | Type { |
68 | 26.4M | ty, |
69 | 26.4M | _marker: PhantomData, |
70 | 26.4M | } |
71 | 26.4M | } |
72 | | |
73 | 1.52M | fn const_zero(self) -> LLVMValueRef { |
74 | 1.52M | unsafe { |
75 | 1.52M | match LLVMGetTypeKind(self.ty) { |
76 | 0 | LLVMTypeKind::LLVMMetadataTypeKind => LLVMConstPointerNull(self.ty), |
77 | 1.52M | _ => LLVMConstNull(self.ty), |
78 | | } |
79 | | } |
80 | 1.52M | } |
81 | | |
82 | 3.73M | fn ptr_type(self, address_space: AddressSpace) -> PointerType<'ctx> { |
83 | 3.73M | unsafe { PointerType::new(LLVMPointerType(self.ty, address_space.0)) } |
84 | 3.73M | } |
85 | | |
86 | 1.69M | fn vec_type(self, size: u32) -> VectorType<'ctx> { |
87 | 1.69M | assert!(size != 0, "Vectors of size zero are not allowed."); |
88 | | // -- https://llvm.org/docs/LangRef.html#vector-type |
89 | | |
90 | 1.69M | unsafe { VectorType::new(LLVMVectorType(self.ty, size)) } |
91 | 1.69M | } |
92 | | |
93 | | #[cfg(not(feature = "experimental"))] |
94 | 11.5M | fn fn_type(self, param_types: &[BasicMetadataTypeEnum<'ctx>], is_var_args: bool) -> FunctionType<'ctx> { |
95 | 36.7M | let mut param_types: Vec<LLVMTypeRef> = param_types.iter().map(|val| val.as_type_ref()).collect(); |
96 | 11.5M | unsafe { |
97 | 11.5M | FunctionType::new(LLVMFunctionType( |
98 | 11.5M | self.ty, |
99 | 11.5M | param_types.as_mut_ptr(), |
100 | 11.5M | param_types.len() as u32, |
101 | 11.5M | is_var_args as i32, |
102 | 11.5M | )) |
103 | 11.5M | } |
104 | 11.5M | } |
105 | | |
106 | | #[cfg(feature = "experimental")] |
107 | | fn fn_type(self, param_types: &[BasicMetadataTypeEnum<'ctx>], is_var_args: bool) -> FunctionType<'ctx> { |
108 | | let pool: Bump<[usize; 16]> = Bump::uninit(); |
109 | | let mut pool_start = None; |
110 | | |
111 | | for (i, param_type) in param_types.iter().enumerate() { |
112 | | let addr = pool.leak(param_type.as_type_ref()).expect("Found more than 16 params"); |
113 | | |
114 | | if i == 0 { |
115 | | pool_start = Some(addr as *mut _); |
116 | | } |
117 | | } |
118 | | |
119 | | unsafe { |
120 | | FunctionType::new(LLVMFunctionType( |
121 | | self.ty, |
122 | | pool_start.unwrap_or(std::ptr::null_mut()), |
123 | | param_types.len() as u32, |
124 | | is_var_args as i32, |
125 | | )) |
126 | | } |
127 | | } |
128 | | |
129 | 0 | fn array_type(self, size: u32) -> ArrayType<'ctx> { |
130 | 0 | unsafe { ArrayType::new(LLVMArrayType(self.ty, size)) } |
131 | 0 | } |
132 | | |
133 | 11.6k | fn get_undef(self) -> LLVMValueRef { |
134 | 11.6k | unsafe { LLVMGetUndef(self.ty) } |
135 | 11.6k | } |
136 | | |
137 | 0 | fn get_alignment(self) -> IntValue<'ctx> { |
138 | 0 | unsafe { IntValue::new(LLVMAlignOf(self.ty)) } |
139 | 0 | } |
140 | | |
141 | 16.0k | fn get_context(self) -> ContextRef<'ctx> { |
142 | 16.0k | unsafe { ContextRef::new(LLVMGetTypeContext(self.ty)) } |
143 | 16.0k | } |
144 | | |
145 | | // REVIEW: This should be known at compile time, maybe as a const fn? |
146 | | // On an enum or trait, this would not be known at compile time (unless |
147 | | // enum has only sized types for example) |
148 | 0 | fn is_sized(self) -> bool { |
149 | 0 | unsafe { LLVMTypeIsSized(self.ty) == 1 } |
150 | 0 | } |
151 | | |
152 | 0 | fn size_of(self) -> Option<IntValue<'ctx>> { |
153 | 0 | if !self.is_sized() { |
154 | 0 | return None; |
155 | 0 | } |
156 | 0 |
|
157 | 0 | unsafe { Some(IntValue::new(LLVMSizeOf(self.ty))) } |
158 | 0 | } |
159 | | |
160 | 0 | fn print_to_string(self) -> LLVMString { |
161 | 0 | unsafe { LLVMString::new(LLVMPrintTypeToString(self.ty)) } |
162 | 0 | } |
163 | | |
164 | 0 | pub fn get_element_type(self) -> AnyTypeEnum<'ctx> { |
165 | 0 | unsafe { AnyTypeEnum::new(LLVMGetElementType(self.ty)) } |
166 | 0 | } |
167 | | } |
168 | | |
169 | | impl fmt::Debug for Type<'_> { |
170 | 0 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
171 | 0 | let llvm_type = self.print_to_string(); |
172 | 0 |
|
173 | 0 | f.debug_struct("Type") |
174 | 0 | .field("address", &self.ty) |
175 | 0 | .field("llvm_type", &llvm_type) |
176 | 0 | .finish() |
177 | 0 | } |
178 | | } |