Auto merge of #146526 - jhpratt:rollup-afb1dgo, r=jhpratt
Rollup of 8 pull requests Successful merges: - rust-lang/rust#113095 (Document `become` keyword) - rust-lang/rust#146159 (Some hygiene doc improvements) - rust-lang/rust#146171 (tidy: check that error messages don't start with a capitalized letter) - rust-lang/rust#146419 (Update the arm-* and aarch64-* platform docs.) - rust-lang/rust#146473 (Revert "Constify SystemTime methods") - rust-lang/rust#146506 (Fix small typo in check-cfg.md) - rust-lang/rust#146517 (fix Condvar::wait_timeout docs) - rust-lang/rust#146521 (document `core::ffi::VaArgSafe`) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
a015919e54
45 changed files with 673 additions and 255 deletions
|
|
@ -31,7 +31,7 @@ codegen_ssa_cpu_required = target requires explicitly specifying a cpu with `-C
|
|||
codegen_ssa_create_temp_dir = couldn't create a temp dir: {$error}
|
||||
|
||||
codegen_ssa_dlltool_fail_import_library =
|
||||
Dlltool could not create import library with {$dlltool_path} {$dlltool_args}:
|
||||
dlltool could not create import library with {$dlltool_path} {$dlltool_args}:
|
||||
{$stdout}
|
||||
{$stderr}
|
||||
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ passes_const_stable_not_stable =
|
|||
.label = attribute specified here
|
||||
|
||||
passes_custom_mir_incompatible_dialect_and_phase =
|
||||
The {$dialect} dialect is not compatible with the {$phase} phase
|
||||
the {$dialect} dialect is not compatible with the {$phase} phase
|
||||
.dialect_span = this dialect...
|
||||
.phase_span = ... is not compatible with this phase
|
||||
|
||||
|
|
|
|||
|
|
@ -46,6 +46,8 @@ use crate::symbol::{Symbol, kw, sym};
|
|||
use crate::{DUMMY_SP, HashStableContext, Span, SpanDecoder, SpanEncoder, with_session_globals};
|
||||
|
||||
/// A `SyntaxContext` represents a chain of pairs `(ExpnId, Transparency)` named "marks".
|
||||
///
|
||||
/// See <https://rustc-dev-guide.rust-lang.org/macro-expansion.html> for more explanation.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub struct SyntaxContext(u32);
|
||||
|
||||
|
|
@ -61,7 +63,10 @@ pub type SyntaxContextKey = (SyntaxContext, ExpnId, Transparency);
|
|||
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
struct SyntaxContextData {
|
||||
/// The last macro expansion in the chain.
|
||||
/// (Here we say the most deeply nested macro expansion is the "outermost" expansion.)
|
||||
outer_expn: ExpnId,
|
||||
/// Transparency of the last macro expansion
|
||||
outer_transparency: Transparency,
|
||||
parent: SyntaxContext,
|
||||
/// This context, but with all transparent and semi-opaque expansions filtered away.
|
||||
|
|
@ -450,11 +455,13 @@ impl HygieneData {
|
|||
self.syntax_context_data[ctxt.0 as usize].opaque_and_semiopaque
|
||||
}
|
||||
|
||||
/// See [`SyntaxContextData::outer_expn`]
|
||||
#[inline]
|
||||
fn outer_expn(&self, ctxt: SyntaxContext) -> ExpnId {
|
||||
self.syntax_context_data[ctxt.0 as usize].outer_expn
|
||||
}
|
||||
|
||||
/// The last macro expansion and its Transparency
|
||||
#[inline]
|
||||
fn outer_mark(&self, ctxt: SyntaxContext) -> (ExpnId, Transparency) {
|
||||
let data = &self.syntax_context_data[ctxt.0 as usize];
|
||||
|
|
@ -900,6 +907,7 @@ impl SyntaxContext {
|
|||
HygieneData::with(|data| data.normalize_to_macro_rules(self))
|
||||
}
|
||||
|
||||
/// See [`SyntaxContextData::outer_expn`]
|
||||
#[inline]
|
||||
pub fn outer_expn(self) -> ExpnId {
|
||||
HygieneData::with(|data| data.outer_expn(self))
|
||||
|
|
@ -912,6 +920,7 @@ impl SyntaxContext {
|
|||
HygieneData::with(|data| data.expn_data(data.outer_expn(self)).clone())
|
||||
}
|
||||
|
||||
/// See [`HygieneData::outer_mark`]
|
||||
#[inline]
|
||||
fn outer_mark(self) -> (ExpnId, Transparency) {
|
||||
HygieneData::with(|data| data.outer_mark(self))
|
||||
|
|
@ -982,19 +991,20 @@ impl Span {
|
|||
#[derive(Clone, Debug, Encodable, Decodable, HashStable_Generic)]
|
||||
pub struct ExpnData {
|
||||
// --- The part unique to each expansion.
|
||||
/// The kind of this expansion - macro or compiler desugaring.
|
||||
pub kind: ExpnKind,
|
||||
/// The expansion that produced this expansion.
|
||||
/// The expansion that contains the definition of the macro for this expansion.
|
||||
pub parent: ExpnId,
|
||||
/// The location of the actual macro invocation or syntax sugar , e.g.
|
||||
/// `let x = foo!();` or `if let Some(y) = x {}`
|
||||
/// The span of the macro call which produced this expansion.
|
||||
///
|
||||
/// This may recursively refer to other macro invocations, e.g., if
|
||||
/// `foo!()` invoked `bar!()` internally, and there was an
|
||||
/// expression inside `bar!`; the call_site of the expression in
|
||||
/// the expansion would point to the `bar!` invocation; that
|
||||
/// call_site span would have its own ExpnData, with the call_site
|
||||
/// pointing to the `foo!` invocation.
|
||||
/// This span will typically have a different `ExpnData` and `call_site`.
|
||||
/// This recursively traces back through any macro calls which expanded into further
|
||||
/// macro calls, until the "source call-site" is reached at the root SyntaxContext.
|
||||
/// For example, if `food!()` expands to `fruit!()` which then expands to `grape`,
|
||||
/// then the call-site of `grape` is `fruit!()` and the call-site of `fruit!()`
|
||||
/// is `food!()`.
|
||||
///
|
||||
/// For a desugaring expansion, this is the span of the expression or node that was
|
||||
/// desugared.
|
||||
pub call_site: Span,
|
||||
/// Used to force two `ExpnData`s to have different `Fingerprint`s.
|
||||
/// Due to macro expansion, it's possible to end up with two `ExpnId`s
|
||||
|
|
|
|||
|
|
@ -710,8 +710,8 @@ impl Span {
|
|||
if !ctxt.is_root() { ctxt.outer_expn_data().call_site.source_callsite() } else { self }
|
||||
}
|
||||
|
||||
/// The `Span` for the tokens in the previous macro expansion from which `self` was generated,
|
||||
/// if any.
|
||||
/// Returns the call-site span of the last macro expansion which produced this `Span`.
|
||||
/// (see [`ExpnData::call_site`]). Returns `None` if this is not an expansion.
|
||||
pub fn parent_callsite(self) -> Option<Span> {
|
||||
let ctxt = self.ctxt();
|
||||
(!ctxt.is_root()).then(|| ctxt.outer_expn_data().call_site)
|
||||
|
|
|
|||
|
|
@ -202,18 +202,23 @@ mod sealed {
|
|||
impl<T> Sealed for *const T {}
|
||||
}
|
||||
|
||||
/// Trait which permits the allowed types to be used with [`VaListImpl::arg`].
|
||||
/// Types that are valid to read using [`VaListImpl::arg`].
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This trait must only be implemented for types that C passes as varargs without implicit promotion.
|
||||
/// The standard library implements this trait for primitive types that are
|
||||
/// expected to have a variable argument application-binary interface (ABI) on all
|
||||
/// platforms.
|
||||
///
|
||||
/// In C varargs, integers smaller than [`c_int`] and floats smaller than [`c_double`]
|
||||
/// are implicitly promoted to [`c_int`] and [`c_double`] respectively. Implementing this trait for
|
||||
/// types that are subject to this promotion rule is invalid.
|
||||
/// When C passes variable arguments, integers smaller than [`c_int`] and floats smaller
|
||||
/// than [`c_double`] are implicitly promoted to [`c_int`] and [`c_double`] respectively.
|
||||
/// Implementing this trait for types that are subject to this promotion rule is invalid.
|
||||
///
|
||||
/// [`c_int`]: core::ffi::c_int
|
||||
/// [`c_double`]: core::ffi::c_double
|
||||
// We may unseal this trait in the future, but currently our `va_arg` implementations don't support
|
||||
// types with an alignment larger than 8, or with a non-scalar layout. Inline assembly can be used
|
||||
// to accept unsupported types in the meantime.
|
||||
pub unsafe trait VaArgSafe: sealed::Sealed {}
|
||||
|
||||
// i8 and i16 are implicitly promoted to c_int in C, and cannot implement `VaArgSafe`.
|
||||
|
|
@ -233,7 +238,19 @@ unsafe impl<T> VaArgSafe for *mut T {}
|
|||
unsafe impl<T> VaArgSafe for *const T {}
|
||||
|
||||
impl<'f> VaListImpl<'f> {
|
||||
/// Advance to the next arg.
|
||||
/// Advance to and read the next variable argument.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This function is only sound to call when the next variable argument:
|
||||
///
|
||||
/// - has a type that is ABI-compatible with the type `T`
|
||||
/// - has a value that is a properly initialized value of type `T`
|
||||
///
|
||||
/// Calling this function with an incompatible type, an invalid value, or when there
|
||||
/// are no more variable arguments, is unsound.
|
||||
///
|
||||
/// [valid]: https://doc.rust-lang.org/nightly/nomicon/what-unsafe-does.html
|
||||
#[inline]
|
||||
pub unsafe fn arg<T: VaArgSafe>(&mut self) -> T {
|
||||
// SAFETY: the caller must uphold the safety contract for `va_arg`.
|
||||
|
|
|
|||
|
|
@ -1257,6 +1257,108 @@ mod ref_keyword {}
|
|||
/// [`async`]: ../std/keyword.async.html
|
||||
mod return_keyword {}
|
||||
|
||||
#[doc(keyword = "become")]
|
||||
//
|
||||
/// Perform a tail-call of a function.
|
||||
///
|
||||
/// <div class="warning">
|
||||
///
|
||||
/// `feature(explicit_tail_calls)` is currently incomplete and may not work properly.
|
||||
/// </div>
|
||||
///
|
||||
/// When tail calling a function, instead of its stack frame being added to the
|
||||
/// stack, the stack frame of the caller is directly replaced with the callee's.
|
||||
/// This means that as long as a loop in a call graph only uses tail calls, the
|
||||
/// stack growth will be bounded.
|
||||
///
|
||||
/// This is useful for writing functional-style code (since it prevents recursion
|
||||
/// from exhausting resources) or for code optimization (since a tail call
|
||||
/// *might* be cheaper than a normal call, tail calls can be used in a similar
|
||||
/// manner to computed goto).
|
||||
///
|
||||
/// Example of using `become` to implement functional-style `fold`:
|
||||
/// ```
|
||||
/// #![feature(explicit_tail_calls)]
|
||||
/// #![expect(incomplete_features)]
|
||||
///
|
||||
/// fn fold<T: Copy, S>(slice: &[T], init: S, f: impl Fn(S, T) -> S) -> S {
|
||||
/// match slice {
|
||||
/// // without `become`, on big inputs this could easily overflow the
|
||||
/// // stack. using a tail call guarantees that the stack will not grow unboundedly
|
||||
/// [first, rest @ ..] => become fold(rest, f(init, *first), f),
|
||||
/// [] => init,
|
||||
/// }
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// Compilers can already perform "tail call optimization" -- they can replace normal
|
||||
/// calls with tail calls, although there are no guarantees that this will be done.
|
||||
/// However, to perform TCO, the call needs to be the last thing that happens
|
||||
/// in the functions and be returned from it. This requirement is often broken
|
||||
/// by drop code for locals, which is run after computing the return expression:
|
||||
///
|
||||
/// ```
|
||||
/// fn example() {
|
||||
/// let string = "meow".to_owned();
|
||||
/// println!("{string}");
|
||||
/// return help(); // this is *not* the last thing that happens in `example`...
|
||||
/// }
|
||||
///
|
||||
/// // ... because it is desugared to this:
|
||||
/// fn example_desugared() {
|
||||
/// let string = "meow".to_owned();
|
||||
/// println!("{string}");
|
||||
/// let tmp = help();
|
||||
/// drop(string);
|
||||
/// return tmp;
|
||||
/// }
|
||||
///
|
||||
/// fn help() {}
|
||||
/// ```
|
||||
///
|
||||
/// For this reason, `become` also changes the drop order, such that locals are
|
||||
/// dropped *before* evaluating the call.
|
||||
///
|
||||
/// In order to guarantee that the compiler can perform a tail call, `become`
|
||||
/// currently has these requirements:
|
||||
/// 1. callee and caller must have the same ABI, arguments, and return type
|
||||
/// 2. callee and caller must not have varargs
|
||||
/// 3. caller must not be marked with `#[track_caller]`
|
||||
/// - callee is allowed to be marked with `#[track_caller]` as otherwise
|
||||
/// adding `#[track_caller]` would be a breaking change. if callee is
|
||||
/// marked with `#[track_caller]` a tail call is not guaranteed.
|
||||
/// 4. callee and caller cannot be a closure
|
||||
/// (unless it's coerced to a function pointer)
|
||||
///
|
||||
/// It is possible to tail-call a function pointer:
|
||||
/// ```
|
||||
/// #![feature(explicit_tail_calls)]
|
||||
/// #![expect(incomplete_features)]
|
||||
///
|
||||
/// #[derive(Copy, Clone)]
|
||||
/// enum Inst { Inc, Dec }
|
||||
///
|
||||
/// fn dispatch(stream: &[Inst], state: u32) -> u32 {
|
||||
/// const TABLE: &[fn(&[Inst], u32) -> u32] = &[increment, decrement];
|
||||
/// match stream {
|
||||
/// [inst, rest @ ..] => become TABLE[*inst as usize](rest, state),
|
||||
/// [] => state,
|
||||
/// }
|
||||
/// }
|
||||
///
|
||||
/// fn increment(stream: &[Inst], state: u32) -> u32 {
|
||||
/// become dispatch(stream, state + 1)
|
||||
/// }
|
||||
///
|
||||
/// fn decrement(stream: &[Inst], state: u32) -> u32 {
|
||||
/// become dispatch(stream, state - 1)
|
||||
/// }
|
||||
///
|
||||
/// let program = &[Inst::Inc, Inst::Inc, Inst::Dec, Inst::Inc];
|
||||
/// assert_eq!(dispatch(program, 0), 2);
|
||||
/// ```
|
||||
mod become_keyword {}
|
||||
|
||||
#[doc(keyword = "self")]
|
||||
//
|
||||
/// The receiver of a method, or the current module.
|
||||
|
|
|
|||
|
|
@ -284,7 +284,6 @@
|
|||
#![feature(core_float_math)]
|
||||
#![feature(decl_macro)]
|
||||
#![feature(deprecated_suggestion)]
|
||||
#![feature(derive_const)]
|
||||
#![feature(doc_cfg)]
|
||||
#![feature(doc_cfg_hide)]
|
||||
#![feature(doc_masked)]
|
||||
|
|
@ -332,11 +331,7 @@
|
|||
#![feature(cfg_select)]
|
||||
#![feature(char_internals)]
|
||||
#![feature(clone_to_uninit)]
|
||||
#![feature(const_cmp)]
|
||||
#![feature(const_convert)]
|
||||
#![feature(const_ops)]
|
||||
#![feature(const_option_ops)]
|
||||
#![feature(const_try)]
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(core_io_borrowed_buf)]
|
||||
#![feature(drop_guard)]
|
||||
|
|
|
|||
|
|
@ -198,11 +198,10 @@ impl Condvar {
|
|||
/// the system time. This function is susceptible to spurious wakeups.
|
||||
/// Condition variables normally have a boolean predicate associated with
|
||||
/// them, and the predicate must always be checked each time this function
|
||||
/// returns to protect against spurious wakeups. Additionally, it is
|
||||
/// typically desirable for the timeout to not exceed some duration in
|
||||
/// spite of spurious wakes, thus the sleep-duration is decremented by the
|
||||
/// amount slept. Alternatively, use the `wait_timeout_while` method
|
||||
/// to wait with a timeout while a predicate is true.
|
||||
/// returns to protect against spurious wakeups. Furthermore, since the timeout
|
||||
/// is given relative to the moment this function is called, it needs to be adjusted
|
||||
/// when this function is called in a loop. The [`wait_timeout_while`] method
|
||||
/// lets you wait with a timeout while a predicate is true, taking care of all these concerns.
|
||||
///
|
||||
/// The returned [`WaitTimeoutResult`] value indicates if the timeout is
|
||||
/// known to have elapsed.
|
||||
|
|
|
|||
|
|
@ -269,11 +269,10 @@ impl Condvar {
|
|||
/// the system time. This function is susceptible to spurious wakeups.
|
||||
/// Condition variables normally have a boolean predicate associated with
|
||||
/// them, and the predicate must always be checked each time this function
|
||||
/// returns to protect against spurious wakeups. Additionally, it is
|
||||
/// typically desirable for the timeout to not exceed some duration in
|
||||
/// spite of spurious wakes, thus the sleep-duration is decremented by the
|
||||
/// amount slept. Alternatively, use the `wait_timeout_while` method
|
||||
/// to wait with a timeout while a predicate is true.
|
||||
/// returns to protect against spurious wakeups. Furthermore, since the timeout
|
||||
/// is given relative to the moment this function is called, it needs to be adjusted
|
||||
/// when this function is called in a loop. The [`wait_timeout_while`] method
|
||||
/// lets you wait with a timeout while a predicate is true, taking care of all these concerns.
|
||||
///
|
||||
/// The returned [`WaitTimeoutResult`] value indicates if the timeout is
|
||||
/// known to have elapsed.
|
||||
|
|
|
|||
|
|
@ -25,15 +25,8 @@ impl Timespec {
|
|||
Timespec { t: timespec { tv_sec, tv_nsec } }
|
||||
}
|
||||
|
||||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
|
||||
const fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> {
|
||||
// FIXME: const PartialOrd
|
||||
let mut cmp = self.t.tv_sec - other.t.tv_sec;
|
||||
if cmp == 0 {
|
||||
cmp = self.t.tv_nsec as i64 - other.t.tv_nsec as i64;
|
||||
}
|
||||
|
||||
if cmp >= 0 {
|
||||
fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> {
|
||||
if self >= other {
|
||||
Ok(if self.t.tv_nsec >= other.t.tv_nsec {
|
||||
Duration::new(
|
||||
(self.t.tv_sec - other.t.tv_sec) as u64,
|
||||
|
|
@ -53,22 +46,20 @@ impl Timespec {
|
|||
}
|
||||
}
|
||||
|
||||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
|
||||
const fn checked_add_duration(&self, other: &Duration) -> Option<Timespec> {
|
||||
fn checked_add_duration(&self, other: &Duration) -> Option<Timespec> {
|
||||
let mut secs = self.t.tv_sec.checked_add_unsigned(other.as_secs())?;
|
||||
|
||||
// Nano calculations can't overflow because nanos are <1B which fit
|
||||
// in a u32.
|
||||
let mut nsec = other.subsec_nanos() + self.t.tv_nsec as u32;
|
||||
if nsec >= NSEC_PER_SEC as u32 {
|
||||
nsec -= NSEC_PER_SEC as u32;
|
||||
let mut nsec = other.subsec_nanos() + u32::try_from(self.t.tv_nsec).unwrap();
|
||||
if nsec >= NSEC_PER_SEC.try_into().unwrap() {
|
||||
nsec -= u32::try_from(NSEC_PER_SEC).unwrap();
|
||||
secs = secs.checked_add(1)?;
|
||||
}
|
||||
Some(Timespec { t: timespec { tv_sec: secs, tv_nsec: nsec as _ } })
|
||||
}
|
||||
|
||||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
|
||||
const fn checked_sub_duration(&self, other: &Duration) -> Option<Timespec> {
|
||||
fn checked_sub_duration(&self, other: &Duration) -> Option<Timespec> {
|
||||
let mut secs = self.t.tv_sec.checked_sub_unsigned(other.as_secs())?;
|
||||
|
||||
// Similar to above, nanos can't overflow.
|
||||
|
|
@ -222,18 +213,15 @@ impl SystemTime {
|
|||
SystemTime(time)
|
||||
}
|
||||
|
||||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
|
||||
pub const fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
|
||||
pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
|
||||
self.0.sub_timespec(&other.0)
|
||||
}
|
||||
|
||||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
|
||||
pub const fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
Some(SystemTime(self.0.checked_add_duration(other)?))
|
||||
}
|
||||
|
||||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
|
||||
pub const fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
Some(SystemTime(self.0.checked_sub_duration(other)?))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,22 +32,15 @@ impl SystemTime {
|
|||
SystemTime(usercalls::insecure_time())
|
||||
}
|
||||
|
||||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
|
||||
pub const fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
|
||||
// FIXME: ok_or_else with const closures
|
||||
match self.0.checked_sub(other.0) {
|
||||
Some(duration) => Ok(duration),
|
||||
None => Err(other.0 - self.0),
|
||||
}
|
||||
pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
|
||||
self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0)
|
||||
}
|
||||
|
||||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
|
||||
pub const fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
Some(SystemTime(self.0.checked_add(*other)?))
|
||||
}
|
||||
|
||||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
|
||||
pub const fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
Some(SystemTime(self.0.checked_sub(*other)?))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,8 +39,7 @@ impl SystemTime {
|
|||
Self(t)
|
||||
}
|
||||
|
||||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
|
||||
pub const fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
|
||||
pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
|
||||
if self.0 >= other.0 {
|
||||
Ok(Duration::from_secs((self.0 as u64).wrapping_sub(other.0 as u64)))
|
||||
} else {
|
||||
|
|
@ -48,13 +47,11 @@ impl SystemTime {
|
|||
}
|
||||
}
|
||||
|
||||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
|
||||
pub const fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
Some(SystemTime(self.0.checked_add_unsigned(other.as_secs())?))
|
||||
}
|
||||
|
||||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
|
||||
pub const fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
Some(SystemTime(self.0.checked_sub_unsigned(other.as_secs())?))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -80,32 +80,19 @@ impl SystemTime {
|
|||
.unwrap_or_else(|| panic!("time not implemented on this platform"))
|
||||
}
|
||||
|
||||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
|
||||
pub const fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
|
||||
// FIXME: ok_or_else with const closures
|
||||
match self.0.checked_sub(other.0) {
|
||||
Some(duration) => Ok(duration),
|
||||
None => Err(other.0 - self.0),
|
||||
}
|
||||
pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
|
||||
self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0)
|
||||
}
|
||||
|
||||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
|
||||
pub const fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
let temp = self.0.checked_add(*other)?;
|
||||
pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
let temp = Self(self.0.checked_add(*other)?);
|
||||
|
||||
// Check if can be represented in UEFI
|
||||
// FIXME: const PartialOrd
|
||||
let mut cmp = temp.as_secs() - MAX_UEFI_TIME.0.as_secs();
|
||||
if cmp == 0 {
|
||||
cmp = temp.subsec_nanos() as u64 - MAX_UEFI_TIME.0.subsec_nanos() as u64;
|
||||
}
|
||||
|
||||
if cmp <= 0 { Some(SystemTime(temp)) } else { None }
|
||||
if temp <= MAX_UEFI_TIME { Some(temp) } else { None }
|
||||
}
|
||||
|
||||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
|
||||
pub const fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
Some(SystemTime(self.0.checked_sub(*other)?))
|
||||
pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
self.0.checked_sub(*other).map(Self)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,18 +38,15 @@ impl SystemTime {
|
|||
SystemTime { t: Timespec::now(libc::CLOCK_REALTIME) }
|
||||
}
|
||||
|
||||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
|
||||
pub const fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
|
||||
pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
|
||||
self.t.sub_timespec(&other.t)
|
||||
}
|
||||
|
||||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
|
||||
pub const fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
Some(SystemTime { t: self.t.checked_add_duration(other)? })
|
||||
}
|
||||
|
||||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
|
||||
pub const fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
Some(SystemTime { t: self.t.checked_sub_duration(other)? })
|
||||
}
|
||||
}
|
||||
|
|
@ -136,15 +133,8 @@ impl Timespec {
|
|||
Timespec::new(t.tv_sec as i64, t.tv_nsec as i64).unwrap()
|
||||
}
|
||||
|
||||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
|
||||
pub const fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> {
|
||||
// FIXME: const PartialOrd
|
||||
let mut cmp = self.tv_sec - other.tv_sec;
|
||||
if cmp == 0 {
|
||||
cmp = self.tv_nsec.as_inner() as i64 - other.tv_nsec.as_inner() as i64;
|
||||
}
|
||||
|
||||
if cmp >= 0 {
|
||||
pub fn sub_timespec(&self, other: &Timespec) -> Result<Duration, Duration> {
|
||||
if self >= other {
|
||||
// NOTE(eddyb) two aspects of this `if`-`else` are required for LLVM
|
||||
// to optimize it into a branchless form (see also #75545):
|
||||
//
|
||||
|
|
@ -179,8 +169,7 @@ impl Timespec {
|
|||
}
|
||||
}
|
||||
|
||||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
|
||||
pub const fn checked_add_duration(&self, other: &Duration) -> Option<Timespec> {
|
||||
pub fn checked_add_duration(&self, other: &Duration) -> Option<Timespec> {
|
||||
let mut secs = self.tv_sec.checked_add_unsigned(other.as_secs())?;
|
||||
|
||||
// Nano calculations can't overflow because nanos are <1B which fit
|
||||
|
|
@ -190,11 +179,10 @@ impl Timespec {
|
|||
nsec -= NSEC_PER_SEC as u32;
|
||||
secs = secs.checked_add(1)?;
|
||||
}
|
||||
Some(unsafe { Timespec::new_unchecked(secs, nsec as i64) })
|
||||
Some(unsafe { Timespec::new_unchecked(secs, nsec.into()) })
|
||||
}
|
||||
|
||||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
|
||||
pub const fn checked_sub_duration(&self, other: &Duration) -> Option<Timespec> {
|
||||
pub fn checked_sub_duration(&self, other: &Duration) -> Option<Timespec> {
|
||||
let mut secs = self.tv_sec.checked_sub_unsigned(other.as_secs())?;
|
||||
|
||||
// Similar to above, nanos can't overflow.
|
||||
|
|
@ -203,7 +191,7 @@ impl Timespec {
|
|||
nsec += NSEC_PER_SEC as i32;
|
||||
secs = secs.checked_sub(1)?;
|
||||
}
|
||||
Some(unsafe { Timespec::new_unchecked(secs, nsec as i64) })
|
||||
Some(unsafe { Timespec::new_unchecked(secs, nsec.into()) })
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
|
|
|
|||
|
|
@ -31,22 +31,15 @@ impl SystemTime {
|
|||
panic!("time not implemented on this platform")
|
||||
}
|
||||
|
||||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
|
||||
pub const fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
|
||||
// FIXME: ok_or_else with const closures
|
||||
match self.0.checked_sub(other.0) {
|
||||
Some(duration) => Ok(duration),
|
||||
None => Err(other.0 - self.0),
|
||||
}
|
||||
pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
|
||||
self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0)
|
||||
}
|
||||
|
||||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
|
||||
pub const fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
Some(SystemTime(self.0.checked_add(*other)?))
|
||||
}
|
||||
|
||||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
|
||||
pub const fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
Some(SystemTime(self.0.checked_sub(*other)?))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,34 +43,23 @@ impl SystemTime {
|
|||
SystemTime(current_time(wasi::CLOCKID_REALTIME))
|
||||
}
|
||||
|
||||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
|
||||
pub const fn from_wasi_timestamp(ts: wasi::Timestamp) -> SystemTime {
|
||||
pub fn from_wasi_timestamp(ts: wasi::Timestamp) -> SystemTime {
|
||||
SystemTime(Duration::from_nanos(ts))
|
||||
}
|
||||
|
||||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
|
||||
pub const fn to_wasi_timestamp(&self) -> Option<wasi::Timestamp> {
|
||||
// FIXME: const TryInto
|
||||
let ns = self.0.as_nanos();
|
||||
if ns <= u64::MAX as u128 { Some(ns as u64) } else { None }
|
||||
pub fn to_wasi_timestamp(&self) -> Option<wasi::Timestamp> {
|
||||
self.0.as_nanos().try_into().ok()
|
||||
}
|
||||
|
||||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
|
||||
pub const fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
|
||||
// FIXME: ok_or_else with const closures
|
||||
match self.0.checked_sub(other.0) {
|
||||
Some(duration) => Ok(duration),
|
||||
None => Err(other.0 - self.0),
|
||||
}
|
||||
pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
|
||||
self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0)
|
||||
}
|
||||
|
||||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
|
||||
pub const fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
Some(SystemTime(self.0.checked_add(*other)?))
|
||||
}
|
||||
|
||||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
|
||||
pub const fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
Some(SystemTime(self.0.checked_sub(*other)?))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,34 +36,23 @@ impl SystemTime {
|
|||
SystemTime(Duration::new(now.seconds, now.nanoseconds))
|
||||
}
|
||||
|
||||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
|
||||
pub const fn from_wasi_timestamp(ts: wasi::Timestamp) -> SystemTime {
|
||||
pub fn from_wasi_timestamp(ts: wasi::Timestamp) -> SystemTime {
|
||||
SystemTime(Duration::from_nanos(ts))
|
||||
}
|
||||
|
||||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
|
||||
pub const fn to_wasi_timestamp(&self) -> Option<wasi::Timestamp> {
|
||||
// FIXME: const TryInto
|
||||
let ns = self.0.as_nanos();
|
||||
if ns <= u64::MAX as u128 { Some(ns as u64) } else { None }
|
||||
pub fn to_wasi_timestamp(&self) -> Option<wasi::Timestamp> {
|
||||
self.0.as_nanos().try_into().ok()
|
||||
}
|
||||
|
||||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
|
||||
pub const fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
|
||||
// FIXME: ok_or_else with const closures
|
||||
match self.0.checked_sub(other.0) {
|
||||
Some(duration) => Ok(duration),
|
||||
None => Err(other.0 - self.0),
|
||||
}
|
||||
pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
|
||||
self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0)
|
||||
}
|
||||
|
||||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
|
||||
pub const fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
Some(SystemTime(self.0.checked_add(*other)?))
|
||||
}
|
||||
|
||||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
|
||||
pub const fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
Some(SystemTime(self.0.checked_sub(*other)?))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -72,8 +72,7 @@ impl SystemTime {
|
|||
}
|
||||
}
|
||||
|
||||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
|
||||
const fn from_intervals(intervals: i64) -> SystemTime {
|
||||
fn from_intervals(intervals: i64) -> SystemTime {
|
||||
SystemTime {
|
||||
t: c::FILETIME {
|
||||
dwLowDateTime: intervals as u32,
|
||||
|
|
@ -82,13 +81,11 @@ impl SystemTime {
|
|||
}
|
||||
}
|
||||
|
||||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
|
||||
const fn intervals(&self) -> i64 {
|
||||
fn intervals(&self) -> i64 {
|
||||
(self.t.dwLowDateTime as i64) | ((self.t.dwHighDateTime as i64) << 32)
|
||||
}
|
||||
|
||||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
|
||||
pub const fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
|
||||
pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
|
||||
let me = self.intervals();
|
||||
let other = other.intervals();
|
||||
if me >= other {
|
||||
|
|
@ -98,14 +95,12 @@ impl SystemTime {
|
|||
}
|
||||
}
|
||||
|
||||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
|
||||
pub const fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
let intervals = self.intervals().checked_add(checked_dur2intervals(other)?)?;
|
||||
Some(SystemTime::from_intervals(intervals))
|
||||
}
|
||||
|
||||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
|
||||
pub const fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
let intervals = self.intervals().checked_sub(checked_dur2intervals(other)?)?;
|
||||
Some(SystemTime::from_intervals(intervals))
|
||||
}
|
||||
|
|
@ -155,18 +150,15 @@ impl Hash for SystemTime {
|
|||
}
|
||||
}
|
||||
|
||||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
|
||||
const fn checked_dur2intervals(dur: &Duration) -> Option<i64> {
|
||||
// FIXME: const TryInto
|
||||
let secs = dur
|
||||
.as_secs()
|
||||
fn checked_dur2intervals(dur: &Duration) -> Option<i64> {
|
||||
dur.as_secs()
|
||||
.checked_mul(INTERVALS_PER_SEC)?
|
||||
.checked_add(dur.subsec_nanos() as u64 / 100)?;
|
||||
if secs <= i64::MAX as u64 { Some(secs.cast_signed()) } else { None }
|
||||
.checked_add(dur.subsec_nanos() as u64 / 100)?
|
||||
.try_into()
|
||||
.ok()
|
||||
}
|
||||
|
||||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
|
||||
const fn intervals2dur(intervals: u64) -> Duration {
|
||||
fn intervals2dur(intervals: u64) -> Duration {
|
||||
Duration::new(intervals / INTERVALS_PER_SEC, ((intervals % INTERVALS_PER_SEC) * 100) as u32)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -43,22 +43,15 @@ impl SystemTime {
|
|||
SystemTime { 0: Duration::from_millis((upper as u64) << 32 | lower as u64) }
|
||||
}
|
||||
|
||||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
|
||||
pub const fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
|
||||
// FIXME: ok_or_else with const closures
|
||||
match self.0.checked_sub(other.0) {
|
||||
Some(duration) => Ok(duration),
|
||||
None => Err(other.0 - self.0),
|
||||
}
|
||||
pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
|
||||
self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0)
|
||||
}
|
||||
|
||||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
|
||||
pub const fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
pub fn checked_add_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
Some(SystemTime(self.0.checked_add(*other)?))
|
||||
}
|
||||
|
||||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
|
||||
pub const fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
pub fn checked_sub_duration(&self, other: &Duration) -> Option<SystemTime> {
|
||||
Some(SystemTime(self.0.checked_sub(*other)?))
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -551,13 +551,8 @@ impl SystemTime {
|
|||
/// println!("{difference:?}");
|
||||
/// ```
|
||||
#[stable(feature = "time2", since = "1.8.0")]
|
||||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
|
||||
pub const fn duration_since(&self, earlier: SystemTime) -> Result<Duration, SystemTimeError> {
|
||||
// FIXME: map_err in const
|
||||
match self.0.sub_time(&earlier.0) {
|
||||
Ok(time) => Ok(time),
|
||||
Err(err) => Err(SystemTimeError(err)),
|
||||
}
|
||||
pub fn duration_since(&self, earlier: SystemTime) -> Result<Duration, SystemTimeError> {
|
||||
self.0.sub_time(&earlier.0).map_err(SystemTimeError)
|
||||
}
|
||||
|
||||
/// Returns the difference from this system time to the
|
||||
|
|
@ -594,8 +589,7 @@ impl SystemTime {
|
|||
/// `SystemTime` (which means it's inside the bounds of the underlying data structure), `None`
|
||||
/// otherwise.
|
||||
#[stable(feature = "time_checked_add", since = "1.34.0")]
|
||||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
|
||||
pub const fn checked_add(&self, duration: Duration) -> Option<SystemTime> {
|
||||
pub fn checked_add(&self, duration: Duration) -> Option<SystemTime> {
|
||||
self.0.checked_add_duration(&duration).map(SystemTime)
|
||||
}
|
||||
|
||||
|
|
@ -603,15 +597,13 @@ impl SystemTime {
|
|||
/// `SystemTime` (which means it's inside the bounds of the underlying data structure), `None`
|
||||
/// otherwise.
|
||||
#[stable(feature = "time_checked_add", since = "1.34.0")]
|
||||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
|
||||
pub const fn checked_sub(&self, duration: Duration) -> Option<SystemTime> {
|
||||
pub fn checked_sub(&self, duration: Duration) -> Option<SystemTime> {
|
||||
self.0.checked_sub_duration(&duration).map(SystemTime)
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "time2", since = "1.8.0")]
|
||||
#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
|
||||
impl const Add<Duration> for SystemTime {
|
||||
impl Add<Duration> for SystemTime {
|
||||
type Output = SystemTime;
|
||||
|
||||
/// # Panics
|
||||
|
|
@ -624,16 +616,14 @@ impl const Add<Duration> for SystemTime {
|
|||
}
|
||||
|
||||
#[stable(feature = "time_augmented_assignment", since = "1.9.0")]
|
||||
#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
|
||||
impl const AddAssign<Duration> for SystemTime {
|
||||
impl AddAssign<Duration> for SystemTime {
|
||||
fn add_assign(&mut self, other: Duration) {
|
||||
*self = *self + other;
|
||||
}
|
||||
}
|
||||
|
||||
#[stable(feature = "time2", since = "1.8.0")]
|
||||
#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
|
||||
impl const Sub<Duration> for SystemTime {
|
||||
impl Sub<Duration> for SystemTime {
|
||||
type Output = SystemTime;
|
||||
|
||||
fn sub(self, dur: Duration) -> SystemTime {
|
||||
|
|
@ -642,8 +632,7 @@ impl const Sub<Duration> for SystemTime {
|
|||
}
|
||||
|
||||
#[stable(feature = "time_augmented_assignment", since = "1.9.0")]
|
||||
#[rustc_const_unstable(feature = "const_ops", issue = "143802")]
|
||||
impl const SubAssign<Duration> for SystemTime {
|
||||
impl SubAssign<Duration> for SystemTime {
|
||||
fn sub_assign(&mut self, other: Duration) {
|
||||
*self = *self - other;
|
||||
}
|
||||
|
|
@ -710,8 +699,7 @@ impl SystemTimeError {
|
|||
/// ```
|
||||
#[must_use]
|
||||
#[stable(feature = "time2", since = "1.8.0")]
|
||||
#[rustc_const_unstable(feature = "const_system_time", issue = "144517")]
|
||||
pub const fn duration(&self) -> Duration {
|
||||
pub fn duration(&self) -> Duration {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@
|
|||
- [\*-apple-visionos](platform-support/apple-visionos.md)
|
||||
- [aarch64-nintendo-switch-freestanding](platform-support/aarch64-nintendo-switch-freestanding.md)
|
||||
- [aarch64-unknown-linux-musl](platform-support/aarch64-unknown-linux-musl.md)
|
||||
- [aarch64-unknown-none*](platform-support/aarch64-unknown-none.md)
|
||||
- [aarch64_be-unknown-none-softfloat](platform-support/aarch64_be-unknown-none-softfloat.md)
|
||||
- [aarch64_be-unknown-linux-musl](platform-support/aarch64_be-unknown-linux-musl.md)
|
||||
- [amdgcn-amd-amdhsa](platform-support/amdgcn-amd-amdhsa.md)
|
||||
|
|
@ -55,7 +56,9 @@
|
|||
- [arm-none-eabi](platform-support/arm-none-eabi.md)
|
||||
- [armv4t-none-eabi](platform-support/armv4t-none-eabi.md)
|
||||
- [armv5te-none-eabi](platform-support/armv5te-none-eabi.md)
|
||||
- [armv7r-none-eabi](platform-support/armv7r-none-eabi.md)
|
||||
- [armv7a-none-eabi{,hf}](platform-support/armv7a-none-eabi.md)
|
||||
- [armv7r-none-eabi{,hf}](platform-support/armv7r-none-eabi.md)
|
||||
- [armebv7r-none-eabi{,hf}](platform-support/armebv7r-none-eabi.md)
|
||||
- [armv8r-none-eabihf](platform-support/armv8r-none-eabihf.md)
|
||||
- [thumbv6m-none-eabi](./platform-support/thumbv6m-none-eabi.md)
|
||||
- [thumbv7em-none-eabi\*](./platform-support/thumbv7em-none-eabi.md)
|
||||
|
|
|
|||
|
|
@ -134,7 +134,7 @@ As of `2025-01-02T`, the list of known names is as follows:
|
|||
- `unix`
|
||||
- `windows`
|
||||
|
||||
> Starting with 1.85.0, the `test` cfg is consider to be a "userspace" config
|
||||
> Starting with 1.85.0, the `test` cfg is considered to be a "userspace" config
|
||||
> despite being also set by `rustc` and should be managed by the build system itself.
|
||||
|
||||
Like with `values(any())`, well known names checking can be disabled by passing `cfg(any())`
|
||||
|
|
|
|||
|
|
@ -149,22 +149,22 @@ target | std | notes
|
|||
[`aarch64-apple-ios-sim`](platform-support/apple-ios.md) | ✓ | Apple iOS Simulator on ARM64
|
||||
[`aarch64-linux-android`](platform-support/android.md) | ✓ | ARM64 Android
|
||||
[`aarch64-unknown-fuchsia`](platform-support/fuchsia.md) | ✓ | ARM64 Fuchsia
|
||||
`aarch64-unknown-none` | * | Bare ARM64, hardfloat
|
||||
`aarch64-unknown-none-softfloat` | * | Bare ARM64, softfloat
|
||||
[`aarch64-unknown-none`](platform-support/aarch64-unknown-none.md) | * | Bare ARM64, hardfloat
|
||||
[`aarch64-unknown-none-softfloat`](platform-support/aarch64-unknown-none.md) | * | Bare ARM64, softfloat
|
||||
[`aarch64-unknown-uefi`](platform-support/unknown-uefi.md) | ? | ARM64 UEFI
|
||||
[`arm-linux-androideabi`](platform-support/android.md) | ✓ | Armv6 Android
|
||||
`arm-unknown-linux-musleabi` | ✓ | Armv6 Linux with musl 1.2.3
|
||||
`arm-unknown-linux-musleabihf` | ✓ | Armv6 Linux with musl 1.2.3, hardfloat
|
||||
[`arm64ec-pc-windows-msvc`](platform-support/arm64ec-pc-windows-msvc.md) | ✓ | Arm64EC Windows MSVC
|
||||
[`armebv7r-none-eabi`](platform-support/armv7r-none-eabi.md) | * | Bare Armv7-R, Big Endian
|
||||
[`armebv7r-none-eabihf`](platform-support/armv7r-none-eabi.md) | * | Bare Armv7-R, Big Endian, hardfloat
|
||||
[`armebv7r-none-eabi`](platform-support/armebv7r-none-eabi.md) | * | Bare Armv7-R, Big Endian
|
||||
[`armebv7r-none-eabihf`](platform-support/armebv7r-none-eabi.md) | * | Bare Armv7-R, Big Endian, hardfloat
|
||||
[`armv5te-unknown-linux-gnueabi`](platform-support/armv5te-unknown-linux-gnueabi.md) | ✓ | Armv5TE Linux (kernel 4.4+, glibc 2.23)
|
||||
`armv5te-unknown-linux-musleabi` | ✓ | Armv5TE Linux with musl 1.2.3
|
||||
[`armv7-linux-androideabi`](platform-support/android.md) | ✓ | Armv7-A Android
|
||||
`armv7-unknown-linux-gnueabi` | ✓ | Armv7-A Linux (kernel 4.15+, glibc 2.27)
|
||||
`armv7-unknown-linux-musleabi` | ✓ | Armv7-A Linux with musl 1.2.3
|
||||
`armv7-unknown-linux-musleabihf` | ✓ | Armv7-A Linux with musl 1.2.3, hardfloat
|
||||
[`armv7a-none-eabi`](platform-support/arm-none-eabi.md) | * | Bare Armv7-A
|
||||
[`armv7a-none-eabi`](platform-support/armv7a-none-eabi.md) | * | Bare Armv7-A
|
||||
[`armv7r-none-eabi`](platform-support/armv7r-none-eabi.md) | * | Bare Armv7-R
|
||||
[`armv7r-none-eabihf`](platform-support/armv7r-none-eabi.md) | * | Bare Armv7-R, hardfloat
|
||||
`i586-unknown-linux-gnu` | ✓ | 32-bit Linux (kernel 3.2+, glibc 2.17, original Pentium) [^x86_32-floats-x87]
|
||||
|
|
|
|||
78
src/doc/rustc/src/platform-support/aarch64-unknown-none.md
Normal file
78
src/doc/rustc/src/platform-support/aarch64-unknown-none.md
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
# `aarch64-unknown-none` and `aarch64-unknown-none-softfloat`
|
||||
|
||||
* **Tier: 2**
|
||||
* **Library Support:** core and alloc (bare-metal, `#![no_std]`)
|
||||
|
||||
Bare-metal targets for CPUs in the Armv8-A architecture family, running in AArch64 mode.
|
||||
|
||||
For the AArch32 mode carried over from Armv7-A, see
|
||||
[`armv7a-none-eabi`](armv7a-none-eabi.md) instead.
|
||||
|
||||
Processors in this family include the [Arm Cortex-A35, 53, 76, etc][aarch64-cpus].
|
||||
|
||||
[aarch64-cpus]: https://en.wikipedia.org/wiki/Comparison_of_ARM_processors#ARMv8-A
|
||||
|
||||
## Target maintainers
|
||||
|
||||
[Rust Embedded Devices Working Group Arm Team]
|
||||
|
||||
[Rust Embedded Devices Working Group Arm Team]: https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team
|
||||
|
||||
## Target CPU and Target Feature options
|
||||
|
||||
All AArch64 processors include an FPU. The difference between the `-none` and
|
||||
`-none-softfloat` targets is whether the FPU is used for passing function arguments.
|
||||
You may prefer the `-softfloat` target when writing a kernel or interfacing with
|
||||
pre-compiled binaries that use the soft-float ABI.
|
||||
|
||||
When using the hardfloat targets, the minimum floating-point features assumed
|
||||
are those of the `fp-armv8`, which excludes NEON SIMD support. If your
|
||||
processor supports a different set of floating-point features than the default
|
||||
expectations of `fp-armv8`, then these should also be enabled or disabled as
|
||||
needed with `-C target-feature=(+/-)`. It is also possible to tell Rust (or
|
||||
LLVM) that you have a specific model of Arm processor, using the
|
||||
[`-Ctarget-cpu`][target-cpu] option. Doing so may change the default set of
|
||||
target-features enabled.
|
||||
|
||||
[target-cpu]: https://doc.rust-lang.org/rustc/codegen-options/index.html#target-cpu
|
||||
[target-feature]: https://doc.rust-lang.org/rustc/codegen-options/index.html#target-feature
|
||||
|
||||
## Requirements
|
||||
|
||||
These targets are cross-compiled and use static linking.
|
||||
|
||||
By default, the `lld` linker included with Rust will be used; however, you may
|
||||
want to use the GNU linker instead. This can be obtained for Windows/Mac/Linux
|
||||
from the [Arm Developer Website][arm-gnu-toolchain], or possibly from your OS's
|
||||
package manager. To use it, add the following to your `.cargo/config.toml`:
|
||||
|
||||
```toml
|
||||
[target.aarch64-unknown-none]
|
||||
linker = "aarch64-none-elf-ld"
|
||||
```
|
||||
|
||||
The GNU linker can also be used by specifying `aarch64-none-elf-gcc` as the
|
||||
linker. This is needed when using GCC's link time optimization.
|
||||
|
||||
These targets don't provide a linker script, so you'll need to bring your own
|
||||
according to the specific device you are using. Pass
|
||||
`-Clink-arg=-Tyour_script.ld` as a rustc argument to make the linker use
|
||||
`your_script.ld` during linking.
|
||||
|
||||
[arm-gnu-toolchain]: https://developer.arm.com/Tools%20and%20Software/GNU%20Toolchain
|
||||
|
||||
## Cross-compilation toolchains and C code
|
||||
|
||||
This target supports C code compiled with the `aarch64-none-elf` target
|
||||
triple and a suitable `-march` or `-mcpu` flag.
|
||||
|
||||
## Start-up and Low-Level Code
|
||||
|
||||
The [Rust Embedded Devices Working Group Arm Team] maintain the
|
||||
[`aarch64-cpu`] crate, which may be useful for writing bare-metal code using
|
||||
this target.
|
||||
|
||||
The *TrustedFirmware* group also maintain [Rust crates for this
|
||||
target](https://github.com/ArmFirmwareCrates).
|
||||
|
||||
[`aarch64-cpu`]: https://docs.rs/aarch64-cpu
|
||||
|
|
@ -12,10 +12,10 @@ their own document.
|
|||
### Tier 2 Target List
|
||||
|
||||
- Arm A-Profile Architectures
|
||||
- `armv7a-none-eabi`
|
||||
- [`armv7a-none-eabi`](armv7a-none-eabi.md)
|
||||
- Arm R-Profile Architectures
|
||||
- [`armv7r-none-eabi` and `armv7r-none-eabihf`](armv7r-none-eabi.md)
|
||||
- [`armebv7r-none-eabi` and `armebv7r-none-eabihf`](armv7r-none-eabi.md)
|
||||
- [`armebv7r-none-eabi` and `armebv7r-none-eabihf`](armebv7r-none-eabi.md)
|
||||
- Arm M-Profile Architectures
|
||||
- [`thumbv6m-none-eabi`](thumbv6m-none-eabi.md)
|
||||
- [`thumbv7m-none-eabi`](thumbv7m-none-eabi.md)
|
||||
|
|
@ -28,7 +28,7 @@ their own document.
|
|||
### Tier 3 Target List
|
||||
|
||||
- Arm A-Profile Architectures
|
||||
- `armv7a-none-eabihf`
|
||||
- [`armv7a-none-eabihf`](armv7a-none-eabi.md)
|
||||
- Arm R-Profile Architectures
|
||||
- [`armv8r-none-eabihf`](armv8r-none-eabihf.md)
|
||||
- Arm M-Profile Architectures
|
||||
|
|
|
|||
55
src/doc/rustc/src/platform-support/armebv7r-none-eabi.md
Normal file
55
src/doc/rustc/src/platform-support/armebv7r-none-eabi.md
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
# `armebv7r-none-eabi` and `armebv7r-none-eabihf`
|
||||
|
||||
* **Tier: 2**
|
||||
* **Library Support:** core and alloc (bare-metal, `#![no_std]`)
|
||||
|
||||
Bare-metal target for CPUs in the Armv7-R architecture family running in Big
|
||||
Endian mode. These processors support dual ARM/Thumb mode, with ARM mode as
|
||||
the default.
|
||||
|
||||
**NOTE:** You should almost always prefer the [little-endian
|
||||
versions](armv7r-none-eabi.md) of these target. Big Endian Arm systems are
|
||||
highly unusual.
|
||||
|
||||
Processors in this family include the [Arm Cortex-R4, 5, 7, and 8][cortex-r].
|
||||
|
||||
See [`arm-none-eabi`](arm-none-eabi.md) for information applicable to all
|
||||
`arm-none-eabi` targets.
|
||||
|
||||
[cortex-r]: https://en.wikipedia.org/wiki/ARM_Cortex-R
|
||||
|
||||
## Target maintainers
|
||||
|
||||
[@chrisnc](https://github.com/chrisnc)
|
||||
|
||||
## Requirements
|
||||
|
||||
Note that some variants of the Cortex-R have both big-endian instructions and
|
||||
data. This configuration is known as BE-32, while data-only big-endianness is
|
||||
known as BE-8. To build programs for BE-32 processors, the GNU linker must be
|
||||
used with the `-mbe32` option. See [ARM Cortex-R Series Programmer's Guide:
|
||||
Endianness][endianness] for more details about different endian modes.
|
||||
|
||||
When using the hardfloat targets, the minimum floating-point features assumed
|
||||
are those of the `vfpv3-d16`, which includes single- and double-precision, with
|
||||
16 double-precision registers. This floating-point unit appears in Cortex-R4F
|
||||
and Cortex-R5F processors. See [VFP in the Cortex-R processors][vfp]
|
||||
for more details on the possible FPU variants.
|
||||
|
||||
If your processor supports a different set of floating-point features than the
|
||||
default expectations of `vfpv3-d16`, then these should also be enabled or
|
||||
disabled as needed with `-C target-feature=(+/-)`.
|
||||
|
||||
[endianness]: https://developer.arm.com/documentation/den0042/a/Coding-for-Cortex-R-Processors/Endianness
|
||||
|
||||
[vfp]: https://developer.arm.com/documentation/den0042/a/Floating-Point/Floating-point-basics-and-the-IEEE-754-standard/VFP-in-the-Cortex-R-processors
|
||||
|
||||
## Start-up and Low-Level Code
|
||||
|
||||
The [Rust Embedded Devices Working Group Arm Team] maintain the [`cortex-ar`]
|
||||
and [`cortex-r-rt`] crates, which may be useful for writing bare-metal code
|
||||
using this target. Those crates include several examples which run in QEMU and
|
||||
build using these targets.
|
||||
|
||||
[`cortex-ar`]: https://docs.rs/cortex-ar
|
||||
[`cortex-r-rt`]: https://docs.rs/cortex-r-rt
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
# armv4t-none-eabi / thumbv4t-none-eabi
|
||||
|
||||
Tier 3
|
||||
* **Tier: 3**
|
||||
* **Library Support:** core and alloc (bare-metal, `#![no_std]`)
|
||||
|
||||
These two targets are part of the [`arm-none-eabi`](arm-none-eabi.md) target
|
||||
group, and all the information there applies.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
# `armv5te-none-eabi`
|
||||
|
||||
**Tier: 3**
|
||||
* **Tier: 3**
|
||||
* **Library Support:** core and alloc (bare-metal, `#![no_std]`)
|
||||
|
||||
Bare-metal target for any cpu in the Armv5TE architecture family, supporting
|
||||
ARM/Thumb code interworking (aka `A32`/`T32`), with `A32` code as the default code
|
||||
|
|
|
|||
70
src/doc/rustc/src/platform-support/armv7a-none-eabi.md
Normal file
70
src/doc/rustc/src/platform-support/armv7a-none-eabi.md
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
# `armv7a-none-eabi` and `armv7a-none-eabihf`
|
||||
|
||||
* **Tier: 2** for `armv7a-none-eabi`
|
||||
* **Tier: 3** for `armv7a-none-eabihf`
|
||||
* **Library Support:** core and alloc (bare-metal, `#![no_std]`)
|
||||
|
||||
Bare-metal target for CPUs in the Armv7-A architecture family, supporting
|
||||
dual ARM/Thumb mode, with ARM mode as the default.
|
||||
|
||||
Note, this is for processors running in AArch32 mode. For the AArch64 mode
|
||||
added in Armv8-A, see [`aarch64-unknown-none`](aarch64-unknown-none.md) instead.
|
||||
|
||||
Processors in this family include the [Arm Cortex-A5, 8, 32, etc][cortex-a].
|
||||
|
||||
See [`arm-none-eabi`](arm-none-eabi.md) for information applicable to all
|
||||
`arm-none-eabi` targets.
|
||||
|
||||
[cortex-a]: https://en.wikipedia.org/wiki/ARM_Cortex-A
|
||||
|
||||
## Target maintainers
|
||||
|
||||
[Rust Embedded Devices Working Group Arm Team]
|
||||
|
||||
[Rust Embedded Devices Working Group Arm Team]: https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team
|
||||
|
||||
## Requirements
|
||||
|
||||
Almost all Armv7-A processors include an FPU (a VFPv3 or a VFPv4). The
|
||||
difference between the `-eabi` and `-eabihf` targets is whether the FPU is
|
||||
used for passing function arguments. You may prefer the `-eabi` soft-float
|
||||
target when the processor does not have a floating point unit or the compiled
|
||||
code should not use the floating point unit.
|
||||
|
||||
When using the hardfloat targets, the minimum floating-point features assumed
|
||||
are those of the VFPv3-D16, which includes single- and double-precision, with
|
||||
16 double-precision registers. This floating-point unit appears in Cortex-A8
|
||||
and Cortex-A9 processors. See [VFP in the Cortex-A processors][vfp] for more
|
||||
details on the possible FPU variants.
|
||||
|
||||
If your processor supports a different set of floating-point features than the
|
||||
default expectations of VFPv3-D16, then these should also be enabled or
|
||||
disabled as needed with `-C target-feature=(+/-)`.
|
||||
|
||||
In general, the following four combinations are possible:
|
||||
|
||||
- VFPv3-D16, target feature `+vfp3` and `-d32`
|
||||
- VFPv3-D32, target feature `+vfp3` and `+d32`
|
||||
- VFPv4-D16, target feature `+vfp4` and `-d32`
|
||||
- VFPv4-D32, target feature `+vfp4` and `+d32`
|
||||
|
||||
An Armv7-A processor may optionally include a NEON hardware unit which
|
||||
provides Single Instruction Multiple Data (SIMD) operations. The
|
||||
implementation of this unit implies VFPv3-D32. The target feature `+neon` may
|
||||
be added to inform the compiler about the availability of NEON.
|
||||
|
||||
You can refer to the [arm-none-eabi](arm-none-eabi.md) documentation for a
|
||||
generic guide on target feature and target CPU specification and how to enable
|
||||
and disable them via `.cargo/config.toml` file.
|
||||
|
||||
[vfp]: https://developer.arm.com/documentation/den0013/0400/Floating-Point/Floating-point-basics-and-the-IEEE-754-standard/ARM-VFP
|
||||
|
||||
## Start-up and Low-Level Code
|
||||
|
||||
The [Rust Embedded Devices Working Group Arm Team] maintain the [`cortex-ar`]
|
||||
and [`cortex-a-rt`] crates, which may be useful for writing bare-metal code
|
||||
using this target. The [`cortex-ar` repository](https://github.com/rust-embedded/cortex-ar)
|
||||
includes several examples which run in QEMU and build using these targets.
|
||||
|
||||
[`cortex-ar`]: https://docs.rs/cortex-ar
|
||||
[`cortex-a-rt`]: https://docs.rs/cortex-a-rt
|
||||
|
|
@ -1,14 +1,13 @@
|
|||
# `arm(eb)?v7r-none-eabi(hf)?`
|
||||
# `armv7r-none-eabi` and `armv7r-none-eabihf`
|
||||
|
||||
**Tier: 2**
|
||||
* **Tier: 2**
|
||||
* **Library Support:** core and alloc (bare-metal, `#![no_std]`)
|
||||
|
||||
Bare-metal target for CPUs in the Armv7-R architecture family, supporting
|
||||
dual ARM/Thumb mode, with ARM mode as the default.
|
||||
|
||||
Processors in this family include the [Arm Cortex-R4, 5, 7, and 8][cortex-r].
|
||||
|
||||
The `eb` versions of this target generate code for big-endian processors.
|
||||
|
||||
See [`arm-none-eabi`](arm-none-eabi.md) for information applicable to all
|
||||
`arm-none-eabi` targets.
|
||||
|
||||
|
|
@ -17,16 +16,12 @@ See [`arm-none-eabi`](arm-none-eabi.md) for information applicable to all
|
|||
## Target maintainers
|
||||
|
||||
[@chrisnc](https://github.com/chrisnc)
|
||||
[Rust Embedded Devices Working Group Arm Team]
|
||||
|
||||
[Rust Embedded Devices Working Group Arm Team]: https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team
|
||||
|
||||
## Requirements
|
||||
|
||||
When using the big-endian version of this target, note that some variants of
|
||||
the Cortex-R have both big-endian instructions and data. This configuration is
|
||||
known as BE-32, while data-only big-endianness is known as BE-8. To build
|
||||
programs for BE-32 processors, the GNU linker must be used with the `-mbe32`
|
||||
option. See [ARM Cortex-R Series Programmer's Guide: Endianness][endianness]
|
||||
for more details about different endian modes.
|
||||
|
||||
When using the hardfloat targets, the minimum floating-point features assumed
|
||||
are those of the `vfpv3-d16`, which includes single- and double-precision, with
|
||||
16 double-precision registers. This floating-point unit appears in Cortex-R4F
|
||||
|
|
@ -41,7 +36,12 @@ disabled as needed with `-C target-feature=(+/-)`.
|
|||
|
||||
[vfp]: https://developer.arm.com/documentation/den0042/a/Floating-Point/Floating-point-basics-and-the-IEEE-754-standard/VFP-in-the-Cortex-R-processors
|
||||
|
||||
## Cross-compilation toolchains and C code
|
||||
## Start-up and Low-Level Code
|
||||
|
||||
This target supports C code compiled with the `arm-none-eabi` target triple and
|
||||
`-march=armv7-r` or a suitable `-mcpu` flag.
|
||||
The [Rust Embedded Devices Working Group Arm Team] maintain the [`cortex-ar`]
|
||||
and [`cortex-r-rt`] crates, which may be useful for writing bare-metal code
|
||||
using this target. Those crates include several examples which run in QEMU and
|
||||
build using these targets.
|
||||
|
||||
[`cortex-ar`]: https://docs.rs/cortex-ar
|
||||
[`cortex-r-rt`]: https://docs.rs/cortex-r-rt
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
# `armv8r-none-eabihf`
|
||||
|
||||
**Tier: 3**
|
||||
* **Tier: 3**
|
||||
* **Library Support:** core and alloc (bare-metal, `#![no_std]`)
|
||||
|
||||
Bare-metal target for CPUs in the Armv8-R architecture family, supporting
|
||||
dual ARM/Thumb mode, with ARM mode as the default.
|
||||
|
|
@ -17,6 +18,9 @@ See [`arm-none-eabi`](arm-none-eabi.md) for information applicable to all
|
|||
## Target maintainers
|
||||
|
||||
[@chrisnc](https://github.com/chrisnc)
|
||||
[Rust Embedded Devices Working Group Arm Team]
|
||||
|
||||
[Rust Embedded Devices Working Group Arm Team]: https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team
|
||||
|
||||
## Requirements
|
||||
|
||||
|
|
@ -34,7 +38,14 @@ Technical Reference Manual for more details.
|
|||
|
||||
[fpu]: https://developer.arm.com/documentation/100026/0104/Advanced-SIMD-and-floating-point-support/About-the-Advanced-SIMD-and-floating-point-support
|
||||
|
||||
## Cross-compilation toolchains and C code
|
||||
### Table of supported CPUs for `armv8r-none-eabihf`
|
||||
|
||||
This target supports C code compiled with the `arm-none-eabi` target triple and
|
||||
`-march=armv8-r` or a suitable `-mcpu` flag.
|
||||
| CPU | FPU | Neon | Target CPU | Target Features |
|
||||
|:----------- | --- |:---- |:---------------- |:------------------ |
|
||||
| Any | SP | No | None | None |
|
||||
| Cortex-R52 | SP | No | `cortex-r52` | `-fp64,-d32,-neon` |
|
||||
| Cortex-R52 | DP | No | `cortex-r52` | `-neon` |
|
||||
| Cortex-R52 | DP | Yes | `cortex-r52` | None |
|
||||
| Cortex-R52+ | SP | No | `cortex-r52plus` | `-fp64,-d32,-neon` |
|
||||
| Cortex-R52+ | DP | No | `cortex-r52plus` | `-neon` |
|
||||
| Cortex-R52+ | DP | Yes | `cortex-r52plus` | None |
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
# `thumbv6m-none-eabi`
|
||||
|
||||
**Tier: 2**
|
||||
* **Tier: 2**
|
||||
* **Library Support:** core and alloc (bare-metal, `#![no_std]`)
|
||||
|
||||
Bare-metal target for CPUs in the [Armv6-M] architecture family, supporting a
|
||||
subset of the [T32 ISA][t32-isa].
|
||||
|
|
@ -26,7 +27,7 @@ only option because there is no FPU support in [Armv6-M].
|
|||
|
||||
## Target maintainers
|
||||
|
||||
* [Rust Embedded Devices Working Group Arm Team](https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team)
|
||||
[Rust Embedded Devices Working Group Arm Team](https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team)
|
||||
|
||||
## Target CPU and Target Feature options
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
# `thumbv7em-none-eabi` and `thumbv7em-none-eabihf`
|
||||
|
||||
**Tier: 2**
|
||||
* **Tier: 2**
|
||||
* **Library Support:** core and alloc (bare-metal, `#![no_std]`)
|
||||
|
||||
Bare-metal target for CPUs in the [Armv7E-M] architecture family, supporting a
|
||||
subset of the [T32 ISA][t32-isa].
|
||||
|
|
@ -21,7 +22,7 @@ See [`arm-none-eabi`](arm-none-eabi.md) for information applicable to all
|
|||
|
||||
## Target maintainers
|
||||
|
||||
* [Rust Embedded Devices Working Group Arm Team](https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team)
|
||||
[Rust Embedded Devices Working Group Arm Team](https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team)
|
||||
|
||||
## Target CPU and Target Feature options
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
# `thumbv7m-none-eabi`
|
||||
|
||||
**Tier: 2**
|
||||
* **Tier: 2**
|
||||
* **Library Support:** core and alloc (bare-metal, `#![no_std]`)
|
||||
|
||||
Bare-metal target for CPUs in the [Armv7-M] architecture family, supporting a
|
||||
subset of the [T32 ISA][t32-isa].
|
||||
|
|
@ -22,7 +23,7 @@ only option because there is no FPU support in [Armv7-M].
|
|||
|
||||
## Target maintainers
|
||||
|
||||
* [Rust Embedded Devices Working Group Arm Team](https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team)
|
||||
[Rust Embedded Devices Working Group Arm Team](https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team)
|
||||
|
||||
## Target CPU and Target Feature options
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
# `thumbv8m.base-none-eabi`
|
||||
|
||||
**Tier: 2**
|
||||
* **Tier: 2**
|
||||
* **Library Support:** core and alloc (bare-metal, `#![no_std]`)
|
||||
|
||||
Bare-metal target for CPUs in the Baseline [Armv8-M] architecture family,
|
||||
supporting a subset of the [T32 ISA][t32-isa].
|
||||
|
|
@ -22,7 +23,7 @@ only option because there is no FPU support in [Armv8-M] Baseline.
|
|||
|
||||
## Target maintainers
|
||||
|
||||
* [Rust Embedded Devices Working Group Arm Team](https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team)
|
||||
[Rust Embedded Devices Working Group Arm Team](https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team)
|
||||
|
||||
## Target CPU and Target Feature options
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
# `thumbv8m.main-none-eabi` and `thumbv8m.main-none-eabihf`
|
||||
|
||||
**Tier: 2**
|
||||
* **Tier: 2**
|
||||
* **Library Support:** core and alloc (bare-metal, `#![no_std]`)
|
||||
|
||||
Bare-metal target for CPUs in the Mainline [Armv8-M] architecture family,
|
||||
supporting a subset of the [T32 ISA][t32-isa].
|
||||
|
|
@ -25,7 +26,7 @@ See [`arm-none-eabi`](arm-none-eabi.md) for information applicable to all
|
|||
|
||||
## Target maintainers
|
||||
|
||||
* [Rust Embedded Devices Working Group Arm Team](https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team)
|
||||
[Rust Embedded Devices Working Group Arm Team](https://github.com/rust-embedded/wg?tab=readme-ov-file#the-arm-team)
|
||||
|
||||
## Target CPU and Target Feature options
|
||||
|
||||
|
|
|
|||
64
src/tools/tidy/src/fluent_lowercase.rs
Normal file
64
src/tools/tidy/src/fluent_lowercase.rs
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
//! Checks that the error messages start with a lowercased letter (except when allowed to).
|
||||
|
||||
use std::path::Path;
|
||||
|
||||
use fluent_syntax::ast::{Entry, Message, PatternElement};
|
||||
|
||||
use crate::walk::{filter_dirs, walk};
|
||||
|
||||
#[rustfmt::skip]
|
||||
const ALLOWED_CAPITALIZED_WORDS: &[&str] = &[
|
||||
// tidy-alphabetical-start
|
||||
"ABI",
|
||||
"ABIs",
|
||||
"ADT",
|
||||
"C",
|
||||
"CGU",
|
||||
"Ferris",
|
||||
"MIR",
|
||||
"OK",
|
||||
"Rust",
|
||||
"VS", // VS Code
|
||||
// tidy-alphabetical-end
|
||||
];
|
||||
|
||||
fn filter_fluent(path: &Path) -> bool {
|
||||
if let Some(ext) = path.extension() { ext.to_str() != Some("ftl") } else { true }
|
||||
}
|
||||
|
||||
fn is_allowed_capitalized_word(msg: &str) -> bool {
|
||||
ALLOWED_CAPITALIZED_WORDS.iter().any(|word| {
|
||||
msg.strip_prefix(word)
|
||||
.map(|tail| tail.chars().next().map(|c| c == '-' || c.is_whitespace()).unwrap_or(true))
|
||||
.unwrap_or_default()
|
||||
})
|
||||
}
|
||||
|
||||
fn check_lowercase(filename: &str, contents: &str, bad: &mut bool) {
|
||||
let (Ok(parse) | Err((parse, _))) = fluent_syntax::parser::parse(contents);
|
||||
|
||||
for entry in &parse.body {
|
||||
if let Entry::Message(msg) = entry
|
||||
&& let Message { value: Some(pattern), .. } = msg
|
||||
&& let [first_pattern, ..] = &pattern.elements[..]
|
||||
&& let PatternElement::TextElement { value } = first_pattern
|
||||
&& value.chars().next().is_some_and(char::is_uppercase)
|
||||
&& !is_allowed_capitalized_word(value)
|
||||
{
|
||||
tidy_error!(
|
||||
bad,
|
||||
"{filename}: message `{value}` starts with an uppercase letter. Fix it or add it to `ALLOWED_CAPITALIZED_WORDS`"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check(path: &Path, bad: &mut bool) {
|
||||
walk(
|
||||
path,
|
||||
|path, is_dir| filter_dirs(path) || (!is_dir && filter_fluent(path)),
|
||||
&mut |ent, contents| {
|
||||
check_lowercase(ent.path().to_str().unwrap(), contents, bad);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
|
@ -257,6 +257,7 @@ pub mod extra_checks;
|
|||
pub mod features;
|
||||
pub mod filenames;
|
||||
pub mod fluent_alphabetical;
|
||||
pub mod fluent_lowercase;
|
||||
pub mod fluent_period;
|
||||
mod fluent_used;
|
||||
pub mod gcc_submodule;
|
||||
|
|
|
|||
|
|
@ -121,6 +121,7 @@ fn main() {
|
|||
check!(error_codes, &root_path, &[&compiler_path, &librustdoc_path], verbose, &ci_info);
|
||||
check!(fluent_alphabetical, &compiler_path, bless);
|
||||
check!(fluent_period, &compiler_path);
|
||||
check!(fluent_lowercase, &compiler_path);
|
||||
check!(target_policy, &root_path);
|
||||
check!(gcc_submodule, &root_path, &compiler_path);
|
||||
|
||||
|
|
|
|||
47
tests/codegen-llvm/cffi/c-variadic-inline.rs
Normal file
47
tests/codegen-llvm/cffi/c-variadic-inline.rs
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
//@ compile-flags: -C opt-level=3
|
||||
#![feature(c_variadic)]
|
||||
|
||||
// Test that the inline attributes are accepted on C-variadic functions.
|
||||
//
|
||||
// Currently LLVM is unable to inline C-variadic functions, but that is valid because despite
|
||||
// the name even `#[inline(always)]` is just a hint.
|
||||
|
||||
#[inline(always)]
|
||||
unsafe extern "C" fn inline_always(mut ap: ...) -> u32 {
|
||||
ap.arg::<u32>()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
unsafe extern "C" fn inline(mut ap: ...) -> u32 {
|
||||
ap.arg::<u32>()
|
||||
}
|
||||
|
||||
#[inline(never)]
|
||||
unsafe extern "C" fn inline_never(mut ap: ...) -> u32 {
|
||||
ap.arg::<u32>()
|
||||
}
|
||||
|
||||
#[cold]
|
||||
unsafe extern "C" fn cold(mut ap: ...) -> u32 {
|
||||
ap.arg::<u32>()
|
||||
}
|
||||
|
||||
#[unsafe(no_mangle)]
|
||||
#[inline(never)]
|
||||
fn helper() {
|
||||
// CHECK-LABEL: helper
|
||||
// CHECK-LABEL: call c_variadic_inline::inline_always
|
||||
// CHECK-LABEL: call c_variadic_inline::inline
|
||||
// CHECK-LABEL: call c_variadic_inline::inline_never
|
||||
// CHECK-LABEL: call c_variadic_inline::cold
|
||||
unsafe {
|
||||
inline_always(1);
|
||||
inline(2);
|
||||
inline_never(3);
|
||||
cold(4);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
helper()
|
||||
}
|
||||
40
tests/ui/c-variadic/naked.rs
Normal file
40
tests/ui/c-variadic/naked.rs
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
//@ run-pass
|
||||
//@ only-x86_64
|
||||
//@ only-linux
|
||||
#![feature(c_variadic)]
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Debug, PartialEq)]
|
||||
struct Data(i32, f64);
|
||||
|
||||
#[unsafe(naked)]
|
||||
unsafe extern "C" fn c_variadic(_: ...) -> Data {
|
||||
// This assembly was generated with GCC, because clang/LLVM is unable to
|
||||
// optimize out the spilling of all registers to the stack.
|
||||
core::arch::naked_asm!(
|
||||
" sub rsp, 96",
|
||||
" mov QWORD PTR [rsp-88], rdi",
|
||||
" test al, al",
|
||||
" je .L7",
|
||||
" movaps XMMWORD PTR [rsp-40], xmm0",
|
||||
".L7:",
|
||||
" lea rax, [rsp+104]",
|
||||
" mov rcx, QWORD PTR [rsp-40]",
|
||||
" mov DWORD PTR [rsp-112], 0",
|
||||
" mov QWORD PTR [rsp-104], rax",
|
||||
" lea rax, [rsp-88]",
|
||||
" mov QWORD PTR [rsp-96], rax",
|
||||
" movq xmm0, rcx",
|
||||
" mov eax, DWORD PTR [rsp-88]",
|
||||
" mov DWORD PTR [rsp-108], 48",
|
||||
" add rsp, 96",
|
||||
" ret",
|
||||
)
|
||||
}
|
||||
|
||||
fn main() {
|
||||
unsafe {
|
||||
assert_eq!(c_variadic(1, 2.0), Data(1, 2.0));
|
||||
assert_eq!(c_variadic(123, 4.56), Data(123, 4.56));
|
||||
}
|
||||
}
|
||||
14
tests/ui/explicit-tail-calls/c-variadic.rs
Normal file
14
tests/ui/explicit-tail-calls/c-variadic.rs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
#![expect(incomplete_features)]
|
||||
#![feature(c_variadic, explicit_tail_calls)]
|
||||
#![allow(unused)]
|
||||
|
||||
unsafe extern "C" fn foo(mut ap: ...) -> u32 {
|
||||
ap.arg::<u32>()
|
||||
}
|
||||
|
||||
extern "C" fn bar() -> u32 {
|
||||
unsafe { become foo(1, 2, 3) }
|
||||
//~^ ERROR c-variadic functions can't be tail-called
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
8
tests/ui/explicit-tail-calls/c-variadic.stderr
Normal file
8
tests/ui/explicit-tail-calls/c-variadic.stderr
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
error: c-variadic functions can't be tail-called
|
||||
--> $DIR/c-variadic.rs:10:14
|
||||
|
|
||||
LL | unsafe { become foo(1, 2, 3) }
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
|
|
@ -20,4 +20,4 @@ pub fn lib_main() {
|
|||
unsafe { f(42); }
|
||||
}
|
||||
|
||||
//~? ERROR Dlltool could not create import library with
|
||||
//~? ERROR dlltool could not create import library with
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
error: Dlltool could not create import library with $DLLTOOL -d $DEF_FILE -D foo.dll -l $LIB_FILE $TARGET_MACHINE $ASM_FLAGS --no-leading-underscore $TEMP_PREFIX:
|
||||
error: dlltool could not create import library with $DLLTOOL -d $DEF_FILE -D foo.dll -l $LIB_FILE $TARGET_MACHINE $ASM_FLAGS --no-leading-underscore $TEMP_PREFIX:
|
||||
|
||||
$DLLTOOL: Syntax error in def file $DEF_FILE:1␍
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue