1
Fork 0

Auto merge of #61305 - Centril:rollup-t39m00m, r=Centril

Rollup of 11 pull requests

Successful merges:

 - #58975 (Implement `iter::Sum` and `iter::Product` for `Option`)
 - #60542 (Add Step::sub_usize)
 - #60555 (Implement nth_back for RChunks(Exact)(Mut))
 - #60766 (Weak::into_raw)
 - #61048 (Feature/nth back chunks)
 - #61191 (librustc_errors: Move annotation collection to own impl)
 - #61235 (Stabilize bufreader_buffer feature)
 - #61249 (Rename Place::local to Place::local_or_deref_local)
 - #61291 (Avoid unneeded bug!() call)
 - #61294 (Rename `TraitOrImpl` to `Assoc` and `trait_or_impl` to `assoc`.)
 - #61297 (Remove LLVM instruction stats and other (obsolete) codegen stats.)

Failed merges:

r? @ghost
This commit is contained in:
bors 2019-05-29 07:50:16 +00:00
commit 81970852e1
29 changed files with 900 additions and 503 deletions

View file

@ -239,7 +239,7 @@ use core::fmt;
use core::hash::{Hash, Hasher}; use core::hash::{Hash, Hasher};
use core::intrinsics::abort; use core::intrinsics::abort;
use core::marker::{self, Unpin, Unsize, PhantomData}; use core::marker::{self, Unpin, Unsize, PhantomData};
use core::mem::{self, align_of_val, forget, size_of_val}; use core::mem::{self, align_of, align_of_val, forget, size_of_val};
use core::ops::{Deref, Receiver, CoerceUnsized, DispatchFromDyn}; use core::ops::{Deref, Receiver, CoerceUnsized, DispatchFromDyn};
use core::pin::Pin; use core::pin::Pin;
use core::ptr::{self, NonNull}; use core::ptr::{self, NonNull};
@ -416,11 +416,7 @@ impl<T: ?Sized> Rc<T> {
/// ``` /// ```
#[stable(feature = "rc_raw", since = "1.17.0")] #[stable(feature = "rc_raw", since = "1.17.0")]
pub unsafe fn from_raw(ptr: *const T) -> Self { pub unsafe fn from_raw(ptr: *const T) -> Self {
// Align the unsized value to the end of the RcBox. let offset = data_offset(ptr);
// Because it is ?Sized, it will always be the last field in memory.
let align = align_of_val(&*ptr);
let layout = Layout::new::<RcBox<()>>();
let offset = (layout.size() + layout.padding_needed_for(align)) as isize;
// Reverse the offset to find the original RcBox. // Reverse the offset to find the original RcBox.
let fake_ptr = ptr as *mut RcBox<T>; let fake_ptr = ptr as *mut RcBox<T>;
@ -1262,6 +1258,143 @@ impl<T> Weak<T> {
ptr: NonNull::new(usize::MAX as *mut RcBox<T>).expect("MAX is not 0"), ptr: NonNull::new(usize::MAX as *mut RcBox<T>).expect("MAX is not 0"),
} }
} }
/// Returns a raw pointer to the object `T` pointed to by this `Weak<T>`.
///
/// It is up to the caller to ensure that the object is still alive when accessing it through
/// the pointer.
///
/// The pointer may be [`null`] or be dangling in case the object has already been destroyed.
///
/// # Examples
///
/// ```
/// #![feature(weak_into_raw)]
///
/// use std::rc::{Rc, Weak};
/// use std::ptr;
///
/// let strong = Rc::new(42);
/// let weak = Rc::downgrade(&strong);
/// // Both point to the same object
/// assert!(ptr::eq(&*strong, Weak::as_raw(&weak)));
/// // The strong here keeps it alive, so we can still access the object.
/// assert_eq!(42, unsafe { *Weak::as_raw(&weak) });
///
/// drop(strong);
/// // But not any more. We can do Weak::as_raw(&weak), but accessing the pointer would lead to
/// // undefined behaviour.
/// // assert_eq!(42, unsafe { *Weak::as_raw(&weak) });
/// ```
///
/// [`null`]: ../../std/ptr/fn.null.html
#[unstable(feature = "weak_into_raw", issue = "60728")]
pub fn as_raw(this: &Self) -> *const T {
match this.inner() {
None => ptr::null(),
Some(inner) => {
let offset = data_offset_sized::<T>();
let ptr = inner as *const RcBox<T>;
// Note: while the pointer we create may already point to dropped value, the
// allocation still lives (it must hold the weak point as long as we are alive).
// Therefore, the offset is OK to do, it won't get out of the allocation.
let ptr = unsafe { (ptr as *const u8).offset(offset) };
ptr as *const T
}
}
}
/// Consumes the `Weak<T>` and turns it into a raw pointer.
///
/// This converts the weak pointer into a raw pointer, preserving the original weak count. It
/// can be turned back into the `Weak<T>` with [`from_raw`].
///
/// The same restrictions of accessing the target of the pointer as with
/// [`as_raw`] apply.
///
/// # Examples
///
/// ```
/// #![feature(weak_into_raw)]
///
/// use std::rc::{Rc, Weak};
///
/// let strong = Rc::new(42);
/// let weak = Rc::downgrade(&strong);
/// let raw = Weak::into_raw(weak);
///
/// assert_eq!(1, Rc::weak_count(&strong));
/// assert_eq!(42, unsafe { *raw });
///
/// drop(unsafe { Weak::from_raw(raw) });
/// assert_eq!(0, Rc::weak_count(&strong));
/// ```
///
/// [`from_raw`]: struct.Weak.html#method.from_raw
/// [`as_raw`]: struct.Weak.html#method.as_raw
#[unstable(feature = "weak_into_raw", issue = "60728")]
pub fn into_raw(this: Self) -> *const T {
let result = Self::as_raw(&this);
mem::forget(this);
result
}
/// Converts a raw pointer previously created by [`into_raw`] back into `Weak<T>`.
///
/// This can be used to safely get a strong reference (by calling [`upgrade`]
/// later) or to deallocate the weak count by dropping the `Weak<T>`.
///
/// It takes ownership of one weak count. In case a [`null`] is passed, a dangling [`Weak`] is
/// returned.
///
/// # Safety
///
/// The pointer must represent one valid weak count. In other words, it must point to `T` which
/// is or *was* managed by an [`Rc`] and the weak count of that [`Rc`] must not have reached
/// 0. It is allowed for the strong count to be 0.
///
/// # Examples
///
/// ```
/// #![feature(weak_into_raw)]
///
/// use std::rc::{Rc, Weak};
///
/// let strong = Rc::new(42);
///
/// let raw_1 = Weak::into_raw(Rc::downgrade(&strong));
/// let raw_2 = Weak::into_raw(Rc::downgrade(&strong));
///
/// assert_eq!(2, Rc::weak_count(&strong));
///
/// assert_eq!(42, *Weak::upgrade(&unsafe { Weak::from_raw(raw_1) }).unwrap());
/// assert_eq!(1, Rc::weak_count(&strong));
///
/// drop(strong);
///
/// // Decrement the last weak count.
/// assert!(Weak::upgrade(&unsafe { Weak::from_raw(raw_2) }).is_none());
/// ```
///
/// [`null`]: ../../std/ptr/fn.null.html
/// [`into_raw`]: struct.Weak.html#method.into_raw
/// [`upgrade`]: struct.Weak.html#method.upgrade
/// [`Rc`]: struct.Rc.html
/// [`Weak`]: struct.Weak.html
#[unstable(feature = "weak_into_raw", issue = "60728")]
pub unsafe fn from_raw(ptr: *const T) -> Self {
if ptr.is_null() {
Self::new()
} else {
// See Rc::from_raw for details
let offset = data_offset(ptr);
let fake_ptr = ptr as *mut RcBox<T>;
let ptr = set_data_ptr(fake_ptr, (ptr as *mut u8).offset(-offset));
Weak {
ptr: NonNull::new(ptr).expect("Invalid pointer passed to from_raw"),
}
}
}
} }
pub(crate) fn is_dangling<T: ?Sized>(ptr: NonNull<T>) -> bool { pub(crate) fn is_dangling<T: ?Sized>(ptr: NonNull<T>) -> bool {
@ -2007,3 +2140,20 @@ impl<T: ?Sized> AsRef<T> for Rc<T> {
#[stable(feature = "pin", since = "1.33.0")] #[stable(feature = "pin", since = "1.33.0")]
impl<T: ?Sized> Unpin for Rc<T> { } impl<T: ?Sized> Unpin for Rc<T> { }
unsafe fn data_offset<T: ?Sized>(ptr: *const T) -> isize {
// Align the unsized value to the end of the RcBox.
// Because it is ?Sized, it will always be the last field in memory.
let align = align_of_val(&*ptr);
let layout = Layout::new::<RcBox<()>>();
(layout.size() + layout.padding_needed_for(align)) as isize
}
/// Computes the offset of the data field within ArcInner.
///
/// Unlike [`data_offset`], this doesn't need the pointer, but it works only on `T: Sized`.
fn data_offset_sized<T>() -> isize {
let align = align_of::<T>();
let layout = Layout::new::<RcBox<()>>();
(layout.size() + layout.padding_needed_for(align)) as isize
}

View file

@ -13,7 +13,7 @@ use core::borrow;
use core::fmt; use core::fmt;
use core::cmp::{self, Ordering}; use core::cmp::{self, Ordering};
use core::intrinsics::abort; use core::intrinsics::abort;
use core::mem::{self, align_of_val, size_of_val}; use core::mem::{self, align_of, align_of_val, size_of_val};
use core::ops::{Deref, Receiver, CoerceUnsized, DispatchFromDyn}; use core::ops::{Deref, Receiver, CoerceUnsized, DispatchFromDyn};
use core::pin::Pin; use core::pin::Pin;
use core::ptr::{self, NonNull}; use core::ptr::{self, NonNull};
@ -397,11 +397,7 @@ impl<T: ?Sized> Arc<T> {
/// ``` /// ```
#[stable(feature = "rc_raw", since = "1.17.0")] #[stable(feature = "rc_raw", since = "1.17.0")]
pub unsafe fn from_raw(ptr: *const T) -> Self { pub unsafe fn from_raw(ptr: *const T) -> Self {
// Align the unsized value to the end of the ArcInner. let offset = data_offset(ptr);
// Because it is ?Sized, it will always be the last field in memory.
let align = align_of_val(&*ptr);
let layout = Layout::new::<ArcInner<()>>();
let offset = (layout.size() + layout.padding_needed_for(align)) as isize;
// Reverse the offset to find the original ArcInner. // Reverse the offset to find the original ArcInner.
let fake_ptr = ptr as *mut ArcInner<T>; let fake_ptr = ptr as *mut ArcInner<T>;
@ -1071,6 +1067,144 @@ impl<T> Weak<T> {
ptr: NonNull::new(usize::MAX as *mut ArcInner<T>).expect("MAX is not 0"), ptr: NonNull::new(usize::MAX as *mut ArcInner<T>).expect("MAX is not 0"),
} }
} }
/// Returns a raw pointer to the object `T` pointed to by this `Weak<T>`.
///
/// It is up to the caller to ensure that the object is still alive when accessing it through
/// the pointer.
///
/// The pointer may be [`null`] or be dangling in case the object has already been destroyed.
///
/// # Examples
///
/// ```
/// #![feature(weak_into_raw)]
///
/// use std::sync::{Arc, Weak};
/// use std::ptr;
///
/// let strong = Arc::new(42);
/// let weak = Arc::downgrade(&strong);
/// // Both point to the same object
/// assert!(ptr::eq(&*strong, Weak::as_raw(&weak)));
/// // The strong here keeps it alive, so we can still access the object.
/// assert_eq!(42, unsafe { *Weak::as_raw(&weak) });
///
/// drop(strong);
/// // But not any more. We can do Weak::as_raw(&weak), but accessing the pointer would lead to
/// // undefined behaviour.
/// // assert_eq!(42, unsafe { *Weak::as_raw(&weak) });
/// ```
///
/// [`null`]: ../../std/ptr/fn.null.html
#[unstable(feature = "weak_into_raw", issue = "60728")]
pub fn as_raw(this: &Self) -> *const T {
match this.inner() {
None => ptr::null(),
Some(inner) => {
let offset = data_offset_sized::<T>();
let ptr = inner as *const ArcInner<T>;
// Note: while the pointer we create may already point to dropped value, the
// allocation still lives (it must hold the weak point as long as we are alive).
// Therefore, the offset is OK to do, it won't get out of the allocation.
let ptr = unsafe { (ptr as *const u8).offset(offset) };
ptr as *const T
}
}
}
/// Consumes the `Weak<T>` and turns it into a raw pointer.
///
/// This converts the weak pointer into a raw pointer, preserving the original weak count. It
/// can be turned back into the `Weak<T>` with [`from_raw`].
///
/// The same restrictions of accessing the target of the pointer as with
/// [`as_raw`] apply.
///
/// # Examples
///
/// ```
/// #![feature(weak_into_raw)]
///
/// use std::sync::{Arc, Weak};
///
/// let strong = Arc::new(42);
/// let weak = Arc::downgrade(&strong);
/// let raw = Weak::into_raw(weak);
///
/// assert_eq!(1, Arc::weak_count(&strong));
/// assert_eq!(42, unsafe { *raw });
///
/// drop(unsafe { Weak::from_raw(raw) });
/// assert_eq!(0, Arc::weak_count(&strong));
/// ```
///
/// [`from_raw`]: struct.Weak.html#method.from_raw
/// [`as_raw`]: struct.Weak.html#method.as_raw
#[unstable(feature = "weak_into_raw", issue = "60728")]
pub fn into_raw(this: Self) -> *const T {
let result = Self::as_raw(&this);
mem::forget(this);
result
}
/// Converts a raw pointer previously created by [`into_raw`] back into
/// `Weak<T>`.
///
/// This can be used to safely get a strong reference (by calling [`upgrade`]
/// later) or to deallocate the weak count by dropping the `Weak<T>`.
///
/// It takes ownership of one weak count. In case a [`null`] is passed, a dangling [`Weak`] is
/// returned.
///
/// # Safety
///
/// The pointer must represent one valid weak count. In other words, it must point to `T` which
/// is or *was* managed by an [`Arc`] and the weak count of that [`Arc`] must not have reached
/// 0. It is allowed for the strong count to be 0.
///
/// # Examples
///
/// ```
/// #![feature(weak_into_raw)]
///
/// use std::sync::{Arc, Weak};
///
/// let strong = Arc::new(42);
///
/// let raw_1 = Weak::into_raw(Arc::downgrade(&strong));
/// let raw_2 = Weak::into_raw(Arc::downgrade(&strong));
///
/// assert_eq!(2, Arc::weak_count(&strong));
///
/// assert_eq!(42, *Weak::upgrade(&unsafe { Weak::from_raw(raw_1) }).unwrap());
/// assert_eq!(1, Arc::weak_count(&strong));
///
/// drop(strong);
///
/// // Decrement the last weak count.
/// assert!(Weak::upgrade(&unsafe { Weak::from_raw(raw_2) }).is_none());
/// ```
///
/// [`null`]: ../../std/ptr/fn.null.html
/// [`into_raw`]: struct.Weak.html#method.into_raw
/// [`upgrade`]: struct.Weak.html#method.upgrade
/// [`Weak`]: struct.Weak.html
/// [`Arc`]: struct.Arc.html
#[unstable(feature = "weak_into_raw", issue = "60728")]
pub unsafe fn from_raw(ptr: *const T) -> Self {
if ptr.is_null() {
Self::new()
} else {
// See Arc::from_raw for details
let offset = data_offset(ptr);
let fake_ptr = ptr as *mut ArcInner<T>;
let ptr = set_data_ptr(fake_ptr, (ptr as *mut u8).offset(-offset));
Weak {
ptr: NonNull::new(ptr).expect("Invalid pointer passed to from_raw"),
}
}
}
} }
impl<T: ?Sized> Weak<T> { impl<T: ?Sized> Weak<T> {
@ -2150,3 +2284,21 @@ impl<T: ?Sized> AsRef<T> for Arc<T> {
#[stable(feature = "pin", since = "1.33.0")] #[stable(feature = "pin", since = "1.33.0")]
impl<T: ?Sized> Unpin for Arc<T> { } impl<T: ?Sized> Unpin for Arc<T> { }
/// Computes the offset of the data field within ArcInner.
unsafe fn data_offset<T: ?Sized>(ptr: *const T) -> isize {
// Align the unsized value to the end of the ArcInner.
// Because it is ?Sized, it will always be the last field in memory.
let align = align_of_val(&*ptr);
let layout = Layout::new::<ArcInner<()>>();
(layout.size() + layout.padding_needed_for(align)) as isize
}
/// Computes the offset of the data field within ArcInner.
///
/// Unlike [`data_offset`], this doesn't need the pointer, but it works only on `T: Sized`.
fn data_offset_sized<T>() -> isize {
let align = align_of::<T>();
let layout = Layout::new::<ArcInner<()>>();
(layout.size() + layout.padding_needed_for(align)) as isize
}

View file

@ -34,6 +34,13 @@ pub trait Step: Clone + PartialOrd + Sized {
/// Adds a `usize`, returning `None` on overflow. /// Adds a `usize`, returning `None` on overflow.
fn add_usize(&self, n: usize) -> Option<Self>; fn add_usize(&self, n: usize) -> Option<Self>;
/// Subtracts a `usize`, returning `None` on underflow.
fn sub_usize(&self, n: usize) -> Option<Self> {
// this default implementation makes the addition of `sub_usize` a non-breaking change
let _ = n;
unimplemented!()
}
} }
// These are still macro-generated because the integer literals resolve to different types. // These are still macro-generated because the integer literals resolve to different types.
@ -85,6 +92,15 @@ macro_rules! step_impl_unsigned {
} }
} }
#[inline]
#[allow(unreachable_patterns)]
fn sub_usize(&self, n: usize) -> Option<Self> {
match <$t>::try_from(n) {
Ok(n_as_t) => self.checked_sub(n_as_t),
Err(_) => None,
}
}
step_identical_methods!(); step_identical_methods!();
} }
)*) )*)
@ -125,6 +141,25 @@ macro_rules! step_impl_signed {
} }
} }
#[inline]
#[allow(unreachable_patterns)]
fn sub_usize(&self, n: usize) -> Option<Self> {
match <$unsigned>::try_from(n) {
Ok(n_as_unsigned) => {
// Wrapping in unsigned space handles cases like
// `80_i8.sub_usize(200) == Some(-120_i8)`,
// even though 200_usize is out of range for i8.
let wrapped = (*self as $unsigned).wrapping_sub(n_as_unsigned) as $t;
if wrapped <= *self {
Some(wrapped)
} else {
None // Subtraction underflowed
}
}
Err(_) => None,
}
}
step_identical_methods!(); step_identical_methods!();
} }
)*) )*)

