-use crate::abi::{FnType, FnTypeExt};
+use crate::abi::{FnAbi};
use crate::common::*;
use crate::type_::Type;
-use rustc::hir;
use rustc::ty::{self, Ty, TypeFoldable};
-use rustc::ty::layout::{self, Align, LayoutOf, Size, TyLayout};
-use rustc_target::abi::FloatTy;
-use rustc_mir::monomorphize::item::DefPathBasedNames;
+use rustc::ty::layout::{self, Align, LayoutOf, FnAbiExt, PointeeInfo, Size, TyLayout};
+use rustc_target::abi::TyLayoutMethods;
+use rustc::ty::print::obsolete::DefPathBasedNames;
use rustc_codegen_ssa::traits::*;
+use log::debug;
+use rustc::bug;
use std::fmt::Write;
layout::Abi::Aggregate { .. } => {}
}
- let name = match layout.ty.sty {
+ let name = match layout.ty.kind {
ty::Closure(..) |
ty::Generator(..) |
ty::Adt(..) |
let printer = DefPathBasedNames::new(cx.tcx, true, true);
printer.push_type_name(layout.ty, &mut name, false);
if let (&ty::Adt(def, _), &layout::Variants::Single { index })
- = (&layout.ty.sty, &layout.variants)
+ = (&layout.ty.kind, &layout.variants)
{
if def.is_enum() && !def.variants.is_empty() {
write!(&mut name, "::{}", def.variants[index].ident).unwrap();
}
}
+ if let (&ty::Generator(_, substs, _), &layout::Variants::Single { index })
+ = (&layout.ty.kind, &layout.variants)
+ {
+ write!(&mut name, "::{}", substs.as_generator().variant_name(index)).unwrap();
+ }
Some(name)
}
_ => None
}
}
-#[derive(Copy, Clone, PartialEq, Eq)]
-pub enum PointerKind {
- /// Most general case, we know no restrictions to tell LLVM.
- Shared,
-
- /// `&T` where `T` contains no `UnsafeCell`, is `noalias` and `readonly`.
- Frozen,
-
- /// `&mut T`, when we know `noalias` is safe for LLVM.
- UniqueBorrowed,
-
- /// `Box<T>`, unlike `UniqueBorrowed`, it also has `noalias` on returns.
- UniqueOwned
-}
-
-#[derive(Copy, Clone)]
-pub struct PointeeInfo {
- pub size: Size,
- pub align: Align,
- pub safe: Option<PointerKind>,
-}
-
pub trait LayoutLlvmExt<'tcx> {
fn is_llvm_immediate(&self) -> bool;
- fn is_llvm_scalar_pair<'a>(&self) -> bool;
+ fn is_llvm_scalar_pair(&self) -> bool;
fn llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type;
fn immediate_llvm_type<'a>(&self, cx: &CodegenCx<'a, 'tcx>) -> &'a Type;
fn scalar_llvm_type_at<'a>(&self, cx: &CodegenCx<'a, 'tcx>,
}
}
- fn is_llvm_scalar_pair<'a>(&self) -> bool {
+ fn is_llvm_scalar_pair(&self) -> bool {
match self.abi {
layout::Abi::ScalarPair(..) => true,
layout::Abi::Uninhabited |
if let Some(&llty) = cx.scalar_lltypes.borrow().get(&self.ty) {
return llty;
}
- let llty = match self.ty.sty {
+ let llty = match self.ty.kind {
ty::Ref(_, ty, _) |
ty::RawPtr(ty::TypeAndMut { ty, .. }) => {
cx.type_ptr_to(cx.layout_of(ty).llvm_type(cx))
cx.type_ptr_to(cx.layout_of(self.ty.boxed_ty()).llvm_type(cx))
}
ty::FnPtr(sig) => {
- let sig = cx.tcx.normalize_erasing_late_bound_regions(
- ty::ParamEnv::reveal_all(),
- &sig,
- );
- cx.fn_ptr_backend_type(&FnType::new(cx, sig, &[]))
+ cx.fn_ptr_backend_type(&FnAbi::of_fn_ptr(cx, sig, &[]))
}
_ => self.scalar_llvm_type_at(cx, scalar, Size::ZERO)
};
scalar: &layout::Scalar, offset: Size) -> &'a Type {
match scalar.value {
layout::Int(i, _) => cx.type_from_integer( i),
- layout::Float(FloatTy::F32) => cx.type_f32(),
- layout::Float(FloatTy::F64) => cx.type_f64(),
+ layout::F32 => cx.type_f32(),
+ layout::F64 => cx.type_f64(),
layout::Pointer => {
// If we know the alignment, pick something better than i8.
let pointee = if let Some(pointee) = self.pointee_info_at(cx, offset) {
index: usize, immediate: bool) -> &'a Type {
// HACK(eddyb) special-case fat pointers until LLVM removes
// pointee types, to avoid bitcasting every `OperandRef::deref`.
- match self.ty.sty {
+ match self.ty.kind {
ty::Ref(..) |
ty::RawPtr(_) => {
return self.field(cx, index).llvm_type(cx);
return pointee;
}
- let mut result = None;
- match self.ty.sty {
- ty::RawPtr(mt) if offset.bytes() == 0 => {
- let (size, align) = cx.size_and_align_of(mt.ty);
- result = Some(PointeeInfo {
- size,
- align,
- safe: None
- });
- }
-
- ty::Ref(_, ty, mt) if offset.bytes() == 0 => {
- let (size, align) = cx.size_and_align_of(ty);
-
- let kind = match mt {
- hir::MutImmutable => if cx.type_is_freeze(ty) {
- PointerKind::Frozen
- } else {
- PointerKind::Shared
- },
- hir::MutMutable => {
- // Previously we would only emit noalias annotations for LLVM >= 6 or in
- // panic=abort mode. That was deemed right, as prior versions had many bugs
- // in conjunction with unwinding, but later versions didn’t seem to have
- // said issues. See issue #31681.
- //
- // Alas, later on we encountered a case where noalias would generate wrong
- // code altogether even with recent versions of LLVM in *safe* code with no
- // unwinding involved. See #54462.
- //
- // For now, do not enable mutable_noalias by default at all, while the
- // issue is being figured out.
- let mutable_noalias = cx.tcx.sess.opts.debugging_opts.mutable_noalias
- .unwrap_or(false);
- if mutable_noalias {
- PointerKind::UniqueBorrowed
- } else {
- PointerKind::Shared
- }
- }
- };
-
- result = Some(PointeeInfo {
- size,
- align,
- safe: Some(kind)
- });
- }
-
- _ => {
- let mut data_variant = match self.variants {
- layout::Variants::NicheFilling { dataful_variant, .. } => {
- // Only the niche itself is always initialized,
- // so only check for a pointer at its offset.
- //
- // If the niche is a pointer, it's either valid
- // (according to its type), or null (which the
- // niche field's scalar validity range encodes).
- // This allows using `dereferenceable_or_null`
- // for e.g., `Option<&T>`, and this will continue
- // to work as long as we don't start using more
- // niches than just null (e.g., the first page
- // of the address space, or unaligned pointers).
- if self.fields.offset(0) == offset {
- Some(self.for_variant(cx, dataful_variant))
- } else {
- None
- }
- }
- _ => Some(*self)
- };
-
- if let Some(variant) = data_variant {
- // We're not interested in any unions.
- if let layout::FieldPlacement::Union(_) = variant.fields {
- data_variant = None;
- }
- }
-
- if let Some(variant) = data_variant {
- let ptr_end = offset + layout::Pointer.size(cx);
- for i in 0..variant.fields.count() {
- let field_start = variant.fields.offset(i);
- if field_start <= offset {
- let field = variant.field(cx, i);
- if ptr_end <= field_start + field.size {
- // We found the right field, look inside it.
- result = field.pointee_info_at(cx, offset - field_start);
- break;
- }
- }
- }
- }
-
- // FIXME(eddyb) This should be for `ptr::Unique<T>`, not `Box<T>`.
- if let Some(ref mut pointee) = result {
- if let ty::Adt(def, _) = self.ty.sty {
- if def.is_box() && offset.bytes() == 0 {
- pointee.safe = Some(PointerKind::UniqueOwned);
- }
- }
- }
- }
- }
+ let result = Ty::pointee_info_at(*self, cx, offset);
cx.pointee_infos.borrow_mut().insert((self.ty, offset), result);
result