Auto merge of #151533 - JonathanBrouwer:rollup-P3oXrte, r=JonathanBrouwer

Rollup of 5 pull requests

Successful merges:

 - rust-lang/rust#149639 (inline constant localized typeck constraint computation)
 - rust-lang/rust#150780 (Add -Z large-data-threshold)
 - rust-lang/rust#151520 (Rename `HandleCycleError` to `CycleErrorHandling`)
 - rust-lang/rust#151525 (update enzyme, includes an extra patch to fix MacOS builds in CI)
 - rust-lang/rust#151527 (Clean up or resolve cfg-related instances of `FIXME(f16_f128)`)

r? @ghost
This commit is contained in:
bors
2026-01-23 10:48:41 +00:00
34 changed files with 228 additions and 170 deletions
@@ -45,7 +45,6 @@ pub(super) fn convert_typeck_constraints<'tcx>(
{
localize_statement_constraint(
tcx,
body,
stmt,
&outlives_constraint,
point,
@@ -74,7 +73,6 @@ pub(super) fn convert_typeck_constraints<'tcx>(
/// needed CFG `from`-`to` intra-block nodes.
fn localize_statement_constraint<'tcx>(
tcx: TyCtxt<'tcx>,
body: &Body<'tcx>,
stmt: &Statement<'tcx>,
outlives_constraint: &OutlivesConstraint<'tcx>,
current_point: PointIndex,
@@ -114,28 +112,22 @@ fn localize_statement_constraint<'tcx>(
},
"there should be no common regions between the LHS and RHS of an assignment"
);
let lhs_ty = body.local_decls[lhs.local].ty;
let successor_point = current_point;
compute_constraint_direction(
tcx,
outlives_constraint,
&lhs_ty,
current_point,
successor_point,
universal_regions,
)
}
_ => {
// For the other cases, we localize an outlives constraint to where it arises.
LocalizedOutlivesConstraint {
source: outlives_constraint.sup,
from: current_point,
target: outlives_constraint.sub,
to: current_point,
}
// Assignments should be the only statement that can both generate constraints that
// apply on entry (specific to the RHS place) *and* others that only apply on exit (the
// subset of RHS regions that actually flow into the LHS): i.e., where midpoints would
// be used to ensure the former happen before the latter, within the same MIR Location.
}
}
// We generally localize an outlives constraint to where it arises.
LocalizedOutlivesConstraint {
source: outlives_constraint.sup,
from: current_point,
target: outlives_constraint.sub,
to: current_point,
}
}
/// For a given outlives constraint arising from a MIR terminator, localize the constraint with the
@@ -150,14 +142,12 @@ fn localize_terminator_constraint<'tcx>(
universal_regions: &UniversalRegions<'tcx>,
) -> LocalizedOutlivesConstraint {
// FIXME: check if other terminators need the same handling as `Call`s, in particular
// Assert/Yield/Drop. A handful of tests are failing with Drop related issues, as well as some
// coroutine tests, and that may be why.
// Assert/Yield/Drop.
match &terminator.kind {
// FIXME: also handle diverging calls.
TerminatorKind::Call { destination, target: Some(target), .. } => {
// Calls are similar to assignments, and thus follow the same pattern. If there is a
// target for the call we also relate what flows into the destination here to entry to
// that successor.
// If there is a target for the call we also relate what flows into the destination here
// to entry to that successor.
let destination_ty = destination.ty(&body.local_decls, tcx);
let successor_location = Location { block: *target, statement_index: 0 };
let successor_point = liveness.point_from_location(successor_location);
@@ -39,6 +39,7 @@ pub(crate) fn new(
debug_info_compression: llvm::CompressionKind,
use_emulated_tls: bool,
use_wasm_eh: bool,
large_data_threshold: u64,
) -> Result<Self, LlvmError<'static>> {
// SAFETY: llvm::LLVMRustCreateTargetMachine copies pointed to data
let tm_ptr = unsafe {
@@ -65,6 +66,7 @@ pub(crate) fn new(
debug_info_compression,
use_emulated_tls,
use_wasm_eh,
large_data_threshold,
)
};
@@ -275,6 +275,8 @@ pub(crate) fn target_machine_factory(
let use_wasm_eh = wants_wasm_eh(sess);
let large_data_threshold = sess.opts.unstable_opts.large_data_threshold.unwrap_or(0);
let prof = SelfProfilerRef::clone(&sess.prof);
Arc::new(move |config: TargetMachineFactoryConfig| {
// Self-profile timer for invoking a factory to create a target machine.
@@ -316,6 +318,7 @@ pub(crate) fn target_machine_factory(
debuginfo_compression,
use_emulated_tls,
use_wasm_eh,
large_data_threshold,
)
})
}
@@ -665,8 +665,8 @@ fn msvc_basic_name(self) -> &'static str {
impl MsvcBasicName for ty::FloatTy {
fn msvc_basic_name(self) -> &'static str {
// FIXME(f16_f128): `f16` and `f128` have no MSVC representation. We could improve the
// debuginfo. See: <https://github.com/rust-lang/rust/issues/121837>
// FIXME(f128): `f128` has no MSVC representation. We could improve the debuginfo.
// See: <https://github.com/rust-lang/rust/issues/121837>
match self {
ty::FloatTy::F16 => {
bug!("`f16` should have been handled in `build_basic_type_di_node`")
@@ -2347,6 +2347,7 @@ pub(crate) fn LLVMRustCreateTargetMachine(
DebugInfoCompression: CompressionKind,
UseEmulatedTls: bool,
UseWasmEH: bool,
LargeDataThreshold: u64,
) -> *mut TargetMachine;
pub(crate) fn LLVMRustAddLibraryInfo<'a>(
@@ -305,7 +305,7 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
bool EmitStackSizeSection, bool RelaxELFRelocations, bool UseInitArray,
const char *SplitDwarfFile, const char *OutputObjFile,
LLVMRustCompressionKind DebugInfoCompression, bool UseEmulatedTls,
bool UseWasmEH) {
bool UseWasmEH, uint64_t LargeDataThreshold) {
auto OptLevel = fromRust(RustOptLevel);
auto RM = fromRust(RustReloc);
@@ -381,6 +381,11 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine(
TargetMachine *TM = TheTarget->createTargetMachine(
Trip.getTriple(), CPU, Feature, Options, RM, CM, OptLevel);
#endif
if (LargeDataThreshold != 0) {
TM->setLargeDataThreshold(LargeDataThreshold);
}
return wrap(TM);
}
+3 -3
View File
@@ -4,10 +4,9 @@
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::hir_id::OwnerId;
use rustc_macros::HashStable;
use rustc_query_system::HandleCycleError;
use rustc_query_system::dep_graph::{DepNodeIndex, SerializedDepNodeIndex};
pub(crate) use rustc_query_system::query::QueryJobId;
use rustc_query_system::query::*;
use rustc_query_system::query::{CycleError, CycleErrorHandling, HashResult, QueryCache};
use rustc_span::{ErrorGuaranteed, Span};
pub use sealed::IntoQueryParam;
@@ -23,7 +22,8 @@ pub struct DynamicQuery<'tcx, C: QueryCache> {
pub name: &'static str,
pub eval_always: bool,
pub dep_kind: DepKind,
pub handle_cycle_error: HandleCycleError,
/// How this query deals with query cycle errors.
pub cycle_error_handling: CycleErrorHandling,
// Offset of this query's state field in the QueryStates struct
pub query_state: usize,
// Offset of this query's cache field in the QueryCaches struct
+5 -5
View File
@@ -18,13 +18,13 @@
queries,
};
use rustc_middle::ty::TyCtxt;
use rustc_query_system::Value;
use rustc_query_system::dep_graph::SerializedDepNodeIndex;
use rustc_query_system::ich::StableHashingContext;
use rustc_query_system::query::{
CycleError, HashResult, QueryCache, QueryConfig, QueryMap, QueryMode, QueryState,
get_query_incr, get_query_non_incr,
CycleError, CycleErrorHandling, HashResult, QueryCache, QueryConfig, QueryMap, QueryMode,
QueryState, get_query_incr, get_query_non_incr,
};
use rustc_query_system::{HandleCycleError, Value};
use rustc_span::{ErrorGuaranteed, Span};
use crate::plumbing::{__rust_begin_short_backtrace, encode_all_query_results, try_mark_green};
@@ -181,8 +181,8 @@ fn dep_kind(self) -> DepKind {
}
#[inline(always)]
fn handle_cycle_error(self) -> HandleCycleError {
self.dynamic.handle_cycle_error
fn cycle_error_handling(self) -> CycleErrorHandling {
self.dynamic.cycle_error_handling
}
#[inline(always)]
+7 -7
View File
@@ -199,21 +199,21 @@ pub fn query_key_hash_verify_all<'tcx>(tcx: TyCtxt<'tcx>) {
}
}
macro_rules! handle_cycle_error {
macro_rules! cycle_error_handling {
([]) => {{
rustc_query_system::HandleCycleError::Error
rustc_query_system::query::CycleErrorHandling::Error
}};
([(cycle_fatal) $($rest:tt)*]) => {{
rustc_query_system::HandleCycleError::Fatal
rustc_query_system::query::CycleErrorHandling::Fatal
}};
([(cycle_stash) $($rest:tt)*]) => {{
rustc_query_system::HandleCycleError::Stash
rustc_query_system::query::CycleErrorHandling::Stash
}};
([(cycle_delay_bug) $($rest:tt)*]) => {{
rustc_query_system::HandleCycleError::DelayBug
rustc_query_system::query::CycleErrorHandling::DelayBug
}};
([$other:tt $($modifiers:tt)*]) => {
handle_cycle_error!([$($modifiers)*])
cycle_error_handling!([$($modifiers)*])
};
}
@@ -618,7 +618,7 @@ pub(crate) fn dynamic_query<'tcx>()
name: stringify!($name),
eval_always: is_eval_always!([$($modifiers)*]),
dep_kind: dep_graph::dep_kinds::$name,
handle_cycle_error: handle_cycle_error!([$($modifiers)*]),
cycle_error_handling: cycle_error_handling!([$($modifiers)*]),
query_state: std::mem::offset_of!(QueryStates<'tcx>, $name),
query_cache: std::mem::offset_of!(QueryCaches<'tcx>, $name),
cache_on_disk: |tcx, key| ::rustc_middle::query::cached::$name(tcx, key),
-8
View File
@@ -11,14 +11,6 @@ pub(crate) struct CycleStack {
pub desc: String,
}
#[derive(Copy, Clone)]
pub enum HandleCycleError {
Error,
Fatal,
DelayBug,
Stash,
}
#[derive(Subdiagnostic)]
pub(crate) enum StackCount {
#[note(query_system_cycle_stack_single)]
+1 -1
View File
@@ -12,7 +12,7 @@
pub mod query;
mod values;
pub use error::{HandleCycleError, QueryOverflow, QueryOverflowNote};
pub use error::{QueryOverflow, QueryOverflowNote};
pub use values::Value;
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
@@ -7,10 +7,9 @@
use rustc_span::ErrorGuaranteed;
use crate::dep_graph::{DepKind, DepNode, DepNodeParams, SerializedDepNodeIndex};
use crate::error::HandleCycleError;
use crate::ich::StableHashingContext;
use crate::query::caches::QueryCache;
use crate::query::{CycleError, DepNodeIndex, QueryContext, QueryState};
use crate::query::{CycleError, CycleErrorHandling, DepNodeIndex, QueryContext, QueryState};
pub type HashResult<V> = Option<fn(&mut StableHashingContext<'_>, &V) -> Fingerprint>;
@@ -67,7 +66,7 @@ fn value_from_cycle_error(
fn feedable(self) -> bool;
fn dep_kind(self) -> DepKind;
fn handle_cycle_error(self) -> HandleCycleError;
fn cycle_error_handling(self) -> CycleErrorHandling;
fn hash_result(self) -> HashResult<Self::Value>;
// Just here for convenience and checking that the key matches the kind, don't override this.
@@ -20,6 +20,18 @@
mod job;
mod plumbing;
/// How a particular query deals with query cycle errors.
///
/// Inspected by the code that actually handles cycle errors, to decide what
/// approach to use.
#[derive(Copy, Clone)]
pub enum CycleErrorHandling {
Error,
Fatal,
DelayBug,
Stash,
}
/// Description of a frame in the query stack.
///
/// This is mostly used in case of cycles for error reporting.
@@ -19,12 +19,13 @@
use tracing::instrument;
use super::QueryConfig;
use crate::HandleCycleError;
use crate::dep_graph::{DepContext, DepGraphData, DepNode, DepNodeIndex, DepNodeParams};
use crate::ich::StableHashingContext;
use crate::query::caches::QueryCache;
use crate::query::job::{QueryInfo, QueryJob, QueryJobId, QueryJobInfo, QueryLatch, report_cycle};
use crate::query::{QueryContext, QueryMap, QueryStackFrame, SerializedDepNodeIndex};
use crate::query::{
CycleErrorHandling, QueryContext, QueryMap, QueryStackFrame, SerializedDepNodeIndex,
};
#[inline]
fn equivalent_key<K: Eq, V>(k: &K) -> impl Fn(&(K, V)) -> bool + '_ {
@@ -142,22 +143,21 @@ fn handle_cycle_error<Q, Qcx>(
Q: QueryConfig<Qcx>,
Qcx: QueryContext,
{
use HandleCycleError::*;
match query.handle_cycle_error() {
Error => {
match query.cycle_error_handling() {
CycleErrorHandling::Error => {
let guar = error.emit();
query.value_from_cycle_error(*qcx.dep_context(), cycle_error, guar)
}
Fatal => {
CycleErrorHandling::Fatal => {
error.emit();
qcx.dep_context().sess().dcx().abort_if_errors();
unreachable!()
}
DelayBug => {
CycleErrorHandling::DelayBug => {
let guar = error.delay_as_bug();
query.value_from_cycle_error(*qcx.dep_context(), cycle_error, guar)
}
Stash => {
CycleErrorHandling::Stash => {
let guar = if let Some(root) = cycle_error.cycle.first()
&& let Some(span) = root.query.span
{
+3
View File
@@ -2426,6 +2426,9 @@ pub(crate) fn parse_align(slot: &mut Option<Align>, v: Option<&str>) -> bool {
`=skip-entry`
`=skip-exit`
Multiple options can be combined with commas."),
large_data_threshold: Option<u64> = (None, parse_opt_number, [TRACKED],
"set the threshold for objects to be stored in a \"large data\" section \
(only effective with -Ccode-model=medium, default: 65536)"),
layout_seed: Option<u64> = (None, parse_opt_number, [TRACKED],
"seed layout randomization"),
link_directives: bool = (true, parse_bool, [TRACKED],
+1 -1
View File
@@ -47,7 +47,7 @@ pub fn supported_types(
types! { _: I8, I16, I32, F16, F32; }
}
}
// FIXME(f16_f128): Add `q: F128;` once LLVM support the `Q` extension.
// FIXME(f128): Add `q: F128;` once LLVM support the `Q` extension.
Self::freg => types! { f: F16, F32; d: F64; },
Self::vreg => &[],
}
+4 -4
View File
@@ -154,7 +154,7 @@ fn from(small: $Small) -> Self {
// * 53 bits in f64
// * 113 bits in f128
// Lossy float conversions are not implemented at this time.
// FIXME(f16_f128): The `f16`/`f128` impls `#[stable]` attributes should be changed to reference
// FIXME(f16,f128): The `f16`/`f128` impls `#[stable]` attributes should be changed to reference
// `f16`/`f128` when they are stabilised (trait impls have to have a `#[stable]` attribute, but none
// of the `f16`/`f128` impls can be used on stable as the `f16` and `f128` types are unstable).
@@ -168,7 +168,7 @@ fn from(small: $Small) -> Self {
impl_from!(i16 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
impl_from!(i32 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
impl_from!(i32 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
// FIXME(f16_f128): This impl would allow using `f128` on stable before it is stabilised.
// FIXME(f128): This impl would allow using `f128` on stable before it is stabilised.
// impl_from!(i64 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
// unsigned integer -> float
@@ -181,11 +181,11 @@ fn from(small: $Small) -> Self {
impl_from!(u16 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
impl_from!(u32 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
impl_from!(u32 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
// FIXME(f16_f128): This impl would allow using `f128` on stable before it is stabilised.
// FIXME(f128): This impl would allow using `f128` on stable before it is stabilised.
// impl_from!(u64 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
// float -> float
// FIXME(f16_f128): adding additional `From<{float}>` impls to `f32` breaks inference. See
// FIXME(f16,f128): adding additional `From<{float}>` impls to `f32` breaks inference. See
// <https://github.com/rust-lang/rust/issues/123831>
impl_from!(f16 => f64, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
impl_from!(f16 => f128, #[stable(feature = "lossless_float_conv", since = "1.6.0")]);
+1 -1
View File
@@ -236,7 +236,7 @@ fn fmt(&self, fmt: &mut Formatter<'_>) -> Result {
#[cfg(target_has_reliable_f16)]
floating! { f16 }
// FIXME(f16_f128): A fallback is used when the backend+target does not support f16 well, in order
// FIXME(f16): A fallback is used when the backend+target does not support f16 well, in order
// to avoid ICEs.
#[cfg(not(target_has_reliable_f16))]
+1 -1
View File
@@ -179,7 +179,7 @@ fn from_str(src: &str) -> Result<Self, ParseFloatError> {
from_str_float_impl!(f32);
from_str_float_impl!(f64);
// FIXME(f16_f128): A fallback is used when the backend+target does not support f16 well, in order
// FIXME(f16): A fallback is used when the backend+target does not support f16 well, in order
// to avoid ICEs.
#[cfg(not(target_has_reliable_f16))]
+30 -57
View File
@@ -137,10 +137,8 @@ pub mod consts {
pub const LN_10: f128 = 2.30258509299404568401799145468436420760110148862877297603333_f128;
}
#[doc(test(attr(feature(cfg_target_has_reliable_f16_f128), allow(internal_features))))]
impl f128 {
// FIXME(f16_f128): almost all methods in this `impl` are missing examples and a const
// implementation. Add these once we can run code on all platforms and have f16/f128 in CTFE.
/// The radix or base of the internal representation of `f128`.
#[unstable(feature = "f128", issue = "116909")]
pub const RADIX: u32 = 2;
@@ -277,8 +275,7 @@ impl f128 {
///
/// ```
/// #![feature(f128)]
/// # // FIXME(f16_f128): remove when `unordtf2` is available
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
/// # #[cfg(target_has_reliable_f128)] {
///
/// let nan = f128::NAN;
/// let f = 7.0_f128;
@@ -300,8 +297,7 @@ pub const fn is_nan(self) -> bool {
///
/// ```
/// #![feature(f128)]
/// # // FIXME(f16_f128): remove when `eqtf2` is available
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
/// # #[cfg(target_has_reliable_f128)] {
///
/// let f = 7.0f128;
/// let inf = f128::INFINITY;
@@ -326,8 +322,7 @@ pub const fn is_infinite(self) -> bool {
///
/// ```
/// #![feature(f128)]
/// # // FIXME(f16_f128): remove when `lttf2` is available
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
/// # #[cfg(target_has_reliable_f128)] {
///
/// let f = 7.0f128;
/// let inf: f128 = f128::INFINITY;
@@ -355,8 +350,7 @@ pub const fn is_finite(self) -> bool {
///
/// ```
/// #![feature(f128)]
/// # // FIXME(f16_f128): remove when `eqtf2` is available
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
/// # #[cfg(target_has_reliable_f128)] {
///
/// let min = f128::MIN_POSITIVE; // 3.362103143e-4932f128
/// let max = f128::MAX;
@@ -386,8 +380,7 @@ pub const fn is_subnormal(self) -> bool {
///
/// ```
/// #![feature(f128)]
/// # // FIXME(f16_f128): remove when `eqtf2` is available
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
/// # #[cfg(target_has_reliable_f128)] {
///
/// let min = f128::MIN_POSITIVE; // 3.362103143e-4932f128
/// let max = f128::MAX;
@@ -419,8 +412,7 @@ pub const fn is_normal(self) -> bool {
///
/// ```
/// #![feature(f128)]
/// # // FIXME(f16_f128): remove when `eqtf2` is available
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
/// # #[cfg(target_has_reliable_f128)] {
///
/// use std::num::FpCategory;
///
@@ -514,8 +506,7 @@ pub const fn is_sign_negative(self) -> bool {
///
/// ```rust
/// #![feature(f128)]
/// # // FIXME(f16_f128): remove when `eqtf2` is available
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
/// # #[cfg(target_has_reliable_f128)] {
///
/// // f128::EPSILON is the difference between 1.0 and the next number up.
/// assert_eq!(1.0f128.next_up(), 1.0 + f128::EPSILON);
@@ -569,8 +560,7 @@ pub const fn next_up(self) -> Self {
///
/// ```rust
/// #![feature(f128)]
/// # // FIXME(f16_f128): remove when `eqtf2` is available
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
/// # #[cfg(target_has_reliable_f128)] {
///
/// let x = 1.0f128;
/// // Clamp value into range [0, 1).
@@ -613,8 +603,7 @@ pub const fn next_down(self) -> Self {
///
/// ```
/// #![feature(f128)]
/// # // FIXME(f16_f128): remove when `eqtf2` is available
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
/// # #[cfg(target_has_reliable_f128)] {
///
/// let x = 2.0_f128;
/// let abs_difference = (x.recip() - (1.0 / x)).abs();
@@ -640,8 +629,7 @@ pub const fn recip(self) -> Self {
///
/// ```
/// #![feature(f128)]
/// # // FIXME(f16_f128): remove when `eqtf2` is available
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
/// # #[cfg(target_has_reliable_f128)] {
///
/// let angle = std::f128::consts::PI;
///
@@ -671,8 +659,7 @@ pub const fn to_degrees(self) -> Self {
///
/// ```
/// #![feature(f128)]
/// # // FIXME(f16_f128): remove when `eqtf2` is available
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
/// # #[cfg(target_has_reliable_f128)] {
///
/// let angle = 180.0f128;
///
@@ -706,8 +693,7 @@ pub const fn to_radians(self) -> f128 {
///
/// ```
/// #![feature(f128)]
/// # // Using aarch64 because `reliable_f128_math` is needed
/// # #[cfg(all(target_arch = "aarch64", target_os = "linux"))] {
/// # #[cfg(target_has_reliable_f128_math)] {
///
/// let x = 1.0f128;
/// let y = 2.0f128;
@@ -738,8 +724,7 @@ pub const fn max(self, other: f128) -> f128 {
///
/// ```
/// #![feature(f128)]
/// # // Using aarch64 because `reliable_f128_math` is needed
/// # #[cfg(all(target_arch = "aarch64", target_os = "linux"))] {
/// # #[cfg(target_has_reliable_f128_math)] {
///
/// let x = 1.0f128;
/// let y = 2.0f128;
@@ -771,8 +756,7 @@ pub const fn min(self, other: f128) -> f128 {
/// ```
/// #![feature(f128)]
/// #![feature(float_minimum_maximum)]
/// # // Using aarch64 because `reliable_f128_math` is needed
/// # #[cfg(all(target_arch = "aarch64", target_os = "linux"))] {
/// # #[cfg(target_has_reliable_f128_math)] {
///
/// let x = 1.0f128;
/// let y = 2.0f128;
@@ -804,8 +788,7 @@ pub const fn maximum(self, other: f128) -> f128 {
/// ```
/// #![feature(f128)]
/// #![feature(float_minimum_maximum)]
/// # // Using aarch64 because `reliable_f128_math` is needed
/// # #[cfg(all(target_arch = "aarch64", target_os = "linux"))] {
/// # #[cfg(target_has_reliable_f128_math)] {
///
/// let x = 1.0f128;
/// let y = 2.0f128;
@@ -831,8 +814,7 @@ pub const fn minimum(self, other: f128) -> f128 {
///
/// ```
/// #![feature(f128)]
/// # // Using aarch64 because `reliable_f128_math` is needed
/// # #[cfg(all(target_arch = "aarch64", target_os = "linux"))] {
/// # #[cfg(target_has_reliable_f128)] {
///
/// assert_eq!(1f128.midpoint(4.0), 2.5);
/// assert_eq!((-5.5f128).midpoint(8.0), 1.25);
@@ -862,8 +844,7 @@ pub const fn midpoint(self, other: f128) -> f128 {
///
/// ```
/// #![feature(f128)]
/// # // FIXME(f16_f128): remove when `float*itf` is available
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
/// # #[cfg(target_has_reliable_f128)] {
///
/// let value = 4.6_f128;
/// let rounded = unsafe { value.to_int_unchecked::<u16>() };
@@ -906,10 +887,11 @@ pub unsafe fn to_int_unchecked<Int>(self) -> Int
///
/// ```
/// #![feature(f128)]
/// # #[cfg(target_has_reliable_f128)] {
///
/// # // FIXME(f16_f128): enable this once const casting works
/// # // assert_ne!((1f128).to_bits(), 1f128 as u128); // to_bits() is not casting!
/// assert_ne!((1f128).to_bits(), 1f128 as u128); // to_bits() is not casting!
/// assert_eq!((12.5f128).to_bits(), 0x40029000000000000000000000000000);
/// # }
/// ```
#[inline]
#[unstable(feature = "f128", issue = "116909")]
@@ -952,8 +934,7 @@ pub const fn to_bits(self) -> u128 {
///
/// ```
/// #![feature(f128)]
/// # // FIXME(f16_f128): remove when `eqtf2` is available
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
/// # #[cfg(target_has_reliable_f128)] {
///
/// let v = f128::from_bits(0x40029000000000000000000000000000);
/// assert_eq!(v, 12.5);
@@ -1064,8 +1045,7 @@ pub const fn from_bits(v: u128) -> Self {
///
/// ```
/// #![feature(f128)]
/// # // FIXME(f16_f128): remove when `eqtf2` is available
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
/// # #[cfg(target_has_reliable_f128)] {
///
/// let value = f128::from_be_bytes(
/// [0x40, 0x02, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -1090,8 +1070,7 @@ pub const fn from_bits(v: u128) -> Self {
///
/// ```
/// #![feature(f128)]
/// # // FIXME(f16_f128): remove when `eqtf2` is available
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
/// # #[cfg(target_has_reliable_f128)] {
///
/// let value = f128::from_le_bytes(
/// [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -1123,8 +1102,7 @@ pub const fn from_bits(v: u128) -> Self {
///
/// ```
/// #![feature(f128)]
/// # // FIXME(f16_f128): remove when `eqtf2` is available
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
/// # #[cfg(target_has_reliable_f128)] {
///
/// let value = f128::from_ne_bytes(if cfg!(target_endian = "big") {
/// [0x40, 0x02, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00,
@@ -1257,8 +1235,7 @@ pub const fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering {
///
/// ```
/// #![feature(f128)]
/// # // FIXME(f16_f128): remove when `{eq,gt,unord}tf` are available
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
/// # #[cfg(target_has_reliable_f128)] {
///
/// assert!((-3.0f128).clamp(-2.0, 1.0) == -2.0);
/// assert!((0.0f128).clamp(-2.0, 1.0) == 0.0);
@@ -1333,7 +1310,7 @@ pub fn clamp_magnitude(self, limit: f128) -> f128 {
///
/// ```
/// #![feature(f128)]
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
/// # #[cfg(target_has_reliable_f128)] {
///
/// let x = 3.5_f128;
/// let y = -3.5_f128;
@@ -1349,9 +1326,7 @@ pub fn clamp_magnitude(self, limit: f128) -> f128 {
#[rustc_const_unstable(feature = "f128", issue = "116909")]
#[must_use = "method returns a new number and does not mutate the original value"]
pub const fn abs(self) -> Self {
// FIXME(f16_f128): replace with `intrinsics::fabsf128` when available
// We don't do this now because LLVM has lowering bugs for f128 math.
Self::from_bits(self.to_bits() & !(1 << 127))
intrinsics::fabsf128(self)
}
/// Returns a number that represents the sign of `self`.
@@ -1364,7 +1339,7 @@ pub const fn abs(self) -> Self {
///
/// ```
/// #![feature(f128)]
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
/// # #[cfg(target_has_reliable_f128)] {
///
/// let f = 3.5_f128;
///
@@ -1400,7 +1375,7 @@ pub const fn signum(self) -> f128 {
///
/// ```
/// #![feature(f128)]
/// # #[cfg(all(target_arch = "x86_64", target_os = "linux"))] {
/// # #[cfg(target_has_reliable_f128)] {
///
/// let f = 3.5_f128;
///
@@ -1477,8 +1452,6 @@ pub const fn algebraic_rem(self, rhs: f128) -> f128 {
}
// Functions in this module fall into `core_float_math`
// FIXME(f16_f128): all doctests must be gated to platforms that have `long double` === `_Float128`
// due to https://github.com/llvm/llvm-project/issues/44744. aarch64 linux matches this.
// #[unstable(feature = "core_float_math", issue = "137578")]
#[cfg(not(test))]
#[doc(test(attr(feature(cfg_target_has_reliable_f16_f128), expect(internal_features))))]
+1 -5
View File
@@ -134,9 +134,6 @@ pub mod consts {
#[doc(test(attr(feature(cfg_target_has_reliable_f16_f128), allow(internal_features))))]
impl f16 {
// FIXME(f16_f128): almost all methods in this `impl` are missing examples and a const
// implementation. Add these once we can run code on all platforms and have f16/f128 in CTFE.
/// The radix or base of the internal representation of `f16`.
#[unstable(feature = "f16", issue = "116909")]
pub const RADIX: u32 = 2;
@@ -887,8 +884,7 @@ pub unsafe fn to_int_unchecked<Int>(self) -> Int
/// #![feature(f16)]
/// # #[cfg(target_has_reliable_f16)] {
///
/// # // FIXME(f16_f128): enable this once const casting works
/// # // assert_ne!((1f16).to_bits(), 1f16 as u128); // to_bits() is not casting!
/// assert_ne!((1f16).to_bits(), 1f16 as u16); // to_bits() is not casting!
/// assert_eq!((12.5f16).to_bits(), 0x4a40);
/// # }
/// ```
+3 -7
View File
@@ -391,7 +391,7 @@ const fn flt (x: $fty) -> $fty { x }
}
}
// FIXME(f16_f128): merge into `num` once the required `fmodl`/`fmodf128` function is available on
// FIXME(f128): merge into `num` once the required `fmodl`/`fmodf128` function is available on
// all platforms.
float_test! {
name: num_rem,
@@ -1357,15 +1357,11 @@ const fn q_nan() -> Float {
}
}
// FIXME(f16): Tests involving sNaN are disabled because without optimizations, `total_cmp` is
// getting incorrectly lowered to code that includes a `extend`/`trunc` round trip, which quiets
// sNaNs. See: https://github.com/llvm/llvm-project/issues/104915
float_test! {
name: total_cmp_s_nan,
attrs: {
const: #[cfg(false)],
f16: #[cfg(miri)],
f16: #[cfg(any(miri, target_has_reliable_f16_math))],
f128: #[cfg(any(miri, target_has_reliable_f128_math))],
},
test<Float> {
@@ -1636,7 +1632,7 @@ fn s_nan() -> Float {
}
}
// FIXME(f16_f128): Uncomment and adapt these tests once the From<{u64,i64}> impls are added.
// FIXME(f128): Uncomment and adapt these tests once the From<{u64,i64}> impls are added.
// float_test! {
// name: from_u64_i64,
// attrs: {
@@ -7,7 +7,6 @@
const FPATHS_F64: &[FPath<f64>] =
&[((0, 0, false, false), Some(0.0)), ((0, 0, false, false), Some(0.0))];
// FIXME(f16_f128): enable on all targets once possible.
#[test]
#[cfg(target_has_reliable_f16)]
fn check_fast_path_f16() {
@@ -2,7 +2,6 @@
use crate::num::{ldexp_f32, ldexp_f64};
// FIXME(f16_f128): enable on all targets once possible.
#[test]
#[cfg(target_has_reliable_f16)]
fn test_f16_integer_decode() {
@@ -54,7 +53,6 @@ fn test_f64_integer_decode() {
/* Sanity checks of computed magic numbers */
// FIXME(f16_f128): enable on all targets once possible.
#[test]
#[cfg(target_has_reliable_f16)]
fn test_f16_consts() {
@@ -17,7 +17,6 @@ fn compute_float64(q: i64, w: u64) -> (i32, u64) {
(fp.p_biased, fp.m)
}
// FIXME(f16_f128): enable on all targets once possible.
#[test]
#[cfg(target_has_reliable_f16)]
fn compute_float_f16_rounding() {
@@ -92,8 +92,6 @@ fn fast_path_correct() {
test_literal!(1.448997445238699);
}
// FIXME(f16_f128): remove gates once tests work on all targets
#[test]
fn lonely_dot() {
#[cfg(target_has_reliable_f16)]
+1 -1
View File
@@ -287,7 +287,7 @@ pub fn f16_exact_sanity_test<F>(mut f: F)
check_exact!(f(f16::MIN_POSITIVE) => b"6103515625 ", -4);
check_exact!(f(minf16) => b"59604644775390625", -7);
// FIXME(f16_f128): these should gain the check_exact_one tests like `f32` and `f64` have,
// FIXME(f16): these should gain the check_exact_one tests like `f32` and `f64` have,
// but these values are not easy to generate. The algorithm from the Paxon paper [1] needs
// to be adapted to binary16.
}
+1 -2
View File
@@ -1,4 +1,3 @@
// FIXME(f16_f128): only tested on platforms that have symbols and aren't buggy
#![cfg(target_has_reliable_f128)]
use std::f128::consts;
@@ -35,7 +34,7 @@ macro_rules! assert_f128_biteq {
#[test]
fn test_num_f128() {
// FIXME(f16_f128): replace with a `test_num` call once the required `fmodl`/`fmodf128`
// FIXME(f128): replace with a `test_num` call once the required `fmodl`/`fmodf128`
// function is available on all platforms.
let ten = 10f128;
let two = 2f128;
-3
View File
@@ -1,4 +1,3 @@
// FIXME(f16_f128): only tested on platforms that have symbols and aren't buggy
#![cfg(target_has_reliable_f16)]
use std::f16::consts;
@@ -258,8 +257,6 @@ fn test_ln_gamma() {
#[test]
fn test_real_consts() {
// FIXME(f16_f128): add math tests when available
let pi: f16 = consts::PI;
let frac_pi_2: f16 = consts::FRAC_PI_2;
let frac_pi_3: f16 = consts::FRAC_PI_3;
@@ -0,0 +1,27 @@
# `large-data-threshold`
-----------------------
This flag controls the threshold for static data to be placed in large data
sections when using the `medium` code model on x86-64.
When using `-Ccode-model=medium`, static data smaller than this threshold will
use RIP-relative addressing (32-bit offsets), while larger data will use
absolute 64-bit addressing. This allows the compiler to generate more efficient
code for smaller data while still supporting data larger than 2GB.
The default threshold is 65536 bytes (64KB) if not specified.
## Example
```sh
rustc -Ccode-model=medium -Zlarge-data-threshold=1024 main.rs
```
This sets the threshold to 1KB, meaning only data smaller than 1024 bytes will
use RIP-relative addressing.
## Platform Support
This flag is only effective on x86-64 targets when using `-Ccode-model=medium`.
On other architectures or with other code models, this flag has no effect.
@@ -0,0 +1,73 @@
// Test for -Z large_data_threshold=...
// This test verifies that with the medium code model, data above the threshold
// is placed in large data sections (.ldata, .lbss, .lrodata).
//@ assembly-output: emit-asm
//@ compile-flags: -Ccode-model=medium -Zlarge-data-threshold=4
//@ compile-flags: --target=x86_64-unknown-linux-gnu
//@ needs-llvm-components: x86
#![feature(no_core, lang_items)]
#![no_std]
#![no_core]
#![crate_type = "lib"]
#[lang = "pointee_sized"]
pub trait PointeeSized {}
#[lang = "meta_sized"]
pub trait MetaSized: PointeeSized {}
#[lang = "sized"]
pub trait Sized: MetaSized {}
#[lang = "drop_in_place"]
fn drop_in_place<T>(_: *mut T) {}
#[used]
#[no_mangle]
// U is below the threshold, should be in .data
static mut U: u16 = 123;
#[used]
#[no_mangle]
// V is below the threshold, should be in .bss
static mut V: u16 = 0;
#[used]
#[no_mangle]
// W is at the threshold, should be in .data
static mut W: u32 = 123;
#[used]
#[no_mangle]
// X is at the threshold, should be in .bss
static mut X: u32 = 0;
#[used]
#[no_mangle]
// Y is over the threshold, should be in .ldata
static mut Y: u64 = 123;
#[used]
#[no_mangle]
// Z is over the threshold, should be in .lbss
static mut Z: u64 = 0;
// CHECK: .section .data.U,
// CHECK-NOT: .section
// CHECK: U:
// CHECK: .section .bss.V,
// CHECK-NOT: .section
// CHECK: V:
// CHECK: .section .data.W,
// CHECK-NOT: .section
// CHECK: W:
// CHECK: .section .bss.X,
// CHECK-NOT: .section
// CHECK: X:
// CHECK: .section .ldata.Y,
// CHECK-NOT: .section
// CHECK: Y:
// CHECK: .section .lbss.Z,
// CHECK-NOT: .section
// CHECK: Z:
@@ -1,9 +1,11 @@
//@ run-pass
//@ compile-flags: --check-cfg=cfg(target_has_reliable_f16,target_has_reliable_f128)
// Test half-open range patterns against their expression equivalents
// via `.contains(...)` and make sure the dynamic semantics match.
#![allow(unreachable_patterns)]
#![feature(cfg_target_has_reliable_f16_f128)]
#![feature(f128)]
#![feature(f16)]
@@ -42,8 +44,7 @@ fn range_to_inclusive() {
assert!(!yes!('b', ..='a'));
// f16; `..=X`
// FIXME(f16_f128): remove gate when ABI issues are resolved
#[cfg(all(target_arch = "aarch64", target_os = "linux"))]
#[cfg(target_has_reliable_f16)]
{
assert!(yes!(f16::NEG_INFINITY, ..=f16::NEG_INFINITY));
assert!(yes!(f16::NEG_INFINITY, ..=1.0f16));
@@ -64,8 +65,7 @@ fn range_to_inclusive() {
assert!(!yes!(1.6f64, ..=-1.5f64));
// f128; `..=X`
// FIXME(f16_f128): remove gate when ABI issues are resolved
#[cfg(all(target_arch = "aarch64", target_os = "linux"))]
#[cfg(target_has_reliable_f128)]
{
assert!(yes!(f128::NEG_INFINITY, ..=f128::NEG_INFINITY));
assert!(yes!(f128::NEG_INFINITY, ..=1.0f128));
@@ -106,8 +106,7 @@ fn range_to() {
assert!(!yes!('b', ..'a'));
// f16; `..X`
// FIXME(f16_f128): remove gate when ABI issues are resolved
#[cfg(all(target_arch = "aarch64", target_os = "linux"))]
#[cfg(target_has_reliable_f16)]
{
assert!(yes!(f16::NEG_INFINITY, ..1.0f16));
assert!(!yes!(1.5f16, ..1.5f16));
@@ -131,8 +130,7 @@ fn range_to() {
assert!(!yes!(1.6f64, ..1.5f64));
// f128; `..X`
// FIXME(f16_f128): remove gate when ABI issues are resolved
#[cfg(all(target_arch = "aarch64", target_os = "linux"))]
#[cfg(target_has_reliable_f128)]
{
assert!(yes!(f128::NEG_INFINITY, ..1.0f128));
assert!(!yes!(1.5f128, ..1.5f128));
@@ -174,8 +172,7 @@ fn range_from() {
assert!(yes!(core::char::MAX, core::char::MAX..));
// f16; `X..`
// FIXME(f16_f128): remove gate when ABI issues are resolved
#[cfg(all(target_arch = "aarch64", target_os = "linux"))]
#[cfg(target_has_reliable_f16)]
{
assert!(yes!(f16::NEG_INFINITY, f16::NEG_INFINITY..));
assert!(yes!(f16::INFINITY, f16::NEG_INFINITY..));
@@ -208,8 +205,7 @@ fn range_from() {
assert!(yes!(f64::INFINITY, f64::INFINITY..));
// f128; `X..`
// FIXME(f16_f128): remove gate when ABI issues are resolved
#[cfg(all(target_arch = "aarch64", target_os = "linux"))]
#[cfg(target_has_reliable_f128)]
{
assert!(yes!(f128::NEG_INFINITY, f128::NEG_INFINITY..));
assert!(yes!(f128::INFINITY, f128::NEG_INFINITY..));
+6 -6
View File
@@ -1,12 +1,12 @@
//@ run-pass
//@ compile-flags: --check-cfg=cfg(target_has_reliable_f16,target_has_reliable_f128)
// Makes sure we use `==` (not bitwise) semantics for float comparison.
#![feature(cfg_target_has_reliable_f16_f128)]
#![feature(f128)]
#![feature(f16)]
// FIXME(f16_f128): remove gates when ABI issues are resolved
#[cfg(all(target_arch = "aarch64", target_os = "linux"))]
#[cfg(target_has_reliable_f16)]
fn check_f16() {
const F1: f16 = 0.0;
const F2: f16 = -0.0;
@@ -34,7 +34,7 @@ fn check_f64() {
assert!(matches!(F2, F1));
}
#[cfg(all(target_arch = "aarch64", target_os = "linux"))]
#[cfg(target_has_reliable_f128)]
fn check_f128() {
const F1: f128 = 0.0;
const F2: f128 = -0.0;
@@ -45,10 +45,10 @@ fn check_f128() {
}
fn main() {
#[cfg(all(target_arch = "aarch64", target_os = "linux"))]
#[cfg(target_has_reliable_f16)]
check_f16();
check_f32();
check_f64();
#[cfg(all(target_arch = "aarch64", target_os = "linux"))]
#[cfg(target_has_reliable_f128)]
check_f128();
}