]>
Commit | Line | Data |
---|---|---|
9fa01778 | 1 | pub use crate::llvm::Type; |
b7449926 | 2 | |
ba9703b0 XL |
3 | use crate::abi::{FnAbiLlvmExt, LlvmType}; |
4 | use crate::common; | |
dfeec247 | 5 | use crate::context::CodegenCx; |
9fa01778 XL |
6 | use crate::llvm; |
7 | use crate::llvm::{Bool, False, True}; | |
9fa01778 | 8 | use crate::type_of::LayoutLlvmExt; |
ba9703b0 | 9 | use crate::value::Value; |
a1dfa0c6 | 10 | use rustc_codegen_ssa::common::TypeKind; |
ba9703b0 | 11 | use rustc_codegen_ssa::traits::*; |
dfeec247 | 12 | use rustc_data_structures::small_c_str::SmallCStr; |
ba9703b0 XL |
13 | use rustc_middle::bug; |
14 | use rustc_middle::ty::layout::TyAndLayout; | |
5869c6ff | 15 | use rustc_middle::ty::{self, Ty}; |
dfeec247 | 16 | use rustc_target::abi::call::{CastTarget, FnAbi, Reg}; |
3dfed10e | 17 | use rustc_target::abi::{AddressSpace, Align, Integer, Size}; |
1a4d82fc | 18 | |
54a0048b | 19 | use std::fmt; |
0731742a | 20 | use std::ptr; |
1a4d82fc | 21 | |
064997fb | 22 | use libc::{c_char, c_uint}; |
1a4d82fc | 23 | |
b7449926 XL |
24 | impl PartialEq for Type { |
25 | fn eq(&self, other: &Self) -> bool { | |
0731742a | 26 | ptr::eq(self, other) |
b7449926 | 27 | } |
1a4d82fc JJ |
28 | } |
29 | ||
54a0048b | 30 | impl fmt::Debug for Type { |
9fa01778 | 31 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
dfeec247 XL |
32 | f.write_str( |
33 | &llvm::build_string(|s| unsafe { | |
34 | llvm::LLVMRustWriteTypeToString(self, s); | |
35 | }) | |
36 | .expect("non-UTF8 type description from LLVM"), | |
37 | ) | |
54a0048b SL |
38 | } |
39 | } | |
40 | ||
a2a8927a | 41 | impl<'ll> CodegenCx<'ll, '_> { |
923072b8 | 42 | pub(crate) fn type_named_struct(&self, name: &str) -> &'ll Type { |
a1dfa0c6 | 43 | let name = SmallCStr::new(name); |
dfeec247 | 44 | unsafe { llvm::LLVMStructCreateNamed(self.llcx, name.as_ptr()) } |
1a4d82fc JJ |
45 | } |
46 | ||
923072b8 | 47 | pub(crate) fn set_struct_body(&self, ty: &'ll Type, els: &[&'ll Type], packed: bool) { |
dfeec247 | 48 | unsafe { llvm::LLVMStructSetBody(ty, els.as_ptr(), els.len() as c_uint, packed as Bool) } |
1a4d82fc JJ |
49 | } |
50 | ||
923072b8 | 51 | pub(crate) fn type_void(&self) -> &'ll Type { |
dfeec247 | 52 | unsafe { llvm::LLVMVoidTypeInContext(self.llcx) } |
1a4d82fc JJ |
53 | } |
54 | ||
923072b8 | 55 | pub(crate) fn type_metadata(&self) -> &'ll Type { |
dfeec247 | 56 | unsafe { llvm::LLVMRustMetadataTypeInContext(self.llcx) } |
1a4d82fc JJ |
57 | } |
58 | ||
532ac7d7 | 59 | ///x Creates an integer type with the given number of bits, e.g., i24 |
923072b8 | 60 | pub(crate) fn type_ix(&self, num_bits: u64) -> &'ll Type { |
dfeec247 | 61 | unsafe { llvm::LLVMIntTypeInContext(self.llcx, num_bits as c_uint) } |
532ac7d7 XL |
62 | } |
63 | ||
923072b8 | 64 | pub(crate) fn type_vector(&self, ty: &'ll Type, len: u64) -> &'ll Type { |
dfeec247 | 65 | unsafe { llvm::LLVMVectorType(ty, len as c_uint) } |
532ac7d7 XL |
66 | } |
67 | ||
923072b8 | 68 | pub(crate) fn func_params_types(&self, ty: &'ll Type) -> Vec<&'ll Type> { |
532ac7d7 XL |
69 | unsafe { |
70 | let n_args = llvm::LLVMCountParamTypes(ty) as usize; | |
71 | let mut args = Vec::with_capacity(n_args); | |
72 | llvm::LLVMGetParamTypes(ty, args.as_mut_ptr()); | |
73 | args.set_len(n_args); | |
74 | args | |
75 | } | |
76 | } | |
77 | ||
923072b8 | 78 | pub(crate) fn type_bool(&self) -> &'ll Type { |
532ac7d7 XL |
79 | self.type_i8() |
80 | } | |
81 | ||
923072b8 | 82 | pub(crate) fn type_int_from_ty(&self, t: ty::IntTy) -> &'ll Type { |
532ac7d7 | 83 | match t { |
5869c6ff XL |
84 | ty::IntTy::Isize => self.type_isize(), |
85 | ty::IntTy::I8 => self.type_i8(), | |
86 | ty::IntTy::I16 => self.type_i16(), | |
87 | ty::IntTy::I32 => self.type_i32(), | |
88 | ty::IntTy::I64 => self.type_i64(), | |
89 | ty::IntTy::I128 => self.type_i128(), | |
532ac7d7 XL |
90 | } |
91 | } | |
92 | ||
923072b8 | 93 | pub(crate) fn type_uint_from_ty(&self, t: ty::UintTy) -> &'ll Type { |
532ac7d7 | 94 | match t { |
5869c6ff XL |
95 | ty::UintTy::Usize => self.type_isize(), |
96 | ty::UintTy::U8 => self.type_i8(), | |
97 | ty::UintTy::U16 => self.type_i16(), | |
98 | ty::UintTy::U32 => self.type_i32(), | |
99 | ty::UintTy::U64 => self.type_i64(), | |
100 | ty::UintTy::U128 => self.type_i128(), | |
532ac7d7 XL |
101 | } |
102 | } | |
103 | ||
923072b8 | 104 | pub(crate) fn type_float_from_ty(&self, t: ty::FloatTy) -> &'ll Type { |
532ac7d7 | 105 | match t { |
5869c6ff XL |
106 | ty::FloatTy::F32 => self.type_f32(), |
107 | ty::FloatTy::F64 => self.type_f64(), | |
532ac7d7 XL |
108 | } |
109 | } | |
110 | ||
923072b8 | 111 | pub(crate) fn type_pointee_for_align(&self, align: Align) -> &'ll Type { |
532ac7d7 | 112 | // FIXME(eddyb) We could find a better approximation if ity.align < align. |
ba9703b0 | 113 | let ity = Integer::approximate_align(self, align); |
532ac7d7 XL |
114 | self.type_from_integer(ity) |
115 | } | |
116 | ||
117 | /// Return a LLVM type that has at most the required alignment, | |
118 | /// and exactly the required size, as a best-effort padding array. | |
923072b8 | 119 | pub(crate) fn type_padding_filler(&self, size: Size, align: Align) -> &'ll Type { |
ba9703b0 | 120 | let unit = Integer::approximate_align(self, align); |
532ac7d7 XL |
121 | let size = size.bytes(); |
122 | let unit_size = unit.size().bytes(); | |
123 | assert_eq!(size % unit_size, 0); | |
124 | self.type_array(self.type_from_integer(unit), size / unit_size) | |
125 | } | |
126 | ||
923072b8 | 127 | pub(crate) fn type_variadic_func(&self, args: &[&'ll Type], ret: &'ll Type) -> &'ll Type { |
dfeec247 | 128 | unsafe { llvm::LLVMFunctionType(ret, args.as_ptr(), args.len() as c_uint, True) } |
532ac7d7 XL |
129 | } |
130 | ||
923072b8 | 131 | pub(crate) fn type_array(&self, ty: &'ll Type, len: u64) -> &'ll Type { |
dfeec247 | 132 | unsafe { llvm::LLVMRustArrayType(ty, len) } |
532ac7d7 XL |
133 | } |
134 | } | |
135 | ||
a2a8927a | 136 | impl<'ll, 'tcx> BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> { |
a1dfa0c6 | 137 | fn type_i1(&self) -> &'ll Type { |
dfeec247 | 138 | unsafe { llvm::LLVMInt1TypeInContext(self.llcx) } |
1a4d82fc JJ |
139 | } |
140 | ||
a1dfa0c6 | 141 | fn type_i8(&self) -> &'ll Type { |
dfeec247 | 142 | unsafe { llvm::LLVMInt8TypeInContext(self.llcx) } |
cc61c64b XL |
143 | } |
144 | ||
a1dfa0c6 | 145 | fn type_i16(&self) -> &'ll Type { |
dfeec247 | 146 | unsafe { llvm::LLVMInt16TypeInContext(self.llcx) } |
1a4d82fc JJ |
147 | } |
148 | ||
a1dfa0c6 | 149 | fn type_i32(&self) -> &'ll Type { |
dfeec247 | 150 | unsafe { llvm::LLVMInt32TypeInContext(self.llcx) } |
32a655c1 SL |
151 | } |
152 | ||
a1dfa0c6 | 153 | fn type_i64(&self) -> &'ll Type { |
dfeec247 | 154 | unsafe { llvm::LLVMInt64TypeInContext(self.llcx) } |
85aaf69f SL |
155 | } |
156 | ||
a1dfa0c6 | 157 | fn type_i128(&self) -> &'ll Type { |
dfeec247 | 158 | unsafe { llvm::LLVMIntTypeInContext(self.llcx, 128) } |
1a4d82fc JJ |
159 | } |
160 | ||
a1dfa0c6 XL |
161 | fn type_isize(&self) -> &'ll Type { |
162 | self.isize_ty | |
1a4d82fc JJ |
163 | } |
164 | ||
a1dfa0c6 | 165 | fn type_f32(&self) -> &'ll Type { |
dfeec247 | 166 | unsafe { llvm::LLVMFloatTypeInContext(self.llcx) } |
1a4d82fc JJ |
167 | } |
168 | ||
a1dfa0c6 | 169 | fn type_f64(&self) -> &'ll Type { |
dfeec247 | 170 | unsafe { llvm::LLVMDoubleTypeInContext(self.llcx) } |
1a4d82fc JJ |
171 | } |
172 | ||
dfeec247 XL |
173 | fn type_func(&self, args: &[&'ll Type], ret: &'ll Type) -> &'ll Type { |
174 | unsafe { llvm::LLVMFunctionType(ret, args.as_ptr(), args.len() as c_uint, False) } | |
1a4d82fc JJ |
175 | } |
176 | ||
dfeec247 | 177 | fn type_struct(&self, els: &[&'ll Type], packed: bool) -> &'ll Type { |
b7449926 | 178 | unsafe { |
dfeec247 XL |
179 | llvm::LLVMStructTypeInContext( |
180 | self.llcx, | |
181 | els.as_ptr(), | |
182 | els.len() as c_uint, | |
183 | packed as Bool, | |
184 | ) | |
b7449926 | 185 | } |
1a4d82fc JJ |
186 | } |
187 | ||
a1dfa0c6 | 188 | fn type_kind(&self, ty: &'ll Type) -> TypeKind { |
dfeec247 | 189 | unsafe { llvm::LLVMRustGetTypeKind(ty).to_generic() } |
1a4d82fc JJ |
190 | } |
191 | ||
a1dfa0c6 | 192 | fn type_ptr_to(&self, ty: &'ll Type) -> &'ll Type { |
dfeec247 XL |
193 | assert_ne!( |
194 | self.type_kind(ty), | |
195 | TypeKind::Function, | |
3dfed10e | 196 | "don't call ptr_to on function types, use ptr_to_llvm_type on FnAbi instead or explicitly specify an address space if it makes sense" |
dfeec247 | 197 | ); |
3dfed10e XL |
198 | ty.ptr_to(AddressSpace::DATA) |
199 | } | |
200 | ||
201 | fn type_ptr_to_ext(&self, ty: &'ll Type, address_space: AddressSpace) -> &'ll Type { | |
202 | ty.ptr_to(address_space) | |
1a4d82fc JJ |
203 | } |
204 | ||
a1dfa0c6 | 205 | fn element_type(&self, ty: &'ll Type) -> &'ll Type { |
94222f64 XL |
206 | match self.type_kind(ty) { |
207 | TypeKind::Array | TypeKind::Vector => unsafe { llvm::LLVMGetElementType(ty) }, | |
208 | TypeKind::Pointer => bug!("element_type is not supported for opaque pointers"), | |
209 | other => bug!("element_type called on unsupported type {:?}", other), | |
210 | } | |
1a4d82fc JJ |
211 | } |
212 | ||
a1dfa0c6 | 213 | fn vector_length(&self, ty: &'ll Type) -> usize { |
dfeec247 | 214 | unsafe { llvm::LLVMGetVectorSize(ty) as usize } |
1a4d82fc JJ |
215 | } |
216 | ||
a1dfa0c6 XL |
217 | fn float_width(&self, ty: &'ll Type) -> usize { |
218 | match self.type_kind(ty) { | |
b7449926 XL |
219 | TypeKind::Float => 32, |
220 | TypeKind::Double => 64, | |
221 | TypeKind::X86_FP80 => 80, | |
222 | TypeKind::FP128 | TypeKind::PPC_FP128 => 128, | |
dfeec247 | 223 | _ => bug!("llvm_float_width called on a non-float type"), |
1a4d82fc JJ |
224 | } |
225 | } | |
85aaf69f | 226 | |
a1dfa0c6 | 227 | fn int_width(&self, ty: &'ll Type) -> u64 { |
dfeec247 | 228 | unsafe { llvm::LLVMGetIntTypeWidth(ty) as u64 } |
85aaf69f | 229 | } |
9e0c209e | 230 | |
a1dfa0c6 XL |
231 | fn val_ty(&self, v: &'ll Value) -> &'ll Type { |
232 | common::val_ty(v) | |
233 | } | |
a1dfa0c6 XL |
234 | } |
235 | ||
236 | impl Type { | |
237 | pub fn i8_llcx(llcx: &llvm::Context) -> &Type { | |
dfeec247 | 238 | unsafe { llvm::LLVMInt8TypeInContext(llcx) } |
9e0c209e | 239 | } |
ff7c6d11 | 240 | |
0731742a | 241 | // Creates an integer type with the given number of bits, e.g., i24 |
dfeec247 XL |
242 | pub fn ix_llcx(llcx: &llvm::Context, num_bits: u64) -> &Type { |
243 | unsafe { llvm::LLVMIntTypeInContext(llcx, num_bits as c_uint) } | |
ff7c6d11 XL |
244 | } |
245 | ||
ba9703b0 | 246 | pub fn i8p_llcx(llcx: &llvm::Context) -> &Type { |
3dfed10e | 247 | Type::i8_llcx(llcx).ptr_to(AddressSpace::DATA) |
ff7c6d11 XL |
248 | } |
249 | ||
3dfed10e | 250 | fn ptr_to(&self, address_space: AddressSpace) -> &Type { |
c295e0f8 | 251 | unsafe { llvm::LLVMPointerType(self, address_space.0) } |
ff7c6d11 | 252 | } |
1a4d82fc | 253 | } |
a1dfa0c6 | 254 | |
a2a8927a | 255 | impl<'ll, 'tcx> LayoutTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> { |
ba9703b0 | 256 | fn backend_type(&self, layout: TyAndLayout<'tcx>) -> &'ll Type { |
a1dfa0c6 XL |
257 | layout.llvm_type(self) |
258 | } | |
ba9703b0 | 259 | fn immediate_backend_type(&self, layout: TyAndLayout<'tcx>) -> &'ll Type { |
a1dfa0c6 XL |
260 | layout.immediate_llvm_type(self) |
261 | } | |
ba9703b0 | 262 | fn is_backend_immediate(&self, layout: TyAndLayout<'tcx>) -> bool { |
a1dfa0c6 XL |
263 | layout.is_llvm_immediate() |
264 | } | |
ba9703b0 | 265 | fn is_backend_scalar_pair(&self, layout: TyAndLayout<'tcx>) -> bool { |
a1dfa0c6 XL |
266 | layout.is_llvm_scalar_pair() |
267 | } | |
ba9703b0 | 268 | fn backend_field_index(&self, layout: TyAndLayout<'tcx>, index: usize) -> u64 { |
94222f64 | 269 | layout.llvm_field_index(self, index) |
a1dfa0c6 | 270 | } |
dc9dc135 | 271 | fn scalar_pair_element_backend_type( |
a1dfa0c6 | 272 | &self, |
ba9703b0 | 273 | layout: TyAndLayout<'tcx>, |
a1dfa0c6 | 274 | index: usize, |
dfeec247 | 275 | immediate: bool, |
a1dfa0c6 XL |
276 | ) -> &'ll Type { |
277 | layout.scalar_pair_element_llvm_type(self, index, immediate) | |
278 | } | |
279 | fn cast_backend_type(&self, ty: &CastTarget) -> &'ll Type { | |
280 | ty.llvm_type(self) | |
281 | } | |
94222f64 XL |
282 | fn fn_decl_backend_type(&self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> &'ll Type { |
283 | fn_abi.llvm_type(self) | |
284 | } | |
60c5eb7d XL |
285 | fn fn_ptr_backend_type(&self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> &'ll Type { |
286 | fn_abi.ptr_to_llvm_type(self) | |
a1dfa0c6 XL |
287 | } |
288 | fn reg_backend_type(&self, ty: &Reg) -> &'ll Type { | |
289 | ty.llvm_type(self) | |
290 | } | |
291 | } | |
064997fb FG |
292 | |
293 | impl<'ll, 'tcx> TypeMembershipMethods<'tcx> for CodegenCx<'ll, 'tcx> { | |
294 | fn set_type_metadata(&self, function: &'ll Value, typeid: String) { | |
295 | let typeid_metadata = self.typeid_metadata(typeid); | |
296 | let v = [self.const_usize(0), typeid_metadata]; | |
297 | unsafe { | |
298 | llvm::LLVMGlobalSetMetadata( | |
299 | function, | |
300 | llvm::MD_type as c_uint, | |
301 | llvm::LLVMValueAsMetadata(llvm::LLVMMDNodeInContext( | |
302 | self.llcx, | |
303 | v.as_ptr(), | |
304 | v.len() as c_uint, | |
305 | )), | |
306 | ) | |
307 | } | |
308 | } | |
309 | ||
310 | fn typeid_metadata(&self, typeid: String) -> &'ll Value { | |
311 | unsafe { | |
312 | llvm::LLVMMDStringInContext( | |
313 | self.llcx, | |
314 | typeid.as_ptr() as *const c_char, | |
315 | typeid.len() as c_uint, | |
316 | ) | |
317 | } | |
318 | } | |
319 | } |