diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs index f14463fe94029..23fdd272ffd33 100644 --- a/compiler/rustc_arena/src/lib.rs +++ b/compiler/rustc_arena/src/lib.rs @@ -37,9 +37,10 @@ use std::ptr::{self, NonNull}; use std::slice; use std::{cmp, intrinsics}; +/// This calls the passed function while ensuring it won't be inlined into the caller. #[inline(never)] #[cold] -fn cold_path<F: FnOnce() -> R, R>(f: F) -> R { +fn outline<F: FnOnce() -> R, R>(f: F) -> R { f() } @@ -600,7 +601,7 @@ impl DroplessArena { unsafe { self.write_from_iter(iter, len, mem) } } (_, _) => { - cold_path(move || -> &mut [T] { + outline(move || -> &mut [T] { let mut vec: SmallVec<[_; 8]> = iter.collect(); if vec.is_empty() { return &mut []; diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 7d037ddfa986c..461ec3a90ed97 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -51,9 +51,10 @@ use std::fmt; pub use rustc_index::static_assert_size; +/// This calls the passed function while ensuring it won't be inlined into the caller. #[inline(never)] #[cold] -pub fn cold_path<F: FnOnce() -> R, R>(f: F) -> R { +pub fn outline<F: FnOnce() -> R, R>(f: F) -> R { f() } diff --git a/compiler/rustc_data_structures/src/profiling.rs b/compiler/rustc_data_structures/src/profiling.rs index 3c76c2b79911a..e688feb5fe176 100644 --- a/compiler/rustc_data_structures/src/profiling.rs +++ b/compiler/rustc_data_structures/src/profiling.rs @@ -81,8 +81,8 @@ //! //! [mm]: https://github.com/rust-lang/measureme/ -use crate::cold_path; use crate::fx::FxHashMap; +use crate::outline; use std::borrow::Borrow; use std::collections::hash_map::Entry; @@ -697,7 +697,7 @@ impl<'a> TimingGuard<'a> { #[inline] pub fn finish_with_query_invocation_id(self, query_invocation_id: QueryInvocationId) { if let Some(guard) = self.0 { - cold_path(|| { + outline(|| { let event_id = StringId::new_virtual(query_invocation_id.0); let event_id = EventId::from_virtual(event_id); guard.finish_with_override_event_id(event_id); diff --git a/compiler/rustc_data_structures/src/sync/worker_local.rs b/compiler/rustc_data_structures/src/sync/worker_local.rs index 1f838cc4648dc..ffafdba13cea1 100644 --- a/compiler/rustc_data_structures/src/sync/worker_local.rs +++ b/compiler/rustc_data_structures/src/sync/worker_local.rs @@ -6,7 +6,7 @@ use std::ptr; use std::sync::Arc; #[cfg(parallel_compiler)] -use {crate::cold_path, crate::sync::CacheAligned}; +use {crate::outline, crate::sync::CacheAligned}; /// A pointer to the `RegistryData` which uniquely identifies a registry. /// This identifier can be reused if the registry gets freed. @@ -25,11 +25,7 @@ impl RegistryId { fn verify(self) -> usize { let (id, index) = THREAD_DATA.with(|data| (data.registry_id.get(), data.index.get())); - if id == self { - index - } else { - cold_path(|| panic!("Unable to verify registry association")) - } + if id == self { index } else { outline(|| panic!("Unable to verify registry association")) } } } diff --git a/compiler/rustc_error_codes/src/error_codes/E0094.md b/compiler/rustc_error_codes/src/error_codes/E0094.md index 67a8c3678c5ff..d8c1a3cb55cb5 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0094.md +++ b/compiler/rustc_error_codes/src/error_codes/E0094.md @@ -3,7 +3,7 @@ An invalid number of generic parameters was passed to an intrinsic function. Erroneous code example: ```compile_fail,E0094 -#![feature(intrinsics)] +#![feature(intrinsics, rustc_attrs)] #![allow(internal_features)] extern "rust-intrinsic" { @@ -18,7 +18,7 @@ and verify with the function declaration in the Rust source code. Example: ``` -#![feature(intrinsics)] +#![feature(intrinsics, rustc_attrs)] #![allow(internal_features)] extern "rust-intrinsic" { diff --git a/compiler/rustc_error_codes/src/error_codes/E0211.md b/compiler/rustc_error_codes/src/error_codes/E0211.md index 70f14fffae673..19a482f6c93e4 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0211.md +++ b/compiler/rustc_error_codes/src/error_codes/E0211.md @@ -4,7 +4,7 @@ You used a function or type which doesn't fit the requirements for where it was used. Erroneous code examples: ```compile_fail -#![feature(intrinsics)] +#![feature(intrinsics, rustc_attrs)] #![allow(internal_features)] extern "rust-intrinsic" { @@ -41,7 +41,7 @@ impl Foo { For the first code example, please check the function definition. Example: ``` -#![feature(intrinsics)] +#![feature(intrinsics, rustc_attrs)] #![allow(internal_features)] extern "rust-intrinsic" { diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 04ebe22a9eb8a..18397af565fa0 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -537,7 +537,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ allow_internal_unsafe, Normal, template!(Word), WarnFollowing, "allow_internal_unsafe side-steps the unsafe_code lint", ), - ungated!(rustc_safe_intrinsic, Normal, template!(Word), DuplicatesOk), rustc_attr!(rustc_allowed_through_unstable_modules, Normal, template!(Word), WarnFollowing, "rustc_allowed_through_unstable_modules special cases accidental stabilizations of stable items \ through unstable paths"), @@ -806,6 +805,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_doc_primitive, Normal, template!(NameValueStr: "primitive name"), ErrorFollowing, r#"`rustc_doc_primitive` is a rustc internal attribute"#, ), + rustc_attr!( + rustc_safe_intrinsic, Normal, template!(Word), WarnFollowing, + "the `#[rustc_safe_intrinsic]` attribute is used internally to mark intrinsics as safe" + ), // ========================================================================== // Internal attributes, Testing: diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index dc0776c5dade9..214c6d70960e5 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -648,6 +648,10 @@ passes_rustc_lint_opt_ty = `#[rustc_lint_opt_ty]` should be applied to a struct .label = not a struct +passes_rustc_safe_intrinsic = + attribute should be applied to intrinsic functions + .label = not an intrinsic function + passes_rustc_std_internal_symbol = attribute should be applied to functions or statics .label = not a function or static diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index afba366a365a9..9a7564cb213d7 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -195,6 +195,9 @@ impl CheckAttrVisitor<'_> { | sym::rustc_promotable => self.check_stability_promotable(&attr, span, target), sym::link_ordinal => self.check_link_ordinal(&attr, span, target), sym::rustc_confusables => self.check_confusables(&attr, target), + sym::rustc_safe_intrinsic => { + self.check_rustc_safe_intrinsic(hir_id, attr, span, target) + } _ => true, }; @@ -2042,6 +2045,29 @@ impl CheckAttrVisitor<'_> { } } + fn check_rustc_safe_intrinsic( + &self, + hir_id: HirId, + attr: &Attribute, + span: Span, + target: Target, + ) -> bool { + let hir = self.tcx.hir(); + + if let Target::ForeignFn = target + && let Some(parent) = hir.opt_parent_id(hir_id) + && let hir::Node::Item(Item { + kind: ItemKind::ForeignMod { abi: Abi::RustIntrinsic | Abi::PlatformIntrinsic, .. }, + .. + }) = hir.get(parent) + { + return true; + } + + self.tcx.sess.emit_err(errors::RustcSafeIntrinsic { attr_span: attr.span, span }); + false + } + fn check_rustc_std_internal_symbol( &self, attr: &Attribute, diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 2ec6a0b924140..bcf5abbfe7d9d 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -620,6 +620,15 @@ pub struct RustcAllowConstFnUnstable { pub span: Span, } +#[derive(Diagnostic)] +#[diag(passes_rustc_safe_intrinsic)] +pub struct RustcSafeIntrinsic { + #[primary_span] + pub attr_span: Span, + #[label] + pub span: Span, +} + #[derive(Diagnostic)] #[diag(passes_rustc_std_internal_symbol)] pub struct RustcStdInternalSymbol { diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index f93edffca79e3..ae8414ebba6d7 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -18,7 +18,7 @@ use rustc_data_structures::sharded::Sharded; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::sync::Lock; #[cfg(parallel_compiler)] -use rustc_data_structures::{cold_path, sync}; +use rustc_data_structures::{outline, sync}; use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed, FatalError}; use rustc_span::{Span, DUMMY_SP}; use std::cell::Cell; @@ -265,7 +265,7 @@ where match result { Ok(()) => { let Some((v, index)) = query.query_cache(qcx).lookup(&key) else { - cold_path(|| { + outline(|| { // We didn't find the query result in the query cache. Check if it was // poisoned due to a panic instead. let lock = query.query_state(qcx).active.get_shard_by_value(&key).lock(); diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 68724c480376a..c58fdbcb5e1b6 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -33,7 +33,7 @@ extern crate rustc_macros; #[macro_use] extern crate tracing; -use rustc_data_structures::{cold_path, AtomicRef}; +use rustc_data_structures::{outline, AtomicRef}; use rustc_macros::HashStable_Generic; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; @@ -1592,7 +1592,7 @@ impl SourceFile { return &lines[..]; } - cold_path(|| { + outline(|| { self.convert_diffs_to_lines_frozen(); if let Some(SourceFileLines::Lines(lines)) = self.lines.get() { return &lines[..]; diff --git a/src/doc/embedded-book b/src/doc/embedded-book index 99ad2847b865e..eac173690b8cc 160000 --- a/src/doc/embedded-book +++ b/src/doc/embedded-book @@ -1 +1 @@ -Subproject commit 99ad2847b865e96d8ae7b333d3ee96963557e621 +Subproject commit eac173690b8cc99094e1d88bd49dd61127fbd285 diff --git a/src/doc/nomicon b/src/doc/nomicon index e3f3af69dce71..ddfa421448768 160000 --- a/src/doc/nomicon +++ b/src/doc/nomicon @@ -1 +1 @@ -Subproject commit e3f3af69dce71cd37a785bccb7e58449197d940c +Subproject commit ddfa4214487686e91b21aa29afb972c08a8f0d5b diff --git a/src/doc/reference b/src/doc/reference index ee7c676fd6e28..5262e1c3b43a2 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit ee7c676fd6e287459cb407337652412c990686c0 +Subproject commit 5262e1c3b43a2c489df8f6717683a44c7a2260fd diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide index 08bb147d51e81..a13b7c28ed705 160000 --- a/src/doc/rustc-dev-guide +++ b/src/doc/rustc-dev-guide @@ -1 +1 @@ -Subproject commit 08bb147d51e815b96e8db7ba4cf870f201c11ff8 +Subproject commit a13b7c28ed705891c681ce5417b3d1cdb12cecd1 diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index 0d3f6338af45d..7473b09920fba 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -375,7 +375,7 @@ library, as an equivalent command-line argument is provided to `rustc` when buil This feature allows you to generate an index-page with a given markdown file. A good example of it is the [rust documentation index](https://doc.rust-lang.org/nightly/index.html). -With this, you'll have a page which you can custom as much as you want at the top of your crates. +With this, you'll have a page which you can customize as much as you want at the top of your crates. Using `index-page` option enables `enable-index-page` option as well. diff --git a/tests/ui/codegen/issue-79865-llvm-miscompile.rs b/tests/ui/codegen/issue-79865-llvm-miscompile.rs new file mode 100644 index 0000000000000..b77f09f8e9a70 --- /dev/null +++ b/tests/ui/codegen/issue-79865-llvm-miscompile.rs @@ -0,0 +1,38 @@ +// run-pass +// only-x86_64 +// compile-flags: -C opt-level=3 + +// Regression test for issue #79865. +// The assertion will fail when compiled with Rust 1.56..=1.59 +// due to a LLVM miscompilation. + +use std::arch::x86_64::*; + +fn main() { + if is_x86_feature_detected!("avx") { + let res: [f64; 4] = unsafe { std::mem::transmute::<_, _>(first()) }; + assert_eq!(res, [22.0, 44.0, 66.0, 88.0]); + } +} + +#[target_feature(enable = "avx")] +unsafe fn first() -> __m256d { + second() +} + +unsafe fn second() -> __m256d { + let v0 = _mm256_setr_pd(1.0, 2.0, 3.0, 4.0); + let v1 = _mm256_setr_pd(10.0, 20.0, 30.0, 40.0); + + // needs to be called twice to hit the miscompilation + let (add, _) = add_sub(v0, v1); + let (add, _) = add_sub(add, add); + add +} + +#[inline(never)] // needed to hit the miscompilation +unsafe fn add_sub(v1: __m256d, v0: __m256d) -> (__m256d, __m256d) { + let add = _mm256_add_pd(v0, v1); + let sub = _mm256_sub_pd(v0, v1); + (add, sub) +} diff --git a/tests/ui/error-codes/E0094.rs b/tests/ui/error-codes/E0094.rs index a2ec932c12455..97ebcff99dc94 100644 --- a/tests/ui/error-codes/E0094.rs +++ b/tests/ui/error-codes/E0094.rs @@ -1,4 +1,4 @@ -#![feature(intrinsics)] +#![feature(intrinsics, rustc_attrs)] extern "rust-intrinsic" { #[rustc_safe_intrinsic] diff --git a/tests/ui/extern/extern-with-type-bounds.rs b/tests/ui/extern/extern-with-type-bounds.rs index a72aa4171a103..99e9801fd4010 100644 --- a/tests/ui/extern/extern-with-type-bounds.rs +++ b/tests/ui/extern/extern-with-type-bounds.rs @@ -1,4 +1,4 @@ -#![feature(intrinsics)] +#![feature(intrinsics, rustc_attrs)] extern "rust-intrinsic" { // Real example from libcore diff --git a/tests/ui/intrinsics/feature-gate-safe-intrinsic.rs b/tests/ui/intrinsics/feature-gate-safe-intrinsic.rs new file mode 100644 index 0000000000000..ffaa4d771d99b --- /dev/null +++ b/tests/ui/intrinsics/feature-gate-safe-intrinsic.rs @@ -0,0 +1,6 @@ +#[rustc_safe_intrinsic] +//~^ ERROR the `#[rustc_safe_intrinsic]` attribute is used internally to mark intrinsics as safe +//~| ERROR attribute should be applied to intrinsic functions +fn safe() {} + +fn main() {} diff --git a/tests/ui/intrinsics/feature-gate-safe-intrinsic.stderr b/tests/ui/intrinsics/feature-gate-safe-intrinsic.stderr new file mode 100644 index 0000000000000..8aeb56598ec1c --- /dev/null +++ b/tests/ui/intrinsics/feature-gate-safe-intrinsic.stderr @@ -0,0 +1,20 @@ +error[E0658]: the `#[rustc_safe_intrinsic]` attribute is used internally to mark intrinsics as safe + --> $DIR/feature-gate-safe-intrinsic.rs:1:1 + | +LL | #[rustc_safe_intrinsic] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable + +error: attribute should be applied to intrinsic functions + --> $DIR/feature-gate-safe-intrinsic.rs:1:1 + | +LL | #[rustc_safe_intrinsic] + | ^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn safe() {} + | ------------ not an intrinsic function + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/intrinsics/intrinsic-alignment.rs b/tests/ui/intrinsics/intrinsic-alignment.rs index 30b8a21269a9c..6f9df64417e8e 100644 --- a/tests/ui/intrinsics/intrinsic-alignment.rs +++ b/tests/ui/intrinsics/intrinsic-alignment.rs @@ -1,7 +1,7 @@ // run-pass // ignore-wasm32-bare seems not important to test here -#![feature(intrinsics)] +#![feature(intrinsics, rustc_attrs)] mod rusti { extern "rust-intrinsic" { diff --git a/tests/ui/repr/16-bit-repr-c-enum.rs b/tests/ui/repr/16-bit-repr-c-enum.rs index 2acfde4be46d9..d4fea2b192b48 100644 --- a/tests/ui/repr/16-bit-repr-c-enum.rs +++ b/tests/ui/repr/16-bit-repr-c-enum.rs @@ -5,7 +5,7 @@ // [avr] compile-flags: --target=avr-unknown-gnu-atmega328 --crate-type=rlib // [msp430] needs-llvm-components: msp430 // [msp430] compile-flags: --target=msp430-none-elf --crate-type=rlib -#![feature(no_core, lang_items, intrinsics, staged_api)] +#![feature(no_core, lang_items, intrinsics, staged_api, rustc_attrs)] #![no_core] #![crate_type = "lib"] #![stable(feature = "", since = "")] diff --git a/tests/ui/structs-enums/rec-align-u32.rs b/tests/ui/structs-enums/rec-align-u32.rs index ee704198d193b..b3c323d2a29f5 100644 --- a/tests/ui/structs-enums/rec-align-u32.rs +++ b/tests/ui/structs-enums/rec-align-u32.rs @@ -3,7 +3,7 @@ #![allow(unused_unsafe)] // Issue #2303 -#![feature(intrinsics)] +#![feature(intrinsics, rustc_attrs)] use std::mem; diff --git a/tests/ui/structs-enums/rec-align-u64.rs b/tests/ui/structs-enums/rec-align-u64.rs index c3b201fb1c66d..de008bcc01d29 100644 --- a/tests/ui/structs-enums/rec-align-u64.rs +++ b/tests/ui/structs-enums/rec-align-u64.rs @@ -5,7 +5,7 @@ // Issue #2303 -#![feature(intrinsics)] +#![feature(intrinsics, rustc_attrs)] use std::mem;