View file

@ -223,3 +223,113 @@ impl<T, U, E> Product<Result<U, E>> for Result<T, E>
ResultShunt::process(iter, |i| i.product()) ResultShunt::process(iter, |i| i.product())
} }
} }
/// An iterator adapter that produces output as long as the underlying
/// iterator produces `Option::Some` values.
struct OptionShunt<I> {
iter: I,
exited_early: bool,
}
impl<I, T> OptionShunt<I>
where
I: Iterator<Item = Option<T>>,
{
/// Process the given iterator as if it yielded a `T` instead of a
/// `Option<T>`. Any `None` value will stop the inner iterator and
/// the overall result will be a `None`.
pub fn process<F, U>(iter: I, mut f: F) -> Option<U>
where
F: FnMut(&mut Self) -> U,
{
let mut shunt = OptionShunt::new(iter);
let value = f(shunt.by_ref());
shunt.reconstruct(value)
}
fn new(iter: I) -> Self {
OptionShunt {
iter,
exited_early: false,
}
}
/// Consume the adapter and rebuild a `Option` value.
fn reconstruct<U>(self, val: U) -> Option<U> {
if self.exited_early {
None
} else {
Some(val)
}
}
}
impl<I, T> Iterator for OptionShunt<I>
where
I: Iterator<Item = Option<T>>,
{
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
match self.iter.next() {
Some(Some(v)) => Some(v),
Some(None) => {
self.exited_early = true;
None
}
None => None,
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
if self.exited_early {
(0, Some(0))
} else {
let (_, upper) = self.iter.size_hint();
(0, upper)
}
}
}
#[stable(feature = "iter_arith_traits_option", since = "1.37.0")]
impl<T, U> Sum<Option<U>> for Option<T>
where
T: Sum<U>,
{
/// Takes each element in the `Iterator`: if it is a `None`, no further
/// elements are taken, and the `None` is returned. Should no `None` occur,
/// the sum of all elements is returned.
///
/// # Examples
///
/// This sums up the position of the character 'a' in a vector of strings,
/// if a word did not have the character 'a' the operation returns `None`:
///
/// ```
/// let words = vec!["have", "a", "great", "day"];
/// let total: Option<usize> = words.iter().map(|w| w.find('a')).sum();
/// assert_eq!(total, Some(5));
/// ```
fn sum<I>(iter: I) -> Option<T>
where
I: Iterator<Item = Option<U>>,
{
OptionShunt::process(iter, |i| i.sum())
}
}
#[stable(feature = "iter_arith_traits_option", since = "1.37.0")]
impl<T, U> Product<Option<U>> for Option<T>
where
T: Product<U>,
{
/// Takes each element in the `Iterator`: if it is a `None`, no further
/// elements are taken, and the `None` is returned. Should no `None` occur,
/// the product of all elements is returned.
fn product<I>(iter: I) -> Option<T>
where
I: Iterator<Item = Option<U>>,
{
OptionShunt::process(iter, |i| i.product())
}
}

View file

@ -4158,6 +4158,24 @@ impl<'a, T> DoubleEndedIterator for Chunks<'a, T> {
Some(snd) Some(snd)
} }
} }
#[inline]
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
let len = self.len();
if n >= len {
self.v = &[];
None
} else {
let start = (len - 1 - n) * self.chunk_size;
let end = match start.checked_add(self.chunk_size) {
Some(res) => cmp::min(res, self.v.len()),
None => self.v.len(),
};
let nth_back = &self.v[start..end];
self.v = &self.v[..start];
Some(nth_back)
}
}
} }
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
@ -4649,6 +4667,23 @@ impl<'a, T> DoubleEndedIterator for RChunks<'a, T> {
Some(fst) Some(fst)
} }
} }
#[inline]
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
let len = self.len();
if n >= len {
self.v = &[];
None
} else {
// can't underflow because `n < len`
let offset_from_end = (len - 1 - n) * self.chunk_size;
let end = self.v.len() - offset_from_end;
let start = end.saturating_sub(self.chunk_size);
let nth_back = &self.v[start..end];
self.v = &self.v[end..];
Some(nth_back)
}
}
} }
#[stable(feature = "rchunks", since = "1.31.0")] #[stable(feature = "rchunks", since = "1.31.0")]
@ -4774,6 +4809,24 @@ impl<'a, T> DoubleEndedIterator for RChunksMut<'a, T> {
Some(head) Some(head)
} }
} }
#[inline]
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
let len = self.len();
if n >= len {
self.v = &mut [];
None
} else {
// can't underflow because `n < len`
let offset_from_end = (len - 1 - n) * self.chunk_size;
let end = self.v.len() - offset_from_end;
let start = end.saturating_sub(self.chunk_size);
let (tmp, tail) = mem::replace(&mut self.v, &mut []).split_at_mut(end);
let (_, nth_back) = tmp.split_at_mut(start);
self.v = tail;
Some(nth_back)
}
}
} }
#[stable(feature = "rchunks", since = "1.31.0")] #[stable(feature = "rchunks", since = "1.31.0")]
@ -4898,6 +4951,24 @@ impl<'a, T> DoubleEndedIterator for RChunksExact<'a, T> {
Some(fst) Some(fst)
} }
} }
#[inline]
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
let len = self.len();
if n >= len {
self.v = &[];
None
} else {
// now that we know that `n` corresponds to a chunk,
// none of these operations can underflow/overflow
let offset = (len - n) * self.chunk_size;
let start = self.v.len() - offset;
let end = start + self.chunk_size;
let nth_back = &self.v[start..end];
self.v = &self.v[end..];
Some(nth_back)
}
}
} }
#[stable(feature = "rchunks", since = "1.31.0")] #[stable(feature = "rchunks", since = "1.31.0")]
@ -5016,6 +5087,25 @@ impl<'a, T> DoubleEndedIterator for RChunksExactMut<'a, T> {
Some(head) Some(head)
} }
} }
#[inline]
fn nth_back(&mut self, n: usize) -> Option<Self::Item> {
let len = self.len();
if n >= len {
self.v = &mut [];
None
} else {
// now that we know that `n` corresponds to a chunk,
// none of these operations can underflow/overflow
let offset = (len - n) * self.chunk_size;
let start = self.v.len() - offset;
let end = start + self.chunk_size;
let (tmp, tail) = mem::replace(&mut self.v, &mut []).split_at_mut(end);
let (_, nth_back) = tmp.split_at_mut(start);
self.v = tail;
Some(nth_back)
}
}
} }
#[stable(feature = "rchunks", since = "1.31.0")] #[stable(feature = "rchunks", since = "1.31.0")]

View file

