1 pub use crate::llvm
::Type
;
3 use crate::abi
::{FnAbiLlvmExt, LlvmType}
;
5 use crate::context
::CodegenCx
;
7 use crate::llvm
::{Bool, False, True}
;
8 use crate::type_of
::LayoutLlvmExt
;
9 use crate::value
::Value
;
11 use rustc_codegen_ssa
::common
::TypeKind
;
12 use rustc_codegen_ssa
::traits
::*;
13 use rustc_data_structures
::small_c_str
::SmallCStr
;
14 use rustc_middle
::bug
;
15 use rustc_middle
::ty
::layout
::TyAndLayout
;
16 use rustc_middle
::ty
::Ty
;
17 use rustc_target
::abi
::call
::{CastTarget, FnAbi, Reg}
;
18 use rustc_target
::abi
::{AddressSpace, Align, Integer, Size}
;
25 impl PartialEq
for Type
{
26 fn eq(&self, other
: &Self) -> bool
{
31 impl fmt
::Debug
for Type
{
32 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
34 &llvm
::build_string(|s
| unsafe {
35 llvm
::LLVMRustWriteTypeToString(self, s
);
37 .expect("non-UTF8 type description from LLVM"),
42 impl CodegenCx
<'ll
, 'tcx
> {
43 crate fn type_named_struct(&self, name
: &str) -> &'ll Type
{
44 let name
= SmallCStr
::new(name
);
45 unsafe { llvm::LLVMStructCreateNamed(self.llcx, name.as_ptr()) }
48 crate fn set_struct_body(&self, ty
: &'ll Type
, els
: &[&'ll Type
], packed
: bool
) {
49 unsafe { llvm::LLVMStructSetBody(ty, els.as_ptr(), els.len() as c_uint, packed as Bool) }
52 crate fn type_void(&self) -> &'ll Type
{
53 unsafe { llvm::LLVMVoidTypeInContext(self.llcx) }
56 crate fn type_metadata(&self) -> &'ll Type
{
57 unsafe { llvm::LLVMRustMetadataTypeInContext(self.llcx) }
60 ///x Creates an integer type with the given number of bits, e.g., i24
61 crate fn type_ix(&self, num_bits
: u64) -> &'ll Type
{
62 unsafe { llvm::LLVMIntTypeInContext(self.llcx, num_bits as c_uint) }
65 crate fn type_x86_mmx(&self) -> &'ll Type
{
66 unsafe { llvm::LLVMX86MMXTypeInContext(self.llcx) }
69 crate fn type_vector(&self, ty
: &'ll Type
, len
: u64) -> &'ll Type
{
70 unsafe { llvm::LLVMVectorType(ty, len as c_uint) }
73 crate fn func_params_types(&self, ty
: &'ll Type
) -> Vec
<&'ll Type
> {
75 let n_args
= llvm
::LLVMCountParamTypes(ty
) as usize;
76 let mut args
= Vec
::with_capacity(n_args
);
77 llvm
::LLVMGetParamTypes(ty
, args
.as_mut_ptr());
83 crate fn type_bool(&self) -> &'ll Type
{
87 crate fn type_int_from_ty(&self, t
: ast
::IntTy
) -> &'ll Type
{
89 ast
::IntTy
::Isize
=> self.type_isize(),
90 ast
::IntTy
::I8
=> self.type_i8(),
91 ast
::IntTy
::I16
=> self.type_i16(),
92 ast
::IntTy
::I32
=> self.type_i32(),
93 ast
::IntTy
::I64
=> self.type_i64(),
94 ast
::IntTy
::I128
=> self.type_i128(),
98 crate fn type_uint_from_ty(&self, t
: ast
::UintTy
) -> &'ll Type
{
100 ast
::UintTy
::Usize
=> self.type_isize(),
101 ast
::UintTy
::U8
=> self.type_i8(),
102 ast
::UintTy
::U16
=> self.type_i16(),
103 ast
::UintTy
::U32
=> self.type_i32(),
104 ast
::UintTy
::U64
=> self.type_i64(),
105 ast
::UintTy
::U128
=> self.type_i128(),
109 crate fn type_float_from_ty(&self, t
: ast
::FloatTy
) -> &'ll Type
{
111 ast
::FloatTy
::F32
=> self.type_f32(),
112 ast
::FloatTy
::F64
=> self.type_f64(),
116 crate fn type_pointee_for_align(&self, align
: Align
) -> &'ll Type
{
117 // FIXME(eddyb) We could find a better approximation if ity.align < align.
118 let ity
= Integer
::approximate_align(self, align
);
119 self.type_from_integer(ity
)
122 /// Return a LLVM type that has at most the required alignment,
123 /// and exactly the required size, as a best-effort padding array.
124 crate fn type_padding_filler(&self, size
: Size
, align
: Align
) -> &'ll Type
{
125 let unit
= Integer
::approximate_align(self, align
);
126 let size
= size
.bytes();
127 let unit_size
= unit
.size().bytes();
128 assert_eq
!(size
% unit_size
, 0);
129 self.type_array(self.type_from_integer(unit
), size
/ unit_size
)
132 crate fn type_variadic_func(&self, args
: &[&'ll Type
], ret
: &'ll Type
) -> &'ll Type
{
133 unsafe { llvm::LLVMFunctionType(ret, args.as_ptr(), args.len() as c_uint, True) }
136 crate fn type_array(&self, ty
: &'ll Type
, len
: u64) -> &'ll Type
{
137 unsafe { llvm::LLVMRustArrayType(ty, len) }
141 impl BaseTypeMethods
<'tcx
> for CodegenCx
<'ll
, 'tcx
> {
142 fn type_i1(&self) -> &'ll Type
{
143 unsafe { llvm::LLVMInt1TypeInContext(self.llcx) }
146 fn type_i8(&self) -> &'ll Type
{
147 unsafe { llvm::LLVMInt8TypeInContext(self.llcx) }
150 fn type_i16(&self) -> &'ll Type
{
151 unsafe { llvm::LLVMInt16TypeInContext(self.llcx) }
154 fn type_i32(&self) -> &'ll Type
{
155 unsafe { llvm::LLVMInt32TypeInContext(self.llcx) }
158 fn type_i64(&self) -> &'ll Type
{
159 unsafe { llvm::LLVMInt64TypeInContext(self.llcx) }
162 fn type_i128(&self) -> &'ll Type
{
163 unsafe { llvm::LLVMIntTypeInContext(self.llcx, 128) }
166 fn type_isize(&self) -> &'ll Type
{
170 fn type_f32(&self) -> &'ll Type
{
171 unsafe { llvm::LLVMFloatTypeInContext(self.llcx) }
174 fn type_f64(&self) -> &'ll Type
{
175 unsafe { llvm::LLVMDoubleTypeInContext(self.llcx) }
178 fn type_func(&self, args
: &[&'ll Type
], ret
: &'ll Type
) -> &'ll Type
{
179 unsafe { llvm::LLVMFunctionType(ret, args.as_ptr(), args.len() as c_uint, False) }
182 fn type_struct(&self, els
: &[&'ll Type
], packed
: bool
) -> &'ll Type
{
184 llvm
::LLVMStructTypeInContext(
193 fn type_kind(&self, ty
: &'ll Type
) -> TypeKind
{
194 unsafe { llvm::LLVMRustGetTypeKind(ty).to_generic() }
197 fn type_ptr_to(&self, ty
: &'ll Type
) -> &'ll Type
{
201 "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"
203 ty
.ptr_to(AddressSpace
::DATA
)
206 fn type_ptr_to_ext(&self, ty
: &'ll Type
, address_space
: AddressSpace
) -> &'ll Type
{
207 ty
.ptr_to(address_space
)
210 fn element_type(&self, ty
: &'ll Type
) -> &'ll Type
{
211 unsafe { llvm::LLVMGetElementType(ty) }
214 fn vector_length(&self, ty
: &'ll Type
) -> usize {
215 unsafe { llvm::LLVMGetVectorSize(ty) as usize }
218 fn float_width(&self, ty
: &'ll Type
) -> usize {
219 match self.type_kind(ty
) {
220 TypeKind
::Float
=> 32,
221 TypeKind
::Double
=> 64,
222 TypeKind
::X86_FP80
=> 80,
223 TypeKind
::FP128
| TypeKind
::PPC_FP128
=> 128,
224 _
=> bug
!("llvm_float_width called on a non-float type"),
228 fn int_width(&self, ty
: &'ll Type
) -> u64 {
229 unsafe { llvm::LLVMGetIntTypeWidth(ty) as u64 }
232 fn val_ty(&self, v
: &'ll Value
) -> &'ll Type
{
238 pub fn i8_llcx(llcx
: &llvm
::Context
) -> &Type
{
239 unsafe { llvm::LLVMInt8TypeInContext(llcx) }
242 // Creates an integer type with the given number of bits, e.g., i24
243 pub fn ix_llcx(llcx
: &llvm
::Context
, num_bits
: u64) -> &Type
{
244 unsafe { llvm::LLVMIntTypeInContext(llcx, num_bits as c_uint) }
247 pub fn i8p_llcx(llcx
: &llvm
::Context
) -> &Type
{
248 Type
::i8_llcx(llcx
).ptr_to(AddressSpace
::DATA
)
251 fn ptr_to(&self, address_space
: AddressSpace
) -> &Type
{
252 unsafe { llvm::LLVMPointerType(&self, address_space.0) }
256 impl LayoutTypeMethods
<'tcx
> for CodegenCx
<'ll
, 'tcx
> {
257 fn backend_type(&self, layout
: TyAndLayout
<'tcx
>) -> &'ll Type
{
258 layout
.llvm_type(self)
260 fn immediate_backend_type(&self, layout
: TyAndLayout
<'tcx
>) -> &'ll Type
{
261 layout
.immediate_llvm_type(self)
263 fn is_backend_immediate(&self, layout
: TyAndLayout
<'tcx
>) -> bool
{
264 layout
.is_llvm_immediate()
266 fn is_backend_scalar_pair(&self, layout
: TyAndLayout
<'tcx
>) -> bool
{
267 layout
.is_llvm_scalar_pair()
269 fn backend_field_index(&self, layout
: TyAndLayout
<'tcx
>, index
: usize) -> u64 {
270 layout
.llvm_field_index(index
)
272 fn scalar_pair_element_backend_type(
274 layout
: TyAndLayout
<'tcx
>,
278 layout
.scalar_pair_element_llvm_type(self, index
, immediate
)
280 fn cast_backend_type(&self, ty
: &CastTarget
) -> &'ll Type
{
283 fn fn_ptr_backend_type(&self, fn_abi
: &FnAbi
<'tcx
, Ty
<'tcx
>>) -> &'ll Type
{
284 fn_abi
.ptr_to_llvm_type(self)
286 fn reg_backend_type(&self, ty
: &Reg
) -> &'ll Type
{