1 pub use crate::llvm::Type; 2 3 use crate::abi::{FnAbiLlvmExt, LlvmType}; 4 use crate::common; 5 use crate::context::CodegenCx; 6 use crate::llvm; 7 use crate::llvm::{Bool, False, True}; 8 use crate::type_of::LayoutLlvmExt; 9 use crate::value::Value; 10 use rustc_codegen_ssa::common::TypeKind; 11 use rustc_codegen_ssa::traits::*; 12 use rustc_data_structures::small_c_str::SmallCStr; 13 use rustc_middle::bug; 14 use rustc_middle::ty::layout::TyAndLayout; 15 use rustc_middle::ty::{self, Ty}; 16 use rustc_target::abi::call::{CastTarget, FnAbi, Reg}; 17 use rustc_target::abi::{AddressSpace, Align, Integer, Size}; 18 19 use std::fmt; 20 use std::ptr; 21 22 use libc::c_uint; 23 24 impl PartialEq for Type { eq(&self, other: &Self) -> bool25 fn eq(&self, other: &Self) -> bool { 26 ptr::eq(self, other) 27 } 28 } 29 30 impl fmt::Debug for Type { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result31 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 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 ) 38 } 39 } 40 41 impl CodegenCx<'ll, 'tcx> { type_named_struct(&self, name: &str) -> &'ll Type42 crate fn type_named_struct(&self, name: &str) -> &'ll Type { 43 let name = SmallCStr::new(name); 44 unsafe { llvm::LLVMStructCreateNamed(self.llcx, name.as_ptr()) } 45 } 46 set_struct_body(&self, ty: &'ll Type, els: &[&'ll Type], packed: bool)47 crate fn set_struct_body(&self, ty: &'ll Type, els: &[&'ll Type], packed: bool) { 48 unsafe { llvm::LLVMStructSetBody(ty, els.as_ptr(), els.len() as c_uint, packed as Bool) } 49 } 50 type_void(&self) -> &'ll Type51 crate fn type_void(&self) -> &'ll Type { 52 unsafe { llvm::LLVMVoidTypeInContext(self.llcx) } 53 } 54 type_metadata(&self) -> &'ll Type55 crate fn type_metadata(&self) -> &'ll Type { 56 unsafe { llvm::LLVMRustMetadataTypeInContext(self.llcx) } 57 } 58 59 ///x Creates an integer type with the given number of bits, e.g., i24 type_ix(&self, num_bits: u64) -> &'ll Type60 crate fn type_ix(&self, num_bits: u64) -> &'ll Type { 61 unsafe { llvm::LLVMIntTypeInContext(self.llcx, num_bits as c_uint) } 62 } 63 type_vector(&self, ty: &'ll Type, len: u64) -> &'ll Type64 crate fn type_vector(&self, ty: &'ll Type, len: u64) -> &'ll Type { 65 unsafe { llvm::LLVMVectorType(ty, len as c_uint) } 66 } 67 func_params_types(&self, ty: &'ll Type) -> Vec<&'ll Type>68 crate fn func_params_types(&self, ty: &'ll Type) -> Vec<&'ll Type> { 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 type_bool(&self) -> &'ll Type78 crate fn type_bool(&self) -> &'ll Type { 79 self.type_i8() 80 } 81 type_int_from_ty(&self, t: ty::IntTy) -> &'ll Type82 crate fn type_int_from_ty(&self, t: ty::IntTy) -> &'ll Type { 83 match t { 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(), 90 } 91 } 92 type_uint_from_ty(&self, t: ty::UintTy) -> &'ll Type93 crate fn type_uint_from_ty(&self, t: ty::UintTy) -> &'ll Type { 94 match t { 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(), 101 } 102 } 103 type_float_from_ty(&self, t: ty::FloatTy) -> &'ll Type104 crate fn type_float_from_ty(&self, t: ty::FloatTy) -> &'ll Type { 105 match t { 106 ty::FloatTy::F32 => self.type_f32(), 107 ty::FloatTy::F64 => self.type_f64(), 108 } 109 } 110 type_pointee_for_align(&self, align: Align) -> &'ll Type111 crate fn type_pointee_for_align(&self, align: Align) -> &'ll Type { 112 // FIXME(eddyb) We could find a better approximation if ity.align < align. 113 let ity = Integer::approximate_align(self, align); 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. type_padding_filler(&self, size: Size, align: Align) -> &'ll Type119 crate fn type_padding_filler(&self, size: Size, align: Align) -> &'ll Type { 120 let unit = Integer::approximate_align(self, align); 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 type_variadic_func(&self, args: &[&'ll Type], ret: &'ll Type) -> &'ll Type127 crate fn type_variadic_func(&self, args: &[&'ll Type], ret: &'ll Type) -> &'ll Type { 128 unsafe { llvm::LLVMFunctionType(ret, args.as_ptr(), args.len() as c_uint, True) } 129 } 130 type_array(&self, ty: &'ll Type, len: u64) -> &'ll Type131 crate fn type_array(&self, ty: &'ll Type, len: u64) -> &'ll Type { 132 unsafe { llvm::LLVMRustArrayType(ty, len) } 133 } 134 } 135 136 impl BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> { type_i1(&self) -> &'ll Type137 fn type_i1(&self) -> &'ll Type { 138 unsafe { llvm::LLVMInt1TypeInContext(self.llcx) } 139 } 140 type_i8(&self) -> &'ll Type141 fn type_i8(&self) -> &'ll Type { 142 unsafe { llvm::LLVMInt8TypeInContext(self.llcx) } 143 } 144 type_i16(&self) -> &'ll Type145 fn type_i16(&self) -> &'ll Type { 146 unsafe { llvm::LLVMInt16TypeInContext(self.llcx) } 147 } 148 type_i32(&self) -> &'ll Type149 fn type_i32(&self) -> &'ll Type { 150 unsafe { llvm::LLVMInt32TypeInContext(self.llcx) } 151 } 152 type_i64(&self) -> &'ll Type153 fn type_i64(&self) -> &'ll Type { 154 unsafe { llvm::LLVMInt64TypeInContext(self.llcx) } 155 } 156 type_i128(&self) -> &'ll Type157 fn type_i128(&self) -> &'ll Type { 158 unsafe { llvm::LLVMIntTypeInContext(self.llcx, 128) } 159 } 160 type_isize(&self) -> &'ll Type161 fn type_isize(&self) -> &'ll Type { 162 self.isize_ty 163 } 164 type_f32(&self) -> &'ll Type165 fn type_f32(&self) -> &'ll Type { 166 unsafe { llvm::LLVMFloatTypeInContext(self.llcx) } 167 } 168 type_f64(&self) -> &'ll Type169 fn type_f64(&self) -> &'ll Type { 170 unsafe { llvm::LLVMDoubleTypeInContext(self.llcx) } 171 } 172 type_func(&self, args: &[&'ll Type], ret: &'ll Type) -> &'ll Type173 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) } 175 } 176 type_struct(&self, els: &[&'ll Type], packed: bool) -> &'ll Type177 fn type_struct(&self, els: &[&'ll Type], packed: bool) -> &'ll Type { 178 unsafe { 179 llvm::LLVMStructTypeInContext( 180 self.llcx, 181 els.as_ptr(), 182 els.len() as c_uint, 183 packed as Bool, 184 ) 185 } 186 } 187 type_kind(&self, ty: &'ll Type) -> TypeKind188 fn type_kind(&self, ty: &'ll Type) -> TypeKind { 189 unsafe { llvm::LLVMRustGetTypeKind(ty).to_generic() } 190 } 191 type_ptr_to(&self, ty: &'ll Type) -> &'ll Type192 fn type_ptr_to(&self, ty: &'ll Type) -> &'ll Type { 193 assert_ne!( 194 self.type_kind(ty), 195 TypeKind::Function, 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" 197 ); 198 ty.ptr_to(AddressSpace::DATA) 199 } 200 type_ptr_to_ext(&self, ty: &'ll Type, address_space: AddressSpace) -> &'ll Type201 fn type_ptr_to_ext(&self, ty: &'ll Type, address_space: AddressSpace) -> &'ll Type { 202 ty.ptr_to(address_space) 203 } 204 element_type(&self, ty: &'ll Type) -> &'ll Type205 fn element_type(&self, ty: &'ll Type) -> &'ll Type { 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 } 211 } 212 vector_length(&self, ty: &'ll Type) -> usize213 fn vector_length(&self, ty: &'ll Type) -> usize { 214 unsafe { llvm::LLVMGetVectorSize(ty) as usize } 215 } 216 float_width(&self, ty: &'ll Type) -> usize217 fn float_width(&self, ty: &'ll Type) -> usize { 218 match self.type_kind(ty) { 219 TypeKind::Float => 32, 220 TypeKind::Double => 64, 221 TypeKind::X86_FP80 => 80, 222 TypeKind::FP128 | TypeKind::PPC_FP128 => 128, 223 _ => bug!("llvm_float_width called on a non-float type"), 224 } 225 } 226 int_width(&self, ty: &'ll Type) -> u64227 fn int_width(&self, ty: &'ll Type) -> u64 { 228 unsafe { llvm::LLVMGetIntTypeWidth(ty) as u64 } 229 } 230 val_ty(&self, v: &'ll Value) -> &'ll Type231 fn val_ty(&self, v: &'ll Value) -> &'ll Type { 232 common::val_ty(v) 233 } 234 } 235 236 impl Type { i8_llcx(llcx: &llvm::Context) -> &Type237 pub fn i8_llcx(llcx: &llvm::Context) -> &Type { 238 unsafe { llvm::LLVMInt8TypeInContext(llcx) } 239 } 240 241 // Creates an integer type with the given number of bits, e.g., i24 ix_llcx(llcx: &llvm::Context, num_bits: u64) -> &Type242 pub fn ix_llcx(llcx: &llvm::Context, num_bits: u64) -> &Type { 243 unsafe { llvm::LLVMIntTypeInContext(llcx, num_bits as c_uint) } 244 } 245 i8p_llcx(llcx: &llvm::Context) -> &Type246 pub fn i8p_llcx(llcx: &llvm::Context) -> &Type { 247 Type::i8_llcx(llcx).ptr_to(AddressSpace::DATA) 248 } 249 ptr_to(&self, address_space: AddressSpace) -> &Type250 fn ptr_to(&self, address_space: AddressSpace) -> &Type { 251 unsafe { llvm::LLVMPointerType(self, address_space.0) } 252 } 253 } 254 255 impl LayoutTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> { backend_type(&self, layout: TyAndLayout<'tcx>) -> &'ll Type256 fn backend_type(&self, layout: TyAndLayout<'tcx>) -> &'ll Type { 257 layout.llvm_type(self) 258 } immediate_backend_type(&self, layout: TyAndLayout<'tcx>) -> &'ll Type259 fn immediate_backend_type(&self, layout: TyAndLayout<'tcx>) -> &'ll Type { 260 layout.immediate_llvm_type(self) 261 } is_backend_immediate(&self, layout: TyAndLayout<'tcx>) -> bool262 fn is_backend_immediate(&self, layout: TyAndLayout<'tcx>) -> bool { 263 layout.is_llvm_immediate() 264 } is_backend_scalar_pair(&self, layout: TyAndLayout<'tcx>) -> bool265 fn is_backend_scalar_pair(&self, layout: TyAndLayout<'tcx>) -> bool { 266 layout.is_llvm_scalar_pair() 267 } backend_field_index(&self, layout: TyAndLayout<'tcx>, index: usize) -> u64268 fn backend_field_index(&self, layout: TyAndLayout<'tcx>, index: usize) -> u64 { 269 layout.llvm_field_index(self, index) 270 } scalar_pair_element_backend_type( &self, layout: TyAndLayout<'tcx>, index: usize, immediate: bool, ) -> &'ll Type271 fn scalar_pair_element_backend_type( 272 &self, 273 layout: TyAndLayout<'tcx>, 274 index: usize, 275 immediate: bool, 276 ) -> &'ll Type { 277 layout.scalar_pair_element_llvm_type(self, index, immediate) 278 } cast_backend_type(&self, ty: &CastTarget) -> &'ll Type279 fn cast_backend_type(&self, ty: &CastTarget) -> &'ll Type { 280 ty.llvm_type(self) 281 } fn_decl_backend_type(&self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> &'ll Type282 fn fn_decl_backend_type(&self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> &'ll Type { 283 fn_abi.llvm_type(self) 284 } fn_ptr_backend_type(&self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> &'ll Type285 fn fn_ptr_backend_type(&self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> &'ll Type { 286 fn_abi.ptr_to_llvm_type(self) 287 } reg_backend_type(&self, ty: &Reg) -> &'ll Type288 fn reg_backend_type(&self, ty: &Reg) -> &'ll Type { 289 ty.llvm_type(self) 290 } 291 } 292