@ -1084,6 +1084,14 @@ fn test_iterator_sum_result() {
assert_eq!(v.iter().cloned().sum::<Result<i32, _>>(), Err(())); assert_eq!(v.iter().cloned().sum::<Result<i32, _>>(), Err(()));
} }
#[test]
fn test_iterator_sum_option() {
let v: &[Option<i32>] = &[Some(1), Some(2), Some(3), Some(4)];
assert_eq!(v.iter().cloned().sum::<Option<i32>>(), Some(10));
let v: &[Option<i32>] = &[Some(1), None, Some(3), Some(4)];
assert_eq!(v.iter().cloned().sum::<Option<i32>>(), None);
}
#[test] #[test]
fn test_iterator_product() { fn test_iterator_product() {
let v: &[i32] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; let v: &[i32] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
@ -1126,6 +1134,14 @@ impl Ord for Mod3 {
} }
} }
#[test]
fn test_iterator_product_option() {
let v: &[Option<i32>] = &[Some(1), Some(2), Some(3), Some(4)];
assert_eq!(v.iter().cloned().product::<Option<i32>>(), Some(24));
let v: &[Option<i32>] = &[Some(1), None, Some(3), Some(4)];
assert_eq!(v.iter().cloned().product::<Option<i32>>(), None);
}
#[test] #[test]
fn test_iterator_max() { fn test_iterator_max() {
let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

View file

@ -134,6 +134,30 @@ fn test_chunks_nth() {
assert_eq!(c2.next(), None); assert_eq!(c2.next(), None);
} }
#[test]
fn test_chunks_nth_back() {
let v: &[i32] = &[0, 1, 2, 3, 4, 5];
let mut c = v.chunks(2);
assert_eq!(c.nth_back(1).unwrap(), &[2, 3]);
assert_eq!(c.next().unwrap(), &[0, 1]);
assert_eq!(c.next(), None);
let v2: &[i32] = &[0, 1, 2, 3, 4];
let mut c2 = v2.chunks(3);
assert_eq!(c2.nth_back(1).unwrap(), &[0, 1, 2]);
assert_eq!(c2.next(), None);
assert_eq!(c2.next_back(), None);
let v3: &[i32] = &[0, 1, 2, 3, 4];
let mut c3 = v3.chunks(10);
assert_eq!(c3.nth_back(0).unwrap(), &[0, 1, 2, 3, 4]);
assert_eq!(c3.next(), None);
let v4: &[i32] = &[0, 1, 2];
let mut c4 = v4.chunks(10);
assert_eq!(c4.nth_back(1_000_000_000usize), None);
}
#[test] #[test]
fn test_chunks_last() { fn test_chunks_last() {
let v: &[i32] = &[0, 1, 2, 3, 4, 5]; let v: &[i32] = &[0, 1, 2, 3, 4, 5];
@ -356,6 +380,19 @@ fn test_rchunks_nth() {
assert_eq!(c2.next(), None); assert_eq!(c2.next(), None);
} }
#[test]
fn test_rchunks_nth_back() {
let v: &[i32] = &[0, 1, 2, 3, 4, 5];
let mut c = v.rchunks(2);
assert_eq!(c.nth_back(1).unwrap(), &[2, 3]);
assert_eq!(c.next_back().unwrap(), &[4, 5]);
let v2: &[i32] = &[0, 1, 2, 3, 4];
let mut c2 = v2.rchunks(3);
assert_eq!(c2.nth_back(1).unwrap(), &[2, 3, 4]);
assert_eq!(c2.next_back(), None);
}
#[test] #[test]
fn test_rchunks_last() { fn test_rchunks_last() {
let v: &[i32] = &[0, 1, 2, 3, 4, 5]; let v: &[i32] = &[0, 1, 2, 3, 4, 5];
@ -407,6 +444,19 @@ fn test_rchunks_mut_nth() {
assert_eq!(c2.next(), None); assert_eq!(c2.next(), None);
} }
#[test]
fn test_rchunks_mut_nth_back() {
let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
let mut c = v.rchunks_mut(2);
assert_eq!(c.nth_back(1).unwrap(), &[2, 3]);
assert_eq!(c.next_back().unwrap(), &[4, 5]);
let v2: &mut [i32] = &mut [0, 1, 2, 3, 4];
let mut c2 = v2.rchunks_mut(3);
assert_eq!(c2.nth_back(1).unwrap(), &[2, 3, 4]);
assert_eq!(c2.next_back(), None);
}
#[test] #[test]
fn test_rchunks_mut_last() { fn test_rchunks_mut_last() {
let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5]; let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
@ -460,6 +510,19 @@ fn test_rchunks_exact_nth() {
assert_eq!(c2.next(), None); assert_eq!(c2.next(), None);
} }
#[test]
fn test_rchunks_exact_nth_back() {
let v: &[i32] = &[0, 1, 2, 3, 4, 5];
let mut c = v.rchunks_exact(2);
assert_eq!(c.nth_back(1).unwrap(), &[2, 3]);
assert_eq!(c.next_back().unwrap(), &[4, 5]);
let v2: &[i32] = &[0, 1, 2, 3, 4, 5, 6];
let mut c2 = v2.rchunks_exact(3);
assert_eq!(c2.nth_back(1).unwrap(), &[4, 5, 6]);
assert_eq!(c2.next(), None);
}
#[test] #[test]
fn test_rchunks_exact_last() { fn test_rchunks_exact_last() {
let v: &[i32] = &[0, 1, 2, 3, 4, 5]; let v: &[i32] = &[0, 1, 2, 3, 4, 5];
@ -518,6 +581,19 @@ fn test_rchunks_exact_mut_nth() {
assert_eq!(c2.next(), None); assert_eq!(c2.next(), None);
} }
#[test]
fn test_rchunks_exact_mut_nth_back() {
let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
let mut c = v.rchunks_exact_mut(2);
assert_eq!(c.nth_back(1).unwrap(), &[2, 3]);
assert_eq!(c.next_back().unwrap(), &[4, 5]);
let v2: &mut [i32] = &mut [0, 1, 2, 3, 4, 5, 6];
let mut c2 = v2.rchunks_exact_mut(3);
assert_eq!(c2.nth_back(1).unwrap(), &[4, 5, 6]);
assert_eq!(c2.next(), None);
}
#[test] #[test]
fn test_rchunks_exact_mut_last() { fn test_rchunks_exact_mut_last() {
let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5]; let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];

View file

@ -2037,7 +2037,7 @@ impl<'tcx> Place<'tcx> {
/// a single deref of a local. /// a single deref of a local.
// //
// FIXME: can we safely swap the semantics of `fn base_local` below in here instead? // FIXME: can we safely swap the semantics of `fn base_local` below in here instead?
pub fn local(&self) -> Option<Local> { pub fn local_or_deref_local(&self) -> Option<Local> {
match self { match self {
Place::Base(PlaceBase::Local(local)) | Place::Base(PlaceBase::Local(local)) |
Place::Projection(box Projection { Place::Projection(box Projection {

View file

@ -188,49 +188,6 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for CodegenUnit<'tcx> {
} }
} }
#[derive(Clone, Default)]
pub struct Stats {
pub n_glues_created: usize,
pub n_null_glues: usize,
pub n_real_glues: usize,
pub n_fns: usize,
pub n_inlines: usize,
pub n_closures: usize,
pub n_llvm_insns: usize,
pub llvm_insns: FxHashMap<String, usize>,
// (ident, llvm-instructions)
pub fn_stats: Vec<(String, usize)>,
}
impl_stable_hash_for!(struct self::Stats {
n_glues_created,
n_null_glues,
n_real_glues,
n_fns,
n_inlines,
n_closures,
n_llvm_insns,
llvm_insns,
fn_stats
});
impl Stats {
pub fn extend(&mut self, stats: Stats) {
self.n_glues_created += stats.n_glues_created;
self.n_null_glues += stats.n_null_glues;
self.n_real_glues += stats.n_real_glues;
self.n_fns += stats.n_fns;
self.n_inlines += stats.n_inlines;
self.n_closures += stats.n_closures;
self.n_llvm_insns += stats.n_llvm_insns;
for (k, v) in stats.llvm_insns {
*self.llvm_insns.entry(k).or_insert(0) += v;
}
self.fn_stats.extend(stats.fn_stats);
}
}
pub struct CodegenUnitNameBuilder<'a, 'gcx: 'tcx, 'tcx: 'a> { pub struct CodegenUnitNameBuilder<'a, 'gcx: 'tcx, 'tcx: 'a> {
tcx: TyCtxt<'a, 'gcx, 'tcx>, tcx: TyCtxt<'a, 'gcx, 'tcx>,
cache: FxHashMap<CrateNum, String>, cache: FxHashMap<CrateNum, String>,

View file

@ -1216,21 +1216,12 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
"measure time of each rustc pass"), "measure time of each rustc pass"),
time: bool = (false, parse_bool, [UNTRACKED], time: bool = (false, parse_bool, [UNTRACKED],
"measure time of rustc processes"), "measure time of rustc processes"),
count_llvm_insns: bool = (false, parse_bool,
[UNTRACKED_WITH_WARNING(true,
"The output generated by `-Z count_llvm_insns` might not be reliable \
when used with incremental compilation")],
"count where LLVM instrs originate"),
time_llvm_passes: bool = (false, parse_bool, [UNTRACKED_WITH_WARNING(true, time_llvm_passes: bool = (false, parse_bool, [UNTRACKED_WITH_WARNING(true,
"The output of `-Z time-llvm-passes` will only reflect timings of \ "The output of `-Z time-llvm-passes` will only reflect timings of \
re-codegened modules when used with incremental compilation" )], re-codegened modules when used with incremental compilation" )],
"measure time of each LLVM pass"), "measure time of each LLVM pass"),
input_stats: bool = (false, parse_bool, [UNTRACKED], input_stats: bool = (false, parse_bool, [UNTRACKED],
"gather statistics about the input"), "gather statistics about the input"),
codegen_stats: bool = (false, parse_bool, [UNTRACKED_WITH_WARNING(true,
"The output of `-Z codegen-stats` might not be accurate when incremental \
compilation is enabled")],
"gather codegen statistics"),
asm_comments: bool = (false, parse_bool, [TRACKED], asm_comments: bool = (false, parse_bool, [TRACKED],
"generate comments into the assembly (may change behavior)"), "generate comments into the assembly (may change behavior)"),
verify_llvm_ir: bool = (false, parse_bool, [TRACKED], verify_llvm_ir: bool = (false, parse_bool, [TRACKED],
@ -3259,14 +3250,10 @@ mod tests {
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.time_passes = true; opts.debugging_opts.time_passes = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.count_llvm_insns = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.time_llvm_passes = true; opts.debugging_opts.time_llvm_passes = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.input_stats = true; opts.debugging_opts.input_stats = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.codegen_stats = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.borrowck_stats = true; opts.debugging_opts.borrowck_stats = true;
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash()); assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
opts.debugging_opts.meta_stats = true; opts.debugging_opts.meta_stats = true;

View file

@ -519,15 +519,9 @@ impl Session {
pub fn instrument_mcount(&self) -> bool { pub fn instrument_mcount(&self) -> bool {
self.opts.debugging_opts.instrument_mcount self.opts.debugging_opts.instrument_mcount
} }
pub fn count_llvm_insns(&self) -> bool {
self.opts.debugging_opts.count_llvm_insns
}
pub fn time_llvm_passes(&self) -> bool { pub fn time_llvm_passes(&self) -> bool {
self.opts.debugging_opts.time_llvm_passes self.opts.debugging_opts.time_llvm_passes
} }
pub fn codegen_stats(&self) -> bool {
self.opts.debugging_opts.codegen_stats
}
pub fn meta_stats(&self) -> bool { pub fn meta_stats(&self) -> bool {
self.opts.debugging_opts.meta_stats self.opts.debugging_opts.meta_stats
} }

View file

@ -24,7 +24,7 @@ use crate::common;
use crate::context::CodegenCx; use crate::context::CodegenCx;
use crate::monomorphize::partitioning::CodegenUnitExt; use crate::monomorphize::partitioning::CodegenUnitExt;
use rustc::dep_graph; use rustc::dep_graph;
use rustc::mir::mono::{Linkage, Visibility, Stats}; use rustc::mir::mono::{Linkage, Visibility};
use rustc::middle::cstore::{EncodedMetadata}; use rustc::middle::cstore::{EncodedMetadata};
use rustc::ty::TyCtxt; use rustc::ty::TyCtxt;
use rustc::middle::exported_symbols; use rustc::middle::exported_symbols;
@ -104,17 +104,17 @@ pub fn iter_globals(llmod: &'ll llvm::Module) -> ValueIter<'ll> {
} }
} }
pub fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pub fn compile_codegen_unit(tcx: TyCtxt<'a, 'tcx, 'tcx>, cgu_name: InternedString) {
cgu_name: InternedString)
-> Stats {
let start_time = Instant::now(); let start_time = Instant::now();
let dep_node = tcx.codegen_unit(cgu_name).codegen_dep_node(tcx); let dep_node = tcx.codegen_unit(cgu_name).codegen_dep_node(tcx);
let ((stats, module), _) = tcx.dep_graph.with_task(dep_node, let (module, _) = tcx.dep_graph.with_task(
tcx, dep_node,
cgu_name, tcx,
module_codegen, cgu_name,
dep_graph::hash_result); module_codegen,
dep_graph::hash_result,
);
let time_to_codegen = start_time.elapsed(); let time_to_codegen = start_time.elapsed();
// We assume that the cost to run LLVM on a CGU is proportional to // We assume that the cost to run LLVM on a CGU is proportional to
@ -123,17 +123,15 @@ pub fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
time_to_codegen.subsec_nanos() as u64; time_to_codegen.subsec_nanos() as u64;
submit_codegened_module_to_llvm(&LlvmCodegenBackend(()), tcx, module, cost); submit_codegened_module_to_llvm(&LlvmCodegenBackend(()), tcx, module, cost);
return stats;
fn module_codegen<'ll, 'tcx>( fn module_codegen<'ll, 'tcx>(
tcx: TyCtxt<'ll, 'tcx, 'tcx>, tcx: TyCtxt<'ll, 'tcx, 'tcx>,
cgu_name: InternedString) cgu_name: InternedString,
-> (Stats, ModuleCodegen<ModuleLlvm>) ) -> ModuleCodegen<ModuleLlvm> {
{
let cgu = tcx.codegen_unit(cgu_name); let cgu = tcx.codegen_unit(cgu_name);
// Instantiate monomorphizations without filling out definitions yet... // Instantiate monomorphizations without filling out definitions yet...
let llvm_module = ModuleLlvm::new(tcx, &cgu_name.as_str()); let llvm_module = ModuleLlvm::new(tcx, &cgu_name.as_str());
let stats = { {
let cx = CodegenCx::new(tcx, cgu, &llvm_module); let cx = CodegenCx::new(tcx, cgu, &llvm_module);
let mono_items = cx.codegen_unit let mono_items = cx.codegen_unit
.items_in_deterministic_order(cx.tcx); .items_in_deterministic_order(cx.tcx);
@ -169,15 +167,13 @@ pub fn compile_codegen_unit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
if cx.sess().opts.debuginfo != DebugInfo::None { if cx.sess().opts.debuginfo != DebugInfo::None {
cx.debuginfo_finalize(); cx.debuginfo_finalize();
} }
}
cx.consume_stats().into_inner() ModuleCodegen {
};
(stats, ModuleCodegen {
name: cgu_name.to_string(), name: cgu_name.to_string(),
module_llvm: llvm_module, module_llvm: llvm_module,
kind: ModuleKind::Regular, kind: ModuleKind::Regular,
}) }
} }
} }

View file

@ -147,21 +147,18 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
} }
fn ret_void(&mut self) { fn ret_void(&mut self) {
self.count_insn("retvoid");
unsafe { unsafe {
llvm::LLVMBuildRetVoid(self.llbuilder); llvm::LLVMBuildRetVoid(self.llbuilder);
} }
} }
fn ret(&mut self, v: &'ll Value) { fn ret(&mut self, v: &'ll Value) {
self.count_insn("ret");
unsafe { unsafe {
llvm::LLVMBuildRet(self.llbuilder, v); llvm::LLVMBuildRet(self.llbuilder, v);
} }
} }
fn br(&mut self, dest: &'ll BasicBlock) { fn br(&mut self, dest: &'ll BasicBlock) {
self.count_insn("br");
unsafe { unsafe {
llvm::LLVMBuildBr(self.llbuilder, dest); llvm::LLVMBuildBr(self.llbuilder, dest);
} }
@ -173,7 +170,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
then_llbb: &'ll BasicBlock, then_llbb: &'ll BasicBlock,
else_llbb: &'ll BasicBlock, else_llbb: &'ll BasicBlock,
) { ) {
self.count_insn("condbr");
unsafe { unsafe {
llvm::LLVMBuildCondBr(self.llbuilder, cond, then_llbb, else_llbb); llvm::LLVMBuildCondBr(self.llbuilder, cond, then_llbb, else_llbb);
} }
@ -204,7 +200,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
catch: &'ll BasicBlock, catch: &'ll BasicBlock,
funclet: Option<&Funclet<'ll>>, funclet: Option<&Funclet<'ll>>,
) -> &'ll Value { ) -> &'ll Value {
self.count_insn("invoke");
debug!("Invoke {:?} with args ({:?})", debug!("Invoke {:?} with args ({:?})",
llfn, llfn,
@ -227,7 +222,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
} }
fn unreachable(&mut self) { fn unreachable(&mut self) {
self.count_insn("unreachable");
unsafe { unsafe {
llvm::LLVMBuildUnreachable(self.llbuilder); llvm::LLVMBuildUnreachable(self.llbuilder);
} }
@ -235,21 +229,18 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
/* Arithmetic */ /* Arithmetic */
fn add(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { fn add(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
self.count_insn("add");
unsafe { unsafe {
llvm::LLVMBuildAdd(self.llbuilder, lhs, rhs, noname()) llvm::LLVMBuildAdd(self.llbuilder, lhs, rhs, noname())
} }
} }
fn fadd(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { fn fadd(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
self.count_insn("fadd");
unsafe { unsafe {
llvm::LLVMBuildFAdd(self.llbuilder, lhs, rhs, noname()) llvm::LLVMBuildFAdd(self.llbuilder, lhs, rhs, noname())
} }
} }
fn fadd_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { fn fadd_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
self.count_insn("fadd");
unsafe { unsafe {
let instr = llvm::LLVMBuildFAdd(self.llbuilder, lhs, rhs, noname()); let instr = llvm::LLVMBuildFAdd(self.llbuilder, lhs, rhs, noname());
llvm::LLVMRustSetHasUnsafeAlgebra(instr); llvm::LLVMRustSetHasUnsafeAlgebra(instr);
@ -258,21 +249,18 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
} }
fn sub(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { fn sub(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
self.count_insn("sub");
unsafe { unsafe {
llvm::LLVMBuildSub(self.llbuilder, lhs, rhs, noname()) llvm::LLVMBuildSub(self.llbuilder, lhs, rhs, noname())
} }
} }
fn fsub(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { fn fsub(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
self.count_insn("fsub");
unsafe { unsafe {
llvm::LLVMBuildFSub(self.llbuilder, lhs, rhs, noname()) llvm::LLVMBuildFSub(self.llbuilder, lhs, rhs, noname())
} }
} }
fn fsub_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { fn fsub_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
self.count_insn("fsub");
unsafe { unsafe {
let instr = llvm::LLVMBuildFSub(self.llbuilder, lhs, rhs, noname()); let instr = llvm::LLVMBuildFSub(self.llbuilder, lhs, rhs, noname());
llvm::LLVMRustSetHasUnsafeAlgebra(instr); llvm::LLVMRustSetHasUnsafeAlgebra(instr);
@ -281,21 +269,18 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
} }
fn mul(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { fn mul(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
self.count_insn("mul");
unsafe { unsafe {
llvm::LLVMBuildMul(self.llbuilder, lhs, rhs, noname()) llvm::LLVMBuildMul(self.llbuilder, lhs, rhs, noname())
} }
} }
fn fmul(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { fn fmul(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
self.count_insn("fmul");
unsafe { unsafe {
llvm::LLVMBuildFMul(self.llbuilder, lhs, rhs, noname()) llvm::LLVMBuildFMul(self.llbuilder, lhs, rhs, noname())
} }
} }
fn fmul_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { fn fmul_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
self.count_insn("fmul");
unsafe { unsafe {
let instr = llvm::LLVMBuildFMul(self.llbuilder, lhs, rhs, noname()); let instr = llvm::LLVMBuildFMul(self.llbuilder, lhs, rhs, noname());
llvm::LLVMRustSetHasUnsafeAlgebra(instr); llvm::LLVMRustSetHasUnsafeAlgebra(instr);
@ -305,42 +290,36 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
fn udiv(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { fn udiv(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
self.count_insn("udiv");
unsafe { unsafe {
llvm::LLVMBuildUDiv(self.llbuilder, lhs, rhs, noname()) llvm::LLVMBuildUDiv(self.llbuilder, lhs, rhs, noname())
} }
} }
fn exactudiv(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { fn exactudiv(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
self.count_insn("exactudiv");
unsafe { unsafe {
llvm::LLVMBuildExactUDiv(self.llbuilder, lhs, rhs, noname()) llvm::LLVMBuildExactUDiv(self.llbuilder, lhs, rhs, noname())
} }
} }
fn sdiv(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { fn sdiv(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
self.count_insn("sdiv");
unsafe { unsafe {
llvm::LLVMBuildSDiv(self.llbuilder, lhs, rhs, noname()) llvm::LLVMBuildSDiv(self.llbuilder, lhs, rhs, noname())
} }
} }
fn exactsdiv(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { fn exactsdiv(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
self.count_insn("exactsdiv");
unsafe { unsafe {
llvm::LLVMBuildExactSDiv(self.llbuilder, lhs, rhs, noname()) llvm::LLVMBuildExactSDiv(self.llbuilder, lhs, rhs, noname())
} }
} }
fn fdiv(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { fn fdiv(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
self.count_insn("fdiv");
unsafe { unsafe {
llvm::LLVMBuildFDiv(self.llbuilder, lhs, rhs, noname()) llvm::LLVMBuildFDiv(self.llbuilder, lhs, rhs, noname())
} }
} }
fn fdiv_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { fn fdiv_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
self.count_insn("fdiv");
unsafe { unsafe {
let instr = llvm::LLVMBuildFDiv(self.llbuilder, lhs, rhs, noname()); let instr = llvm::LLVMBuildFDiv(self.llbuilder, lhs, rhs, noname());
llvm::LLVMRustSetHasUnsafeAlgebra(instr); llvm::LLVMRustSetHasUnsafeAlgebra(instr);
@ -349,28 +328,24 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
} }
fn urem(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { fn urem(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
self.count_insn("urem");
unsafe { unsafe {
llvm::LLVMBuildURem(self.llbuilder, lhs, rhs, noname()) llvm::LLVMBuildURem(self.llbuilder, lhs, rhs, noname())
} }
} }
fn srem(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { fn srem(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
self.count_insn("srem");
unsafe { unsafe {
llvm::LLVMBuildSRem(self.llbuilder, lhs, rhs, noname()) llvm::LLVMBuildSRem(self.llbuilder, lhs, rhs, noname())
} }
} }
fn frem(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { fn frem(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
self.count_insn("frem");
unsafe { unsafe {
llvm::LLVMBuildFRem(self.llbuilder, lhs, rhs, noname()) llvm::LLVMBuildFRem(self.llbuilder, lhs, rhs, noname())
} }
} }
fn frem_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { fn frem_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
self.count_insn("frem");
unsafe { unsafe {
let instr = llvm::LLVMBuildFRem(self.llbuilder, lhs, rhs, noname()); let instr = llvm::LLVMBuildFRem(self.llbuilder, lhs, rhs, noname());
llvm::LLVMRustSetHasUnsafeAlgebra(instr); llvm::LLVMRustSetHasUnsafeAlgebra(instr);
@ -379,63 +354,54 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
} }
fn shl(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { fn shl(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
self.count_insn("shl");
unsafe { unsafe {
llvm::LLVMBuildShl(self.llbuilder, lhs, rhs, noname()) llvm::LLVMBuildShl(self.llbuilder, lhs, rhs, noname())
} }
} }
fn lshr(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { fn lshr(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
self.count_insn("lshr");
unsafe { unsafe {
llvm::LLVMBuildLShr(self.llbuilder, lhs, rhs, noname()) llvm::LLVMBuildLShr(self.llbuilder, lhs, rhs, noname())
} }
} }
fn ashr(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { fn ashr(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
self.count_insn("ashr");
unsafe { unsafe {
llvm::LLVMBuildAShr(self.llbuilder, lhs, rhs, noname()) llvm::LLVMBuildAShr(self.llbuilder, lhs, rhs, noname())
} }
} }
fn and(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { fn and(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
self.count_insn("and");
unsafe { unsafe {
llvm::LLVMBuildAnd(self.llbuilder, lhs, rhs, noname()) llvm::LLVMBuildAnd(self.llbuilder, lhs, rhs, noname())
} }
} }
fn or(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { fn or(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
self.count_insn("or");
unsafe { unsafe {
llvm::LLVMBuildOr(self.llbuilder, lhs, rhs, noname()) llvm::LLVMBuildOr(self.llbuilder, lhs, rhs, noname())
} }
} }
fn xor(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { fn xor(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
self.count_insn("xor");
unsafe { unsafe {
llvm::LLVMBuildXor(self.llbuilder, lhs, rhs, noname()) llvm::LLVMBuildXor(self.llbuilder, lhs, rhs, noname())
} }
} }
fn neg(&mut self, v: &'ll Value) -> &'ll Value { fn neg(&mut self, v: &'ll Value) -> &'ll Value {
self.count_insn("neg");
unsafe { unsafe {
llvm::LLVMBuildNeg(self.llbuilder, v, noname()) llvm::LLVMBuildNeg(self.llbuilder, v, noname())
} }
} }
fn fneg(&mut self, v: &'ll Value) -> &'ll Value { fn fneg(&mut self, v: &'ll Value) -> &'ll Value {
self.count_insn("fneg");
unsafe { unsafe {
llvm::LLVMBuildFNeg(self.llbuilder, v, noname()) llvm::LLVMBuildFNeg(self.llbuilder, v, noname())
} }
} }
fn not(&mut self, v: &'ll Value) -> &'ll Value { fn not(&mut self, v: &'ll Value) -> &'ll Value {
self.count_insn("not");
unsafe { unsafe {
llvm::LLVMBuildNot(self.llbuilder, v, noname()) llvm::LLVMBuildNot(self.llbuilder, v, noname())
} }
@ -524,7 +490,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
} }
fn dynamic_alloca(&mut self, ty: &'ll Type, name: &str, align: Align) -> &'ll Value { fn dynamic_alloca(&mut self, ty: &'ll Type, name: &str, align: Align) -> &'ll Value {
self.count_insn("alloca");
unsafe { unsafe {
let alloca = if name.is_empty() { let alloca = if name.is_empty() {
llvm::LLVMBuildAlloca(self.llbuilder, ty, noname()) llvm::LLVMBuildAlloca(self.llbuilder, ty, noname())
@ -543,7 +508,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
len: &'ll Value, len: &'ll Value,
name: &str, name: &str,
align: Align) -> &'ll Value { align: Align) -> &'ll Value {
self.count_insn("alloca");
unsafe { unsafe {
let alloca = if name.is_empty() { let alloca = if name.is_empty() {
llvm::LLVMBuildArrayAlloca(self.llbuilder, ty, len, noname()) llvm::LLVMBuildArrayAlloca(self.llbuilder, ty, len, noname())
@ -558,7 +522,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
} }
fn load(&mut self, ptr: &'ll Value, align: Align) -> &'ll Value { fn load(&mut self, ptr: &'ll Value, align: Align) -> &'ll Value {
self.count_insn("load");
unsafe { unsafe {
let load = llvm::LLVMBuildLoad(self.llbuilder, ptr, noname()); let load = llvm::LLVMBuildLoad(self.llbuilder, ptr, noname());
llvm::LLVMSetAlignment(load, align.bytes() as c_uint); llvm::LLVMSetAlignment(load, align.bytes() as c_uint);
@ -567,11 +530,10 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
} }
fn volatile_load(&mut self, ptr: &'ll Value) -> &'ll Value { fn volatile_load(&mut self, ptr: &'ll Value) -> &'ll Value {
self.count_insn("load.volatile");
unsafe { unsafe {
let insn = llvm::LLVMBuildLoad(self.llbuilder, ptr, noname()); let load = llvm::LLVMBuildLoad(self.llbuilder, ptr, noname());
llvm::LLVMSetVolatile(insn, llvm::True); llvm::LLVMSetVolatile(load, llvm::True);
insn load
} }
} }
@ -581,7 +543,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
order: rustc_codegen_ssa::common::AtomicOrdering, order: rustc_codegen_ssa::common::AtomicOrdering,
size: Size, size: Size,
) -> &'ll Value { ) -> &'ll Value {
self.count_insn("load.atomic");
unsafe { unsafe {
let load = llvm::LLVMRustBuildAtomicLoad( let load = llvm::LLVMRustBuildAtomicLoad(
self.llbuilder, self.llbuilder,
@ -745,7 +706,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
flags: MemFlags, flags: MemFlags,
) -> &'ll Value { ) -> &'ll Value {
debug!("Store {:?} -> {:?} ({:?})", val, ptr, flags); debug!("Store {:?} -> {:?} ({:?})", val, ptr, flags);
self.count_insn("store");
let ptr = self.check_store(val, ptr); let ptr = self.check_store(val, ptr);
unsafe { unsafe {
let store = llvm::LLVMBuildStore(self.llbuilder, val, ptr); let store = llvm::LLVMBuildStore(self.llbuilder, val, ptr);
@ -774,7 +734,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
fn atomic_store(&mut self, val: &'ll Value, ptr: &'ll Value, fn atomic_store(&mut self, val: &'ll Value, ptr: &'ll Value,
order: rustc_codegen_ssa::common::AtomicOrdering, size: Size) { order: rustc_codegen_ssa::common::AtomicOrdering, size: Size) {
debug!("Store {:?} -> {:?}", val, ptr); debug!("Store {:?} -> {:?}", val, ptr);
self.count_insn("store.atomic");
let ptr = self.check_store(val, ptr); let ptr = self.check_store(val, ptr);
unsafe { unsafe {
let store = llvm::LLVMRustBuildAtomicStore( let store = llvm::LLVMRustBuildAtomicStore(
@ -789,7 +748,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
} }
fn gep(&mut self, ptr: &'ll Value, indices: &[&'ll Value]) -> &'ll Value { fn gep(&mut self, ptr: &'ll Value, indices: &[&'ll Value]) -> &'ll Value {
self.count_insn("gep");
unsafe { unsafe {
llvm::LLVMBuildGEP(self.llbuilder, ptr, indices.as_ptr(), llvm::LLVMBuildGEP(self.llbuilder, ptr, indices.as_ptr(),
indices.len() as c_uint, noname()) indices.len() as c_uint, noname())
@ -797,7 +755,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
} }
fn inbounds_gep(&mut self, ptr: &'ll Value, indices: &[&'ll Value]) -> &'ll Value { fn inbounds_gep(&mut self, ptr: &'ll Value, indices: &[&'ll Value]) -> &'ll Value {
self.count_insn("inboundsgep");
unsafe { unsafe {
llvm::LLVMBuildInBoundsGEP( llvm::LLVMBuildInBoundsGEP(
self.llbuilder, ptr, indices.as_ptr(), indices.len() as c_uint, noname()) self.llbuilder, ptr, indices.as_ptr(), indices.len() as c_uint, noname())
@ -805,7 +762,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
} }
fn struct_gep(&mut self, ptr: &'ll Value, idx: u64) -> &'ll Value { fn struct_gep(&mut self, ptr: &'ll Value, idx: u64) -> &'ll Value {
self.count_insn("structgep");
assert_eq!(idx as c_uint as u64, idx); assert_eq!(idx as c_uint as u64, idx);
unsafe { unsafe {
llvm::LLVMBuildStructGEP(self.llbuilder, ptr, idx as c_uint, noname()) llvm::LLVMBuildStructGEP(self.llbuilder, ptr, idx as c_uint, noname())
@ -814,77 +770,66 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
/* Casts */ /* Casts */
fn trunc(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { fn trunc(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
self.count_insn("trunc");
unsafe { unsafe {
llvm::LLVMBuildTrunc(self.llbuilder, val, dest_ty, noname()) llvm::LLVMBuildTrunc(self.llbuilder, val, dest_ty, noname())
} }
} }
fn sext(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { fn sext(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
self.count_insn("sext");
unsafe { unsafe {
llvm::LLVMBuildSExt(self.llbuilder, val, dest_ty, noname()) llvm::LLVMBuildSExt(self.llbuilder, val, dest_ty, noname())
} }
} }
fn fptoui(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { fn fptoui(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
self.count_insn("fptoui");
unsafe { unsafe {
llvm::LLVMBuildFPToUI(self.llbuilder, val, dest_ty, noname()) llvm::LLVMBuildFPToUI(self.llbuilder, val, dest_ty, noname())
} }
} }
fn fptosi(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { fn fptosi(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
self.count_insn("fptosi");
unsafe { unsafe {
llvm::LLVMBuildFPToSI(self.llbuilder, val, dest_ty,noname()) llvm::LLVMBuildFPToSI(self.llbuilder, val, dest_ty,noname())
} }
} }
fn uitofp(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { fn uitofp(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
self.count_insn("uitofp");
unsafe { unsafe {
llvm::LLVMBuildUIToFP(self.llbuilder, val, dest_ty, noname()) llvm::LLVMBuildUIToFP(self.llbuilder, val, dest_ty, noname())
} }
} }
fn sitofp(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { fn sitofp(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
self.count_insn("sitofp");
unsafe { unsafe {
llvm::LLVMBuildSIToFP(self.llbuilder, val, dest_ty, noname()) llvm::LLVMBuildSIToFP(self.llbuilder, val, dest_ty, noname())
} }
} }
fn fptrunc(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { fn fptrunc(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
self.count_insn("fptrunc");
unsafe { unsafe {
llvm::LLVMBuildFPTrunc(self.llbuilder, val, dest_ty, noname()) llvm::LLVMBuildFPTrunc(self.llbuilder, val, dest_ty, noname())
} }
} }
fn fpext(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { fn fpext(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
self.count_insn("fpext");
unsafe { unsafe {
llvm::LLVMBuildFPExt(self.llbuilder, val, dest_ty, noname()) llvm::LLVMBuildFPExt(self.llbuilder, val, dest_ty, noname())
} }
} }
fn ptrtoint(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { fn ptrtoint(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
self.count_insn("ptrtoint");
unsafe { unsafe {
llvm::LLVMBuildPtrToInt(self.llbuilder, val, dest_ty, noname()) llvm::LLVMBuildPtrToInt(self.llbuilder, val, dest_ty, noname())
} }
} }
fn inttoptr(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { fn inttoptr(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
self.count_insn("inttoptr");
unsafe { unsafe {
llvm::LLVMBuildIntToPtr(self.llbuilder, val, dest_ty, noname()) llvm::LLVMBuildIntToPtr(self.llbuilder, val, dest_ty, noname())
} }
} }
fn bitcast(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { fn bitcast(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
self.count_insn("bitcast");
unsafe { unsafe {
llvm::LLVMBuildBitCast(self.llbuilder, val, dest_ty, noname()) llvm::LLVMBuildBitCast(self.llbuilder, val, dest_ty, noname())
} }
@ -892,14 +837,12 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
fn intcast(&mut self, val: &'ll Value, dest_ty: &'ll Type, is_signed: bool) -> &'ll Value { fn intcast(&mut self, val: &'ll Value, dest_ty: &'ll Type, is_signed: bool) -> &'ll Value {
self.count_insn("intcast");
unsafe { unsafe {
llvm::LLVMRustBuildIntCast(self.llbuilder, val, dest_ty, is_signed) llvm::LLVMRustBuildIntCast(self.llbuilder, val, dest_ty, is_signed)
} }
} }
fn pointercast(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { fn pointercast(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
self.count_insn("pointercast");
unsafe { unsafe {
llvm::LLVMBuildPointerCast(self.llbuilder, val, dest_ty, noname()) llvm::LLVMBuildPointerCast(self.llbuilder, val, dest_ty, noname())
} }
@ -907,7 +850,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
/* Comparisons */ /* Comparisons */
fn icmp(&mut self, op: IntPredicate, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { fn icmp(&mut self, op: IntPredicate, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
self.count_insn("icmp");
let op = llvm::IntPredicate::from_generic(op); let op = llvm::IntPredicate::from_generic(op);
unsafe { unsafe {
llvm::LLVMBuildICmp(self.llbuilder, op as c_uint, lhs, rhs, noname()) llvm::LLVMBuildICmp(self.llbuilder, op as c_uint, lhs, rhs, noname())
@ -915,7 +857,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
} }
fn fcmp(&mut self, op: RealPredicate, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { fn fcmp(&mut self, op: RealPredicate, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
self.count_insn("fcmp");
unsafe { unsafe {
llvm::LLVMBuildFCmp(self.llbuilder, op as c_uint, lhs, rhs, noname()) llvm::LLVMBuildFCmp(self.llbuilder, op as c_uint, lhs, rhs, noname())
} }
@ -984,7 +925,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
then_val: &'ll Value, then_val: &'ll Value,
else_val: &'ll Value, else_val: &'ll Value,
) -> &'ll Value { ) -> &'ll Value {
self.count_insn("select");
unsafe { unsafe {
llvm::LLVMBuildSelect(self.llbuilder, cond, then_val, else_val, noname()) llvm::LLVMBuildSelect(self.llbuilder, cond, then_val, else_val, noname())
} }
@ -992,14 +932,12 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
#[allow(dead_code)] #[allow(dead_code)]
fn va_arg(&mut self, list: &'ll Value, ty: &'ll Type) -> &'ll Value { fn va_arg(&mut self, list: &'ll Value, ty: &'ll Type) -> &'ll Value {
self.count_insn("vaarg");
unsafe { unsafe {
llvm::LLVMBuildVAArg(self.llbuilder, list, ty, noname()) llvm::LLVMBuildVAArg(self.llbuilder, list, ty, noname())
} }
} }
fn extract_element(&mut self, vec: &'ll Value, idx: &'ll Value) -> &'ll Value { fn extract_element(&mut self, vec: &'ll Value, idx: &'ll Value) -> &'ll Value {
self.count_insn("extractelement");
unsafe { unsafe {
llvm::LLVMBuildExtractElement(self.llbuilder, vec, idx, noname()) llvm::LLVMBuildExtractElement(self.llbuilder, vec, idx, noname())
} }
@ -1016,7 +954,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
} }
fn extract_value(&mut self, agg_val: &'ll Value, idx: u64) -> &'ll Value { fn extract_value(&mut self, agg_val: &'ll Value, idx: u64) -> &'ll Value {
self.count_insn("extractvalue");
assert_eq!(idx as c_uint as u64, idx); assert_eq!(idx as c_uint as u64, idx);
unsafe { unsafe {
llvm::LLVMBuildExtractValue(self.llbuilder, agg_val, idx as c_uint, noname()) llvm::LLVMBuildExtractValue(self.llbuilder, agg_val, idx as c_uint, noname())
@ -1025,7 +962,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
fn insert_value(&mut self, agg_val: &'ll Value, elt: &'ll Value, fn insert_value(&mut self, agg_val: &'ll Value, elt: &'ll Value,
idx: u64) -> &'ll Value { idx: u64) -> &'ll Value {
self.count_insn("insertvalue");
assert_eq!(idx as c_uint as u64, idx); assert_eq!(idx as c_uint as u64, idx);
unsafe { unsafe {
llvm::LLVMBuildInsertValue(self.llbuilder, agg_val, elt, idx as c_uint, llvm::LLVMBuildInsertValue(self.llbuilder, agg_val, elt, idx as c_uint,
@ -1035,7 +971,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
fn landing_pad(&mut self, ty: &'ll Type, pers_fn: &'ll Value, fn landing_pad(&mut self, ty: &'ll Type, pers_fn: &'ll Value,
num_clauses: usize) -> &'ll Value { num_clauses: usize) -> &'ll Value {
self.count_insn("landingpad");
unsafe { unsafe {
llvm::LLVMBuildLandingPad(self.llbuilder, ty, pers_fn, llvm::LLVMBuildLandingPad(self.llbuilder, ty, pers_fn,
num_clauses as c_uint, noname()) num_clauses as c_uint, noname())
@ -1043,14 +978,12 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
} }
fn set_cleanup(&mut self, landing_pad: &'ll Value) { fn set_cleanup(&mut self, landing_pad: &'ll Value) {
self.count_insn("setcleanup");
unsafe { unsafe {
llvm::LLVMSetCleanup(landing_pad, llvm::True); llvm::LLVMSetCleanup(landing_pad, llvm::True);
} }
} }
fn resume(&mut self, exn: &'ll Value) -> &'ll Value { fn resume(&mut self, exn: &'ll Value) -> &'ll Value {
self.count_insn("resume");
unsafe { unsafe {
llvm::LLVMBuildResume(self.llbuilder, exn) llvm::LLVMBuildResume(self.llbuilder, exn)
} }
@ -1059,7 +992,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
fn cleanup_pad(&mut self, fn cleanup_pad(&mut self,
parent: Option<&'ll Value>, parent: Option<&'ll Value>,
args: &[&'ll Value]) -> Funclet<'ll> { args: &[&'ll Value]) -> Funclet<'ll> {
self.count_insn("cleanuppad");
let name = const_cstr!("cleanuppad"); let name = const_cstr!("cleanuppad");
let ret = unsafe { let ret = unsafe {
llvm::LLVMRustBuildCleanupPad(self.llbuilder, llvm::LLVMRustBuildCleanupPad(self.llbuilder,
@ -1075,7 +1007,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
&mut self, funclet: &Funclet<'ll>, &mut self, funclet: &Funclet<'ll>,
unwind: Option<&'ll BasicBlock>, unwind: Option<&'ll BasicBlock>,
) -> &'ll Value { ) -> &'ll Value {
self.count_insn("cleanupret");
let ret = unsafe { let ret = unsafe {
llvm::LLVMRustBuildCleanupRet(self.llbuilder, funclet.cleanuppad(), unwind) llvm::LLVMRustBuildCleanupRet(self.llbuilder, funclet.cleanuppad(), unwind)
}; };
@ -1085,7 +1016,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
fn catch_pad(&mut self, fn catch_pad(&mut self,
parent: &'ll Value, parent: &'ll Value,
args: &[&'ll Value]) -> Funclet<'ll> { args: &[&'ll Value]) -> Funclet<'ll> {
self.count_insn("catchpad");
let name = const_cstr!("catchpad"); let name = const_cstr!("catchpad");
let ret = unsafe { let ret = unsafe {
llvm::LLVMRustBuildCatchPad(self.llbuilder, parent, llvm::LLVMRustBuildCatchPad(self.llbuilder, parent,
@ -1101,7 +1031,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
unwind: Option<&'ll BasicBlock>, unwind: Option<&'ll BasicBlock>,
num_handlers: usize, num_handlers: usize,
) -> &'ll Value { ) -> &'ll Value {
self.count_insn("catchswitch");
let name = const_cstr!("catchswitch"); let name = const_cstr!("catchswitch");
let ret = unsafe { let ret = unsafe {
llvm::LLVMRustBuildCatchSwitch(self.llbuilder, parent, unwind, llvm::LLVMRustBuildCatchSwitch(self.llbuilder, parent, unwind,
@ -1199,7 +1128,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
args: &[&'ll Value], args: &[&'ll Value],
funclet: Option<&Funclet<'ll>>, funclet: Option<&Funclet<'ll>>,
) -> &'ll Value { ) -> &'ll Value {
self.count_insn("call");
debug!("Call {:?} with args ({:?})", debug!("Call {:?} with args ({:?})",
llfn, llfn,
@ -1221,7 +1149,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
} }
fn zext(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value { fn zext(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
self.count_insn("zext");
unsafe { unsafe {
llvm::LLVMBuildZExt(self.llbuilder, val, dest_ty, noname()) llvm::LLVMBuildZExt(self.llbuilder, val, dest_ty, noname())
} }
@ -1285,19 +1212,6 @@ impl Builder<'a, 'll, 'tcx> {
} }
} }
fn count_insn(&self, category: &str) {
if self.sess().codegen_stats() {
self.stats.borrow_mut().n_llvm_insns += 1;
}
if self.sess().count_llvm_insns() {
*self.stats
.borrow_mut()
.llvm_insns
.entry(category.to_string())
.or_insert(0) += 1;
}
}
fn position_at_start(&mut self, llbb: &'ll BasicBlock) { fn position_at_start(&mut self, llbb: &'ll BasicBlock) {
unsafe { unsafe {
llvm::LLVMRustPositionBuilderAtStart(self.llbuilder, llbb); llvm::LLVMRustPositionBuilderAtStart(self.llbuilder, llbb);
@ -1305,12 +1219,10 @@ impl Builder<'a, 'll, 'tcx> {
} }
pub fn minnum(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { pub fn minnum(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
self.count_insn("minnum");
unsafe { llvm::LLVMRustBuildMinNum(self.llbuilder, lhs, rhs) } unsafe { llvm::LLVMRustBuildMinNum(self.llbuilder, lhs, rhs) }
} }
pub fn maxnum(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value { pub fn maxnum(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
self.count_insn("maxnum");
unsafe { llvm::LLVMRustBuildMaxNum(self.llbuilder, lhs, rhs) } unsafe { llvm::LLVMRustBuildMaxNum(self.llbuilder, lhs, rhs) }
} }
@ -1319,7 +1231,6 @@ impl Builder<'a, 'll, 'tcx> {
elt: &'ll Value, elt: &'ll Value,
idx: &'ll Value, idx: &'ll Value,
) -> &'ll Value { ) -> &'ll Value {
self.count_insn("insertelement");
unsafe { unsafe {
llvm::LLVMBuildInsertElement(self.llbuilder, vec, elt, idx, noname()) llvm::LLVMBuildInsertElement(self.llbuilder, vec, elt, idx, noname())
} }
@ -1331,14 +1242,12 @@ impl Builder<'a, 'll, 'tcx> {
v2: &'ll Value, v2: &'ll Value,
mask: &'ll Value, mask: &'ll Value,
) -> &'ll Value { ) -> &'ll Value {
self.count_insn("shufflevector");
unsafe { unsafe {
llvm::LLVMBuildShuffleVector(self.llbuilder, v1, v2, mask, noname()) llvm::LLVMBuildShuffleVector(self.llbuilder, v1, v2, mask, noname())
} }
} }
pub fn vector_reduce_fadd_fast(&mut self, acc: &'ll Value, src: &'ll Value) -> &'ll Value { pub fn vector_reduce_fadd_fast(&mut self, acc: &'ll Value, src: &'ll Value) -> &'ll Value {
self.count_insn("vector.reduce.fadd_fast");
unsafe { unsafe {
// FIXME: add a non-fast math version once // FIXME: add a non-fast math version once
// https://bugs.llvm.org/show_bug.cgi?id=36732 // https://bugs.llvm.org/show_bug.cgi?id=36732
@ -1349,7 +1258,6 @@ impl Builder<'a, 'll, 'tcx> {
} }
} }
pub fn vector_reduce_fmul_fast(&mut self, acc: &'ll Value, src: &'ll Value) -> &'ll Value { pub fn vector_reduce_fmul_fast(&mut self, acc: &'ll Value, src: &'ll Value) -> &'ll Value {
self.count_insn("vector.reduce.fmul_fast");
unsafe { unsafe {
// FIXME: add a non-fast math version once // FIXME: add a non-fast math version once
// https://bugs.llvm.org/show_bug.cgi?id=36732 // https://bugs.llvm.org/show_bug.cgi?id=36732
@ -1360,35 +1268,27 @@ impl Builder<'a, 'll, 'tcx> {
} }
} }
pub fn vector_reduce_add(&mut self, src: &'ll Value) -> &'ll Value { pub fn vector_reduce_add(&mut self, src: &'ll Value) -> &'ll Value {
self.count_insn("vector.reduce.add");
unsafe { llvm::LLVMRustBuildVectorReduceAdd(self.llbuilder, src) } unsafe { llvm::LLVMRustBuildVectorReduceAdd(self.llbuilder, src) }
} }
pub fn vector_reduce_mul(&mut self, src: &'ll Value) -> &'ll Value { pub fn vector_reduce_mul(&mut self, src: &'ll Value) -> &'ll Value {
self.count_insn("vector.reduce.mul");
unsafe { llvm::LLVMRustBuildVectorReduceMul(self.llbuilder, src) } unsafe { llvm::LLVMRustBuildVectorReduceMul(self.llbuilder, src) }
} }
pub fn vector_reduce_and(&mut self, src: &'ll Value) -> &'ll Value { pub fn vector_reduce_and(&mut self, src: &'ll Value) -> &'ll Value {
self.count_insn("vector.reduce.and");
unsafe { llvm::LLVMRustBuildVectorReduceAnd(self.llbuilder, src) } unsafe { llvm::LLVMRustBuildVectorReduceAnd(self.llbuilder, src) }
} }
pub fn vector_reduce_or(&mut self, src: &'ll Value) -> &'ll Value { pub fn vector_reduce_or(&mut self, src: &'ll Value) -> &'ll Value {
self.count_insn("vector.reduce.or");
unsafe { llvm::LLVMRustBuildVectorReduceOr(self.llbuilder, src) } unsafe { llvm::LLVMRustBuildVectorReduceOr(self.llbuilder, src) }
} }
pub fn vector_reduce_xor(&mut self, src: &'ll Value) -> &'ll Value { pub fn vector_reduce_xor(&mut self, src: &'ll Value) -> &'ll Value {
self.count_insn("vector.reduce.xor");
unsafe { llvm::LLVMRustBuildVectorReduceXor(self.llbuilder, src) } unsafe { llvm::LLVMRustBuildVectorReduceXor(self.llbuilder, src) }
} }
pub fn vector_reduce_fmin(&mut self, src: &'ll Value) -> &'ll Value { pub fn vector_reduce_fmin(&mut self, src: &'ll Value) -> &'ll Value {
self.count_insn("vector.reduce.fmin");
unsafe { llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ false) } unsafe { llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ false) }
} }
pub fn vector_reduce_fmax(&mut self, src: &'ll Value) -> &'ll Value { pub fn vector_reduce_fmax(&mut self, src: &'ll Value) -> &'ll Value {
self.count_insn("vector.reduce.fmax");
unsafe { llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ false) } unsafe { llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ false) }
} }
pub fn vector_reduce_fmin_fast(&mut self, src: &'ll Value) -> &'ll Value { pub fn vector_reduce_fmin_fast(&mut self, src: &'ll Value) -> &'ll Value {
self.count_insn("vector.reduce.fmin_fast");
unsafe { unsafe {
let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ true); let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ true);
llvm::LLVMRustSetHasUnsafeAlgebra(instr); llvm::LLVMRustSetHasUnsafeAlgebra(instr);
@ -1396,7 +1296,6 @@ impl Builder<'a, 'll, 'tcx> {
} }
} }
pub fn vector_reduce_fmax_fast(&mut self, src: &'ll Value) -> &'ll Value { pub fn vector_reduce_fmax_fast(&mut self, src: &'ll Value) -> &'ll Value {
self.count_insn("vector.reduce.fmax_fast");
unsafe { unsafe {
let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ true); let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ true);
llvm::LLVMRustSetHasUnsafeAlgebra(instr); llvm::LLVMRustSetHasUnsafeAlgebra(instr);
@ -1404,11 +1303,9 @@ impl Builder<'a, 'll, 'tcx> {
} }
} }
pub fn vector_reduce_min(&mut self, src: &'ll Value, is_signed: bool) -> &'ll Value { pub fn vector_reduce_min(&mut self, src: &'ll Value, is_signed: bool) -> &'ll Value {
self.count_insn("vector.reduce.min");
unsafe { llvm::LLVMRustBuildVectorReduceMin(self.llbuilder, src, is_signed) } unsafe { llvm::LLVMRustBuildVectorReduceMin(self.llbuilder, src, is_signed) }
} }
pub fn vector_reduce_max(&mut self, src: &'ll Value, is_signed: bool) -> &'ll Value { pub fn vector_reduce_max(&mut self, src: &'ll Value, is_signed: bool) -> &'ll Value {
self.count_insn("vector.reduce.max");
unsafe { llvm::LLVMRustBuildVectorReduceMax(self.llbuilder, src, is_signed) } unsafe { llvm::LLVMRustBuildVectorReduceMax(self.llbuilder, src, is_signed) }
} }
@ -1419,7 +1316,6 @@ impl Builder<'a, 'll, 'tcx> {
} }
pub fn catch_ret(&mut self, funclet: &Funclet<'ll>, unwind: &'ll BasicBlock) -> &'ll Value { pub fn catch_ret(&mut self, funclet: &Funclet<'ll>, unwind: &'ll BasicBlock) -> &'ll Value {
self.count_insn("catchret");
let ret = unsafe { let ret = unsafe {
llvm::LLVMRustBuildCatchRet(self.llbuilder, funclet.cleanuppad(), unwind) llvm::LLVMRustBuildCatchRet(self.llbuilder, funclet.cleanuppad(), unwind)
}; };
@ -1488,7 +1384,6 @@ impl Builder<'a, 'll, 'tcx> {
} }
pub fn va_arg(&mut self, list: &'ll Value, ty: &'ll Type) -> &'ll Value { pub fn va_arg(&mut self, list: &'ll Value, ty: &'ll Type) -> &'ll Value {
self.count_insn("vaarg");
unsafe { unsafe {
llvm::LLVMBuildVAArg(self.llbuilder, list, ty, noname()) llvm::LLVMBuildVAArg(self.llbuilder, list, ty, noname())
} }
@ -1511,7 +1406,6 @@ impl Builder<'a, 'll, 'tcx> {
} }
fn phi(&mut self, ty: &'ll Type, vals: &[&'ll Value], bbs: &[&'ll BasicBlock]) -> &'ll Value { fn phi(&mut self, ty: &'ll Type, vals: &[&'ll Value], bbs: &[&'ll BasicBlock]) -> &'ll Value {
self.count_insn("addincoming");
assert_eq!(vals.len(), bbs.len()); assert_eq!(vals.len(), bbs.len());
let phi = unsafe { let phi = unsafe {
llvm::LLVMBuildPhi(self.llbuilder, ty, noname()) llvm::LLVMBuildPhi(self.llbuilder, ty, noname())
@ -1525,7 +1419,6 @@ impl Builder<'a, 'll, 'tcx> {
} }
fn add_incoming_to_phi(&mut self, phi: &'ll Value, val: &'ll Value, bb: &'ll BasicBlock) { fn add_incoming_to_phi(&mut self, phi: &'ll Value, val: &'ll Value, bb: &'ll BasicBlock) {
self.count_insn("addincoming");
unsafe { unsafe {
llvm::LLVMAddIncoming(phi, &val, &bb, 1 as c_uint); llvm::LLVMAddIncoming(phi, &val, &bb, 1 as c_uint);
} }

View file

@ -12,7 +12,6 @@ use rustc_codegen_ssa::traits::*;
use rustc_data_structures::base_n; use rustc_data_structures::base_n;
use rustc_data_structures::small_c_str::SmallCStr; use rustc_data_structures::small_c_str::SmallCStr;
use rustc::mir::mono::Stats;
use rustc::session::config::{self, DebugInfo}; use rustc::session::config::{self, DebugInfo};
use rustc::session::Session; use rustc::session::Session;
use rustc::ty::layout::{ use rustc::ty::layout::{
@ -44,7 +43,6 @@ pub struct CodegenCx<'ll, 'tcx: 'll> {
pub llmod: &'ll llvm::Module, pub llmod: &'ll llvm::Module,
pub llcx: &'ll llvm::Context, pub llcx: &'ll llvm::Context,
pub stats: RefCell<Stats>,
pub codegen_unit: Arc<CodegenUnit<'tcx>>, pub codegen_unit: Arc<CodegenUnit<'tcx>>,
/// Cache instances of monomorphic and polymorphic items /// Cache instances of monomorphic and polymorphic items
@ -284,7 +282,6 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
tls_model, tls_model,
llmod, llmod,
llcx, llcx,
stats: RefCell::new(Stats::default()),
codegen_unit, codegen_unit,
instances: Default::default(), instances: Default::default(),
vtables: Default::default(), vtables: Default::default(),
@ -408,14 +405,6 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> {
self.check_overflow self.check_overflow
} }
fn stats(&self) -> &RefCell<Stats> {
&self.stats
}
fn consume_stats(self) -> RefCell<Stats> {
self.stats
}
fn codegen_unit(&self) -> &Arc<CodegenUnit<'tcx>> { fn codegen_unit(&self) -> &Arc<CodegenUnit<'tcx>> {
&self.codegen_unit &self.codegen_unit
} }

View file

@ -52,7 +52,6 @@ use rustc_codegen_ssa::CompiledModule;
use errors::{FatalError, Handler}; use errors::{FatalError, Handler};
use rustc::dep_graph::WorkProduct; use rustc::dep_graph::WorkProduct;
use syntax_pos::symbol::InternedString; use syntax_pos::symbol::InternedString;
use rustc::mir::mono::Stats;
pub use llvm_util::target_features; pub use llvm_util::target_features;
use std::any::Any; use std::any::Any;
use std::sync::{mpsc, Arc}; use std::sync::{mpsc, Arc};
@ -130,8 +129,8 @@ impl ExtraBackendMethods for LlvmCodegenBackend {
&self, &self,
tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>,
cgu_name: InternedString, cgu_name: InternedString,
) -> Stats { ) {
base::compile_codegen_unit(tcx, cgu_name) base::compile_codegen_unit(tcx, cgu_name);
} }
fn target_machine_factory( fn target_machine_factory(
&self, &self,

View file

@ -20,7 +20,7 @@ use rustc::hir::def_id::{DefId, LOCAL_CRATE};
use rustc::middle::cstore::EncodedMetadata; use rustc::middle::cstore::EncodedMetadata;
use rustc::middle::lang_items::StartFnLangItem; use rustc::middle::lang_items::StartFnLangItem;
use rustc::middle::weak_lang_items; use rustc::middle::weak_lang_items;
use rustc::mir::mono::{Stats, CodegenUnitNameBuilder}; use rustc::mir::mono::CodegenUnitNameBuilder;
use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, VariantIdx, HasTyCtxt}; use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, VariantIdx, HasTyCtxt};
use rustc::ty::query::Providers; use rustc::ty::query::Providers;
@ -28,7 +28,6 @@ use rustc::middle::cstore::{self, LinkagePreference};
use rustc::util::common::{time, print_time_passes_entry}; use rustc::util::common::{time, print_time_passes_entry};
use rustc::session::config::{self, EntryFnType, Lto}; use rustc::session::config::{self, EntryFnType, Lto};
use rustc::session::Session; use rustc::session::Session;
use rustc_mir::monomorphize::item::DefPathBasedNames;
use rustc_mir::monomorphize::Instance; use rustc_mir::monomorphize::Instance;
use rustc_mir::monomorphize::partitioning::{CodegenUnit, CodegenUnitExt}; use rustc_mir::monomorphize::partitioning::{CodegenUnit, CodegenUnitExt};
use rustc::util::nodemap::FxHashMap; use rustc::util::nodemap::FxHashMap;
@ -58,40 +57,6 @@ use rustc::hir;
use crate::mir::operand::OperandValue; use crate::mir::operand::OperandValue;
use std::marker::PhantomData;
pub struct StatRecorder<'a, 'tcx, Cx: 'a + CodegenMethods<'tcx>> {
cx: &'a Cx,
name: Option<String>,
istart: usize,
_marker: PhantomData<&'tcx ()>,
}
impl<'a, 'tcx, Cx: CodegenMethods<'tcx>> StatRecorder<'a, 'tcx, Cx> {
pub fn new(cx: &'a Cx, name: String) -> Self {
let istart = cx.stats().borrow().n_llvm_insns;
StatRecorder {
cx,
name: Some(name),
istart,
_marker: PhantomData,
}
}
}
impl<'a, 'tcx, Cx: CodegenMethods<'tcx>> Drop for StatRecorder<'a, 'tcx, Cx> {
fn drop(&mut self) {
if self.cx.sess().codegen_stats() {
let mut stats = self.cx.stats().borrow_mut();
let iend = stats.n_llvm_insns;
stats.fn_stats.push((self.name.take().unwrap(), iend - self.istart));
stats.n_fns += 1;
// Reset LLVM insn count to avoid compound costs.
stats.n_llvm_insns = self.istart;
}
}
}
pub fn bin_op_to_icmp_predicate(op: hir::BinOpKind, pub fn bin_op_to_icmp_predicate(op: hir::BinOpKind,
signed: bool) signed: bool)
-> IntPredicate { -> IntPredicate {
@ -408,15 +373,6 @@ pub fn codegen_instance<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
cx: &'a Bx::CodegenCx, cx: &'a Bx::CodegenCx,
instance: Instance<'tcx>, instance: Instance<'tcx>,
) { ) {
let _s = if cx.sess().codegen_stats() {
let mut instance_name = String::new();
DefPathBasedNames::new(cx.tcx(), true, true)
.push_def_path(instance.def_id(), &mut instance_name);
Some(StatRecorder::new(cx, instance_name))
} else {
None
};
// this is an info! to allow collecting monomorphization statistics // this is an info! to allow collecting monomorphization statistics
// and to allow finding the last function before LLVM aborts from // and to allow finding the last function before LLVM aborts from
// release builds. // release builds.
@ -428,8 +384,6 @@ pub fn codegen_instance<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
let lldecl = cx.instances().borrow().get(&instance).cloned().unwrap_or_else(|| let lldecl = cx.instances().borrow().get(&instance).cloned().unwrap_or_else(||
bug!("Instance `{:?}` not already declared", instance)); bug!("Instance `{:?}` not already declared", instance));
cx.stats().borrow_mut().n_closures += 1;
let mir = cx.tcx().instance_mir(instance.def); let mir = cx.tcx().instance_mir(instance.def);
mir::codegen_mir::<Bx>(cx, lldecl, &mir, instance, sig); mir::codegen_mir::<Bx>(cx, lldecl, &mir, instance, sig);
} }
@ -653,7 +607,6 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
}; };
let mut total_codegen_time = Duration::new(0, 0); let mut total_codegen_time = Duration::new(0, 0);
let mut all_stats = Stats::default();
for cgu in codegen_units.into_iter() { for cgu in codegen_units.into_iter() {
ongoing_codegen.wait_for_signal_to_codegen_item(); ongoing_codegen.wait_for_signal_to_codegen_item();
@ -666,8 +619,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
CguReuse::No => { CguReuse::No => {
tcx.sess.profiler(|p| p.start_activity(format!("codegen {}", cgu.name()))); tcx.sess.profiler(|p| p.start_activity(format!("codegen {}", cgu.name())));
let start_time = Instant::now(); let start_time = Instant::now();
let stats = backend.compile_codegen_unit(tcx, *cgu.name()); backend.compile_codegen_unit(tcx, *cgu.name());
all_stats.extend(stats);
total_codegen_time += start_time.elapsed(); total_codegen_time += start_time.elapsed();
tcx.sess.profiler(|p| p.end_activity(format!("codegen {}", cgu.name()))); tcx.sess.profiler(|p| p.end_activity(format!("codegen {}", cgu.name())));
false false
@ -701,28 +653,6 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
symbol_names_test::report_symbol_names(tcx); symbol_names_test::report_symbol_names(tcx);
if tcx.sess.codegen_stats() {
println!("--- codegen stats ---");
println!("n_glues_created: {}", all_stats.n_glues_created);
println!("n_null_glues: {}", all_stats.n_null_glues);
println!("n_real_glues: {}", all_stats.n_real_glues);
println!("n_fns: {}", all_stats.n_fns);
println!("n_inlines: {}", all_stats.n_inlines);
println!("n_closures: {}", all_stats.n_closures);
println!("fn stats:");
all_stats.fn_stats.sort_by_key(|&(_, insns)| insns);
for &(ref name, insns) in all_stats.fn_stats.iter() {
println!("{} insns, {}", insns, *name);
}
}
if tcx.sess.count_llvm_insns() {
for (k, v) in all_stats.llvm_insns.iter() {
println!("{:7} {}", *v, *k);
}
}
ongoing_codegen.check_for_errors(tcx.sess); ongoing_codegen.check_for_errors(tcx.sess);
assert_and_save_dep_graph(tcx); assert_and_save_dep_graph(tcx);

View file

@ -396,22 +396,20 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
let cx = self.cx; let cx = self.cx;
let tcx = self.cx.tcx(); let tcx = self.cx.tcx();
if let mir::Place::Base(mir::PlaceBase::Local(index)) = *place { let result = match *place {
match self.locals[index] { mir::Place::Base(mir::PlaceBase::Local(index)) => {
LocalRef::Place(place) => { match self.locals[index] {
return place; LocalRef::Place(place) => {
} return place;
LocalRef::UnsizedPlace(place) => { }
return bx.load_operand(place).deref(cx); LocalRef::UnsizedPlace(place) => {
} return bx.load_operand(place).deref(cx);
LocalRef::Operand(..) => { }
bug!("using operand local {:?} as place", place); LocalRef::Operand(..) => {
bug!("using operand local {:?} as place", place);
}
} }
} }
}
let result = match *place {
mir::Place::Base(mir::PlaceBase::Local(_)) => bug!(), // handled above
mir::Place::Base( mir::Place::Base(
mir::PlaceBase::Static( mir::PlaceBase::Static(
box mir::Static { ty, kind: mir::StaticKind::Promoted(promoted) } box mir::Static { ty, kind: mir::StaticKind::Promoted(promoted) }

View file

@ -5,7 +5,6 @@ use super::write::WriteBackendMethods;
use super::CodegenObject; use super::CodegenObject;
use rustc::middle::allocator::AllocatorKind; use rustc::middle::allocator::AllocatorKind;
use rustc::middle::cstore::EncodedMetadata; use rustc::middle::cstore::EncodedMetadata;
use rustc::mir::mono::Stats;
use rustc::session::{Session, config}; use rustc::session::{Session, config};
use rustc::ty::TyCtxt; use rustc::ty::TyCtxt;
use rustc_codegen_utils::codegen_backend::CodegenBackend; use rustc_codegen_utils::codegen_backend::CodegenBackend;
@ -49,7 +48,7 @@ pub trait ExtraBackendMethods: CodegenBackend + WriteBackendMethods + Sized + Se
&self, &self,
tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>,
cgu_name: InternedString, cgu_name: InternedString,
) -> Stats; );
// If find_features is true this won't access `sess.crate_types` by assuming // If find_features is true this won't access `sess.crate_types` by assuming
// that `is_pie_binary` is false. When we discover LLVM target features // that `is_pie_binary` is false. When we discover LLVM target features
// `sess.crate_types` is uninitialized so we cannot access it. // `sess.crate_types` is uninitialized so we cannot access it.

View file

@ -1,5 +1,4 @@
use super::BackendTypes; use super::BackendTypes;
use rustc::mir::mono::Stats;
use rustc::session::Session; use rustc::session::Session;
use rustc::ty::{self, Instance, Ty}; use rustc::ty::{self, Instance, Ty};
use rustc::util::nodemap::FxHashMap; use rustc::util::nodemap::FxHashMap;
@ -17,8 +16,6 @@ pub trait MiscMethods<'tcx>: BackendTypes {
fn eh_personality(&self) -> Self::Value; fn eh_personality(&self) -> Self::Value;
fn eh_unwind_resume(&self) -> Self::Value; fn eh_unwind_resume(&self) -> Self::Value;
fn sess(&self) -> &Session; fn sess(&self) -> &Session;
fn stats(&self) -> &RefCell<Stats>;
fn consume_stats(self) -> RefCell<Stats>;
fn codegen_unit(&self) -> &Arc<CodegenUnit<'tcx>>; fn codegen_unit(&self) -> &Arc<CodegenUnit<'tcx>>;
fn used_statics(&self) -> &RefCell<Vec<Self::Value>>; fn used_statics(&self) -> &RefCell<Vec<Self::Value>>;
fn set_frame_pointer_elimination(&self, llfn: Self::Value); fn set_frame_pointer_elimination(&self, llfn: Self::Value);

View file

@ -212,6 +212,11 @@ macro_rules! newtype_index {
fn add_usize(&self, u: usize) -> Option<Self> { fn add_usize(&self, u: usize) -> Option<Self> {
Idx::index(*self).checked_add(u).map(Self::new) Idx::index(*self).checked_add(u).map(Self::new)
} }
#[inline]
fn sub_usize(&self, u: usize) -> Option<Self> {
Idx::index(*self).checked_sub(u).map(Self::new)
}
} }
impl From<$type> for u32 { impl From<$type> for u32 {

View file

@ -162,6 +162,7 @@ impl ColorConfig {
} }
} }
/// Handles the writing of `HumanReadableErrorType::Default` and `HumanReadableErrorType::Short`
pub struct EmitterWriter { pub struct EmitterWriter {
dst: Destination, dst: Destination,
sm: Option<Lrc<SourceMapperDyn>>, sm: Option<Lrc<SourceMapperDyn>>,
@ -170,7 +171,8 @@ pub struct EmitterWriter {
ui_testing: bool, ui_testing: bool,
} }
struct FileWithAnnotatedLines { #[derive(Debug)]
pub struct FileWithAnnotatedLines {
file: Lrc<SourceFile>, file: Lrc<SourceFile>,
lines: Vec<Line>, lines: Vec<Line>,
multiline_depth: usize, multiline_depth: usize,
@ -221,169 +223,6 @@ impl EmitterWriter {
} }
} }
fn preprocess_annotations(&mut self, msp: &MultiSpan) -> Vec<FileWithAnnotatedLines> {
fn add_annotation_to_file(file_vec: &mut Vec<FileWithAnnotatedLines>,
file: Lrc<SourceFile>,
line_index: usize,
ann: Annotation) {
for slot in file_vec.iter_mut() {
// Look through each of our files for the one we're adding to
if slot.file.name == file.name {
// See if we already have a line for it
for line_slot in &mut slot.lines {
if line_slot.line_index == line_index {
line_slot.annotations.push(ann);
return;
}
}
// We don't have a line yet, create one
slot.lines.push(Line {
line_index,
annotations: vec![ann],
});
slot.lines.sort();
return;
}
}
// This is the first time we're seeing the file
file_vec.push(FileWithAnnotatedLines {
file,
lines: vec![Line {
line_index,
annotations: vec![ann],
}],
multiline_depth: 0,
});
}
let mut output = vec![];
let mut multiline_annotations = vec![];
if let Some(ref sm) = self.sm {
for span_label in msp.span_labels() {
if span_label.span.is_dummy() {
continue;
}
let lo = sm.lookup_char_pos(span_label.span.lo());
let mut hi = sm.lookup_char_pos(span_label.span.hi());
// Watch out for "empty spans". If we get a span like 6..6, we
// want to just display a `^` at 6, so convert that to
// 6..7. This is degenerate input, but it's best to degrade
// gracefully -- and the parser likes to supply a span like
// that for EOF, in particular.
if lo.col_display == hi.col_display && lo.line == hi.line {
hi.col_display += 1;
}
let ann_type = if lo.line != hi.line {
let ml = MultilineAnnotation {
depth: 1,
line_start: lo.line,
line_end: hi.line,
start_col: lo.col_display,
end_col: hi.col_display,
is_primary: span_label.is_primary,
label: span_label.label.clone(),
overlaps_exactly: false,
};
multiline_annotations.push((lo.file.clone(), ml.clone()));
AnnotationType::Multiline(ml)
} else {
AnnotationType::Singleline
};
let ann = Annotation {
start_col: lo.col_display,
end_col: hi.col_display,
is_primary: span_label.is_primary,
label: span_label.label.clone(),
annotation_type: ann_type,
};
if !ann.is_multiline() {
add_annotation_to_file(&mut output, lo.file, lo.line, ann);
}
}
}
// Find overlapping multiline annotations, put them at different depths
multiline_annotations.sort_by_key(|&(_, ref ml)| (ml.line_start, ml.line_end));
for item in multiline_annotations.clone() {
let ann = item.1;
for item in multiline_annotations.iter_mut() {
let ref mut a = item.1;
// Move all other multiline annotations overlapping with this one
// one level to the right.
if !(ann.same_span(a)) &&
num_overlap(ann.line_start, ann.line_end, a.line_start, a.line_end, true)
{
a.increase_depth();
} else if ann.same_span(a) && &ann != a {
a.overlaps_exactly = true;
} else {
break;
}
}
}
let mut max_depth = 0; // max overlapping multiline spans
for (file, ann) in multiline_annotations {
if ann.depth > max_depth {
max_depth = ann.depth;
}
let mut end_ann = ann.as_end();
if !ann.overlaps_exactly {
// avoid output like
//
// | foo(
// | _____^
// | |_____|
// | || bar,
// | || );
// | || ^
// | ||______|
// | |______foo
// | baz
//
// and instead get
//
// | foo(
// | _____^
// | | bar,
// | | );
// | | ^
// | | |
// | |______foo
// | baz
add_annotation_to_file(&mut output, file.clone(), ann.line_start, ann.as_start());
// 4 is the minimum vertical length of a multiline span when presented: two lines
// of code and two lines of underline. This is not true for the special case where
// the beginning doesn't have an underline, but the current logic seems to be
// working correctly.
let middle = min(ann.line_start + 4, ann.line_end);
for line in ann.line_start + 1..middle {
// Every `|` that joins the beginning of the span (`___^`) to the end (`|__^`).
add_annotation_to_file(&mut output, file.clone(), line, ann.as_line());
}
if middle < ann.line_end - 1 {
for line in ann.line_end - 1..ann.line_end {
add_annotation_to_file(&mut output, file.clone(), line, ann.as_line());
}
}
} else {
end_ann.annotation_type = AnnotationType::Singleline;
}
add_annotation_to_file(&mut output, file, ann.line_end, end_ann);
}
for file_vec in output.iter_mut() {
file_vec.multiline_depth = max_depth;
}
output
}
fn render_source_line(&self, fn render_source_line(&self,
buffer: &mut StyledBuffer, buffer: &mut StyledBuffer,
file: Lrc<SourceFile>, file: Lrc<SourceFile>,
@ -1093,9 +932,7 @@ impl EmitterWriter {
} }
} }
// Preprocess all the annotations so that they are grouped by file and by line number let mut annotated_files = FileWithAnnotatedLines::collect_annotations(msp, &self.sm);
// This helps us quickly iterate over the whole message (including secondary file spans)
let mut annotated_files = self.preprocess_annotations(msp);
// Make sure our primary file comes first // Make sure our primary file comes first
let (primary_lo, sm) = if let (Some(sm), Some(ref primary_span)) = let (primary_lo, sm) = if let (Some(sm), Some(ref primary_span)) =
@ -1503,6 +1340,176 @@ impl EmitterWriter {
} }
} }
impl FileWithAnnotatedLines {
/// Preprocess all the annotations so that they are grouped by file and by line number
/// This helps us quickly iterate over the whole message (including secondary file spans)
pub fn collect_annotations(
msp: &MultiSpan,
source_map: &Option<Lrc<SourceMapperDyn>>
) -> Vec<FileWithAnnotatedLines> {
fn add_annotation_to_file(file_vec: &mut Vec<FileWithAnnotatedLines>,
file: Lrc<SourceFile>,
line_index: usize,
ann: Annotation) {
for slot in file_vec.iter_mut() {
// Look through each of our files for the one we're adding to
if slot.file.name == file.name {
// See if we already have a line for it
for line_slot in &mut slot.lines {
if line_slot.line_index == line_index {
line_slot.annotations.push(ann);
return;
}
}
// We don't have a line yet, create one
slot.lines.push(Line {
line_index,
annotations: vec![ann],
});
slot.lines.sort();
return;
}
}
// This is the first time we're seeing the file
file_vec.push(FileWithAnnotatedLines {
file,
lines: vec![Line {
line_index,
annotations: vec![ann],
}],
multiline_depth: 0,
});
}
let mut output = vec![];
let mut multiline_annotations = vec![];
if let Some(ref sm) = source_map {
for span_label in msp.span_labels() {
if span_label.span.is_dummy() {
continue;
}
let lo = sm.lookup_char_pos(span_label.span.lo());
let mut hi = sm.lookup_char_pos(span_label.span.hi());
// Watch out for "empty spans". If we get a span like 6..6, we
// want to just display a `^` at 6, so convert that to
// 6..7. This is degenerate input, but it's best to degrade
// gracefully -- and the parser likes to supply a span like
// that for EOF, in particular.
if lo.col_display == hi.col_display && lo.line == hi.line {
hi.col_display += 1;
}
let ann_type = if lo.line != hi.line {
let ml = MultilineAnnotation {
depth: 1,
line_start: lo.line,
line_end: hi.line,
start_col: lo.col_display,
end_col: hi.col_display,
is_primary: span_label.is_primary,
label: span_label.label.clone(),
overlaps_exactly: false,
};
multiline_annotations.push((lo.file.clone(), ml.clone()));
AnnotationType::Multiline(ml)
} else {
AnnotationType::Singleline
};
let ann = Annotation {
start_col: lo.col_display,
end_col: hi.col_display,
is_primary: span_label.is_primary,
label: span_label.label.clone(),
annotation_type: ann_type,
};
if !ann.is_multiline() {
add_annotation_to_file(&mut output, lo.file, lo.line, ann);
}
}
}
// Find overlapping multiline annotations, put them at different depths
multiline_annotations.sort_by_key(|&(_, ref ml)| (ml.line_start, ml.line_end));
for item in multiline_annotations.clone() {
let ann = item.1;
for item in multiline_annotations.iter_mut() {
let ref mut a = item.1;
// Move all other multiline annotations overlapping with this one
// one level to the right.
if !(ann.same_span(a)) &&
num_overlap(ann.line_start, ann.line_end, a.line_start, a.line_end, true)
{
a.increase_depth();
} else if ann.same_span(a) && &ann != a {
a.overlaps_exactly = true;
} else {
break;
}
}
}
let mut max_depth = 0; // max overlapping multiline spans
for (file, ann) in multiline_annotations {
if ann.depth > max_depth {
max_depth = ann.depth;
}
let mut end_ann = ann.as_end();
if !ann.overlaps_exactly {
// avoid output like
//
// | foo(
// | _____^
// | |_____|
// | || bar,
// | || );
// | || ^
// | ||______|
// | |______foo
// | baz
//
// and instead get
//
// | foo(
// | _____^
// | | bar,
// | | );
// | | ^
// | | |
// | |______foo
// | baz
add_annotation_to_file(&mut output, file.clone(), ann.line_start, ann.as_start());
// 4 is the minimum vertical length of a multiline span when presented: two lines
// of code and two lines of underline. This is not true for the special case where
// the beginning doesn't have an underline, but the current logic seems to be
// working correctly.
let middle = min(ann.line_start + 4, ann.line_end);
for line in ann.line_start + 1..middle {
// Every `|` that joins the beginning of the span (`___^`) to the end (`|__^`).
add_annotation_to_file(&mut output, file.clone(), line, ann.as_line());
}
if middle < ann.line_end - 1 {
for line in ann.line_end - 1..ann.line_end {
add_annotation_to_file(&mut output, file.clone(), line, ann.as_line());
}
}
} else {
end_ann.annotation_type = AnnotationType::Singleline;
}
add_annotation_to_file(&mut output, file, ann.line_end, end_ann);
}
for file_vec in output.iter_mut() {
file_vec.multiline_depth = max_depth;
}
output
}
}
fn draw_col_separator(buffer: &mut StyledBuffer, line: usize, col: usize) { fn draw_col_separator(buffer: &mut StyledBuffer, line: usize, col: usize) {
buffer.puts(line, col, "| ", Style::LineNumber); buffer.puts(line, col, "| ", Style::LineNumber);
} }

View file

@ -1616,7 +1616,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
); );
// Find the local from the operand. // Find the local from the operand.
let assigned_from_local = match assigned_from.local() { let assigned_from_local = match assigned_from.local_or_deref_local() {
Some(local) => local, Some(local) => local,
None => continue, None => continue,
}; };
@ -1672,7 +1672,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
); );
// Find the local from the rvalue. // Find the local from the rvalue.
let assigned_from_local = match assigned_from.local() { let assigned_from_local = match assigned_from.local_or_deref_local() {
Some(local) => local, Some(local) => local,
None => continue, None => continue,
}; };
@ -1735,7 +1735,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
assigned_from, assigned_from,
); );
if let Some(assigned_from_local) = assigned_from.local() { if let Some(assigned_from_local) = assigned_from.local_or_deref_local() {
debug!( debug!(
"annotate_argument_and_return_for_borrow: assigned_from_local={:?}", "annotate_argument_and_return_for_borrow: assigned_from_local={:?}",
assigned_from_local, assigned_from_local,

View file

@ -37,15 +37,15 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
diag: &mut DiagnosticBuilder<'_>, diag: &mut DiagnosticBuilder<'_>,
) { ) {
debug!("add_moved_or_invoked_closure_note: location={:?} place={:?}", location, place); debug!("add_moved_or_invoked_closure_note: location={:?} place={:?}", location, place);
let mut target = place.local(); let mut target = place.local_or_deref_local();
for stmt in &self.mir[location.block].statements[location.statement_index..] { for stmt in &self.mir[location.block].statements[location.statement_index..] {
debug!("add_moved_or_invoked_closure_note: stmt={:?} target={:?}", stmt, target); debug!("add_moved_or_invoked_closure_note: stmt={:?} target={:?}", stmt, target);
if let StatementKind::Assign(into, box Rvalue::Use(from)) = &stmt.kind { if let StatementKind::Assign(into, box Rvalue::Use(from)) = &stmt.kind {
debug!("add_fnonce_closure_note: into={:?} from={:?}", into, from); debug!("add_fnonce_closure_note: into={:?} from={:?}", into, from);
match from { match from {
Operand::Copy(ref place) | Operand::Copy(ref place) |
Operand::Move(ref place) if target == place.local() => Operand::Move(ref place) if target == place.local_or_deref_local() =>
target = into.local(), target = into.local_or_deref_local(),
_ => {}, _ => {},
} }
} }
@ -69,8 +69,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
if self.infcx.tcx.parent(id) == self.infcx.tcx.lang_items().fn_once_trait() { if self.infcx.tcx.parent(id) == self.infcx.tcx.lang_items().fn_once_trait() {
let closure = match args.first() { let closure = match args.first() {
Some(Operand::Copy(ref place)) | Some(Operand::Copy(ref place)) |
Some(Operand::Move(ref place)) if target == place.local() => Some(Operand::Move(ref place)) if target == place.local_or_deref_local() =>
place.local().unwrap(), place.local_or_deref_local().unwrap(),
_ => return, _ => return,
}; };

View file

@ -528,7 +528,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
}) => { }) => {
// Not projected from the implicit `self` in a closure. // Not projected from the implicit `self` in a closure.
debug_assert!( debug_assert!(
match base.local() { match base.local_or_deref_local() {
Some(local) => local == Local::new(1), Some(local) => local == Local::new(1),
None => false, None => false,
}, },

View file

@ -46,8 +46,10 @@ impl<'a, 'tcx> BitDenotation<'tcx> for MaybeStorageLive<'a, 'tcx> {
sets: &mut BlockSets<'_, Local>, sets: &mut BlockSets<'_, Local>,
loc: Location) { loc: Location) {
match &self.mir[loc.block].terminator().kind { match &self.mir[loc.block].terminator().kind {
TerminatorKind::Drop { location, .. } => if let Some(l) = location.local() { TerminatorKind::Drop { location, .. } => {
sets.kill(l); if let Some(l) = location.local_or_deref_local() {
sets.kill(l);
}
} }
_ => (), _ => (),
} }

View file

@ -1703,8 +1703,13 @@ impl<'a, 'tcx> PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> {
} }
} }
fn check_trait_or_impl_item(&self, hir_id: hir::HirId, assoc_item_kind: AssocItemKind, fn check_assoc_item(
defaultness: hir::Defaultness, vis: ty::Visibility) { &self,
hir_id: hir::HirId,
assoc_item_kind: AssocItemKind,
defaultness: hir::Defaultness,
vis: ty::Visibility,
) {
let mut check = self.check(hir_id, vis); let mut check = self.check(hir_id, vis);
let (check_ty, is_assoc_ty) = match assoc_item_kind { let (check_ty, is_assoc_ty) = match assoc_item_kind {
@ -1754,8 +1759,12 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx>
self.check(item.hir_id, item_visibility).generics().predicates(); self.check(item.hir_id, item_visibility).generics().predicates();
for trait_item_ref in trait_item_refs { for trait_item_ref in trait_item_refs {
self.check_trait_or_impl_item(trait_item_ref.id.hir_id, trait_item_ref.kind, self.check_assoc_item(
trait_item_ref.defaultness, item_visibility); trait_item_ref.id.hir_id,
trait_item_ref.kind,
trait_item_ref.defaultness,
item_visibility,
);
} }
} }
hir::ItemKind::TraitAlias(..) => { hir::ItemKind::TraitAlias(..) => {
@ -1803,8 +1812,12 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx>
} else { } else {
impl_vis impl_vis
}; };
self.check_trait_or_impl_item(impl_item_ref.id.hir_id, impl_item_ref.kind, self.check_assoc_item(
impl_item_ref.defaultness, impl_item_vis); impl_item_ref.id.hir_id,
impl_item_ref.kind,
impl_item_ref.defaultness,
impl_item_vis,
);
} }
} }
} }

View file

@ -860,7 +860,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
FnKind::ItemFn(_, ref header, ..) => FnKind::ItemFn(_, ref header, ..) =>
(FnItemRibKind, &header.asyncness.node), (FnItemRibKind, &header.asyncness.node),
FnKind::Method(_, ref sig, _, _) => FnKind::Method(_, ref sig, _, _) =>
(TraitOrImplItemRibKind, &sig.header.asyncness.node), (AssocItemRibKind, &sig.header.asyncness.node),
FnKind::Closure(_) => FnKind::Closure(_) =>
// Async closures aren't resolved through `visit_fn`-- they're // Async closures aren't resolved through `visit_fn`-- they're
// processed separately // processed separately
@ -1033,7 +1033,7 @@ enum RibKind<'a> {
/// methods or associated types. Allow references to ty params that impl or trait /// methods or associated types. Allow references to ty params that impl or trait
/// binds. Disallow any other upvars (including other ty params that are /// binds. Disallow any other upvars (including other ty params that are
/// upvars). /// upvars).
TraitOrImplItemRibKind, AssocItemRibKind,
/// We passed through a function definition. Disallow upvars. /// We passed through a function definition. Disallow upvars.
/// Permit only those const parameters that are specified in the function's generics. /// Permit only those const parameters that are specified in the function's generics.
@ -2612,7 +2612,7 @@ impl<'a> Resolver<'a> {
for trait_item in trait_items { for trait_item in trait_items {
let generic_params = HasGenericParams(&trait_item.generics, let generic_params = HasGenericParams(&trait_item.generics,
TraitOrImplItemRibKind); AssocItemRibKind);
this.with_generic_param_rib(generic_params, |this| { this.with_generic_param_rib(generic_params, |this| {
match trait_item.node { match trait_item.node {
TraitItemKind::Const(ref ty, ref default) => { TraitItemKind::Const(ref ty, ref default) => {
@ -2899,7 +2899,7 @@ impl<'a> Resolver<'a> {
// We also need a new scope for the impl item type parameters. // We also need a new scope for the impl item type parameters.
let generic_params = HasGenericParams(&impl_item.generics, let generic_params = HasGenericParams(&impl_item.generics,
TraitOrImplItemRibKind); AssocItemRibKind);
this.with_generic_param_rib(generic_params, |this| { this.with_generic_param_rib(generic_params, |this| {
use self::ResolutionError::*; use self::ResolutionError::*;
match impl_item.node { match impl_item.node {
@ -4074,7 +4074,7 @@ impl<'a> Resolver<'a> {
seen.insert(node_id, depth); seen.insert(node_id, depth);
} }
} }
ItemRibKind | FnItemRibKind | TraitOrImplItemRibKind => { ItemRibKind | FnItemRibKind | AssocItemRibKind => {
// This was an attempt to access an upvar inside a // This was an attempt to access an upvar inside a
// named function item. This is not allowed, so we // named function item. This is not allowed, so we
// report an error. // report an error.
@ -4103,7 +4103,7 @@ impl<'a> Resolver<'a> {
Res::Def(DefKind::TyParam, _) | Res::SelfTy(..) => { Res::Def(DefKind::TyParam, _) | Res::SelfTy(..) => {
for rib in ribs { for rib in ribs {
match rib.kind { match rib.kind {
NormalRibKind | TraitOrImplItemRibKind | ClosureRibKind(..) | NormalRibKind | AssocItemRibKind | ClosureRibKind(..) |
ModuleRibKind(..) | MacroDefinition(..) | ForwardTyParamBanRibKind | ModuleRibKind(..) | MacroDefinition(..) | ForwardTyParamBanRibKind |
ConstantItemRibKind | TyParamAsConstParamTy => { ConstantItemRibKind | TyParamAsConstParamTy => {
// Nothing to do. Continue. // Nothing to do. Continue.

View file

@ -158,7 +158,6 @@ impl<R> BufReader<R> {
/// # Examples /// # Examples
/// ///
/// ```no_run /// ```no_run
/// # #![feature(bufreader_buffer)]
/// use std::io::{BufReader, BufRead}; /// use std::io::{BufReader, BufRead};
/// use std::fs::File; /// use std::fs::File;
/// ///
@ -173,7 +172,7 @@ impl<R> BufReader<R> {
/// Ok(()) /// Ok(())
/// } /// }
/// ``` /// ```
#[unstable(feature = "bufreader_buffer", issue = "45323")] #[stable(feature = "bufreader_buffer", since = "1.37.0")]
pub fn buffer(&self) -> &[u8] { pub fn buffer(&self) -> &[u8] {
&self.buf[self.pos..self.cap] &self.buf[self.pos..self.cap]
} }
@ -552,7 +551,6 @@ impl<W: Write> BufWriter<W> {
/// # Examples /// # Examples
/// ///
/// ```no_run /// ```no_run
/// # #![feature(bufreader_buffer)]
/// use std::io::BufWriter; /// use std::io::BufWriter;
/// use std::net::TcpStream; /// use std::net::TcpStream;
/// ///
@ -561,7 +559,7 @@ impl<W: Write> BufWriter<W> {
/// // See how many bytes are currently buffered /// // See how many bytes are currently buffered
/// let bytes_buffered = buf_writer.buffer().len(); /// let bytes_buffered = buf_writer.buffer().len();
/// ``` /// ```
#[unstable(feature = "bufreader_buffer", issue = "45323")] #[stable(feature = "bufreader_buffer", since = "1.37.0")]
pub fn buffer(&self) -> &[u8] { pub fn buffer(&self) -> &[u8] {
&self.buf &self.buf
} }

View file

@ -180,6 +180,10 @@ impl std::iter::Step for NaiveDate {
fn add_usize(&self, _: usize) -> Option<Self> { fn add_usize(&self, _: usize) -> Option<Self> {
unimplemented!() unimplemented!()
} }
fn sub_usize(&self, _: usize) -> Option<Self> {
unimplemented!()
}
} }
#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)] #[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]