]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc_codegen_llvm/type_.rs
rustc_codegen_llvm: use safe references for Type.
[rust.git] / src / librustc_codegen_llvm / type_.rs
index cb77ce0039756020d941ab60efda17a81b1cfce0..4e3a82f0d74e5e3652cd68c5192134ac6e8fbde0 100644 (file)
 
 #![allow(non_upper_case_globals)]
 
+pub use llvm::Type;
+
 use llvm;
-use llvm::{TypeRef, Bool, False, True, TypeKind};
+use llvm::{Bool, False, True, TypeKind};
 use llvm::{Float, Double, X86_FP80, PPC_FP128, FP128};
 
 use context::CodegenCx;
 
 use std::ffi::CString;
 use std::fmt;
-use std::mem;
 
 use libc::c_uint;
 
-#[derive(Clone, Copy, PartialEq)]
-#[repr(C)]
-pub struct Type {
-    rf: TypeRef
+impl PartialEq for Type {
+    fn eq(&self, other: &Self) -> bool {
+        self as *const _ == other as *const _
+    }
 }
 
 impl fmt::Debug for Type {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         f.write_str(&llvm::build_string(|s| unsafe {
-            llvm::LLVMRustWriteTypeToString(self.to_ref(), s);
+            llvm::LLVMRustWriteTypeToString(self, s);
         }).expect("non-UTF8 type description from LLVM"))
     }
 }
 
