diff --git a/src/librustc_codegen_llvm/type_.rs b/src/librustc_codegen_llvm/type_.rs index e22177ce31d5b..53151fef5096d 100644 --- a/src/librustc_codegen_llvm/type_.rs +++ b/src/librustc_codegen_llvm/type_.rs @@ -18,16 +18,12 @@ use context::CodegenCx; use rustc_codegen_ssa::interfaces::*; use value::Value; - -use syntax::ast; -use rustc::ty::layout::{self, Align, Size, HasTyCtxt}; use rustc::util::nodemap::FxHashMap; -use rustc::ty::{self, Ty}; +use rustc::ty::Ty; use rustc::ty::layout::TyLayout; use rustc_target::abi::call::{CastTarget, FnType, Reg}; use rustc_data_structures::small_c_str::SmallCStr; use common; -use rustc_codegen_ssa; use rustc_codegen_ssa::common::TypeKind; use type_of::LayoutLlvmExt; use abi::{LlvmType, FnTypeExt}; @@ -108,6 +104,10 @@ impl BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> { } } + fn type_isize(&self) -> &'ll Type { + self.isize_ty + } + fn type_f32(&self) -> &'ll Type { unsafe { llvm::LLVMFloatTypeInContext(self.llcx) @@ -274,121 +274,6 @@ impl Type { } } -impl DerivedTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> { - fn type_bool(&self) -> &'ll Type { - self.type_i8() - } - - fn type_i8p(&self) -> &'ll Type { - self.type_ptr_to(self.type_i8()) - } - - fn type_isize(&self) -> &'ll Type { - self.isize_ty - } - - fn type_int(&self) -> &'ll Type { - match &self.sess().target.target.target_c_int_width[..] { - "16" => self.type_i16(), - "32" => self.type_i32(), - "64" => self.type_i64(), - width => bug!("Unsupported target_c_int_width: {}", width), - } - } - - fn type_int_from_ty( - &self, - t: ast::IntTy - ) -> &'ll Type { - match t { - ast::IntTy::Isize => self.isize_ty, - ast::IntTy::I8 => self.type_i8(), - ast::IntTy::I16 => self.type_i16(), - ast::IntTy::I32 => self.type_i32(), - ast::IntTy::I64 => self.type_i64(), - ast::IntTy::I128 => self.type_i128(), - } - } - - fn type_uint_from_ty( - &self, - t: ast::UintTy - ) -> &'ll Type { - match t { - ast::UintTy::Usize => self.isize_ty, - ast::UintTy::U8 => self.type_i8(), - ast::UintTy::U16 => self.type_i16(), - ast::UintTy::U32 => self.type_i32(), - ast::UintTy::U64 => self.type_i64(), - ast::UintTy::U128 => self.type_i128(), - } - } - - fn type_float_from_ty( - &self, - t: ast::FloatTy - ) -> &'ll Type { - match t { - ast::FloatTy::F32 => self.type_f32(), - ast::FloatTy::F64 => self.type_f64(), - } - } - - fn type_from_integer(&self, i: layout::Integer) -> &'ll Type { - use rustc::ty::layout::Integer::*; - match i { - I8 => self.type_i8(), - I16 => self.type_i16(), - I32 => self.type_i32(), - I64 => self.type_i64(), - I128 => self.type_i128(), - } - } - - fn type_pointee_for_abi_align(&self, align: Align) -> &'ll Type { - // FIXME(eddyb) We could find a better approximation if ity.align < align. - let ity = layout::Integer::approximate_abi_align(self, align); - self.type_from_integer(ity) - } - - fn type_padding_filler( - &self, - size: Size, - align: Align - ) -> &'ll Type { - let unit = layout::Integer::approximate_abi_align(self, align); - let size = size.bytes(); - let unit_size = unit.size().bytes(); - assert_eq!(size % unit_size, 0); - self.type_array(self.type_from_integer(unit), size / unit_size) - } - - fn type_needs_drop(&self, ty: Ty<'tcx>) -> bool { - rustc_codegen_ssa::common::type_needs_drop(self.tcx(), ty) - } - - fn type_is_sized(&self, ty: Ty<'tcx>) -> bool { - rustc_codegen_ssa::common::type_is_sized(self.tcx(), ty) - } - - fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool { - rustc_codegen_ssa::common::type_is_freeze(self.tcx(), ty) - } - - fn type_has_metadata(&self, ty: Ty<'tcx>) -> bool { - use syntax_pos::DUMMY_SP; - if ty.is_sized(self.tcx().at(DUMMY_SP), ty::ParamEnv::reveal_all()) { - return false; - } - - let tail = self.tcx().struct_tail(ty); - match tail.sty { - ty::Foreign(..) => false, - ty::Str | ty::Slice(..) | ty::Dynamic(..) => true, - _ => bug!("unexpected unsized tail: {:?}", tail.sty), - } - } -} impl LayoutTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> { fn backend_type(&self, layout: TyLayout<'tcx>) -> &'ll Type { diff --git a/src/librustc_codegen_ssa/interfaces/backend.rs b/src/librustc_codegen_ssa/interfaces/backend.rs index aeaedda0b88ed..6e8233bcb889d 100644 --- a/src/librustc_codegen_ssa/interfaces/backend.rs +++ b/src/librustc_codegen_ssa/interfaces/backend.rs @@ -35,7 +35,7 @@ pub trait BackendTypes { } pub trait Backend<'tcx>: - BackendTypes + HasTyCtxt<'tcx> + LayoutOf, TyLayout = TyLayout<'tcx>> + Sized + BackendTypes + HasTyCtxt<'tcx> + LayoutOf, TyLayout = TyLayout<'tcx>> { } diff --git a/src/librustc_codegen_ssa/interfaces/type_.rs b/src/librustc_codegen_ssa/interfaces/type_.rs index 6d87adb521e9f..1aa1f45f51746 100644 --- a/src/librustc_codegen_ssa/interfaces/type_.rs +++ b/src/librustc_codegen_ssa/interfaces/type_.rs @@ -8,13 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use super::misc::MiscMethods; use super::Backend; use super::HasCodegen; -use common::TypeKind; +use common::{self, TypeKind}; use mir::place::PlaceRef; -use rustc::ty::layout::TyLayout; -use rustc::ty::layout::{self, Align, Size}; -use rustc::ty::Ty; +use rustc::ty::layout::{self, Align, Size, TyLayout}; +use rustc::ty::{self, Ty}; use rustc::util::nodemap::FxHashMap; use rustc_target::abi::call::{ArgType, CastTarget, FnType, Reg}; use std::cell::RefCell; @@ -32,6 +32,7 @@ pub trait BaseTypeMethods<'tcx>: Backend<'tcx> { // Creates an integer type with the given number of bits, e.g. i24 fn type_ix(&self, num_bits: u64) -> Self::Type; + fn type_isize(&self) -> Self::Type; fn type_f32(&self) -> Self::Type; fn type_f64(&self) -> Self::Type; @@ -61,30 +62,109 @@ pub trait BaseTypeMethods<'tcx>: Backend<'tcx> { fn scalar_lltypes(&self) -> &RefCell, Self::Type>>; } -pub trait DerivedTypeMethods<'tcx>: Backend<'tcx> { - fn type_bool(&self) -> Self::Type; - fn type_i8p(&self) -> Self::Type; - fn type_isize(&self) -> Self::Type; - fn type_int(&self) -> Self::Type; - fn type_int_from_ty(&self, t: ast::IntTy) -> Self::Type; - fn type_uint_from_ty(&self, t: ast::UintTy) -> Self::Type; - fn type_float_from_ty(&self, t: ast::FloatTy) -> Self::Type; - fn type_from_integer(&self, i: layout::Integer) -> Self::Type; - - /// Return a LLVM type that has at most the required alignment, - /// as a conservative approximation for unknown pointee types. - fn type_pointee_for_abi_align(&self, align: Align) -> Self::Type; +pub trait DerivedTypeMethods<'tcx>: BaseTypeMethods<'tcx> + MiscMethods<'tcx> { + fn type_bool(&self) -> Self::Type { + self.type_i8() + } + + fn type_i8p(&self) -> Self::Type { + self.type_ptr_to(self.type_i8()) + } + + fn type_int(&self) -> Self::Type { + match &self.sess().target.target.target_c_int_width[..] { + "16" => self.type_i16(), + "32" => self.type_i32(), + "64" => self.type_i64(), + width => bug!("Unsupported target_c_int_width: {}", width), + } + } + + fn type_int_from_ty(&self, t: ast::IntTy) -> Self::Type { + match t { + ast::IntTy::Isize => self.type_isize(), + ast::IntTy::I8 => self.type_i8(), + ast::IntTy::I16 => self.type_i16(), + ast::IntTy::I32 => self.type_i32(), + ast::IntTy::I64 => self.type_i64(), + ast::IntTy::I128 => self.type_i128(), + } + } + + fn type_uint_from_ty(&self, t: ast::UintTy) -> Self::Type { + match t { + ast::UintTy::Usize => self.type_isize(), + ast::UintTy::U8 => self.type_i8(), + ast::UintTy::U16 => self.type_i16(), + ast::UintTy::U32 => self.type_i32(), + ast::UintTy::U64 => self.type_i64(), + ast::UintTy::U128 => self.type_i128(), + } + } + + fn type_float_from_ty(&self, t: ast::FloatTy) -> Self::Type { + match t { + ast::FloatTy::F32 => self.type_f32(), + ast::FloatTy::F64 => self.type_f64(), + } + } + + fn type_from_integer(&self, i: layout::Integer) -> Self::Type { + use rustc::ty::layout::Integer::*; + match i { + I8 => self.type_i8(), + I16 => self.type_i16(), + I32 => self.type_i32(), + I64 => self.type_i64(), + I128 => self.type_i128(), + } + } + + fn type_pointee_for_abi_align(&self, align: Align) -> Self::Type { + // FIXME(eddyb) We could find a better approximation if ity.align < align. + let ity = layout::Integer::approximate_abi_align(self, align); + self.type_from_integer(ity) + } /// Return a LLVM type that has at most the required alignment, /// and exactly the required size, as a best-effort padding array. - fn type_padding_filler(&self, size: Size, align: Align) -> Self::Type; - - fn type_needs_drop(&self, ty: Ty<'tcx>) -> bool; - fn type_is_sized(&self, ty: Ty<'tcx>) -> bool; - fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool; - fn type_has_metadata(&self, ty: Ty<'tcx>) -> bool; + fn type_padding_filler(&self, size: Size, align: Align) -> Self::Type { + let unit = layout::Integer::approximate_abi_align(self, align); + let size = size.bytes(); + let unit_size = unit.size().bytes(); + assert_eq!(size % unit_size, 0); + self.type_array(self.type_from_integer(unit), size / unit_size) + } + + fn type_needs_drop(&self, ty: Ty<'tcx>) -> bool { + common::type_needs_drop(self.tcx(), ty) + } + + fn type_is_sized(&self, ty: Ty<'tcx>) -> bool { + common::type_is_sized(self.tcx(), ty) + } + + fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool { + common::type_is_freeze(self.tcx(), ty) + } + + fn type_has_metadata(&self, ty: Ty<'tcx>) -> bool { + use syntax_pos::DUMMY_SP; + if ty.is_sized(self.tcx().at(DUMMY_SP), ty::ParamEnv::reveal_all()) { + return false; + } + + let tail = self.tcx().struct_tail(ty); + match tail.sty { + ty::Foreign(..) => false, + ty::Str | ty::Slice(..) | ty::Dynamic(..) => true, + _ => bug!("unexpected unsized tail: {:?}", tail.sty), + } + } } +impl DerivedTypeMethods<'tcx> for T where Self: BaseTypeMethods<'tcx> + MiscMethods<'tcx> {} + pub trait LayoutTypeMethods<'tcx>: Backend<'tcx> { fn backend_type(&self, layout: TyLayout<'tcx>) -> Self::Type; fn cast_backend_type(&self, ty: &CastTarget) -> Self::Type; @@ -119,11 +199,6 @@ pub trait ArgTypeMethods<'tcx>: HasCodegen<'tcx> { fn memory_ty(&self, ty: &ArgType<'tcx, Ty<'tcx>>) -> Self::Type; } -pub trait TypeMethods<'tcx>: - BaseTypeMethods<'tcx> + DerivedTypeMethods<'tcx> + LayoutTypeMethods<'tcx> -{ -} +pub trait TypeMethods<'tcx>: DerivedTypeMethods<'tcx> + LayoutTypeMethods<'tcx> {} -impl TypeMethods<'tcx> for T where - Self: BaseTypeMethods<'tcx> + DerivedTypeMethods<'tcx> + LayoutTypeMethods<'tcx> -{} +impl TypeMethods<'tcx> for T where Self: DerivedTypeMethods<'tcx> + LayoutTypeMethods<'tcx> {}