diff --git a/compiler/rustc_attr_parsing/src/interface.rs b/compiler/rustc_attr_parsing/src/interface.rs index eb49f108b0414..ffe0451f29aa9 100644 --- a/compiler/rustc_attr_parsing/src/interface.rs +++ b/compiler/rustc_attr_parsing/src/interface.rs @@ -285,11 +285,6 @@ impl<'sess> AttributeParser<'sess> { mut emit_lint: impl FnMut(LintId, MultiSpan, EmitAttribute), ) -> Vec { let mut attributes = Vec::new(); - // We store the attributes we intend to discard at the end of this function in order to - // check they are applied to the right target and error out if necessary. In practice, we - // end up dropping only derive attributes and derive helpers, both being fully processed - // at macro expansion. - let mut dropped_attributes = Vec::new(); let mut attr_paths: Vec> = Vec::new(); let mut early_parsed_state = EarlyParsedState::default(); @@ -437,20 +432,8 @@ impl<'sess> AttributeParser<'sess> { self.check_invalid_crate_level_attr_item(&attr, n.item.span()); } - let attr = Attribute::Unparsed(Box::new(attr)); - - if self.tools.is_some_and(|tools| { - tools.iter().any(|tool| tool.name == parts[0]) - // FIXME: this can be removed once #152369 has been merged. - // https://github.com/rust-lang/rust/pull/152369 - || [sym::allow, sym::deny, sym::expect, sym::forbid, sym::warn] - .contains(&parts[0]) - }) { - attributes.push(attr); - } else { - dropped_attributes.push(attr); - } - } + attributes.push(Attribute::Unparsed(Box::new(attr))); + }; } } } @@ -466,7 +449,7 @@ impl<'sess> AttributeParser<'sess> { } if !matches!(self.should_emit, ShouldEmit::Nothing) && target == Target::WherePredicate { - self.check_invalid_where_predicate_attrs(attributes.iter().chain(&dropped_attributes)); + self.check_invalid_where_predicate_attrs(attributes.iter()); } attributes diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index dbb40d1f429c1..38bde976b1b02 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -180,7 +180,7 @@ impl ModuleConfig { ), pgo_use: if_regular!(sess.opts.cg.profile_use.clone(), None), pgo_sample_use: if_regular!(sess.opts.unstable_opts.profile_sample_use.clone(), None), - debug_info_for_profiling: sess.opts.unstable_opts.debug_info_for_profiling, + debug_info_for_profiling: sess.opts.unstable_opts.debuginfo_for_profiling, instrument_coverage: if_regular!(sess.instrument_coverage(), false), sanitizer: if_regular!(sess.sanitizers(), SanitizerSet::empty()), diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 0837e7767605c..0498d835df5f5 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -782,8 +782,8 @@ fn test_unstable_options_tracking_hash() { ); tracked!(crate_attr, vec!["abc".to_string()]); tracked!(cross_crate_inline_threshold, InliningThreshold::Always); - tracked!(debug_info_for_profiling, true); tracked!(debug_info_type_line_numbers, true); + tracked!(debuginfo_for_profiling, true); tracked!(default_visibility, Some(rustc_target::spec::SymbolVisibility::Hidden)); tracked!(dep_info_omit_d_target, true); tracked!(direct_access_external_data, Some(true)); diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 1b2e24a684bc9..de606458d048e 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2252,12 +2252,12 @@ options! { "inject the given attribute in the crate"), cross_crate_inline_threshold: InliningThreshold = (InliningThreshold::Sometimes(100), parse_inlining_threshold, [TRACKED], "threshold to allow cross crate inlining of functions"), - debug_info_for_profiling: bool = (false, parse_bool, [TRACKED], - "emit discriminators and other data necessary for AutoFDO"), debug_info_type_line_numbers: bool = (false, parse_bool, [TRACKED], "emit type and line information for additional data types (default: no)"), debuginfo_compression: DebugInfoCompression = (DebugInfoCompression::None, parse_debuginfo_compression, [TRACKED], "compress debug info sections (none, zlib, zstd, default: none)"), + debuginfo_for_profiling: bool = (false, parse_bool, [TRACKED], + "emit discriminators and other data necessary for AutoFDO"), deduplicate_diagnostics: bool = (true, parse_bool, [UNTRACKED], "deduplicate identical diagnostics (default: yes)"), default_visibility: Option = (None, parse_opt_symbol_visibility, [TRACKED], diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs index a8e01e6e78b4b..90326e649058b 100644 --- a/library/core/src/hint.rs +++ b/library/core/src/hint.rs @@ -778,6 +778,9 @@ pub const fn unlikely(b: bool) -> bool { #[stable(feature = "cold_path", since = "1.95.0")] #[rustc_const_stable(feature = "cold_path", since = "1.95.0")] #[inline(always)] +// Even if for some reason the cold_path intrinsic is not visible to codegen, the coldness will +// ensure that branches this is in are still known to be cold. +#[cold] pub const fn cold_path() { crate::intrinsics::cold_path() } diff --git a/src/doc/unstable-book/src/compiler-flags/debug_info_for_profiling.md b/src/doc/unstable-book/src/compiler-flags/debuginfo_for_profiling.md similarity index 93% rename from src/doc/unstable-book/src/compiler-flags/debug_info_for_profiling.md rename to src/doc/unstable-book/src/compiler-flags/debuginfo_for_profiling.md index ee72b6adf8e9f..d25cdcaeb7427 100644 --- a/src/doc/unstable-book/src/compiler-flags/debug_info_for_profiling.md +++ b/src/doc/unstable-book/src/compiler-flags/debuginfo_for_profiling.md @@ -1,4 +1,4 @@ -# `debug-info-for-profiling` +# `debuginfo-for-profiling` --- @@ -22,7 +22,7 @@ external tool `create_llvm_prof` from [this repository] must be used. Given a Rust file `main.rs`, we can produce an optimized binary as follows: ```shell -rustc -O -Zdebug-info-for-profiling main.rs -o main +rustc -O -Zdebuginfo-for-profiling main.rs -o main perf record -b ./main create_llvm_prof --binary=main --out=code.prof rustc -O -Zprofile-sample-use=code.prof main.rs -o main2 diff --git a/src/doc/unstable-book/src/compiler-flags/profile_sample_use.md b/src/doc/unstable-book/src/compiler-flags/profile_sample_use.md index 2dd1f6f8e1a3a..a9bcca3e1522a 100644 --- a/src/doc/unstable-book/src/compiler-flags/profile_sample_use.md +++ b/src/doc/unstable-book/src/compiler-flags/profile_sample_use.md @@ -4,7 +4,7 @@ `-Zprofile-sample-use=code.prof` directs `rustc` to use the profile `code.prof` as a source for Automatic Feedback Directed Optimization (AFDO). -See the documentation of [`-Zdebug-info-for-profiling`] for more information +See the documentation of [`-Zdebuginfo-for-profiling`] for more information on using AFDO. -[`-Zdebug-info-for-profiling`]: debug_info_for_profiling.html +[`-Zdebuginfo-for-profiling`]: debuginfo_for_profiling.html diff --git a/src/librustdoc/html/macro_expansion.rs b/src/librustdoc/html/macro_expansion.rs index ec8b65984852c..4c820415e273c 100644 --- a/src/librustdoc/html/macro_expansion.rs +++ b/src/librustdoc/html/macro_expansion.rs @@ -2,7 +2,7 @@ use rustc_ast::visit::{ AssocCtxt, Visitor, walk_assoc_item, walk_crate, walk_expr, walk_item, walk_pat, walk_stmt, walk_ty, }; -use rustc_ast::{AssocItem, Crate, Expr, Item, Pat, Stmt, Ty}; +use rustc_ast::{AssocItem, Crate, Expr, ForeignItem, Item, Pat, Stmt, Ty}; use rustc_data_structures::fx::FxHashMap; use rustc_span::source_map::SourceMap; use rustc_span::{BytePos, Span}; @@ -174,4 +174,14 @@ impl<'ast> Visitor<'ast> for ExpandedCodeVisitor<'ast> { walk_assoc_item(self, item, ctxt); } } + + fn visit_foreign_item(&mut self, item: &'ast ForeignItem) -> Self::Result { + if item.span.from_expansion() { + self.handle_new_span(item.span, || { + rustc_ast_pretty::pprust::foreign_item_to_string(item) + }); + } else { + walk_item(self, item); + } + } } diff --git a/tests/assembly-llvm/debuginfo-for-profiling.rs b/tests/assembly-llvm/debuginfo-for-profiling.rs new file mode 100644 index 0000000000000..6431142e7b621 --- /dev/null +++ b/tests/assembly-llvm/debuginfo-for-profiling.rs @@ -0,0 +1,56 @@ +// Verify that additional discriminators are emitted for profiling with `-Zdebuginfo-for-profiling`: +// - 0 discriminators are emitted without the flag in the test below +// - at least 1 discriminator is emitted with the flag in the test below. +// Actual count depends on the target +// +// +//@ add-minicore +//@ revisions: DEFAULT-X86 DEFAULT-AARCH64 DEBUGINFO-X86 DEBUGINFO-AARCH64 +//@ assembly-output: emit-asm +//@ compile-flags: -Copt-level=2 -Cdebuginfo=line-tables-only +//@ [DEFAULT-X86] compile-flags: --target=x86_64-unknown-linux-gnu +//@ [DEFAULT-X86] needs-llvm-components: x86 +//@ [DEFAULT-AARCH64] compile-flags: --target=aarch64-unknown-linux-gnu +//@ [DEFAULT-AARCH64] needs-llvm-components: aarch64 +//@ [DEBUGINFO-X86] compile-flags: -Zdebuginfo-for-profiling --target=x86_64-unknown-linux-gnu +//@ [DEBUGINFO-X86] needs-llvm-components: x86 +//@ [DEBUGINFO-AARCH64] compile-flags: -Zdebuginfo-for-profiling --target=aarch64-unknown-linux-gnu +//@ [DEBUGINFO-AARCH64] needs-llvm-components: aarch64 +// DEFAULT-X86-NOT: discriminator +// DEFAULT-AARCH64-NOT: discriminator +// DEBUGINFO-X86-COUNT-1: discriminator +// DEBUGINFO-AARCH64-COUNT-1: discriminator + +#![feature(no_core)] +#![no_std] +#![no_core] +#![crate_type = "lib"] + +extern crate minicore; +use minicore::*; + +extern "C" { + fn add(_x: i32, _y: i32) -> i32; + fn mul(_x: i32, _y: i32) -> i32; + fn compute(_x: i32) -> i32; + fn cond() -> bool; +} + +#[no_mangle] +pub fn f(limit: i32) -> i32 { + unsafe { + let mut sum = 0; + let mut i = 1; + + while cond() { + if cond() { + sum = add(sum, compute(i)); + } else { + sum = add(sum, mul(compute(i), 2)); + } + i = add(i, 1); + } + + sum + } +} diff --git a/tests/codegen-llvm/debuginfo-for-profiling.rs b/tests/codegen-llvm/debuginfo-for-profiling.rs new file mode 100644 index 0000000000000..f7e401415ac7e --- /dev/null +++ b/tests/codegen-llvm/debuginfo-for-profiling.rs @@ -0,0 +1,45 @@ +// Verify that additional discriminators are emitted for profiling with `-Zdebuginfo-for-profiling`: +// - 0 discriminators are emitted without the flag in the test below +// - at least 1 discriminator is emitted with the flag in the test below +// +// +//@ add-minicore +//@ revisions: DEFAULT DEBUGINFO +//@ compile-flags: -Copt-level=2 -Cdebuginfo=line-tables-only +//@ [DEBUGINFO] compile-flags: -Zdebuginfo-for-profiling +// DEFAULT-NOT: discriminator +// DEBUGINFO-COUNT-1: discriminator + +#![feature(no_core)] +#![no_std] +#![no_core] +#![crate_type = "lib"] + +extern crate minicore; +use minicore::*; + +extern "C" { + fn add(_x: i32, _y: i32) -> i32; + fn mul(_x: i32, _y: i32) -> i32; + fn compute(_x: i32) -> i32; + fn cond() -> bool; +} + +#[no_mangle] +pub fn f(limit: i32) -> i32 { + unsafe { + let mut sum = 0; + let mut i = 1; + + while cond() { + if cond() { + sum = add(sum, compute(i)); + } else { + sum = add(sum, mul(compute(i), 2)); + } + i = add(i, 1); + } + + sum + } +} diff --git a/tests/codegen-llvm/hint/cold_path-target_feature.rs b/tests/codegen-llvm/hint/cold_path-target_feature.rs new file mode 100644 index 0000000000000..9e06fd0ceafa1 --- /dev/null +++ b/tests/codegen-llvm/hint/cold_path-target_feature.rs @@ -0,0 +1,56 @@ +//@ compile-flags: -Copt-level=3 +//@ only-x86_64 +#![crate_type = "lib"] + +// This test checks that hint::cold_path still works in #[target_feature] functions. + +use std::hint::cold_path; + +#[inline(never)] +#[no_mangle] +pub fn path_a() { + println!("path a"); +} + +#[inline(never)] +#[no_mangle] +pub fn path_b() { + println!("path b"); +} + +#[no_mangle] +pub fn test1(x: bool) { + if x { + path_a(); + } else { + cold_path(); + path_b(); + } + + // CHECK-LABEL: @test1( + // CHECK: br i1 %x, label %bb1, label %bb2, !prof ![[NUM:[0-9]+]] + // CHECK: bb2: + // CHECK: path_b + // CHECK: bb1: + // CHECK: path_a +} + +#[no_mangle] +#[target_feature(enable = "sse2")] +pub fn with_target_feature(x: bool) { + if x { + path_a(); + } else { + cold_path(); + path_b(); + } + + // CHECK-LABEL: @with_target_feature( + // CHECK: br i1 %x, label %bb1, label %bb2, !prof ![[NUM]] + // CHECK: bb2: + // CHECK: path_b + // CHECK: bb1: + // CHECK: path_a +} + +// CHECK: ![[NUM]] = !{!"branch_weights", {{(!"expected", )?}}i32 2000, i32 1} diff --git a/tests/rustdoc-html/macro-expansion/c-var-args.rs b/tests/rustdoc-html/macro-expansion/c-var-args.rs new file mode 100644 index 0000000000000..1d42036cc7bf7 --- /dev/null +++ b/tests/rustdoc-html/macro-expansion/c-var-args.rs @@ -0,0 +1,19 @@ +// Ensure that C var args (`va_list`) work. +// Regression test for . + +//@ compile-flags: -Zunstable-options --generate-macro-expansion + +#![crate_name = "foo"] + +//@ has 'src/foo/c-var-args.rs.html' + +macro_rules! print { + () => { + fn printf(...); + }; +} + +//@ has - '//*[@class="expansion"]/*[@class="expanded"]' 'fn printf(...);' +extern "C" { + print! {} +} diff --git a/tests/rustdoc-json/attrs/derive_helper.rs b/tests/rustdoc-json/attrs/derive_helper.rs new file mode 100644 index 0000000000000..278d0072decdd --- /dev/null +++ b/tests/rustdoc-json/attrs/derive_helper.rs @@ -0,0 +1,7 @@ +//@ is "$.index[?(@.name=='A')].attrs" '[{"other": "#[default]"}]' +#[derive(Default)] +pub enum Test { + #[default] + A, + B, +}