-macro_rules! ty {
-    ($e:expr) => ( Type::from_ref(unsafe { $e }))
-}
-
-/// Wrapper for LLVM TypeRef
 impl Type {
-    #[inline(always)]
-    pub fn from_ref(r: TypeRef) -> Type {
-        Type {
-            rf: r
+    pub fn void(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
+        unsafe {
+            llvm::LLVMVoidTypeInContext(cx.llcx)
         }
     }
 
-    #[inline(always)] // So it doesn't kill --opt-level=0 builds of the compiler
-    pub fn to_ref(&self) -> TypeRef {
-        self.rf
-    }
-
-    pub fn to_ref_slice(slice: &[Type]) -> &[TypeRef] {
-        unsafe { mem::transmute(slice) }
-    }
-
-    pub fn void(cx: &CodegenCx) -> Type {
-        ty!(llvm::LLVMVoidTypeInContext(cx.llcx))
-    }
-
-    pub fn metadata(cx: &CodegenCx) -> Type {
-        ty!(llvm::LLVMRustMetadataTypeInContext(cx.llcx))
+    pub fn metadata(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
+        unsafe {
+            llvm::LLVMRustMetadataTypeInContext(cx.llcx)
+        }
     }
 
-    pub fn i1(cx: &CodegenCx) -> Type {
-        ty!(llvm::LLVMInt1TypeInContext(cx.llcx))
+    pub fn i1(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
+        unsafe {
+            llvm::LLVMInt1TypeInContext(cx.llcx)
+        }
     }
 
-    pub fn i8(cx: &CodegenCx) -> Type {
-        ty!(llvm::LLVMInt8TypeInContext(cx.llcx))
+    pub fn i8(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
+        unsafe {
+            llvm::LLVMInt8TypeInContext(cx.llcx)
+        }
     }
 
-    pub fn i8_llcx(llcx: &llvm::Context) -> Type {
-        ty!(llvm::LLVMInt8TypeInContext(llcx))
+    pub fn i8_llcx(llcx: &llvm::Context) -> &Type {
+        unsafe {
+            llvm::LLVMInt8TypeInContext(llcx)
+        }
     }
 
-    pub fn i16(cx: &CodegenCx) -> Type {
-        ty!(llvm::LLVMInt16TypeInContext(cx.llcx))
+    pub fn i16(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
+        unsafe {
+            llvm::LLVMInt16TypeInContext(cx.llcx)
+        }
     }
 
-    pub fn i32(cx: &CodegenCx) -> Type {
-        ty!(llvm::LLVMInt32TypeInContext(cx.llcx))
+    pub fn i32(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
+        unsafe {
+            llvm::LLVMInt32TypeInContext(cx.llcx)
+        }
     }
 
-    pub fn i64(cx: &CodegenCx) -> Type {
-        ty!(llvm::LLVMInt64TypeInContext(cx.llcx))
+    pub fn i64(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
+        unsafe {
+            llvm::LLVMInt64TypeInContext(cx.llcx)
+        }
     }
 
-    pub fn i128(cx: &CodegenCx) -> Type {
-        ty!(llvm::LLVMIntTypeInContext(cx.llcx, 128))
+    pub fn i128(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
+        unsafe {
+            llvm::LLVMIntTypeInContext(cx.llcx, 128)
+        }
     }
 
     // Creates an integer type with the given number of bits, e.g. i24
-    pub fn ix(cx: &CodegenCx, num_bits: u64) -> Type {
-        ty!(llvm::LLVMIntTypeInContext(cx.llcx, num_bits as c_uint))
+    pub fn ix(cx: &CodegenCx<'ll, '_>, num_bits: u64) -> &'ll Type {
+        unsafe {
+            llvm::LLVMIntTypeInContext(cx.llcx, num_bits as c_uint)
+        }
     }
 
     // Creates an integer type with the given number of bits, e.g. i24
-    pub fn ix_llcx(llcx: &llvm::Context, num_bits: u64) -> Type {
-        ty!(llvm::LLVMIntTypeInContext(llcx, num_bits as c_uint))
+    pub fn ix_llcx(llcx: &llvm::Context, num_bits: u64) -> &Type {
+        unsafe {
+            llvm::LLVMIntTypeInContext(llcx, num_bits as c_uint)
+        }
     }
 
-    pub fn f32(cx: &CodegenCx) -> Type {
-        ty!(llvm::LLVMFloatTypeInContext(cx.llcx))
+    pub fn f32(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
+        unsafe {
+            llvm::LLVMFloatTypeInContext(cx.llcx)
+        }
     }
 
-    pub fn f64(cx: &CodegenCx) -> Type {
-        ty!(llvm::LLVMDoubleTypeInContext(cx.llcx))
+    pub fn f64(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
+        unsafe {
+            llvm::LLVMDoubleTypeInContext(cx.llcx)
+        }
     }
 
-    pub fn bool(cx: &CodegenCx) -> Type {
+    pub fn bool(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
         Type::i8(cx)
     }
 
-    pub fn char(cx: &CodegenCx) -> Type {
+    pub fn char(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
         Type::i32(cx)
     }
 
-    pub fn i8p(cx: &CodegenCx) -> Type {
+    pub fn i8p(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
         Type::i8(cx).ptr_to()
     }
 
-    pub fn i8p_llcx(llcx: &llvm::Context) -> Type {
+    pub fn i8p_llcx(llcx: &llvm::Context) -> &Type {
         Type::i8_llcx(llcx).ptr_to()
     }
 
-    pub fn isize(cx: &CodegenCx) -> Type {
+    pub fn isize(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
         cx.isize_ty
     }
 
-    pub fn c_int(cx: &CodegenCx) -> Type {
+    pub fn c_int(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
         match &cx.tcx.sess.target.target.target_c_int_width[..] {
             "16" => Type::i16(cx),
             "32" => Type::i32(cx),
@@ -144,7 +150,7 @@ pub fn c_int(cx: &CodegenCx) -> Type {
         }
     }
 
-    pub fn int_from_ty(cx: &CodegenCx, t: ast::IntTy) -> Type {
+    pub fn int_from_ty(cx: &CodegenCx<'ll, '_>, t: ast::IntTy) -> &'ll Type {
         match t {
             ast::IntTy::Isize => cx.isize_ty,
             ast::IntTy::I8 => Type::i8(cx),
@@ -155,7 +161,7 @@ pub fn int_from_ty(cx: &CodegenCx, t: ast::IntTy) -> Type {
         }
     }
 
-    pub fn uint_from_ty(cx: &CodegenCx, t: ast::UintTy) -> Type {
+    pub fn uint_from_ty(cx: &CodegenCx<'ll, '_>, t: ast::UintTy) -> &'ll Type {
         match t {
             ast::UintTy::Usize => cx.isize_ty,
             ast::UintTy::U8 => Type::i8(cx),
@@ -166,83 +172,93 @@ pub fn uint_from_ty(cx: &CodegenCx, t: ast::UintTy) -> Type {
         }
     }
 
-    pub fn float_from_ty(cx: &CodegenCx, t: ast::FloatTy) -> Type {
+    pub fn float_from_ty(cx: &CodegenCx<'ll, '_>, t: ast::FloatTy) -> &'ll Type {
         match t {
             ast::FloatTy::F32 => Type::f32(cx),
             ast::FloatTy::F64 => Type::f64(cx),
         }
     }
 
-    pub fn func(args: &[Type], ret: &Type) -> Type {
-        let slice: &[TypeRef] = Type::to_ref_slice(args);
-        ty!(llvm::LLVMFunctionType(ret.to_ref(), slice.as_ptr(),
-                                   args.len() as c_uint, False))
+    pub fn func(args: &[&'ll Type], ret: &'ll Type) -> &'ll Type {
+        unsafe {
+            llvm::LLVMFunctionType(ret, args.as_ptr(),
+                                   args.len() as c_uint, False)
+        }
     }
 
-    pub fn variadic_func(args: &[Type], ret: &Type) -> Type {
-        let slice: &[TypeRef] = Type::to_ref_slice(args);
-        ty!(llvm::LLVMFunctionType(ret.to_ref(), slice.as_ptr(),
-                                   args.len() as c_uint, True))
+    pub fn variadic_func(args: &[&'ll Type], ret: &'ll Type) -> &'ll Type {
+        unsafe {
+            llvm::LLVMFunctionType(ret, args.as_ptr(),
+                                   args.len() as c_uint, True)
+        }
     }
 
-    pub fn struct_(cx: &CodegenCx, els: &[Type], packed: bool) -> Type {
-        let els: &[TypeRef] = Type::to_ref_slice(els);
-        ty!(llvm::LLVMStructTypeInContext(cx.llcx, els.as_ptr(),
+    pub fn struct_(cx: &CodegenCx<'ll, '_>, els: &[&'ll Type], packed: bool) -> &'ll Type {
+        unsafe {
+            llvm::LLVMStructTypeInContext(cx.llcx, els.as_ptr(),
                                           els.len() as c_uint,
-                                          packed as Bool))
+                                          packed as Bool)
+        }
     }
 
-    pub fn named_struct(cx: &CodegenCx, name: &str) -> Type {
+    pub fn named_struct(cx: &CodegenCx<'ll, '_>, name: &str) -> &'ll Type {
         let name = CString::new(name).unwrap();
-        ty!(llvm::LLVMStructCreateNamed(cx.llcx, name.as_ptr()))
+        unsafe {
+            llvm::LLVMStructCreateNamed(cx.llcx, name.as_ptr())
+        }
     }
 
 
-    pub fn array(ty: &Type, len: u64) -> Type {
-        ty!(llvm::LLVMRustArrayType(ty.to_ref(), len))
+    pub fn array(ty: &Type, len: u64) -> &Type {
+        unsafe {
+            llvm::LLVMRustArrayType(ty, len)
+        }
     }
 
-    pub fn vector(ty: &Type, len: u64) -> Type {
-        ty!(llvm::LLVMVectorType(ty.to_ref(), len as c_uint))
+    pub fn vector(ty: &Type, len: u64) -> &Type {
+        unsafe {
+            llvm::LLVMVectorType(ty, len as c_uint)
+        }
     }
 
     pub fn kind(&self) -> TypeKind {
         unsafe {
-            llvm::LLVMRustGetTypeKind(self.to_ref())
+            llvm::LLVMRustGetTypeKind(self)
         }
     }
 
-    pub fn set_struct_body(&mut self, els: &[Type], packed: bool) {
-        let slice: &[TypeRef] = Type::to_ref_slice(els);
+    pub fn set_struct_body(&'ll self, els: &[&'ll Type], packed: bool) {
         unsafe {
-            llvm::LLVMStructSetBody(self.to_ref(), slice.as_ptr(),
+            llvm::LLVMStructSetBody(self, els.as_ptr(),
                                     els.len() as c_uint, packed as Bool)
         }
     }
 
-    pub fn ptr_to(&self) -> Type {
-        ty!(llvm::LLVMPointerType(self.to_ref(), 0))
+    pub fn ptr_to(&self) -> &Type {
+        unsafe {
+            llvm::LLVMPointerType(self, 0)
+        }
     }
 
-    pub fn element_type(&self) -> Type {
+    pub fn element_type(&self) -> &Type {
         unsafe {
-            Type::from_ref(llvm::LLVMGetElementType(self.to_ref()))
+            llvm::LLVMGetElementType(self)
         }
     }
 
     /// Return the number of elements in `self` if it is a LLVM vector type.
     pub fn vector_length(&self) -> usize {
         unsafe {
-            llvm::LLVMGetVectorSize(self.to_ref()) as usize
+            llvm::LLVMGetVectorSize(self) as usize
         }
     }
 
-    pub fn func_params(&self) -> Vec<Type> {
+    pub fn func_params(&self) -> Vec<&Type> {
         unsafe {
-            let n_args = llvm::LLVMCountParamTypes(self.to_ref()) as usize;
-            let mut args = vec![Type { rf: 0 as *mut _ }; n_args];
-            llvm::LLVMGetParamTypes(self.to_ref(),
-                                    args.as_mut_ptr() as *mut TypeRef);
+            let n_args = llvm::LLVMCountParamTypes(self) as usize;
+            let mut args = Vec::with_capacity(n_args);
+            llvm::LLVMGetParamTypes(self, args.as_mut_ptr());
+            args.set_len(n_args);
             args
         }
     }
@@ -260,11 +276,11 @@ pub fn float_width(&self) -> usize {
     /// Retrieve the bit width of the integer type `self`.
     pub fn int_width(&self) -> u64 {
         unsafe {
-            llvm::LLVMGetIntTypeWidth(self.to_ref()) as u64
+            llvm::LLVMGetIntTypeWidth(self) as u64
         }
     }
 
-    pub fn from_integer(cx: &CodegenCx, i: layout::Integer) -> Type {
+    pub fn from_integer(cx: &CodegenCx<'ll, '_>, i: layout::Integer) -> &'ll Type {
         use rustc::ty::layout::Integer::*;
         match i {
             I8 => Type::i8(cx),
@@ -277,7 +293,7 @@ pub fn from_integer(cx: &CodegenCx, i: layout::Integer) -> Type {
 
     /// Return a LLVM type that has at most the required alignment,
     /// as a conservative approximation for unknown pointee types.
-    pub fn pointee_for_abi_align(cx: &CodegenCx, align: Align) -> Type {
+    pub fn pointee_for_abi_align(cx: &CodegenCx<'ll, '_>, align: Align) -> &'ll Type {
         // FIXME(eddyb) We could find a better approximation if ity.align < align.
         let ity = layout::Integer::approximate_abi_align(cx, align);
         Type::from_integer(cx, ity)
@@ -285,15 +301,17 @@ pub fn pointee_for_abi_align(cx: &CodegenCx, align: Align) -> Type {
 
     /// Return a LLVM type that has at most the required alignment,
     /// and exactly the required size, as a best-effort padding array.
-    pub fn padding_filler(cx: &CodegenCx, size: Size, align: Align) -> Type {
+    pub fn padding_filler(cx: &CodegenCx<'ll, '_>, size: Size, align: Align) -> &'ll Type {
         let unit = layout::Integer::approximate_abi_align(cx, align);
         let size = size.bytes();
         let unit_size = unit.size().bytes();
         assert_eq!(size % unit_size, 0);
-        Type::array(&Type::from_integer(cx, unit), size / unit_size)
+        Type::array(Type::from_integer(cx, unit), size / unit_size)
     }
 
-    pub fn x86_mmx(cx: &CodegenCx) -> Type {
-        ty!(llvm::LLVMX86MMXTypeInContext(cx.llcx))
+    pub fn x86_mmx(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
+        unsafe {
+            llvm::LLVMX86MMXTypeInContext(cx.llcx)
+        }
     }
 }