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:
commit
81970852e1
29 changed files with 900 additions and 503 deletions
|
@ -239,7 +239,7 @@ use core::fmt;
|
|||
use core::hash::{Hash, Hasher};
|
||||
use core::intrinsics::abort;
|
||||
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::pin::Pin;
|
||||
use core::ptr::{self, NonNull};
|
||||
|
@ -416,11 +416,7 @@ impl<T: ?Sized> Rc<T> {
|
|||
/// ```
|
||||
#[stable(feature = "rc_raw", since = "1.17.0")]
|
||||
pub unsafe fn from_raw(ptr: *const T) -> Self {
|
||||
// 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<()>>();
|
||||
let offset = (layout.size() + layout.padding_needed_for(align)) as isize;
|
||||
let offset = data_offset(ptr);
|
||||
|
||||
// Reverse the offset to find the original RcBox.
|
||||
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"),
|
||||
}
|
||||
}
|
||||
|
||||
/// 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 {
|
||||
|
@ -2007,3 +2140,20 @@ impl<T: ?Sized> AsRef<T> for Rc<T> {
|
|||
|
||||
#[stable(feature = "pin", since = "1.33.0")]
|
||||
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
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ use core::borrow;
|
|||
use core::fmt;
|
||||
use core::cmp::{self, Ordering};
|
||||
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::pin::Pin;
|
||||
use core::ptr::{self, NonNull};
|
||||
|
@ -397,11 +397,7 @@ impl<T: ?Sized> Arc<T> {
|
|||
/// ```
|
||||
#[stable(feature = "rc_raw", since = "1.17.0")]
|
||||
pub unsafe fn from_raw(ptr: *const T) -> Self {
|
||||
// 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<()>>();
|
||||
let offset = (layout.size() + layout.padding_needed_for(align)) as isize;
|
||||
let offset = data_offset(ptr);
|
||||
|
||||
// Reverse the offset to find the original ArcInner.
|
||||
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"),
|
||||
}
|
||||
}
|
||||
|
||||
/// 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> {
|
||||
|
@ -2150,3 +2284,21 @@ impl<T: ?Sized> AsRef<T> for Arc<T> {
|
|||
|
||||
#[stable(feature = "pin", since = "1.33.0")]
|
||||
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
|
||||
}
|
||||
|
|
|
@ -34,6 +34,13 @@ pub trait Step: Clone + PartialOrd + Sized {
|
|||
|
||||
/// Adds a `usize`, returning `None` on overflow.
|
||||
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.
|
||||
|
@ -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!();
|
||||
}
|
||||
)*)
|
||||
|
@ -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!();
|
||||
}
|
||||
)*)
|
||||
|
|
|
@ -223,3 +223,113 @@ impl<T, U, E> Product<Result<U, E>> for Result<T, E>
|
|||
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())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4158,6 +4158,24 @@ impl<'a, T> DoubleEndedIterator for Chunks<'a, T> {
|
|||
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")]
|
||||
|
@ -4649,6 +4667,23 @@ impl<'a, T> DoubleEndedIterator for RChunks<'a, T> {
|
|||
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")]
|
||||
|
@ -4774,6 +4809,24 @@ impl<'a, T> DoubleEndedIterator for RChunksMut<'a, T> {
|
|||
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")]
|
||||
|
@ -4898,6 +4951,24 @@ impl<'a, T> DoubleEndedIterator for RChunksExact<'a, T> {
|
|||
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")]
|
||||
|
@ -5016,6 +5087,25 @@ impl<'a, T> DoubleEndedIterator for RChunksExactMut<'a, T> {
|
|||
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")]
|
||||
|
|
|
@ -1084,6 +1084,14 @@ fn test_iterator_sum_result() {
|
|||
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]
|
||||
fn test_iterator_product() {
|
||||
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]
|
||||
fn test_iterator_max() {
|
||||
let v: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
||||
|
|
|
@ -134,6 +134,30 @@ fn test_chunks_nth() {
|
|||
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]
|
||||
fn test_chunks_last() {
|
||||
let v: &[i32] = &[0, 1, 2, 3, 4, 5];
|
||||
|
@ -356,6 +380,19 @@ fn test_rchunks_nth() {
|
|||
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]
|
||||
fn test_rchunks_last() {
|
||||
let v: &[i32] = &[0, 1, 2, 3, 4, 5];
|
||||
|
@ -407,6 +444,19 @@ fn test_rchunks_mut_nth() {
|
|||
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]
|
||||
fn test_rchunks_mut_last() {
|
||||
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);
|
||||
}
|
||||
|
||||
#[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]
|
||||
fn test_rchunks_exact_last() {
|
||||
let v: &[i32] = &[0, 1, 2, 3, 4, 5];
|
||||
|
@ -518,6 +581,19 @@ fn test_rchunks_exact_mut_nth() {
|
|||
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]
|
||||
fn test_rchunks_exact_mut_last() {
|
||||
let v: &mut [i32] = &mut [0, 1, 2, 3, 4, 5];
|
||||
|
|
|
@ -2037,7 +2037,7 @@ impl<'tcx> Place<'tcx> {
|
|||
/// a single deref of a local.
|
||||
//
|
||||
// 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 {
|
||||
Place::Base(PlaceBase::Local(local)) |
|
||||
Place::Projection(box Projection {
|
||||
|
|
|
@ -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> {
|
||||
tcx: TyCtxt<'a, 'gcx, 'tcx>,
|
||||
cache: FxHashMap<CrateNum, String>,
|
||||
|
|
|
@ -1216,21 +1216,12 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
|
|||
"measure time of each rustc pass"),
|
||||
time: bool = (false, parse_bool, [UNTRACKED],
|
||||
"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,
|
||||
"The output of `-Z time-llvm-passes` will only reflect timings of \
|
||||
re-codegened modules when used with incremental compilation" )],
|
||||
"measure time of each LLVM pass"),
|
||||
input_stats: bool = (false, parse_bool, [UNTRACKED],
|
||||
"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],
|
||||
"generate comments into the assembly (may change behavior)"),
|
||||
verify_llvm_ir: bool = (false, parse_bool, [TRACKED],
|
||||
|
@ -3259,14 +3250,10 @@ mod tests {
|
|||
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
|
||||
opts.debugging_opts.time_passes = true;
|
||||
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;
|
||||
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
|
||||
opts.debugging_opts.input_stats = true;
|
||||
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;
|
||||
assert_eq!(reference.dep_tracking_hash(), opts.dep_tracking_hash());
|
||||
opts.debugging_opts.meta_stats = true;
|
||||
|
|
|
@ -519,15 +519,9 @@ impl Session {
|
|||
pub fn instrument_mcount(&self) -> bool {
|
||||
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 {
|
||||
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 {
|
||||
self.opts.debugging_opts.meta_stats
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ use crate::common;
|
|||
use crate::context::CodegenCx;
|
||||
use crate::monomorphize::partitioning::CodegenUnitExt;
|
||||
use rustc::dep_graph;
|
||||
use rustc::mir::mono::{Linkage, Visibility, Stats};
|
||||
use rustc::mir::mono::{Linkage, Visibility};
|
||||
use rustc::middle::cstore::{EncodedMetadata};
|
||||
use rustc::ty::TyCtxt;
|
||||
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>,
|
||||
cgu_name: InternedString)
|
||||
-> Stats {
|
||||
pub fn compile_codegen_unit(tcx: TyCtxt<'a, 'tcx, 'tcx>, cgu_name: InternedString) {
|
||||
let start_time = Instant::now();
|
||||
|
||||
let dep_node = tcx.codegen_unit(cgu_name).codegen_dep_node(tcx);
|
||||
let ((stats, module), _) = tcx.dep_graph.with_task(dep_node,
|
||||
tcx,
|
||||
cgu_name,
|
||||
module_codegen,
|
||||
dep_graph::hash_result);
|
||||
let (module, _) = tcx.dep_graph.with_task(
|
||||
dep_node,
|
||||
tcx,
|
||||
cgu_name,
|
||||
module_codegen,
|
||||
dep_graph::hash_result,
|
||||
);
|
||||
let time_to_codegen = start_time.elapsed();
|
||||
|
||||
// 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;
|
||||
|
||||
submit_codegened_module_to_llvm(&LlvmCodegenBackend(()), tcx, module, cost);
|
||||
return stats;
|
||||
|
||||
fn module_codegen<'ll, 'tcx>(
|
||||
tcx: TyCtxt<'ll, 'tcx, 'tcx>,
|
||||
cgu_name: InternedString)
|
||||
-> (Stats, ModuleCodegen<ModuleLlvm>)
|
||||
{
|
||||
cgu_name: InternedString,
|
||||
) -> ModuleCodegen<ModuleLlvm> {
|
||||
let cgu = tcx.codegen_unit(cgu_name);
|
||||
// Instantiate monomorphizations without filling out definitions yet...
|
||||
let llvm_module = ModuleLlvm::new(tcx, &cgu_name.as_str());
|
||||
let stats = {
|
||||
{
|
||||
let cx = CodegenCx::new(tcx, cgu, &llvm_module);
|
||||
let mono_items = cx.codegen_unit
|
||||
.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 {
|
||||
cx.debuginfo_finalize();
|
||||
}
|
||||
}
|
||||
|
||||
cx.consume_stats().into_inner()
|
||||
};
|
||||
|
||||
(stats, ModuleCodegen {
|
||||
ModuleCodegen {
|
||||
name: cgu_name.to_string(),
|
||||
module_llvm: llvm_module,
|
||||
kind: ModuleKind::Regular,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -147,21 +147,18 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
}
|
||||
|
||||
fn ret_void(&mut self) {
|
||||
self.count_insn("retvoid");
|
||||
unsafe {
|
||||
llvm::LLVMBuildRetVoid(self.llbuilder);
|
||||
}
|
||||
}
|
||||
|
||||
fn ret(&mut self, v: &'ll Value) {
|
||||
self.count_insn("ret");
|
||||
unsafe {
|
||||
llvm::LLVMBuildRet(self.llbuilder, v);
|
||||
}
|
||||
}
|
||||
|
||||
fn br(&mut self, dest: &'ll BasicBlock) {
|
||||
self.count_insn("br");
|
||||
unsafe {
|
||||
llvm::LLVMBuildBr(self.llbuilder, dest);
|
||||
}
|
||||
|
@ -173,7 +170,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
then_llbb: &'ll BasicBlock,
|
||||
else_llbb: &'ll BasicBlock,
|
||||
) {
|
||||
self.count_insn("condbr");
|
||||
unsafe {
|
||||
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,
|
||||
funclet: Option<&Funclet<'ll>>,
|
||||
) -> &'ll Value {
|
||||
self.count_insn("invoke");
|
||||
|
||||
debug!("Invoke {:?} with args ({:?})",
|
||||
llfn,
|
||||
|
@ -227,7 +222,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
}
|
||||
|
||||
fn unreachable(&mut self) {
|
||||
self.count_insn("unreachable");
|
||||
unsafe {
|
||||
llvm::LLVMBuildUnreachable(self.llbuilder);
|
||||
}
|
||||
|
@ -235,21 +229,18 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
|
||||
/* Arithmetic */
|
||||
fn add(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
|
||||
self.count_insn("add");
|
||||
unsafe {
|
||||
llvm::LLVMBuildAdd(self.llbuilder, lhs, rhs, noname())
|
||||
}
|
||||
}
|
||||
|
||||
fn fadd(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
|
||||
self.count_insn("fadd");
|
||||
unsafe {
|
||||
llvm::LLVMBuildFAdd(self.llbuilder, lhs, rhs, noname())
|
||||
}
|
||||
}
|
||||
|
||||
fn fadd_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
|
||||
self.count_insn("fadd");
|
||||
unsafe {
|
||||
let instr = llvm::LLVMBuildFAdd(self.llbuilder, lhs, rhs, noname());
|
||||
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 {
|
||||
self.count_insn("sub");
|
||||
unsafe {
|
||||
llvm::LLVMBuildSub(self.llbuilder, lhs, rhs, noname())
|
||||
}
|
||||
}
|
||||
|
||||
fn fsub(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
|
||||
self.count_insn("fsub");
|
||||
unsafe {
|
||||
llvm::LLVMBuildFSub(self.llbuilder, lhs, rhs, noname())
|
||||
}
|
||||
}
|
||||
|
||||
fn fsub_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
|
||||
self.count_insn("fsub");
|
||||
unsafe {
|
||||
let instr = llvm::LLVMBuildFSub(self.llbuilder, lhs, rhs, noname());
|
||||
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 {
|
||||
self.count_insn("mul");
|
||||
unsafe {
|
||||
llvm::LLVMBuildMul(self.llbuilder, lhs, rhs, noname())
|
||||
}
|
||||
}
|
||||
|
||||
fn fmul(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
|
||||
self.count_insn("fmul");
|
||||
unsafe {
|
||||
llvm::LLVMBuildFMul(self.llbuilder, lhs, rhs, noname())
|
||||
}
|
||||
}
|
||||
|
||||
fn fmul_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
|
||||
self.count_insn("fmul");
|
||||
unsafe {
|
||||
let instr = llvm::LLVMBuildFMul(self.llbuilder, lhs, rhs, noname());
|
||||
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 {
|
||||
self.count_insn("udiv");
|
||||
unsafe {
|
||||
llvm::LLVMBuildUDiv(self.llbuilder, lhs, rhs, noname())
|
||||
}
|
||||
}
|
||||
|
||||
fn exactudiv(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
|
||||
self.count_insn("exactudiv");
|
||||
unsafe {
|
||||
llvm::LLVMBuildExactUDiv(self.llbuilder, lhs, rhs, noname())
|
||||
}
|
||||
}
|
||||
|
||||
fn sdiv(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
|
||||
self.count_insn("sdiv");
|
||||
unsafe {
|
||||
llvm::LLVMBuildSDiv(self.llbuilder, lhs, rhs, noname())
|
||||
}
|
||||
}
|
||||
|
||||
fn exactsdiv(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
|
||||
self.count_insn("exactsdiv");
|
||||
unsafe {
|
||||
llvm::LLVMBuildExactSDiv(self.llbuilder, lhs, rhs, noname())
|
||||
}
|
||||
}
|
||||
|
||||
fn fdiv(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
|
||||
self.count_insn("fdiv");
|
||||
unsafe {
|
||||
llvm::LLVMBuildFDiv(self.llbuilder, lhs, rhs, noname())
|
||||
}
|
||||
}
|
||||
|
||||
fn fdiv_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
|
||||
self.count_insn("fdiv");
|
||||
unsafe {
|
||||
let instr = llvm::LLVMBuildFDiv(self.llbuilder, lhs, rhs, noname());
|
||||
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 {
|
||||
self.count_insn("urem");
|
||||
unsafe {
|
||||
llvm::LLVMBuildURem(self.llbuilder, lhs, rhs, noname())
|
||||
}
|
||||
}
|
||||
|
||||
fn srem(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
|
||||
self.count_insn("srem");
|
||||
unsafe {
|
||||
llvm::LLVMBuildSRem(self.llbuilder, lhs, rhs, noname())
|
||||
}
|
||||
}
|
||||
|
||||
fn frem(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
|
||||
self.count_insn("frem");
|
||||
unsafe {
|
||||
llvm::LLVMBuildFRem(self.llbuilder, lhs, rhs, noname())
|
||||
}
|
||||
}
|
||||
|
||||
fn frem_fast(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
|
||||
self.count_insn("frem");
|
||||
unsafe {
|
||||
let instr = llvm::LLVMBuildFRem(self.llbuilder, lhs, rhs, noname());
|
||||
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 {
|
||||
self.count_insn("shl");
|
||||
unsafe {
|
||||
llvm::LLVMBuildShl(self.llbuilder, lhs, rhs, noname())
|
||||
}
|
||||
}
|
||||
|
||||
fn lshr(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
|
||||
self.count_insn("lshr");
|
||||
unsafe {
|
||||
llvm::LLVMBuildLShr(self.llbuilder, lhs, rhs, noname())
|
||||
}
|
||||
}
|
||||
|
||||
fn ashr(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
|
||||
self.count_insn("ashr");
|
||||
unsafe {
|
||||
llvm::LLVMBuildAShr(self.llbuilder, lhs, rhs, noname())
|
||||
}
|
||||
}
|
||||
|
||||
fn and(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
|
||||
self.count_insn("and");
|
||||
unsafe {
|
||||
llvm::LLVMBuildAnd(self.llbuilder, lhs, rhs, noname())
|
||||
}
|
||||
}
|
||||
|
||||
fn or(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
|
||||
self.count_insn("or");
|
||||
unsafe {
|
||||
llvm::LLVMBuildOr(self.llbuilder, lhs, rhs, noname())
|
||||
}
|
||||
}
|
||||
|
||||
fn xor(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
|
||||
self.count_insn("xor");
|
||||
unsafe {
|
||||
llvm::LLVMBuildXor(self.llbuilder, lhs, rhs, noname())
|
||||
}
|
||||
}
|
||||
|
||||
fn neg(&mut self, v: &'ll Value) -> &'ll Value {
|
||||
self.count_insn("neg");
|
||||
unsafe {
|
||||
llvm::LLVMBuildNeg(self.llbuilder, v, noname())
|
||||
}
|
||||
}
|
||||
|
||||
fn fneg(&mut self, v: &'ll Value) -> &'ll Value {
|
||||
self.count_insn("fneg");
|
||||
unsafe {
|
||||
llvm::LLVMBuildFNeg(self.llbuilder, v, noname())
|
||||
}
|
||||
}
|
||||
|
||||
fn not(&mut self, v: &'ll Value) -> &'ll Value {
|
||||
self.count_insn("not");
|
||||
unsafe {
|
||||
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 {
|
||||
self.count_insn("alloca");
|
||||
unsafe {
|
||||
let alloca = if name.is_empty() {
|
||||
llvm::LLVMBuildAlloca(self.llbuilder, ty, noname())
|
||||
|
@ -543,7 +508,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
len: &'ll Value,
|
||||
name: &str,
|
||||
align: Align) -> &'ll Value {
|
||||
self.count_insn("alloca");
|
||||
unsafe {
|
||||
let alloca = if name.is_empty() {
|
||||
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 {
|
||||
self.count_insn("load");
|
||||
unsafe {
|
||||
let load = llvm::LLVMBuildLoad(self.llbuilder, ptr, noname());
|
||||
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 {
|
||||
self.count_insn("load.volatile");
|
||||
unsafe {
|
||||
let insn = llvm::LLVMBuildLoad(self.llbuilder, ptr, noname());
|
||||
llvm::LLVMSetVolatile(insn, llvm::True);
|
||||
insn
|
||||
let load = llvm::LLVMBuildLoad(self.llbuilder, ptr, noname());
|
||||
llvm::LLVMSetVolatile(load, llvm::True);
|
||||
load
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -581,7 +543,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
order: rustc_codegen_ssa::common::AtomicOrdering,
|
||||
size: Size,
|
||||
) -> &'ll Value {
|
||||
self.count_insn("load.atomic");
|
||||
unsafe {
|
||||
let load = llvm::LLVMRustBuildAtomicLoad(
|
||||
self.llbuilder,
|
||||
|
@ -745,7 +706,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
flags: MemFlags,
|
||||
) -> &'ll Value {
|
||||
debug!("Store {:?} -> {:?} ({:?})", val, ptr, flags);
|
||||
self.count_insn("store");
|
||||
let ptr = self.check_store(val, ptr);
|
||||
unsafe {
|
||||
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,
|
||||
order: rustc_codegen_ssa::common::AtomicOrdering, size: Size) {
|
||||
debug!("Store {:?} -> {:?}", val, ptr);
|
||||
self.count_insn("store.atomic");
|
||||
let ptr = self.check_store(val, ptr);
|
||||
unsafe {
|
||||
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 {
|
||||
self.count_insn("gep");
|
||||
unsafe {
|
||||
llvm::LLVMBuildGEP(self.llbuilder, ptr, indices.as_ptr(),
|
||||
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 {
|
||||
self.count_insn("inboundsgep");
|
||||
unsafe {
|
||||
llvm::LLVMBuildInBoundsGEP(
|
||||
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 {
|
||||
self.count_insn("structgep");
|
||||
assert_eq!(idx as c_uint as u64, idx);
|
||||
unsafe {
|
||||
llvm::LLVMBuildStructGEP(self.llbuilder, ptr, idx as c_uint, noname())
|
||||
|
@ -814,77 +770,66 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
|
||||
/* Casts */
|
||||
fn trunc(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
|
||||
self.count_insn("trunc");
|
||||
unsafe {
|
||||
llvm::LLVMBuildTrunc(self.llbuilder, val, dest_ty, noname())
|
||||
}
|
||||
}
|
||||
|
||||
fn sext(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
|
||||
self.count_insn("sext");
|
||||
unsafe {
|
||||
llvm::LLVMBuildSExt(self.llbuilder, val, dest_ty, noname())
|
||||
}
|
||||
}
|
||||
|
||||
fn fptoui(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
|
||||
self.count_insn("fptoui");
|
||||
unsafe {
|
||||
llvm::LLVMBuildFPToUI(self.llbuilder, val, dest_ty, noname())
|
||||
}
|
||||
}
|
||||
|
||||
fn fptosi(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
|
||||
self.count_insn("fptosi");
|
||||
unsafe {
|
||||
llvm::LLVMBuildFPToSI(self.llbuilder, val, dest_ty,noname())
|
||||
}
|
||||
}
|
||||
|
||||
fn uitofp(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
|
||||
self.count_insn("uitofp");
|
||||
unsafe {
|
||||
llvm::LLVMBuildUIToFP(self.llbuilder, val, dest_ty, noname())
|
||||
}
|
||||
}
|
||||
|
||||
fn sitofp(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
|
||||
self.count_insn("sitofp");
|
||||
unsafe {
|
||||
llvm::LLVMBuildSIToFP(self.llbuilder, val, dest_ty, noname())
|
||||
}
|
||||
}
|
||||
|
||||
fn fptrunc(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
|
||||
self.count_insn("fptrunc");
|
||||
unsafe {
|
||||
llvm::LLVMBuildFPTrunc(self.llbuilder, val, dest_ty, noname())
|
||||
}
|
||||
}
|
||||
|
||||
fn fpext(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
|
||||
self.count_insn("fpext");
|
||||
unsafe {
|
||||
llvm::LLVMBuildFPExt(self.llbuilder, val, dest_ty, noname())
|
||||
}
|
||||
}
|
||||
|
||||
fn ptrtoint(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
|
||||
self.count_insn("ptrtoint");
|
||||
unsafe {
|
||||
llvm::LLVMBuildPtrToInt(self.llbuilder, val, dest_ty, noname())
|
||||
}
|
||||
}
|
||||
|
||||
fn inttoptr(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
|
||||
self.count_insn("inttoptr");
|
||||
unsafe {
|
||||
llvm::LLVMBuildIntToPtr(self.llbuilder, val, dest_ty, noname())
|
||||
}
|
||||
}
|
||||
|
||||
fn bitcast(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
|
||||
self.count_insn("bitcast");
|
||||
unsafe {
|
||||
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 {
|
||||
self.count_insn("intcast");
|
||||
unsafe {
|
||||
llvm::LLVMRustBuildIntCast(self.llbuilder, val, dest_ty, is_signed)
|
||||
}
|
||||
}
|
||||
|
||||
fn pointercast(&mut self, val: &'ll Value, dest_ty: &'ll Type) -> &'ll Value {
|
||||
self.count_insn("pointercast");
|
||||
unsafe {
|
||||
llvm::LLVMBuildPointerCast(self.llbuilder, val, dest_ty, noname())
|
||||
}
|
||||
|
@ -907,7 +850,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
|
||||
/* Comparisons */
|
||||
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);
|
||||
unsafe {
|
||||
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 {
|
||||
self.count_insn("fcmp");
|
||||
unsafe {
|
||||
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,
|
||||
else_val: &'ll Value,
|
||||
) -> &'ll Value {
|
||||
self.count_insn("select");
|
||||
unsafe {
|
||||
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)]
|
||||
fn va_arg(&mut self, list: &'ll Value, ty: &'ll Type) -> &'ll Value {
|
||||
self.count_insn("vaarg");
|
||||
unsafe {
|
||||
llvm::LLVMBuildVAArg(self.llbuilder, list, ty, noname())
|
||||
}
|
||||
}
|
||||
|
||||
fn extract_element(&mut self, vec: &'ll Value, idx: &'ll Value) -> &'ll Value {
|
||||
self.count_insn("extractelement");
|
||||
unsafe {
|
||||
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 {
|
||||
self.count_insn("extractvalue");
|
||||
assert_eq!(idx as c_uint as u64, idx);
|
||||
unsafe {
|
||||
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,
|
||||
idx: u64) -> &'ll Value {
|
||||
self.count_insn("insertvalue");
|
||||
assert_eq!(idx as c_uint as u64, idx);
|
||||
unsafe {
|
||||
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,
|
||||
num_clauses: usize) -> &'ll Value {
|
||||
self.count_insn("landingpad");
|
||||
unsafe {
|
||||
llvm::LLVMBuildLandingPad(self.llbuilder, ty, pers_fn,
|
||||
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) {
|
||||
self.count_insn("setcleanup");
|
||||
unsafe {
|
||||
llvm::LLVMSetCleanup(landing_pad, llvm::True);
|
||||
}
|
||||
}
|
||||
|
||||
fn resume(&mut self, exn: &'ll Value) -> &'ll Value {
|
||||
self.count_insn("resume");
|
||||
unsafe {
|
||||
llvm::LLVMBuildResume(self.llbuilder, exn)
|
||||
}
|
||||
|
@ -1059,7 +992,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
fn cleanup_pad(&mut self,
|
||||
parent: Option<&'ll Value>,
|
||||
args: &[&'ll Value]) -> Funclet<'ll> {
|
||||
self.count_insn("cleanuppad");
|
||||
let name = const_cstr!("cleanuppad");
|
||||
let ret = unsafe {
|
||||
llvm::LLVMRustBuildCleanupPad(self.llbuilder,
|
||||
|
@ -1075,7 +1007,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
&mut self, funclet: &Funclet<'ll>,
|
||||
unwind: Option<&'ll BasicBlock>,
|
||||
) -> &'ll Value {
|
||||
self.count_insn("cleanupret");
|
||||
let ret = unsafe {
|
||||
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,
|
||||
parent: &'ll Value,
|
||||
args: &[&'ll Value]) -> Funclet<'ll> {
|
||||
self.count_insn("catchpad");
|
||||
let name = const_cstr!("catchpad");
|
||||
let ret = unsafe {
|
||||
llvm::LLVMRustBuildCatchPad(self.llbuilder, parent,
|
||||
|
@ -1101,7 +1031,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
unwind: Option<&'ll BasicBlock>,
|
||||
num_handlers: usize,
|
||||
) -> &'ll Value {
|
||||
self.count_insn("catchswitch");
|
||||
let name = const_cstr!("catchswitch");
|
||||
let ret = unsafe {
|
||||
llvm::LLVMRustBuildCatchSwitch(self.llbuilder, parent, unwind,
|
||||
|
@ -1199,7 +1128,6 @@ impl BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
|
|||
args: &[&'ll Value],
|
||||
funclet: Option<&Funclet<'ll>>,
|
||||
) -> &'ll Value {
|
||||
self.count_insn("call");
|
||||
|
||||
debug!("Call {:?} with args ({:?})",
|
||||
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 {
|
||||
self.count_insn("zext");
|
||||
unsafe {
|
||||
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) {
|
||||
unsafe {
|
||||
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 {
|
||||
self.count_insn("minnum");
|
||||
unsafe { llvm::LLVMRustBuildMinNum(self.llbuilder, lhs, rhs) }
|
||||
}
|
||||
|
||||
pub fn maxnum(&mut self, lhs: &'ll Value, rhs: &'ll Value) -> &'ll Value {
|
||||
self.count_insn("maxnum");
|
||||
unsafe { llvm::LLVMRustBuildMaxNum(self.llbuilder, lhs, rhs) }
|
||||
}
|
||||
|
||||
|
@ -1319,7 +1231,6 @@ impl Builder<'a, 'll, 'tcx> {
|
|||
elt: &'ll Value,
|
||||
idx: &'ll Value,
|
||||
) -> &'ll Value {
|
||||
self.count_insn("insertelement");
|
||||
unsafe {
|
||||
llvm::LLVMBuildInsertElement(self.llbuilder, vec, elt, idx, noname())
|
||||
}
|
||||
|
@ -1331,14 +1242,12 @@ impl Builder<'a, 'll, 'tcx> {
|
|||
v2: &'ll Value,
|
||||
mask: &'ll Value,
|
||||
) -> &'ll Value {
|
||||
self.count_insn("shufflevector");
|
||||
unsafe {
|
||||
llvm::LLVMBuildShuffleVector(self.llbuilder, v1, v2, mask, noname())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn vector_reduce_fadd_fast(&mut self, acc: &'ll Value, src: &'ll Value) -> &'ll Value {
|
||||
self.count_insn("vector.reduce.fadd_fast");
|
||||
unsafe {
|
||||
// FIXME: add a non-fast math version once
|
||||
// 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 {
|
||||
self.count_insn("vector.reduce.fmul_fast");
|
||||
unsafe {
|
||||
// FIXME: add a non-fast math version once
|
||||
// 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 {
|
||||
self.count_insn("vector.reduce.add");
|
||||
unsafe { llvm::LLVMRustBuildVectorReduceAdd(self.llbuilder, src) }
|
||||
}
|
||||
pub fn vector_reduce_mul(&mut self, src: &'ll Value) -> &'ll Value {
|
||||
self.count_insn("vector.reduce.mul");
|
||||
unsafe { llvm::LLVMRustBuildVectorReduceMul(self.llbuilder, src) }
|
||||
}
|
||||
pub fn vector_reduce_and(&mut self, src: &'ll Value) -> &'ll Value {
|
||||
self.count_insn("vector.reduce.and");
|
||||
unsafe { llvm::LLVMRustBuildVectorReduceAnd(self.llbuilder, src) }
|
||||
}
|
||||
pub fn vector_reduce_or(&mut self, src: &'ll Value) -> &'ll Value {
|
||||
self.count_insn("vector.reduce.or");
|
||||
unsafe { llvm::LLVMRustBuildVectorReduceOr(self.llbuilder, src) }
|
||||
}
|
||||
pub fn vector_reduce_xor(&mut self, src: &'ll Value) -> &'ll Value {
|
||||
self.count_insn("vector.reduce.xor");
|
||||
unsafe { llvm::LLVMRustBuildVectorReduceXor(self.llbuilder, src) }
|
||||
}
|
||||
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) }
|
||||
}
|
||||
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) }
|
||||
}
|
||||
pub fn vector_reduce_fmin_fast(&mut self, src: &'ll Value) -> &'ll Value {
|
||||
self.count_insn("vector.reduce.fmin_fast");
|
||||
unsafe {
|
||||
let instr = llvm::LLVMRustBuildVectorReduceFMin(self.llbuilder, src, /*NoNaNs:*/ true);
|
||||
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 {
|
||||
self.count_insn("vector.reduce.fmax_fast");
|
||||
unsafe {
|
||||
let instr = llvm::LLVMRustBuildVectorReduceFMax(self.llbuilder, src, /*NoNaNs:*/ true);
|
||||
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 {
|
||||
self.count_insn("vector.reduce.min");
|
||||
unsafe { llvm::LLVMRustBuildVectorReduceMin(self.llbuilder, src, is_signed) }
|
||||
}
|
||||
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) }
|
||||
}
|
||||
|
||||
|
@ -1419,7 +1316,6 @@ impl Builder<'a, 'll, 'tcx> {
|
|||
}
|
||||
|
||||
pub fn catch_ret(&mut self, funclet: &Funclet<'ll>, unwind: &'ll BasicBlock) -> &'ll Value {
|
||||
self.count_insn("catchret");
|
||||
let ret = unsafe {
|
||||
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 {
|
||||
self.count_insn("vaarg");
|
||||
unsafe {
|
||||
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 {
|
||||
self.count_insn("addincoming");
|
||||
assert_eq!(vals.len(), bbs.len());
|
||||
let phi = unsafe {
|
||||
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) {
|
||||
self.count_insn("addincoming");
|
||||
unsafe {
|
||||
llvm::LLVMAddIncoming(phi, &val, &bb, 1 as c_uint);
|
||||
}
|
||||
|
|
|
@ -12,7 +12,6 @@ use rustc_codegen_ssa::traits::*;
|
|||
|
||||
use rustc_data_structures::base_n;
|
||||
use rustc_data_structures::small_c_str::SmallCStr;
|
||||
use rustc::mir::mono::Stats;
|
||||
use rustc::session::config::{self, DebugInfo};
|
||||
use rustc::session::Session;
|
||||
use rustc::ty::layout::{
|
||||
|
@ -44,7 +43,6 @@ pub struct CodegenCx<'ll, 'tcx: 'll> {
|
|||
|
||||
pub llmod: &'ll llvm::Module,
|
||||
pub llcx: &'ll llvm::Context,
|
||||
pub stats: RefCell<Stats>,
|
||||
pub codegen_unit: Arc<CodegenUnit<'tcx>>,
|
||||
|
||||
/// Cache instances of monomorphic and polymorphic items
|
||||
|
@ -284,7 +282,6 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> {
|
|||
tls_model,
|
||||
llmod,
|
||||
llcx,
|
||||
stats: RefCell::new(Stats::default()),
|
||||
codegen_unit,
|
||||
instances: Default::default(),
|
||||
vtables: Default::default(),
|
||||
|
@ -408,14 +405,6 @@ impl MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
|||
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>> {
|
||||
&self.codegen_unit
|
||||
}
|
||||
|
|
|
@ -52,7 +52,6 @@ use rustc_codegen_ssa::CompiledModule;
|
|||
use errors::{FatalError, Handler};
|
||||
use rustc::dep_graph::WorkProduct;
|
||||
use syntax_pos::symbol::InternedString;
|
||||
use rustc::mir::mono::Stats;
|
||||
pub use llvm_util::target_features;
|
||||
use std::any::Any;
|
||||
use std::sync::{mpsc, Arc};
|
||||
|
@ -130,8 +129,8 @@ impl ExtraBackendMethods for LlvmCodegenBackend {
|
|||
&self,
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
cgu_name: InternedString,
|
||||
) -> Stats {
|
||||
base::compile_codegen_unit(tcx, cgu_name)
|
||||
) {
|
||||
base::compile_codegen_unit(tcx, cgu_name);
|
||||
}
|
||||
fn target_machine_factory(
|
||||
&self,
|
||||
|
|
|
@ -20,7 +20,7 @@ use rustc::hir::def_id::{DefId, LOCAL_CRATE};
|
|||
use rustc::middle::cstore::EncodedMetadata;
|
||||
use rustc::middle::lang_items::StartFnLangItem;
|
||||
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::layout::{self, Align, TyLayout, LayoutOf, VariantIdx, HasTyCtxt};
|
||||
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::session::config::{self, EntryFnType, Lto};
|
||||
use rustc::session::Session;
|
||||
use rustc_mir::monomorphize::item::DefPathBasedNames;
|
||||
use rustc_mir::monomorphize::Instance;
|
||||
use rustc_mir::monomorphize::partitioning::{CodegenUnit, CodegenUnitExt};
|
||||
use rustc::util::nodemap::FxHashMap;
|
||||
|
@ -58,40 +57,6 @@ use rustc::hir;
|
|||
|
||||
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,
|
||||
signed: bool)
|
||||
-> IntPredicate {
|
||||
|
@ -408,15 +373,6 @@ pub fn codegen_instance<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>(
|
|||
cx: &'a Bx::CodegenCx,
|
||||
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
|
||||
// and to allow finding the last function before LLVM aborts from
|
||||
// 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(||
|
||||
bug!("Instance `{:?}` not already declared", instance));
|
||||
|
||||
cx.stats().borrow_mut().n_closures += 1;
|
||||
|
||||
let mir = cx.tcx().instance_mir(instance.def);
|
||||
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 all_stats = Stats::default();
|
||||
|
||||
for cgu in codegen_units.into_iter() {
|
||||
ongoing_codegen.wait_for_signal_to_codegen_item();
|
||||
|
@ -666,8 +619,7 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
|
|||
CguReuse::No => {
|
||||
tcx.sess.profiler(|p| p.start_activity(format!("codegen {}", cgu.name())));
|
||||
let start_time = Instant::now();
|
||||
let stats = backend.compile_codegen_unit(tcx, *cgu.name());
|
||||
all_stats.extend(stats);
|
||||
backend.compile_codegen_unit(tcx, *cgu.name());
|
||||
total_codegen_time += start_time.elapsed();
|
||||
tcx.sess.profiler(|p| p.end_activity(format!("codegen {}", cgu.name())));
|
||||
false
|
||||
|
@ -701,28 +653,6 @@ pub fn codegen_crate<B: ExtraBackendMethods>(
|
|||
|
||||
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);
|
||||
|
||||
assert_and_save_dep_graph(tcx);
|
||||
|
|
|
@ -396,22 +396,20 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
|||
let cx = self.cx;
|
||||
let tcx = self.cx.tcx();
|
||||
|
||||
if let mir::Place::Base(mir::PlaceBase::Local(index)) = *place {
|
||||
match self.locals[index] {
|
||||
LocalRef::Place(place) => {
|
||||
return place;
|
||||
}
|
||||
LocalRef::UnsizedPlace(place) => {
|
||||
return bx.load_operand(place).deref(cx);
|
||||
}
|
||||
LocalRef::Operand(..) => {
|
||||
bug!("using operand local {:?} as place", place);
|
||||
let result = match *place {
|
||||
mir::Place::Base(mir::PlaceBase::Local(index)) => {
|
||||
match self.locals[index] {
|
||||
LocalRef::Place(place) => {
|
||||
return place;
|
||||
}
|
||||
LocalRef::UnsizedPlace(place) => {
|
||||
return bx.load_operand(place).deref(cx);
|
||||
}
|
||||
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::PlaceBase::Static(
|
||||
box mir::Static { ty, kind: mir::StaticKind::Promoted(promoted) }
|
||||
|
|
|
@ -5,7 +5,6 @@ use super::write::WriteBackendMethods;
|
|||
use super::CodegenObject;
|
||||
use rustc::middle::allocator::AllocatorKind;
|
||||
use rustc::middle::cstore::EncodedMetadata;
|
||||
use rustc::mir::mono::Stats;
|
||||
use rustc::session::{Session, config};
|
||||
use rustc::ty::TyCtxt;
|
||||
use rustc_codegen_utils::codegen_backend::CodegenBackend;
|
||||
|
@ -49,7 +48,7 @@ pub trait ExtraBackendMethods: CodegenBackend + WriteBackendMethods + Sized + Se
|
|||
&self,
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
cgu_name: InternedString,
|
||||
) -> Stats;
|
||||
);
|
||||
// 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
|
||||
// `sess.crate_types` is uninitialized so we cannot access it.
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use super::BackendTypes;
|
||||
use rustc::mir::mono::Stats;
|
||||
use rustc::session::Session;
|
||||
use rustc::ty::{self, Instance, Ty};
|
||||
use rustc::util::nodemap::FxHashMap;
|
||||
|
@ -17,8 +16,6 @@ pub trait MiscMethods<'tcx>: BackendTypes {
|
|||
fn eh_personality(&self) -> Self::Value;
|
||||
fn eh_unwind_resume(&self) -> Self::Value;
|
||||
fn sess(&self) -> &Session;
|
||||
fn stats(&self) -> &RefCell<Stats>;
|
||||
fn consume_stats(self) -> RefCell<Stats>;
|
||||
fn codegen_unit(&self) -> &Arc<CodegenUnit<'tcx>>;
|
||||
fn used_statics(&self) -> &RefCell<Vec<Self::Value>>;
|
||||
fn set_frame_pointer_elimination(&self, llfn: Self::Value);
|
||||
|
|
|
@ -212,6 +212,11 @@ macro_rules! newtype_index {
|
|||
fn add_usize(&self, u: usize) -> Option<Self> {
|
||||
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 {
|
||||
|
|
|
@ -162,6 +162,7 @@ impl ColorConfig {
|
|||
}
|
||||
}
|
||||
|
||||
/// Handles the writing of `HumanReadableErrorType::Default` and `HumanReadableErrorType::Short`
|
||||
pub struct EmitterWriter {
|
||||
dst: Destination,
|
||||
sm: Option<Lrc<SourceMapperDyn>>,
|
||||
|
@ -170,7 +171,8 @@ pub struct EmitterWriter {
|
|||
ui_testing: bool,
|
||||
}
|
||||
|
||||
struct FileWithAnnotatedLines {
|
||||
#[derive(Debug)]
|
||||
pub struct FileWithAnnotatedLines {
|
||||
file: Lrc<SourceFile>,
|
||||
lines: Vec<Line>,
|
||||
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,
|
||||
buffer: &mut StyledBuffer,
|
||||
file: Lrc<SourceFile>,
|
||||
|
@ -1093,9 +932,7 @@ impl EmitterWriter {
|
|||
}
|
||||
}
|
||||
|
||||
// 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)
|
||||
let mut annotated_files = self.preprocess_annotations(msp);
|
||||
let mut annotated_files = FileWithAnnotatedLines::collect_annotations(msp, &self.sm);
|
||||
|
||||
// Make sure our primary file comes first
|
||||
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) {
|
||||
buffer.puts(line, col, "| ", Style::LineNumber);
|
||||
}
|
||||
|
|
|
@ -1616,7 +1616,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||
);
|
||||
|
||||
// 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,
|
||||
None => continue,
|
||||
};
|
||||
|
@ -1672,7 +1672,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||
);
|
||||
|
||||
// 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,
|
||||
None => continue,
|
||||
};
|
||||
|
@ -1735,7 +1735,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||
assigned_from,
|
||||
);
|
||||
|
||||
if let Some(assigned_from_local) = assigned_from.local() {
|
||||
if let Some(assigned_from_local) = assigned_from.local_or_deref_local() {
|
||||
debug!(
|
||||
"annotate_argument_and_return_for_borrow: assigned_from_local={:?}",
|
||||
assigned_from_local,
|
||||
|
|
|
@ -37,15 +37,15 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
|
|||
diag: &mut DiagnosticBuilder<'_>,
|
||||
) {
|
||||
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..] {
|
||||
debug!("add_moved_or_invoked_closure_note: stmt={:?} target={:?}", stmt, target);
|
||||
if let StatementKind::Assign(into, box Rvalue::Use(from)) = &stmt.kind {
|
||||
debug!("add_fnonce_closure_note: into={:?} from={:?}", into, from);
|
||||
match from {
|
||||
Operand::Copy(ref place) |
|
||||
Operand::Move(ref place) if target == place.local() =>
|
||||
target = into.local(),
|
||||
Operand::Move(ref place) if target == place.local_or_deref_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() {
|
||||
let closure = match args.first() {
|
||||
Some(Operand::Copy(ref place)) |
|
||||
Some(Operand::Move(ref place)) if target == place.local() =>
|
||||
place.local().unwrap(),
|
||||
Some(Operand::Move(ref place)) if target == place.local_or_deref_local() =>
|
||||
place.local_or_deref_local().unwrap(),
|
||||
_ => return,
|
||||
};
|
||||
|
||||
|
|
|
@ -528,7 +528,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
|||
}) => {
|
||||
// Not projected from the implicit `self` in a closure.
|
||||
debug_assert!(
|
||||
match base.local() {
|
||||
match base.local_or_deref_local() {
|
||||
Some(local) => local == Local::new(1),
|
||||
None => false,
|
||||
},
|
||||
|
|
|
@ -46,8 +46,10 @@ impl<'a, 'tcx> BitDenotation<'tcx> for MaybeStorageLive<'a, 'tcx> {
|
|||
sets: &mut BlockSets<'_, Local>,
|
||||
loc: Location) {
|
||||
match &self.mir[loc.block].terminator().kind {
|
||||
TerminatorKind::Drop { location, .. } => if let Some(l) = location.local() {
|
||||
sets.kill(l);
|
||||
TerminatorKind::Drop { location, .. } => {
|
||||
if let Some(l) = location.local_or_deref_local() {
|
||||
sets.kill(l);
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
defaultness: hir::Defaultness, vis: ty::Visibility) {
|
||||
fn check_assoc_item(
|
||||
&self,
|
||||
hir_id: hir::HirId,
|
||||
assoc_item_kind: AssocItemKind,
|
||||
defaultness: hir::Defaultness,
|
||||
vis: ty::Visibility,
|
||||
) {
|
||||
let mut check = self.check(hir_id, vis);
|
||||
|
||||
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();
|
||||
|
||||
for trait_item_ref in trait_item_refs {
|
||||
self.check_trait_or_impl_item(trait_item_ref.id.hir_id, trait_item_ref.kind,
|
||||
trait_item_ref.defaultness, item_visibility);
|
||||
self.check_assoc_item(
|
||||
trait_item_ref.id.hir_id,
|
||||
trait_item_ref.kind,
|
||||
trait_item_ref.defaultness,
|
||||
item_visibility,
|
||||
);
|
||||
}
|
||||
}
|
||||
hir::ItemKind::TraitAlias(..) => {
|
||||
|
@ -1803,8 +1812,12 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx>
|
|||
} else {
|
||||
impl_vis
|
||||
};
|
||||
self.check_trait_or_impl_item(impl_item_ref.id.hir_id, impl_item_ref.kind,
|
||||
impl_item_ref.defaultness, impl_item_vis);
|
||||
self.check_assoc_item(
|
||||
impl_item_ref.id.hir_id,
|
||||
impl_item_ref.kind,
|
||||
impl_item_ref.defaultness,
|
||||
impl_item_vis,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -860,7 +860,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Resolver<'a> {
|
|||
FnKind::ItemFn(_, ref header, ..) =>
|
||||
(FnItemRibKind, &header.asyncness.node),
|
||||
FnKind::Method(_, ref sig, _, _) =>
|
||||
(TraitOrImplItemRibKind, &sig.header.asyncness.node),
|
||||
(AssocItemRibKind, &sig.header.asyncness.node),
|
||||
FnKind::Closure(_) =>
|
||||
// Async closures aren't resolved through `visit_fn`-- they're
|
||||
// processed separately
|
||||
|
@ -1033,7 +1033,7 @@ enum RibKind<'a> {
|
|||
/// methods or associated types. Allow references to ty params that impl or trait
|
||||
/// binds. Disallow any other upvars (including other ty params that are
|
||||
/// upvars).
|
||||
TraitOrImplItemRibKind,
|
||||
AssocItemRibKind,
|
||||
|
||||
/// We passed through a function definition. Disallow upvars.
|
||||
/// 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 {
|
||||
let generic_params = HasGenericParams(&trait_item.generics,
|
||||
TraitOrImplItemRibKind);
|
||||
AssocItemRibKind);
|
||||
this.with_generic_param_rib(generic_params, |this| {
|
||||
match trait_item.node {
|
||||
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.
|
||||
let generic_params = HasGenericParams(&impl_item.generics,
|
||||
TraitOrImplItemRibKind);
|
||||
AssocItemRibKind);
|
||||
this.with_generic_param_rib(generic_params, |this| {
|
||||
use self::ResolutionError::*;
|
||||
match impl_item.node {
|
||||
|
@ -4074,7 +4074,7 @@ impl<'a> Resolver<'a> {
|
|||
seen.insert(node_id, depth);
|
||||
}
|
||||
}
|
||||
ItemRibKind | FnItemRibKind | TraitOrImplItemRibKind => {
|
||||
ItemRibKind | FnItemRibKind | AssocItemRibKind => {
|
||||
// This was an attempt to access an upvar inside a
|
||||
// named function item. This is not allowed, so we
|
||||
// report an error.
|
||||
|
@ -4103,7 +4103,7 @@ impl<'a> Resolver<'a> {
|
|||
Res::Def(DefKind::TyParam, _) | Res::SelfTy(..) => {
|
||||
for rib in ribs {
|
||||
match rib.kind {
|
||||
NormalRibKind | TraitOrImplItemRibKind | ClosureRibKind(..) |
|
||||
NormalRibKind | AssocItemRibKind | ClosureRibKind(..) |
|
||||
ModuleRibKind(..) | MacroDefinition(..) | ForwardTyParamBanRibKind |
|
||||
ConstantItemRibKind | TyParamAsConstParamTy => {
|
||||
// Nothing to do. Continue.
|
||||
|
|
|
@ -158,7 +158,6 @@ impl<R> BufReader<R> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # #![feature(bufreader_buffer)]
|
||||
/// use std::io::{BufReader, BufRead};
|
||||
/// use std::fs::File;
|
||||
///
|
||||
|
@ -173,7 +172,7 @@ impl<R> BufReader<R> {
|
|||
/// Ok(())
|
||||
/// }
|
||||
/// ```
|
||||
#[unstable(feature = "bufreader_buffer", issue = "45323")]
|
||||
#[stable(feature = "bufreader_buffer", since = "1.37.0")]
|
||||
pub fn buffer(&self) -> &[u8] {
|
||||
&self.buf[self.pos..self.cap]
|
||||
}
|
||||
|
@ -552,7 +551,6 @@ impl<W: Write> BufWriter<W> {
|
|||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// # #![feature(bufreader_buffer)]
|
||||
/// use std::io::BufWriter;
|
||||
/// use std::net::TcpStream;
|
||||
///
|
||||
|
@ -561,7 +559,7 @@ impl<W: Write> BufWriter<W> {
|
|||
/// // See how many bytes are currently buffered
|
||||
/// 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] {
|
||||
&self.buf
|
||||
}
|
||||
|
|
|
@ -180,6 +180,10 @@ impl std::iter::Step for NaiveDate {
|
|||
fn add_usize(&self, _: usize) -> Option<Self> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn sub_usize(&self, _: usize) -> Option<Self> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue