From c26142697c417010fe338dddd2b771af872d02ba Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sun, 16 Mar 2025 21:14:41 +0100 Subject: [PATCH 01/20] add `naked_functions_target_feature` unstable feature --- compiler/rustc_feature/src/unstable.rs | 2 ++ compiler/rustc_passes/src/check_attr.rs | 16 +++++++++++++- compiler/rustc_span/src/symbol.rs | 1 + .../ui/asm/naked-functions-target-feature.rs | 21 +++++++++++++++++++ tests/ui/asm/naked-functions.rs | 7 ------- ...ure-gate-naked_functions_target_feature.rs | 15 +++++++++++++ ...gate-naked_functions_target_feature.stderr | 13 ++++++++++++ 7 files changed, 67 insertions(+), 8 deletions(-) create mode 100644 tests/ui/asm/naked-functions-target-feature.rs create mode 100644 tests/ui/feature-gates/feature-gate-naked_functions_target_feature.rs create mode 100644 tests/ui/feature-gates/feature-gate-naked_functions_target_feature.stderr diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 3c61bfd1c93f5..736d18217b474 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -568,6 +568,8 @@ declare_features! ( (incomplete, mut_ref, "1.79.0", Some(123076)), /// Allows using `#[naked]` on functions. (unstable, naked_functions, "1.9.0", Some(90957)), + /// Allows using `#[target_feature(enable = "...")]` on `#[naked]` on functions. + (unstable, naked_functions_target_feature, "1.86.0", Some(138568)), /// Allows specifying the as-needed link modifier (unstable, native_link_modifiers_as_needed, "1.53.0", Some(81490)), /// Allow negative trait implementations. diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index ece5a53aaa9c4..7f624747a4686 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -598,7 +598,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { sym::repr, // code generation sym::cold, - sym::target_feature, // documentation sym::doc, ]; @@ -624,6 +623,21 @@ impl<'tcx> CheckAttrVisitor<'tcx> { _ => {} } + if other_attr.has_name(sym::target_feature) { + if !self.tcx.features().naked_functions_target_feature() { + feature_err( + &self.tcx.sess, + sym::naked_functions_target_feature, + other_attr.span(), + "`#[target_feature(/* ... */)]` is currently unstable on `#[naked]` functions", + ).emit(); + + return; + } else { + continue; + } + } + if !ALLOW_LIST.iter().any(|name| other_attr.has_name(*name)) { self.dcx().emit_err(errors::NakedFunctionIncompatibleAttribute { span: other_attr.span(), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 8a8bec35d8194..9770e315b15c8 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1375,6 +1375,7 @@ symbols! { naked, naked_asm, naked_functions, + naked_functions_target_feature, name, names, native_link_modifiers, diff --git a/tests/ui/asm/naked-functions-target-feature.rs b/tests/ui/asm/naked-functions-target-feature.rs new file mode 100644 index 0000000000000..afe1a38914720 --- /dev/null +++ b/tests/ui/asm/naked-functions-target-feature.rs @@ -0,0 +1,21 @@ +//@ build-pass +//@ needs-asm-support + +#![feature(naked_functions, naked_functions_target_feature)] +#![crate_type = "lib"] + +use std::arch::{asm, naked_asm}; + +#[cfg(target_arch = "x86_64")] +#[target_feature(enable = "sse2")] +#[naked] +pub unsafe extern "C" fn compatible_target_feature() { + naked_asm!(""); +} + +#[cfg(target_arch = "aarch64")] +#[target_feature(enable = "neon")] +#[naked] +pub unsafe extern "C" fn compatible_target_feature() { + naked_asm!(""); +} diff --git a/tests/ui/asm/naked-functions.rs b/tests/ui/asm/naked-functions.rs index e7e5d84f2a5da..3d4d414539c16 100644 --- a/tests/ui/asm/naked-functions.rs +++ b/tests/ui/asm/naked-functions.rs @@ -230,13 +230,6 @@ pub unsafe extern "C" fn compatible_codegen_attributes() { naked_asm!("", options(raw)); } -#[cfg(target_arch = "x86_64")] -#[target_feature(enable = "sse2")] -#[naked] -pub unsafe extern "C" fn compatible_target_feature() { - naked_asm!(""); -} - #[doc = "foo bar baz"] /// a doc comment // a normal comment diff --git a/tests/ui/feature-gates/feature-gate-naked_functions_target_feature.rs b/tests/ui/feature-gates/feature-gate-naked_functions_target_feature.rs new file mode 100644 index 0000000000000..0d3af4c5fe0a4 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-naked_functions_target_feature.rs @@ -0,0 +1,15 @@ +//@ needs-asm-support +//@ only-x86_64 + +#![feature(naked_functions)] + +use std::arch::naked_asm; + +#[naked] +#[target_feature(enable = "avx2")] +//~^ ERROR: `#[target_feature(/* ... */)]` is currently unstable on `#[naked]` functions +extern "C" fn naked() { + unsafe { naked_asm!("") } +} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-naked_functions_target_feature.stderr b/tests/ui/feature-gates/feature-gate-naked_functions_target_feature.stderr new file mode 100644 index 0000000000000..b0592d08046f5 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-naked_functions_target_feature.stderr @@ -0,0 +1,13 @@ +error[E0658]: `#[target_feature(/* ... */)]` is currently unstable on `#[naked]` functions + --> $DIR/feature-gate-naked_functions_target_feature.rs:9:1 + | +LL | #[target_feature(enable = "avx2")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #138568 for more information + = help: add `#![feature(naked_functions_target_feature)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0658`. From 03ece26b79c8b04a916bcd6ee0ab26c8c20e7b66 Mon Sep 17 00:00:00 2001 From: Manuel Drehwald Date: Mon, 17 Mar 2025 16:21:45 -0400 Subject: [PATCH 02/20] update tests --- tests/pretty/autodiff_forward.pp | 2 +- tests/pretty/autodiff_forward.rs | 2 +- tests/pretty/autodiff_reverse.pp | 2 +- tests/pretty/autodiff_reverse.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/pretty/autodiff_forward.pp b/tests/pretty/autodiff_forward.pp index 23c3b5b34a82a..52d6eaff3c381 100644 --- a/tests/pretty/autodiff_forward.pp +++ b/tests/pretty/autodiff_forward.pp @@ -53,7 +53,7 @@ pub fn f3(x: &[f64], y: f64) -> f64 { ::core::panicking::panic("not implemented") } -#[rustc_autodiff(ForwardFirst, Dual, Const, Const,)] +#[rustc_autodiff(Forward, Dual, Const, Const,)] #[inline(never)] pub fn df3(x: &[f64], bx: &[f64], y: f64) -> f64 { unsafe { asm!("NOP", options(pure, nomem)); }; diff --git a/tests/pretty/autodiff_forward.rs b/tests/pretty/autodiff_forward.rs index 35108d0d6f111..bc5582116322b 100644 --- a/tests/pretty/autodiff_forward.rs +++ b/tests/pretty/autodiff_forward.rs @@ -19,7 +19,7 @@ pub fn f2(x: &[f64], y: f64) -> f64 { unimplemented!() } -#[autodiff(df3, ForwardFirst, Dual, Const, Const)] +#[autodiff(df3, Forward, Dual, Const, Const)] pub fn f3(x: &[f64], y: f64) -> f64 { unimplemented!() } diff --git a/tests/pretty/autodiff_reverse.pp b/tests/pretty/autodiff_reverse.pp index a98d3782c7034..b2cf0244af4c6 100644 --- a/tests/pretty/autodiff_reverse.pp +++ b/tests/pretty/autodiff_reverse.pp @@ -51,7 +51,7 @@ pub fn f3(x: &[f64], y: f64) -> f64 { ::core::panicking::panic("not implemented") } -#[rustc_autodiff(ReverseFirst, Duplicated, Const, Active,)] +#[rustc_autodiff(Reverse, Duplicated, Const, Active,)] #[inline(never)] pub fn df3(x: &[f64], dx: &mut [f64], y: f64, dret: f64) -> f64 { unsafe { asm!("NOP", options(pure, nomem)); }; diff --git a/tests/pretty/autodiff_reverse.rs b/tests/pretty/autodiff_reverse.rs index 657201caa9401..3c024272f407e 100644 --- a/tests/pretty/autodiff_reverse.rs +++ b/tests/pretty/autodiff_reverse.rs @@ -18,7 +18,7 @@ pub fn f1(x: &[f64], y: f64) -> f64 { #[autodiff(df2, Reverse)] pub fn f2() {} -#[autodiff(df3, ReverseFirst, Duplicated, Const, Active)] +#[autodiff(df3, Reverse, Duplicated, Const, Active)] pub fn f3(x: &[f64], y: f64) -> f64 { unimplemented!() } From b77590c1176839b127fe1f20b4557267d26d91a7 Mon Sep 17 00:00:00 2001 From: David Tenty Date: Mon, 17 Mar 2025 16:24:55 -0400 Subject: [PATCH 03/20] Use llvm_runtimes for compiler-rt --- src/bootstrap/src/core/build_steps/llvm.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index 1e3148d631cb1..0b1799198daf5 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -479,7 +479,6 @@ impl Step for Llvm { if helpers::forcing_clang_based_tests() { enabled_llvm_projects.push("clang"); - enabled_llvm_projects.push("compiler-rt"); } if builder.config.llvm_polly { @@ -502,6 +501,10 @@ impl Step for Llvm { let mut enabled_llvm_runtimes = Vec::new(); + if helpers::forcing_clang_based_tests() { + enabled_llvm_runtimes.push("compiler-rt"); + } + if builder.config.llvm_offload { enabled_llvm_runtimes.push("offload"); //FIXME(ZuseZ4): LLVM intends to drop the offload dependency on openmp. From f5c37c3732360b21dc6d049003838e99b5ec5263 Mon Sep 17 00:00:00 2001 From: Manuel Drehwald Date: Mon, 17 Mar 2025 16:54:41 -0400 Subject: [PATCH 04/20] [NFC] split up gen_body_helper --- compiler/rustc_builtin_macros/src/autodiff.rs | 89 ++++++++++++++----- 1 file changed, 67 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/autodiff.rs b/compiler/rustc_builtin_macros/src/autodiff.rs index 7b5c4a159b0c5..06cc4d3d8ba46 100644 --- a/compiler/rustc_builtin_macros/src/autodiff.rs +++ b/compiler/rustc_builtin_macros/src/autodiff.rs @@ -359,30 +359,27 @@ mod llvm_enzyme { ty } - /// We only want this function to type-check, since we will replace the body - /// later on llvm level. Using `loop {}` does not cover all return types anymore, - /// so instead we build something that should pass. We also add a inline_asm - /// line, as one more barrier for rustc to prevent inlining of this function. - /// FIXME(ZuseZ4): We still have cases of incorrect inlining across modules, see - /// , so this isn't sufficient. - /// It also triggers an Enzyme crash if we due to a bug ever try to differentiate - /// this function (which should never happen, since it is only a placeholder). - /// Finally, we also add back_box usages of all input arguments, to prevent rustc - /// from optimizing any arguments away. - fn gen_enzyme_body( + // Will generate a body of the type: + // ``` + // { + // unsafe { + // asm!("NOP"); + // } + // ::core::hint::black_box(primal(args)); + // ::core::hint::black_box((args, ret)); + // + // } + // ``` + fn init_body_helper( ecx: &ExtCtxt<'_>, - x: &AutoDiffAttrs, - n_active: u32, - sig: &ast::FnSig, - d_sig: &ast::FnSig, + span: Span, primal: Ident, new_names: &[String], - span: Span, sig_span: Span, new_decl_span: Span, - idents: Vec, + idents: &[Ident], errored: bool, - ) -> P { + ) -> (P, P, P, P) { let blackbox_path = ecx.std_path(&[sym::hint, sym::black_box]); let noop = ast::InlineAsm { asm_macro: ast::AsmMacro::Asm, @@ -431,6 +428,54 @@ mod llvm_enzyme { } body.stmts.push(ecx.stmt_semi(black_box_remaining_args)); + (body, primal_call, black_box_primal_call, blackbox_call_expr) + } + + /// We only want this function to type-check, since we will replace the body + /// later on llvm level. Using `loop {}` does not cover all return types anymore, + /// so instead we build something that should pass. We also add a inline_asm + /// line, as one more barrier for rustc to prevent inlining of this function. + /// FIXME(ZuseZ4): We still have cases of incorrect inlining across modules, see + /// , so this isn't sufficient. + /// It also triggers an Enzyme crash if we due to a bug ever try to differentiate + /// this function (which should never happen, since it is only a placeholder). + /// Finally, we also add back_box usages of all input arguments, to prevent rustc + /// from optimizing any arguments away. + fn gen_enzyme_body( + ecx: &ExtCtxt<'_>, + x: &AutoDiffAttrs, + n_active: u32, + sig: &ast::FnSig, + d_sig: &ast::FnSig, + primal: Ident, + new_names: &[String], + span: Span, + sig_span: Span, + _new_decl_span: Span, + idents: Vec, + errored: bool, + ) -> P { + let new_decl_span = d_sig.span; + + // Just adding some default inline-asm and black_box usages to prevent early inlining + // and optimizations which alter the function signature. + // + // The bb_primal_call is the black_box call of the primal function. We keep it around, + // since it has the convenient property of returning the type of the primal function, + // Remember, we only care to match types here. + // No matter which return we pick, we always wrap it into a std::hint::black_box call, + // to prevent rustc from propagating it into the caller. + let (mut body, primal_call, bb_primal_call, bb_call_expr) = init_body_helper( + ecx, + span, + primal, + new_names, + sig_span, + new_decl_span, + &idents, + errored, + ); + if !has_ret(&d_sig.decl.output) { // there is no return type that we have to match, () works fine. return body; @@ -442,7 +487,7 @@ mod llvm_enzyme { if primal_ret && n_active == 0 && x.mode.is_rev() { // We only have the primal ret. - body.stmts.push(ecx.stmt_expr(black_box_primal_call)); + body.stmts.push(ecx.stmt_expr(bb_primal_call)); return body; } @@ -534,11 +579,11 @@ mod llvm_enzyme { return body; } [arg] => { - ret = ecx.expr_call(new_decl_span, blackbox_call_expr, thin_vec![arg.clone()]); + ret = ecx.expr_call(new_decl_span, bb_call_expr, thin_vec![arg.clone()]); } args => { let ret_tuple: P = ecx.expr_tuple(span, args.into()); - ret = ecx.expr_call(new_decl_span, blackbox_call_expr, thin_vec![ret_tuple]); + ret = ecx.expr_call(new_decl_span, bb_call_expr, thin_vec![ret_tuple]); } } assert!(has_ret(&d_sig.decl.output)); @@ -551,7 +596,7 @@ mod llvm_enzyme { ecx: &ExtCtxt<'_>, span: Span, primal: Ident, - idents: Vec, + idents: &[Ident], ) -> P { let has_self = idents.len() > 0 && idents[0].name == kw::SelfLower; if has_self { From f9d0a14639df0f92645ff58ed4958509473c03ad Mon Sep 17 00:00:00 2001 From: Manuel Drehwald Date: Mon, 17 Mar 2025 17:06:26 -0400 Subject: [PATCH 05/20] resolve repeated attribute fixme --- compiler/rustc_builtin_macros/src/autodiff.rs | 21 +++++++++++++++---- .../rustc_codegen_ssa/src/codegen_attrs.rs | 6 ------ tests/pretty/autodiff_forward.pp | 4 ---- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/autodiff.rs b/compiler/rustc_builtin_macros/src/autodiff.rs index 06cc4d3d8ba46..d476a90fadf18 100644 --- a/compiler/rustc_builtin_macros/src/autodiff.rs +++ b/compiler/rustc_builtin_macros/src/autodiff.rs @@ -282,22 +282,35 @@ mod llvm_enzyme { span, }; + // We're avoid duplicating the attributes `#[rustc_autodiff]` and `#[inline(never)]`. + fn same_attribute(attr: &ast::AttrKind, item: &ast::AttrKind) -> bool { + match (attr, item) { + (ast::AttrKind::Normal(a), ast::AttrKind::Normal(b)) => { + let a = &a.item.path; + let b = &b.item.path; + a.segments.len() == b.segments.len() + && a.segments.iter().zip(b.segments.iter()).all(|(a, b)| a.ident == b.ident) + } + _ => false, + } + } + // Don't add it multiple times: let orig_annotatable: Annotatable = match item { Annotatable::Item(ref mut iitem) => { - if !iitem.attrs.iter().any(|a| a.id == attr.id) { + if !iitem.attrs.iter().any(|a| same_attribute(&a.kind, &attr.kind)) { iitem.attrs.push(attr); } - if !iitem.attrs.iter().any(|a| a.id == inline_never.id) { + if !iitem.attrs.iter().any(|a| same_attribute(&a.kind, &inline_never.kind)) { iitem.attrs.push(inline_never.clone()); } Annotatable::Item(iitem.clone()) } Annotatable::AssocItem(ref mut assoc_item, i @ Impl) => { - if !assoc_item.attrs.iter().any(|a| a.id == attr.id) { + if !assoc_item.attrs.iter().any(|a| same_attribute(&a.kind, &attr.kind)) { assoc_item.attrs.push(attr); } - if !assoc_item.attrs.iter().any(|a| a.id == inline_never.id) { + if !assoc_item.attrs.iter().any(|a| same_attribute(&a.kind, &inline_never.kind)) { assoc_item.attrs.push(inline_never.clone()); } Annotatable::AssocItem(assoc_item.clone(), i) diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 90c53c347689b..5a3f0aa831059 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -798,16 +798,10 @@ fn autodiff_attrs(tcx: TyCtxt<'_>, id: DefId) -> Option { // check for exactly one autodiff attribute on placeholder functions. // There should only be one, since we generate a new placeholder per ad macro. - // FIXME(ZuseZ4): re-enable this check. Currently we add multiple, which doesn't cause harm but - // looks strange e.g. under cargo-expand. let attr = match &attrs[..] { [] => return None, [attr] => attr, - // These two attributes are the same and unfortunately duplicated due to a previous bug. - [attr, _attr2] => attr, _ => { - //FIXME(ZuseZ4): Once we fixed our parser, we should also prohibit the two-attribute - //branch above. span_bug!(attrs[1].span(), "cg_ssa: rustc_autodiff should only exist once per source"); } }; diff --git a/tests/pretty/autodiff_forward.pp b/tests/pretty/autodiff_forward.pp index 52d6eaff3c381..dc7a2712f4231 100644 --- a/tests/pretty/autodiff_forward.pp +++ b/tests/pretty/autodiff_forward.pp @@ -73,10 +73,6 @@ } #[rustc_autodiff] #[inline(never)] -#[rustc_autodiff] -#[inline(never)] -#[rustc_autodiff] -#[inline(never)] pub fn f5(x: &[f64], y: f64) -> f64 { ::core::panicking::panic("not implemented") } From 5f7ff8885346735289bb97d3676110a09844abab Mon Sep 17 00:00:00 2001 From: Manuel Drehwald Date: Mon, 17 Mar 2025 17:23:35 -0400 Subject: [PATCH 06/20] [NFC] use outer_normal_attr helper --- compiler/rustc_builtin_macros/src/autodiff.rs | 32 ++++++++----------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/autodiff.rs b/compiler/rustc_builtin_macros/src/autodiff.rs index d476a90fadf18..bfddb450cd762 100644 --- a/compiler/rustc_builtin_macros/src/autodiff.rs +++ b/compiler/rustc_builtin_macros/src/autodiff.rs @@ -25,6 +25,16 @@ mod llvm_enzyme { use crate::errors; + pub(crate) fn outer_normal_attr( + kind: &P, + id: rustc_ast::AttrId, + span: Span, + ) -> rustc_ast::Attribute { + let style = rustc_ast::AttrStyle::Outer; + let kind = rustc_ast::AttrKind::Normal(kind.clone()); + rustc_ast::Attribute { kind, id, style, span } + } + // If we have a default `()` return type or explicitley `()` return type, // then we often can skip doing some work. fn has_ret(ty: &FnRetTy) -> bool { @@ -268,19 +278,9 @@ mod llvm_enzyme { }; let inline_never_attr = P(ast::NormalAttr { item: inline_item, tokens: None }); let new_id = ecx.sess.psess.attr_id_generator.mk_attr_id(); - let attr: ast::Attribute = ast::Attribute { - kind: ast::AttrKind::Normal(rustc_ad_attr.clone()), - id: new_id, - style: ast::AttrStyle::Outer, - span, - }; + let attr = outer_normal_attr(&rustc_ad_attr, new_id, span); let new_id = ecx.sess.psess.attr_id_generator.mk_attr_id(); - let inline_never: ast::Attribute = ast::Attribute { - kind: ast::AttrKind::Normal(inline_never_attr), - id: new_id, - style: ast::AttrStyle::Outer, - span, - }; + let inline_never = outer_normal_attr(&inline_never_attr, new_id, span); // We're avoid duplicating the attributes `#[rustc_autodiff]` and `#[inline(never)]`. fn same_attribute(attr: &ast::AttrKind, item: &ast::AttrKind) -> bool { @@ -325,13 +325,7 @@ mod llvm_enzyme { delim: rustc_ast::token::Delimiter::Parenthesis, tokens: ts, }); - let d_attr: ast::Attribute = ast::Attribute { - kind: ast::AttrKind::Normal(rustc_ad_attr.clone()), - id: new_id, - style: ast::AttrStyle::Outer, - span, - }; - + let d_attr = outer_normal_attr(&rustc_ad_attr, new_id, span); let d_annotatable = if is_impl { let assoc_item: AssocItemKind = ast::AssocItemKind::Fn(asdf); let d_fn = P(ast::AssocItem { From f4c297802ff34cd6a36d077c1271041fc0501cb7 Mon Sep 17 00:00:00 2001 From: Manuel Drehwald Date: Mon, 17 Mar 2025 18:58:51 -0400 Subject: [PATCH 07/20] [NFC] extract autodiff call lowering in cg_llvm into own function --- .../src/builder/autodiff.rs | 201 ++++++++++-------- 1 file changed, 108 insertions(+), 93 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs index 71705ecb4d0f5..482af98aa1ab6 100644 --- a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs +++ b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs @@ -28,6 +28,113 @@ fn get_params(fnc: &Value) -> Vec<&Value> { } } +fn match_args_from_caller_to_enzyme<'ll>( + cx: &SimpleCx<'ll>, + args: &mut Vec<&'ll llvm::Value>, + inputs: &[DiffActivity], + outer_args: &[&'ll llvm::Value], +) { + debug!("matching autodiff arguments"); + // We now handle the issue that Rust level arguments not always match the llvm-ir level + // arguments. A slice, `&[f32]`, for example, is represented as a pointer and a length on + // llvm-ir level. The number of activities matches the number of Rust level arguments, so we + // need to match those. + // FIXME(ZuseZ4): This logic is a bit more complicated than it should be, can we simplify it + // using iterators and peek()? + let mut outer_pos: usize = 0; + let mut activity_pos = 0; + + let enzyme_const = cx.create_metadata("enzyme_const".to_string()).unwrap(); + let enzyme_out = cx.create_metadata("enzyme_out".to_string()).unwrap(); + let enzyme_dup = cx.create_metadata("enzyme_dup".to_string()).unwrap(); + let enzyme_dupnoneed = cx.create_metadata("enzyme_dupnoneed".to_string()).unwrap(); + + while activity_pos < inputs.len() { + let diff_activity = inputs[activity_pos as usize]; + // Duplicated arguments received a shadow argument, into which enzyme will write the + // gradient. + let (activity, duplicated): (&Metadata, bool) = match diff_activity { + DiffActivity::None => panic!("not a valid input activity"), + DiffActivity::Const => (enzyme_const, false), + DiffActivity::Active => (enzyme_out, false), + DiffActivity::ActiveOnly => (enzyme_out, false), + DiffActivity::Dual => (enzyme_dup, true), + DiffActivity::DualOnly => (enzyme_dupnoneed, true), + DiffActivity::Duplicated => (enzyme_dup, true), + DiffActivity::DuplicatedOnly => (enzyme_dupnoneed, true), + DiffActivity::FakeActivitySize => (enzyme_const, false), + }; + let outer_arg = outer_args[outer_pos]; + args.push(cx.get_metadata_value(activity)); + args.push(outer_arg); + if duplicated { + // We know that duplicated args by construction have a following argument, + // so this can not be out of bounds. + let next_outer_arg = outer_args[outer_pos + 1]; + let next_outer_ty = cx.val_ty(next_outer_arg); + // FIXME(ZuseZ4): We should add support for Vec here too, but it's less urgent since + // vectors behind references (&Vec) are already supported. Users can not pass a + // Vec by value for reverse mode, so this would only help forward mode autodiff. + let slice = { + if activity_pos + 1 >= inputs.len() { + // If there is no arg following our ptr, it also can't be a slice, + // since that would lead to a ptr, int pair. + false + } else { + let next_activity = inputs[activity_pos + 1]; + // We analyze the MIR types and add this dummy activity if we visit a slice. + next_activity == DiffActivity::FakeActivitySize + } + }; + if slice { + // A duplicated slice will have the following two outer_fn arguments: + // (..., ptr1, int1, ptr2, int2, ...). We add the following llvm-ir to our __enzyme call: + // (..., metadata! enzyme_dup, ptr, ptr, int1, ...). + // FIXME(ZuseZ4): We will upstream a safety check later which asserts that + // int2 >= int1, which means the shadow vector is large enough to store the gradient. + assert!(unsafe { + llvm::LLVMRustGetTypeKind(next_outer_ty) == llvm::TypeKind::Integer + }); + let next_outer_arg2 = outer_args[outer_pos + 2]; + let next_outer_ty2 = cx.val_ty(next_outer_arg2); + assert!(unsafe { + llvm::LLVMRustGetTypeKind(next_outer_ty2) == llvm::TypeKind::Pointer + }); + let next_outer_arg3 = outer_args[outer_pos + 3]; + let next_outer_ty3 = cx.val_ty(next_outer_arg3); + assert!(unsafe { + llvm::LLVMRustGetTypeKind(next_outer_ty3) == llvm::TypeKind::Integer + }); + args.push(next_outer_arg2); + args.push(cx.get_metadata_value(enzyme_const)); + args.push(next_outer_arg); + outer_pos += 4; + activity_pos += 2; + } else { + // A duplicated pointer will have the following two outer_fn arguments: + // (..., ptr, ptr, ...). We add the following llvm-ir to our __enzyme call: + // (..., metadata! enzyme_dup, ptr, ptr, ...). + if matches!(diff_activity, DiffActivity::Duplicated | DiffActivity::DuplicatedOnly) + { + assert!( + unsafe { llvm::LLVMRustGetTypeKind(next_outer_ty) } + == llvm::TypeKind::Pointer + ); + } + // In the case of Dual we don't have assumptions, e.g. f32 would be valid. + args.push(next_outer_arg); + outer_pos += 2; + activity_pos += 1; + } + } else { + // We do not differentiate with resprect to this argument. + // We already added the metadata and argument above, so just increase the counters. + outer_pos += 1; + activity_pos += 1; + } + } +} + /// When differentiating `fn_to_diff`, take a `outer_fn` and generate another /// function with expected naming and calling conventions[^1] which will be /// discovered by the enzyme LLVM pass and its body populated with the differentiated @@ -132,12 +239,7 @@ fn generate_enzyme_call<'ll>( let mut args = Vec::with_capacity(num_args as usize + 1); args.push(fn_to_diff); - let enzyme_const = cx.create_metadata("enzyme_const".to_string()).unwrap(); - let enzyme_out = cx.create_metadata("enzyme_out".to_string()).unwrap(); - let enzyme_dup = cx.create_metadata("enzyme_dup".to_string()).unwrap(); - let enzyme_dupnoneed = cx.create_metadata("enzyme_dupnoneed".to_string()).unwrap(); let enzyme_primal_ret = cx.create_metadata("enzyme_primal_return".to_string()).unwrap(); - match output { DiffActivity::Dual => { args.push(cx.get_metadata_value(enzyme_primal_ret)); @@ -148,95 +250,8 @@ fn generate_enzyme_call<'ll>( _ => {} } - debug!("matching autodiff arguments"); - // We now handle the issue that Rust level arguments not always match the llvm-ir level - // arguments. A slice, `&[f32]`, for example, is represented as a pointer and a length on - // llvm-ir level. The number of activities matches the number of Rust level arguments, so we - // need to match those. - // FIXME(ZuseZ4): This logic is a bit more complicated than it should be, can we simplify it - // using iterators and peek()? - let mut outer_pos: usize = 0; - let mut activity_pos = 0; let outer_args: Vec<&llvm::Value> = get_params(outer_fn); - while activity_pos < inputs.len() { - let diff_activity = inputs[activity_pos as usize]; - // Duplicated arguments received a shadow argument, into which enzyme will write the - // gradient. - let (activity, duplicated): (&Metadata, bool) = match diff_activity { - DiffActivity::None => panic!("not a valid input activity"), - DiffActivity::Const => (enzyme_const, false), - DiffActivity::Active => (enzyme_out, false), - DiffActivity::ActiveOnly => (enzyme_out, false), - DiffActivity::Dual => (enzyme_dup, true), - DiffActivity::DualOnly => (enzyme_dupnoneed, true), - DiffActivity::Duplicated => (enzyme_dup, true), - DiffActivity::DuplicatedOnly => (enzyme_dupnoneed, true), - DiffActivity::FakeActivitySize => (enzyme_const, false), - }; - let outer_arg = outer_args[outer_pos]; - args.push(cx.get_metadata_value(activity)); - args.push(outer_arg); - if duplicated { - // We know that duplicated args by construction have a following argument, - // so this can not be out of bounds. - let next_outer_arg = outer_args[outer_pos + 1]; - let next_outer_ty = cx.val_ty(next_outer_arg); - // FIXME(ZuseZ4): We should add support for Vec here too, but it's less urgent since - // vectors behind references (&Vec) are already supported. Users can not pass a - // Vec by value for reverse mode, so this would only help forward mode autodiff. - let slice = { - if activity_pos + 1 >= inputs.len() { - // If there is no arg following our ptr, it also can't be a slice, - // since that would lead to a ptr, int pair. - false - } else { - let next_activity = inputs[activity_pos + 1]; - // We analyze the MIR types and add this dummy activity if we visit a slice. - next_activity == DiffActivity::FakeActivitySize - } - }; - if slice { - // A duplicated slice will have the following two outer_fn arguments: - // (..., ptr1, int1, ptr2, int2, ...). We add the following llvm-ir to our __enzyme call: - // (..., metadata! enzyme_dup, ptr, ptr, int1, ...). - // FIXME(ZuseZ4): We will upstream a safety check later which asserts that - // int2 >= int1, which means the shadow vector is large enough to store the gradient. - assert!(llvm::LLVMRustGetTypeKind(next_outer_ty) == llvm::TypeKind::Integer); - let next_outer_arg2 = outer_args[outer_pos + 2]; - let next_outer_ty2 = cx.val_ty(next_outer_arg2); - assert!(llvm::LLVMRustGetTypeKind(next_outer_ty2) == llvm::TypeKind::Pointer); - let next_outer_arg3 = outer_args[outer_pos + 3]; - let next_outer_ty3 = cx.val_ty(next_outer_arg3); - assert!(llvm::LLVMRustGetTypeKind(next_outer_ty3) == llvm::TypeKind::Integer); - args.push(next_outer_arg2); - args.push(cx.get_metadata_value(enzyme_const)); - args.push(next_outer_arg); - outer_pos += 4; - activity_pos += 2; - } else { - // A duplicated pointer will have the following two outer_fn arguments: - // (..., ptr, ptr, ...). We add the following llvm-ir to our __enzyme call: - // (..., metadata! enzyme_dup, ptr, ptr, ...). - if matches!( - diff_activity, - DiffActivity::Duplicated | DiffActivity::DuplicatedOnly - ) { - assert!( - llvm::LLVMRustGetTypeKind(next_outer_ty) == llvm::TypeKind::Pointer - ); - } - // In the case of Dual we don't have assumptions, e.g. f32 would be valid. - args.push(next_outer_arg); - outer_pos += 2; - activity_pos += 1; - } - } else { - // We do not differentiate with resprect to this argument. - // We already added the metadata and argument above, so just increase the counters. - outer_pos += 1; - activity_pos += 1; - } - } + match_args_from_caller_to_enzyme(&cx, &mut args, &inputs, &outer_args); let call = builder.call(enzyme_ty, ad_fn, &args, None); From 47c07ed9637bb59bb37d7b541ff3ed11d158a9ee Mon Sep 17 00:00:00 2001 From: Manuel Drehwald Date: Mon, 17 Mar 2025 19:13:09 -0400 Subject: [PATCH 08/20] [NFC] simplify matching --- .../rustc_codegen_llvm/src/builder/autodiff.rs | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs index 482af98aa1ab6..7cd4ee539d875 100644 --- a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs +++ b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs @@ -150,9 +150,6 @@ fn generate_enzyme_call<'ll>( outer_fn: &'ll Value, attrs: AutoDiffAttrs, ) { - let inputs = attrs.input_activity; - let output = attrs.ret_activity; - // We have to pick the name depending on whether we want forward or reverse mode autodiff. let mut ad_name: String = match attrs.mode { DiffMode::Forward => "__enzyme_fwddiff", @@ -240,18 +237,12 @@ fn generate_enzyme_call<'ll>( args.push(fn_to_diff); let enzyme_primal_ret = cx.create_metadata("enzyme_primal_return".to_string()).unwrap(); - match output { - DiffActivity::Dual => { - args.push(cx.get_metadata_value(enzyme_primal_ret)); - } - DiffActivity::Active => { - args.push(cx.get_metadata_value(enzyme_primal_ret)); - } - _ => {} + if matches!(attrs.ret_activity, DiffActivity::Dual | DiffActivity::Active) { + args.push(cx.get_metadata_value(enzyme_primal_ret)); } let outer_args: Vec<&llvm::Value> = get_params(outer_fn); - match_args_from_caller_to_enzyme(&cx, &mut args, &inputs, &outer_args); + match_args_from_caller_to_enzyme(&cx, &mut args, &attrs.input_activity, &outer_args); let call = builder.call(enzyme_ty, ad_fn, &args, None); From 81b2d5508eb4e79af7ba4bd32486099eeaabc834 Mon Sep 17 00:00:00 2001 From: Manuel Drehwald Date: Tue, 18 Mar 2025 02:47:37 -0400 Subject: [PATCH 09/20] addressing feedback, removing unused arg --- compiler/rustc_builtin_macros/src/autodiff.rs | 25 ++++--------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/autodiff.rs b/compiler/rustc_builtin_macros/src/autodiff.rs index bfddb450cd762..63f97f3ae29af 100644 --- a/compiler/rustc_builtin_macros/src/autodiff.rs +++ b/compiler/rustc_builtin_macros/src/autodiff.rs @@ -233,20 +233,8 @@ mod llvm_enzyme { .filter(|a| **a == DiffActivity::Active || **a == DiffActivity::ActiveOnly) .count() as u32; let (d_sig, new_args, idents, errored) = gen_enzyme_decl(ecx, &sig, &x, span); - let new_decl_span = d_sig.span; let d_body = gen_enzyme_body( - ecx, - &x, - n_active, - &sig, - &d_sig, - primal, - &new_args, - span, - sig_span, - new_decl_span, - idents, - errored, + ecx, &x, n_active, &sig, &d_sig, primal, &new_args, span, sig_span, idents, errored, ); let d_ident = first_ident(&meta_item_vec[0]); @@ -440,12 +428,10 @@ mod llvm_enzyme { /// We only want this function to type-check, since we will replace the body /// later on llvm level. Using `loop {}` does not cover all return types anymore, - /// so instead we build something that should pass. We also add a inline_asm - /// line, as one more barrier for rustc to prevent inlining of this function. - /// FIXME(ZuseZ4): We still have cases of incorrect inlining across modules, see - /// , so this isn't sufficient. - /// It also triggers an Enzyme crash if we due to a bug ever try to differentiate - /// this function (which should never happen, since it is only a placeholder). + /// so instead we manually build something that should pass the type checker. + /// We also add a inline_asm line, as one more barrier for rustc to prevent inlining + /// or const propagation. inline_asm will also triggers an Enzyme crash if due to another + /// bug would ever try to accidentially differentiate this placeholder function body. /// Finally, we also add back_box usages of all input arguments, to prevent rustc /// from optimizing any arguments away. fn gen_enzyme_body( @@ -458,7 +444,6 @@ mod llvm_enzyme { new_names: &[String], span: Span, sig_span: Span, - _new_decl_span: Span, idents: Vec, errored: bool, ) -> P { From a3669b89825e6f1aabaa3e3993c1a9f9d7b70306 Mon Sep 17 00:00:00 2001 From: "aaishwarymishra@gmail.com" Date: Wed, 12 Mar 2025 16:54:14 +0530 Subject: [PATCH 10/20] updated compiler tests for rustc_intrinsic' Update compiler/rustc_error_codes/src/error_codes/E0622.md Co-authored-by: Ralf Jung reverted chages on E0622.md updated E0622.md --- compiler/rustc_error_codes/src/error_codes/E0092.md | 12 +++++------- compiler/rustc_error_codes/src/error_codes/E0093.md | 10 ++++------ compiler/rustc_error_codes/src/error_codes/E0211.md | 10 ++++------ compiler/rustc_error_codes/src/error_codes/E0511.md | 10 ++++------ 4 files changed, 17 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_error_codes/src/error_codes/E0092.md b/compiler/rustc_error_codes/src/error_codes/E0092.md index 84ec0656d1ac1..be459d040c28d 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0092.md +++ b/compiler/rustc_error_codes/src/error_codes/E0092.md @@ -6,10 +6,9 @@ Erroneous code example: #![feature(intrinsics)] #![allow(internal_features)] -extern "rust-intrinsic" { - fn atomic_foo(); // error: unrecognized atomic operation - // function -} +#[rustc_intrinsic] +unsafe fn atomic_foo(); // error: unrecognized atomic operation + // function ``` Please check you didn't make a mistake in the function's name. All intrinsic @@ -20,7 +19,6 @@ functions are defined in `compiler/rustc_codegen_llvm/src/intrinsic.rs` and in #![feature(intrinsics)] #![allow(internal_features)] -extern "rust-intrinsic" { - fn atomic_fence_seqcst(); // ok! -} +#[rustc_intrinsic] +unsafe fn atomic_fence_seqcst(); // ok! ``` diff --git a/compiler/rustc_error_codes/src/error_codes/E0093.md b/compiler/rustc_error_codes/src/error_codes/E0093.md index 2bda4d74f726d..9929a0699273d 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0093.md +++ b/compiler/rustc_error_codes/src/error_codes/E0093.md @@ -6,9 +6,8 @@ Erroneous code example: #![feature(intrinsics)] #![allow(internal_features)] -extern "rust-intrinsic" { - fn foo(); // error: unrecognized intrinsic function: `foo` -} +#[rustc_intrinsic] +unsafe fn foo(); // error: unrecognized intrinsic function: `foo` fn main() { unsafe { @@ -25,9 +24,8 @@ functions are defined in `compiler/rustc_codegen_llvm/src/intrinsic.rs` and in #![feature(intrinsics)] #![allow(internal_features)] -extern "rust-intrinsic" { - fn atomic_fence_seqcst(); // ok! -} +#[rustc_intrinsic] +unsafe fn atomic_fence_seqcst(); // ok! fn main() { unsafe { diff --git a/compiler/rustc_error_codes/src/error_codes/E0211.md b/compiler/rustc_error_codes/src/error_codes/E0211.md index 7aa42628549f8..c702f14d4d6d4 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0211.md +++ b/compiler/rustc_error_codes/src/error_codes/E0211.md @@ -7,9 +7,8 @@ used. Erroneous code examples: #![feature(intrinsics)] #![allow(internal_features)] -extern "rust-intrinsic" { - fn unreachable(); // error: intrinsic has wrong type -} +#[rustc_intrinsic] +unsafe fn unreachable(); // error: intrinsic has wrong type // or: @@ -43,9 +42,8 @@ For the first code example, please check the function definition. Example: #![feature(intrinsics)] #![allow(internal_features)] -extern "rust-intrinsic" { - fn unreachable() -> !; // ok! -} +#[rustc_intrinsic] +unsafe fn unreachable() -> !; // ok! ``` The second case example is a bit particular: the main function must always diff --git a/compiler/rustc_error_codes/src/error_codes/E0511.md b/compiler/rustc_error_codes/src/error_codes/E0511.md index 45ff49bdebb29..0fb1cfda67dc6 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0511.md +++ b/compiler/rustc_error_codes/src/error_codes/E0511.md @@ -5,9 +5,8 @@ Erroneous code example: ```compile_fail,E0511 #![feature(intrinsics)] -extern "rust-intrinsic" { - fn simd_add(a: T, b: T) -> T; -} +#[rustc_intrinsic] +unsafe fn simd_add(a: T, b: T) -> T; fn main() { unsafe { simd_add(0, 1); } @@ -25,9 +24,8 @@ The generic type has to be a SIMD type. Example: #[derive(Copy, Clone)] struct i32x2([i32; 2]); -extern "rust-intrinsic" { - fn simd_add(a: T, b: T) -> T; -} +#[rustc_intrinsic] +unsafe fn simd_add(a: T, b: T) -> T; unsafe { simd_add(i32x2([0, 0]), i32x2([1, 2])); } // ok! ``` From 599dc823c9d7049e8ee9eb80203a24cac41cb124 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sun, 16 Mar 2025 13:23:41 +0100 Subject: [PATCH 11/20] Simplify `get_git_modified_files` It only ever returned `Some`, so `Option` was useless in its return type. --- src/bootstrap/src/core/build_steps/format.rs | 2 +- src/build_helper/src/git.rs | 4 ++-- src/tools/compiletest/src/lib.rs | 3 +-- src/tools/suggest-tests/src/main.rs | 6 +----- 4 files changed, 5 insertions(+), 10 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs index 9817e47baa101..3435c1773c276 100644 --- a/src/bootstrap/src/core/build_steps/format.rs +++ b/src/bootstrap/src/core/build_steps/format.rs @@ -94,7 +94,7 @@ fn get_modified_rs_files(build: &Builder<'_>) -> Result>, Str return Ok(None); } - get_git_modified_files(&build.config.git_config(), Some(&build.config.src), &["rs"]) + get_git_modified_files(&build.config.git_config(), Some(&build.config.src), &["rs"]).map(Some) } #[derive(serde_derive::Deserialize)] diff --git a/src/build_helper/src/git.rs b/src/build_helper/src/git.rs index 9f778a2fd7742..ea473c8c3976a 100644 --- a/src/build_helper/src/git.rs +++ b/src/build_helper/src/git.rs @@ -173,7 +173,7 @@ pub fn get_git_modified_files( config: &GitConfig<'_>, git_dir: Option<&Path>, extensions: &[&str], -) -> Result>, String> { +) -> Result, String> { let merge_base = get_closest_merge_commit(git_dir, config, &[])?; let mut git = Command::new("git"); @@ -195,7 +195,7 @@ pub fn get_git_modified_files( } }) .collect(); - Ok(Some(files)) + Ok(files) } /// Returns the files that haven't been added to git yet. diff --git a/src/tools/compiletest/src/lib.rs b/src/tools/compiletest/src/lib.rs index dd611b19a8d0d..3ec984edacbe8 100644 --- a/src/tools/compiletest/src/lib.rs +++ b/src/tools/compiletest/src/lib.rs @@ -747,8 +747,7 @@ fn modified_tests(config: &Config, dir: &Path) -> Result, String> { } let files = - get_git_modified_files(&config.git_config(), Some(dir), &vec!["rs", "stderr", "fixed"])? - .unwrap_or(vec![]); + get_git_modified_files(&config.git_config(), Some(dir), &vec!["rs", "stderr", "fixed"])?; // Add new test cases to the list, it will be convenient in daily development. let untracked_files = get_git_untracked_files(&config.git_config(), None)?.unwrap_or(vec![]); diff --git a/src/tools/suggest-tests/src/main.rs b/src/tools/suggest-tests/src/main.rs index ee8cc40404d49..ee212af36260a 100644 --- a/src/tools/suggest-tests/src/main.rs +++ b/src/tools/suggest-tests/src/main.rs @@ -14,11 +14,7 @@ fn main() -> ExitCode { &Vec::new(), ); let modified_files = match modified_files { - Ok(Some(files)) => files, - Ok(None) => { - eprintln!("git error"); - return ExitCode::FAILURE; - } + Ok(files) => files, Err(err) => { eprintln!("Could not get modified files from git: \"{err}\""); return ExitCode::FAILURE; From 2139a783b0c08f6d2718d88112bc50988006daab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sun, 16 Mar 2025 13:26:30 +0100 Subject: [PATCH 12/20] Fix bug in `get_git_modified_files` It was ignoring files without extension. --- src/build_helper/src/git.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/build_helper/src/git.rs b/src/build_helper/src/git.rs index ea473c8c3976a..8d737450444a0 100644 --- a/src/build_helper/src/git.rs +++ b/src/build_helper/src/git.rs @@ -186,7 +186,10 @@ pub fn get_git_modified_files( let (status, name) = f.trim().split_once(char::is_whitespace).unwrap(); if status == "D" { None - } else if Path::new(name).extension().map_or(false, |ext| { + } else if Path::new(name).extension().map_or(extensions.is_empty(), |ext| { + // If there is no extension, we allow the path if `extensions` is empty + // If there is an extension, we allow it if `extension` is empty or it contains the + // extension. extensions.is_empty() || extensions.contains(&ext.to_str().unwrap()) }) { Some(name.to_owned()) From b24dc75ee46c702404d6137e402f967876b0b68d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Wed, 19 Mar 2025 10:31:12 +0100 Subject: [PATCH 13/20] Respect `--src` bootstrap flag Previously it was simply ignored. --- src/bootstrap/src/core/config/config.rs | 94 +++++++++++++------------ 1 file changed, 49 insertions(+), 45 deletions(-) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index f8ed8072c3df7..88ed786582ee7 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -1425,52 +1425,56 @@ impl Config { // Infer the rest of the configuration. - // Infer the source directory. This is non-trivial because we want to support a downloaded bootstrap binary, - // running on a completely different machine from where it was compiled. - let mut cmd = helpers::git(None); - // NOTE: we cannot support running from outside the repository because the only other path we have available - // is set at compile time, which can be wrong if bootstrap was downloaded rather than compiled locally. - // We still support running outside the repository if we find we aren't in a git directory. - - // NOTE: We get a relative path from git to work around an issue on MSYS/mingw. If we used an absolute path, - // and end up using MSYS's git rather than git-for-windows, we would get a unix-y MSYS path. But as bootstrap - // has already been (kinda-cross-)compiled to Windows land, we require a normal Windows path. - cmd.arg("rev-parse").arg("--show-cdup"); - // Discard stderr because we expect this to fail when building from a tarball. - let output = cmd - .as_command_mut() - .stderr(std::process::Stdio::null()) - .output() - .ok() - .and_then(|output| if output.status.success() { Some(output) } else { None }); - if let Some(output) = output { - let git_root_relative = String::from_utf8(output.stdout).unwrap(); - // We need to canonicalize this path to make sure it uses backslashes instead of forward slashes, - // and to resolve any relative components. - let git_root = env::current_dir() - .unwrap() - .join(PathBuf::from(git_root_relative.trim())) - .canonicalize() - .unwrap(); - let s = git_root.to_str().unwrap(); - - // Bootstrap is quite bad at handling /? in front of paths - let git_root = match s.strip_prefix("\\\\?\\") { - Some(p) => PathBuf::from(p), - None => git_root, - }; - // If this doesn't have at least `stage0`, we guessed wrong. This can happen when, - // for example, the build directory is inside of another unrelated git directory. - // In that case keep the original `CARGO_MANIFEST_DIR` handling. - // - // NOTE: this implies that downloadable bootstrap isn't supported when the build directory is outside - // the source directory. We could fix that by setting a variable from all three of python, ./x, and x.ps1. - if git_root.join("src").join("stage0").exists() { - config.src = git_root; - } + if let Some(src) = flags.src { + config.src = src } else { - // We're building from a tarball, not git sources. - // We don't support pre-downloaded bootstrap in this case. + // Infer the source directory. This is non-trivial because we want to support a downloaded bootstrap binary, + // running on a completely different machine from where it was compiled. + let mut cmd = helpers::git(None); + // NOTE: we cannot support running from outside the repository because the only other path we have available + // is set at compile time, which can be wrong if bootstrap was downloaded rather than compiled locally. + // We still support running outside the repository if we find we aren't in a git directory. + + // NOTE: We get a relative path from git to work around an issue on MSYS/mingw. If we used an absolute path, + // and end up using MSYS's git rather than git-for-windows, we would get a unix-y MSYS path. But as bootstrap + // has already been (kinda-cross-)compiled to Windows land, we require a normal Windows path. + cmd.arg("rev-parse").arg("--show-cdup"); + // Discard stderr because we expect this to fail when building from a tarball. + let output = cmd + .as_command_mut() + .stderr(std::process::Stdio::null()) + .output() + .ok() + .and_then(|output| if output.status.success() { Some(output) } else { None }); + if let Some(output) = output { + let git_root_relative = String::from_utf8(output.stdout).unwrap(); + // We need to canonicalize this path to make sure it uses backslashes instead of forward slashes, + // and to resolve any relative components. + let git_root = env::current_dir() + .unwrap() + .join(PathBuf::from(git_root_relative.trim())) + .canonicalize() + .unwrap(); + let s = git_root.to_str().unwrap(); + + // Bootstrap is quite bad at handling /? in front of paths + let git_root = match s.strip_prefix("\\\\?\\") { + Some(p) => PathBuf::from(p), + None => git_root, + }; + // If this doesn't have at least `stage0`, we guessed wrong. This can happen when, + // for example, the build directory is inside of another unrelated git directory. + // In that case keep the original `CARGO_MANIFEST_DIR` handling. + // + // NOTE: this implies that downloadable bootstrap isn't supported when the build directory is outside + // the source directory. We could fix that by setting a variable from all three of python, ./x, and x.ps1. + if git_root.join("src").join("stage0").exists() { + config.src = git_root; + } + } else { + // We're building from a tarball, not git sources. + // We don't support pre-downloaded bootstrap in this case. + } } if cfg!(test) { From 9b88fd09d73b3808d8ff5a8cf3d68a0ca5ac1ca0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Wed, 19 Mar 2025 15:35:47 +0100 Subject: [PATCH 14/20] Update GCC submodule --- src/gcc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gcc b/src/gcc index 48664a6cab29d..13cc8243226a9 160000 --- a/src/gcc +++ b/src/gcc @@ -1 +1 @@ -Subproject commit 48664a6cab29d48138ffa004b7978d52ef73e3ac +Subproject commit 13cc8243226a9028bb08ab6c5e1c5fe6d533bcdf From 7c085f7ffdf731175430b908bc11bd97282cff9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jana=20D=C3=B6nszelmann?= Date: Wed, 19 Mar 2025 17:29:31 +0100 Subject: [PATCH 15/20] add rustc_macro_edition_2021 --- .../src/attributes.rs | 1 + .../rustc_attr_data_structures/src/lib.rs | 11 ++++------- .../rustc_attr_parsing/src/attributes/mod.rs | 1 + .../src/attributes/rustc.rs | 19 +++++++++++++++++++ compiler/rustc_attr_parsing/src/context.rs | 2 ++ compiler/rustc_feature/src/builtin_attrs.rs | 8 ++++++++ compiler/rustc_resolve/src/macros.rs | 6 +++++- compiler/rustc_span/src/symbol.rs | 1 + library/core/src/pin.rs | 1 + library/coretests/tests/pin.rs | 13 +++++++++++++ 10 files changed, 55 insertions(+), 8 deletions(-) create mode 100644 compiler/rustc_attr_parsing/src/attributes/rustc.rs diff --git a/compiler/rustc_attr_data_structures/src/attributes.rs b/compiler/rustc_attr_data_structures/src/attributes.rs index d2d1285b0756f..969bce7ae20a6 100644 --- a/compiler/rustc_attr_data_structures/src/attributes.rs +++ b/compiler/rustc_attr_data_structures/src/attributes.rs @@ -191,6 +191,7 @@ pub enum AttributeKind { }, MacroTransparency(Transparency), Repr(ThinVec<(ReprAttr, Span)>), + RustcMacroEdition2021, Stability { stability: Stability, /// Span of the `#[stable(...)]` or `#[unstable(...)]` attribute diff --git a/compiler/rustc_attr_data_structures/src/lib.rs b/compiler/rustc_attr_data_structures/src/lib.rs index bbd3308809c33..c61b44b273de5 100644 --- a/compiler/rustc_attr_data_structures/src/lib.rs +++ b/compiler/rustc_attr_data_structures/src/lib.rs @@ -182,21 +182,18 @@ macro_rules! find_attr { }}; ($attributes_list: expr, $pattern: pat $(if $guard: expr)? => $e: expr) => {{ - fn check_attribute_iterator<'a>(_: &'_ impl IntoIterator) {} - check_attribute_iterator(&$attributes_list); - - let find_attribute = |iter| { + 'done: { for i in $attributes_list { + let i: &rustc_hir::Attribute = i; match i { rustc_hir::Attribute::Parsed($pattern) $(if $guard)? => { - return Some($e); + break 'done Some($e); } _ => {} } } None - }; - find_attribute($attributes_list) + } }}; } diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs index 6ecd6b4d7dbb7..bac111159db53 100644 --- a/compiler/rustc_attr_parsing/src/attributes/mod.rs +++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs @@ -28,6 +28,7 @@ pub(crate) mod cfg; pub(crate) mod confusables; pub(crate) mod deprecation; pub(crate) mod repr; +pub(crate) mod rustc; pub(crate) mod stability; pub(crate) mod transparency; pub(crate) mod util; diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc.rs b/compiler/rustc_attr_parsing/src/attributes/rustc.rs new file mode 100644 index 0000000000000..bdd3bef2834bb --- /dev/null +++ b/compiler/rustc_attr_parsing/src/attributes/rustc.rs @@ -0,0 +1,19 @@ +use rustc_attr_data_structures::AttributeKind; +use rustc_span::sym; + +use super::{AcceptContext, SingleAttributeParser}; +use crate::parser::ArgParser; + +pub(crate) struct RustcMacroEdition2021Parser; + +// FIXME(jdonszelmann): make these proper diagnostics +impl SingleAttributeParser for RustcMacroEdition2021Parser { + const PATH: &'static [rustc_span::Symbol] = &[sym::rustc_macro_edition_2021]; + + fn on_duplicate(_cx: &crate::context::AcceptContext<'_>, _first_span: rustc_span::Span) {} + + fn convert(_cx: &AcceptContext<'_>, args: &ArgParser<'_>) -> Option { + assert!(args.no_args()); + Some(AttributeKind::RustcMacroEdition2021) + } +} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 35541bb04bd7b..a68d4578b40f7 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -15,6 +15,7 @@ use crate::attributes::allow_unstable::{AllowConstFnUnstableParser, AllowInterna use crate::attributes::confusables::ConfusablesParser; use crate::attributes::deprecation::DeprecationParser; use crate::attributes::repr::ReprParser; +use crate::attributes::rustc::RustcMacroEdition2021Parser; use crate::attributes::stability::{ BodyStabilityParser, ConstStabilityIndirectParser, ConstStabilityParser, StabilityParser, }; @@ -76,6 +77,7 @@ attribute_groups!( // tidy-alphabetical-start Single, Single, + Single, Single, // tidy-alphabetical-end ]; diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 40857e0066ee5..2511ae610f8d3 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -661,6 +661,14 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ "`rustc_never_type_options` is used to experiment with never type fallback and work on \ never type stabilization, and will never be stable" ), + rustc_attr!( + rustc_macro_edition_2021, + Normal, + template!(Word), + ErrorFollowing, + EncodeCrossCrate::No, + "makes spans in this macro edition 2021" + ), // ========================================================================== // Internal attributes: Runtime related: diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 7100d89ad61a8..5bb6ec3e7ced7 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -8,7 +8,7 @@ use std::sync::Arc; use rustc_ast::expand::StrippedCfgItem; use rustc_ast::{self as ast, Crate, NodeId, attr}; use rustc_ast_pretty::pprust; -use rustc_attr_parsing::StabilityLevel; +use rustc_attr_parsing::{AttributeKind, StabilityLevel, find_attr}; use rustc_data_structures::intern::Interned; use rustc_errors::{Applicability, StashKey}; use rustc_expand::base::{ @@ -1125,6 +1125,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { edition, ); + if find_attr!(attrs.iter(), AttributeKind::RustcMacroEdition2021 {}) { + ext.edition = Edition::Edition2021; + } + if let Some(builtin_name) = ext.builtin_name { // The macro was marked with `#[rustc_builtin_macro]`. if let Some(builtin_macro) = self.builtin_macros.get_mut(&builtin_name) { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 8a8bec35d8194..31d9ad104386f 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1793,6 +1793,7 @@ symbols! { rustc_lint_opt_ty, rustc_lint_query_instability, rustc_lint_untracked_query_information, + rustc_macro_edition_2021, rustc_macro_transparency, rustc_main, rustc_mir, diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index 7fcd19f67ee2d..bc097bf198d03 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -1943,6 +1943,7 @@ unsafe impl PinCoerceUnsized for *mut T {} #[stable(feature = "pin_macro", since = "1.68.0")] #[rustc_macro_transparency = "semitransparent"] #[allow_internal_unstable(unsafe_pin_internals)] +#[cfg_attr(not(bootstrap), rustc_macro_edition_2021)] pub macro pin($value:expr $(,)?) { // This is `Pin::new_unchecked(&mut { $value })`, so, for starters, let's // review such a hypothetical macro (that any user-code could define): diff --git a/library/coretests/tests/pin.rs b/library/coretests/tests/pin.rs index b3fb06e710d44..d31b24144e2ac 100644 --- a/library/coretests/tests/pin.rs +++ b/library/coretests/tests/pin.rs @@ -81,3 +81,16 @@ mod pin_coerce_unsized { arg } } + +#[test] +fn spans_2021() { + // Check that we accept a Rust 2024 $expr. + std::pin::pin!(const { 1 }); + + // Check that temporary lifetimes work as in Rust 2021. + match std::pin::pin!(foo(&mut 0)) { + _f => {} + } +} + +async fn foo(_: &mut usize) {} From 93d5ca82b0b1e9cb3aff5939b2a10731caea32f1 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Wed, 19 Mar 2025 17:42:43 +0100 Subject: [PATCH 16/20] Pin tests. --- library/coretests/tests/pin.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/library/coretests/tests/pin.rs b/library/coretests/tests/pin.rs index d31b24144e2ac..43f0448f00641 100644 --- a/library/coretests/tests/pin.rs +++ b/library/coretests/tests/pin.rs @@ -34,6 +34,9 @@ fn pin_const() { } pin_mut_const(); + + // Check that we accept a Rust 2024 $expr. + std::pin::pin!(const { 1 }); } #[allow(unused)] @@ -83,14 +86,11 @@ mod pin_coerce_unsized { } #[test] -fn spans_2021() { - // Check that we accept a Rust 2024 $expr. - std::pin::pin!(const { 1 }); - +fn temp_lifetime() { // Check that temporary lifetimes work as in Rust 2021. + // Regression test for https://github.com/rust-lang/rust/issues/138596 match std::pin::pin!(foo(&mut 0)) { - _f => {} + _ => {} } + async fn foo(_: &mut usize) {} } - -async fn foo(_: &mut usize) {} From 25896cc668ebb652d38e0a1d69a0f983e0b3408e Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Wed, 19 Mar 2025 18:08:23 +0100 Subject: [PATCH 17/20] Add cfg(not(bootstrap)) for new test. --- library/coretests/tests/pin.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/coretests/tests/pin.rs b/library/coretests/tests/pin.rs index 43f0448f00641..a866cf12a3bbf 100644 --- a/library/coretests/tests/pin.rs +++ b/library/coretests/tests/pin.rs @@ -86,6 +86,7 @@ mod pin_coerce_unsized { } #[test] +#[cfg(not(bootstrap))] fn temp_lifetime() { // Check that temporary lifetimes work as in Rust 2021. // Regression test for https://github.com/rust-lang/rust/issues/138596 From 20432c9eee4d22047994f1e334a639c891535aa9 Mon Sep 17 00:00:00 2001 From: Jesus Checa Hidalgo Date: Wed, 19 Mar 2025 19:29:08 +0100 Subject: [PATCH 18/20] Use explicit cpu in some asm and codegen tests. Some tests expect to be compiled for a specific CPU or require certain target features to be present (or absent). These tests work fine with default CPUs but fail in downstream builds for RHEL and Fedora, where we use non-default CPUs such as z13 on s390x, pwr9 on ppc64le, or x86-64-v2/x86-64-v3 on x86_64. --- tests/assembly/powerpc64-struct-abi.rs | 2 +- tests/assembly/s390x-vector-abi.rs | 4 +-- tests/codegen/asm/s390x-clobbers.rs | 2 +- tests/codegen/slice-is-ascii.rs | 2 +- tests/ui/abi/simd-abi-checks-avx.rs | 1 + tests/ui/abi/simd-abi-checks-avx.stderr | 44 ++++++++++++------------- tests/ui/abi/simd-abi-checks-s390x.rs | 2 +- 7 files changed, 29 insertions(+), 28 deletions(-) diff --git a/tests/assembly/powerpc64-struct-abi.rs b/tests/assembly/powerpc64-struct-abi.rs index eb27afc4f23c6..ee4965deb4fdc 100644 --- a/tests/assembly/powerpc64-struct-abi.rs +++ b/tests/assembly/powerpc64-struct-abi.rs @@ -6,7 +6,7 @@ //@[elfv1-be] needs-llvm-components: powerpc //@[elfv2-be] compile-flags: --target powerpc64-unknown-linux-musl //@[elfv2-be] needs-llvm-components: powerpc -//@[elfv2-le] compile-flags: --target powerpc64le-unknown-linux-gnu +//@[elfv2-le] compile-flags: --target powerpc64le-unknown-linux-gnu -C target-cpu=pwr8 //@[elfv2-le] needs-llvm-components: powerpc //@[aix] compile-flags: --target powerpc64-ibm-aix //@[aix] needs-llvm-components: powerpc diff --git a/tests/assembly/s390x-vector-abi.rs b/tests/assembly/s390x-vector-abi.rs index 7d86559c0026d..e159a3576850e 100644 --- a/tests/assembly/s390x-vector-abi.rs +++ b/tests/assembly/s390x-vector-abi.rs @@ -2,9 +2,9 @@ // ignore-tidy-linelength //@ assembly-output: emit-asm //@ compile-flags: -Copt-level=3 -Z merge-functions=disabled -//@[z10] compile-flags: --target s390x-unknown-linux-gnu --cfg no_vector +//@[z10] compile-flags: --target s390x-unknown-linux-gnu -C target-cpu=z10 --cfg no_vector //@[z10] needs-llvm-components: systemz -//@[z10_vector] compile-flags: --target s390x-unknown-linux-gnu -C target-feature=+vector +//@[z10_vector] compile-flags: --target s390x-unknown-linux-gnu -C target-cpu=z10 -C target-feature=+vector //@[z10_vector] needs-llvm-components: systemz //@[z13] compile-flags: --target s390x-unknown-linux-gnu -C target-cpu=z13 //@[z13] needs-llvm-components: systemz diff --git a/tests/codegen/asm/s390x-clobbers.rs b/tests/codegen/asm/s390x-clobbers.rs index cbb6630553cfa..0ba22a32abf38 100644 --- a/tests/codegen/asm/s390x-clobbers.rs +++ b/tests/codegen/asm/s390x-clobbers.rs @@ -1,6 +1,6 @@ //@ add-core-stubs //@ revisions: s390x -//@[s390x] compile-flags: --target s390x-unknown-linux-gnu +//@[s390x] compile-flags: --target s390x-unknown-linux-gnu -C target-cpu=z10 //@[s390x] needs-llvm-components: systemz #![crate_type = "rlib"] diff --git a/tests/codegen/slice-is-ascii.rs b/tests/codegen/slice-is-ascii.rs index b1e97154609b2..67537c871a0a3 100644 --- a/tests/codegen/slice-is-ascii.rs +++ b/tests/codegen/slice-is-ascii.rs @@ -1,5 +1,5 @@ //@ only-x86_64 -//@ compile-flags: -C opt-level=3 +//@ compile-flags: -C opt-level=3 -C target-cpu=x86-64 #![crate_type = "lib"] /// Check that the fast-path of `is_ascii` uses a `pmovmskb` instruction. diff --git a/tests/ui/abi/simd-abi-checks-avx.rs b/tests/ui/abi/simd-abi-checks-avx.rs index acab74300b8f6..fa4b3ba3054f1 100644 --- a/tests/ui/abi/simd-abi-checks-avx.rs +++ b/tests/ui/abi/simd-abi-checks-avx.rs @@ -1,6 +1,7 @@ //@ only-x86_64 //@ build-pass //@ ignore-pass (test emits codegen-time warnings) +//@ compile-flags: -C target-feature=-avx #![feature(avx512_target_feature)] #![feature(portable_simd)] diff --git a/tests/ui/abi/simd-abi-checks-avx.stderr b/tests/ui/abi/simd-abi-checks-avx.stderr index 0dddc7dfa1c1b..5419970f8093b 100644 --- a/tests/ui/abi/simd-abi-checks-avx.stderr +++ b/tests/ui/abi/simd-abi-checks-avx.stderr @@ -1,5 +1,5 @@ warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller - --> $DIR/simd-abi-checks-avx.rs:64:11 + --> $DIR/simd-abi-checks-avx.rs:65:11 | LL | f(g()); | ^^^ function called here @@ -10,7 +10,7 @@ LL | f(g()); = note: `#[warn(abi_unsupported_vector_types)]` on by default warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller - --> $DIR/simd-abi-checks-avx.rs:64:9 + --> $DIR/simd-abi-checks-avx.rs:65:9 | LL | f(g()); | ^^^^^^ function called here @@ -20,7 +20,7 @@ LL | f(g()); = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`) warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller - --> $DIR/simd-abi-checks-avx.rs:72:14 + --> $DIR/simd-abi-checks-avx.rs:73:14 | LL | gavx(favx()); | ^^^^^^ function called here @@ -30,7 +30,7 @@ LL | gavx(favx()); = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`) warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller - --> $DIR/simd-abi-checks-avx.rs:72:9 + --> $DIR/simd-abi-checks-avx.rs:73:9 | LL | gavx(favx()); | ^^^^^^^^^^^^ function called here @@ -40,7 +40,7 @@ LL | gavx(favx()); = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`) warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller - --> $DIR/simd-abi-checks-avx.rs:84:19 + --> $DIR/simd-abi-checks-avx.rs:85:19 | LL | w(Wrapper(g())); | ^^^ function called here @@ -50,7 +50,7 @@ LL | w(Wrapper(g())); = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`) warning: this function call uses SIMD vector type `Wrapper` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller - --> $DIR/simd-abi-checks-avx.rs:84:9 + --> $DIR/simd-abi-checks-avx.rs:85:9 | LL | w(Wrapper(g())); | ^^^^^^^^^^^^^^^ function called here @@ -60,7 +60,7 @@ LL | w(Wrapper(g())); = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`) warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller - --> $DIR/simd-abi-checks-avx.rs:100:9 + --> $DIR/simd-abi-checks-avx.rs:101:9 | LL | some_extern(); | ^^^^^^^^^^^^^ function called here @@ -70,7 +70,7 @@ LL | some_extern(); = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`) warning: this function definition uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled - --> $DIR/simd-abi-checks-avx.rs:27:1 + --> $DIR/simd-abi-checks-avx.rs:28:1 | LL | unsafe extern "C" fn g() -> __m256 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -80,7 +80,7 @@ LL | unsafe extern "C" fn g() -> __m256 { = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`) warning: this function definition uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled - --> $DIR/simd-abi-checks-avx.rs:21:1 + --> $DIR/simd-abi-checks-avx.rs:22:1 | LL | unsafe extern "C" fn f(_: __m256) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -90,7 +90,7 @@ LL | unsafe extern "C" fn f(_: __m256) { = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`) warning: this function definition uses SIMD vector type `Wrapper` which (with the chosen ABI) requires the `avx` target feature, which is not enabled - --> $DIR/simd-abi-checks-avx.rs:15:1 + --> $DIR/simd-abi-checks-avx.rs:16:1 | LL | unsafe extern "C" fn w(_: Wrapper) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -100,7 +100,7 @@ LL | unsafe extern "C" fn w(_: Wrapper) { = help: consider enabling it globally (`-C target-feature=+avx`) or locally (`#[target_feature(enable="avx")]`) warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller - --> $DIR/simd-abi-checks-avx.rs:57:8 + --> $DIR/simd-abi-checks-avx.rs:58:8 | LL | || g() | ^^^ function called here @@ -113,7 +113,7 @@ warning: 11 warnings emitted Future incompatibility report: Future breakage diagnostic: warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller - --> $DIR/simd-abi-checks-avx.rs:64:11 + --> $DIR/simd-abi-checks-avx.rs:65:11 | LL | f(g()); | ^^^ function called here @@ -125,7 +125,7 @@ LL | f(g()); Future breakage diagnostic: warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller - --> $DIR/simd-abi-checks-avx.rs:64:9 + --> $DIR/simd-abi-checks-avx.rs:65:9 | LL | f(g()); | ^^^^^^ function called here @@ -137,7 +137,7 @@ LL | f(g()); Future breakage diagnostic: warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller - --> $DIR/simd-abi-checks-avx.rs:72:14 + --> $DIR/simd-abi-checks-avx.rs:73:14 | LL | gavx(favx()); | ^^^^^^ function called here @@ -149,7 +149,7 @@ LL | gavx(favx()); Future breakage diagnostic: warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller - --> $DIR/simd-abi-checks-avx.rs:72:9 + --> $DIR/simd-abi-checks-avx.rs:73:9 | LL | gavx(favx()); | ^^^^^^^^^^^^ function called here @@ -161,7 +161,7 @@ LL | gavx(favx()); Future breakage diagnostic: warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller - --> $DIR/simd-abi-checks-avx.rs:84:19 + --> $DIR/simd-abi-checks-avx.rs:85:19 | LL | w(Wrapper(g())); | ^^^ function called here @@ -173,7 +173,7 @@ LL | w(Wrapper(g())); Future breakage diagnostic: warning: this function call uses SIMD vector type `Wrapper` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller - --> $DIR/simd-abi-checks-avx.rs:84:9 + --> $DIR/simd-abi-checks-avx.rs:85:9 | LL | w(Wrapper(g())); | ^^^^^^^^^^^^^^^ function called here @@ -185,7 +185,7 @@ LL | w(Wrapper(g())); Future breakage diagnostic: warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller - --> $DIR/simd-abi-checks-avx.rs:100:9 + --> $DIR/simd-abi-checks-avx.rs:101:9 | LL | some_extern(); | ^^^^^^^^^^^^^ function called here @@ -197,7 +197,7 @@ LL | some_extern(); Future breakage diagnostic: warning: this function definition uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled - --> $DIR/simd-abi-checks-avx.rs:27:1 + --> $DIR/simd-abi-checks-avx.rs:28:1 | LL | unsafe extern "C" fn g() -> __m256 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -209,7 +209,7 @@ LL | unsafe extern "C" fn g() -> __m256 { Future breakage diagnostic: warning: this function definition uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled - --> $DIR/simd-abi-checks-avx.rs:21:1 + --> $DIR/simd-abi-checks-avx.rs:22:1 | LL | unsafe extern "C" fn f(_: __m256) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -221,7 +221,7 @@ LL | unsafe extern "C" fn f(_: __m256) { Future breakage diagnostic: warning: this function definition uses SIMD vector type `Wrapper` which (with the chosen ABI) requires the `avx` target feature, which is not enabled - --> $DIR/simd-abi-checks-avx.rs:15:1 + --> $DIR/simd-abi-checks-avx.rs:16:1 | LL | unsafe extern "C" fn w(_: Wrapper) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function defined here @@ -233,7 +233,7 @@ LL | unsafe extern "C" fn w(_: Wrapper) { Future breakage diagnostic: warning: this function call uses SIMD vector type `std::arch::x86_64::__m256` which (with the chosen ABI) requires the `avx` target feature, which is not enabled in the caller - --> $DIR/simd-abi-checks-avx.rs:57:8 + --> $DIR/simd-abi-checks-avx.rs:58:8 | LL | || g() | ^^^ function called here diff --git a/tests/ui/abi/simd-abi-checks-s390x.rs b/tests/ui/abi/simd-abi-checks-s390x.rs index 424ac00edcfc5..3743c75bf1ed5 100644 --- a/tests/ui/abi/simd-abi-checks-s390x.rs +++ b/tests/ui/abi/simd-abi-checks-s390x.rs @@ -1,7 +1,7 @@ //@ add-core-stubs //@ revisions: z10 z13_no_vector z13_soft_float //@ build-fail -//@[z10] compile-flags: --target s390x-unknown-linux-gnu +//@[z10] compile-flags: --target s390x-unknown-linux-gnu -C target-cpu=z10 //@[z10] needs-llvm-components: systemz //@[z13_no_vector] compile-flags: --target s390x-unknown-linux-gnu -C target-cpu=z13 -C target-feature=-vector //@[z13_no_vector] needs-llvm-components: systemz From 0577300b414f43f2384fd4f29cd1f3ed0d406169 Mon Sep 17 00:00:00 2001 From: Mara Bos Date: Wed, 19 Mar 2025 21:51:03 +0100 Subject: [PATCH 19/20] Address review comments. --- compiler/rustc_resolve/src/macros.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 5bb6ec3e7ced7..a7cbc816b8361 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -1125,7 +1125,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { edition, ); - if find_attr!(attrs.iter(), AttributeKind::RustcMacroEdition2021 {}) { + // The #[rustc_macro_edition_2021] attribute is used by the pin!() macro + // as a temporary workaround for a regression in expressiveness in Rust 2024. + // See https://github.com/rust-lang/rust/issues/138718. + if find_attr!(attrs.iter(), AttributeKind::RustcMacroEdition2021) { ext.edition = Edition::Edition2021; } From cafd23896db923e5fc83a81bb0226307940e4dde Mon Sep 17 00:00:00 2001 From: Augie Fackler Date: Tue, 18 Mar 2025 11:11:51 -0400 Subject: [PATCH 20/20] tests: accept some noise from LLVM 21 in symbols-all-mangled I'm not entirely sure this is correct, but it doesn't feel obviously-wrong so I figured I'd just start by sending a PR rather than filing a bug and letting it linger. @rustbot label llvm-main --- tests/run-make/symbols-all-mangled/rmake.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/tests/run-make/symbols-all-mangled/rmake.rs b/tests/run-make/symbols-all-mangled/rmake.rs index 81f2678e55cd0..1fb03c62399a0 100644 --- a/tests/run-make/symbols-all-mangled/rmake.rs +++ b/tests/run-make/symbols-all-mangled/rmake.rs @@ -41,7 +41,13 @@ fn symbols_check_archive(path: &str) { continue; // Unfortunately LLVM doesn't allow us to mangle this symbol } - panic!("Unmangled symbol found: {name}"); + if name.contains(".llvm.") { + // Starting in LLVM 21 we get various implementation-detail functions which + // contain .llvm. that are not a problem. + continue; + } + + panic!("Unmangled symbol found in {path}: {name}"); } } @@ -75,7 +81,13 @@ fn symbols_check(path: &str) { continue; // Unfortunately LLVM doesn't allow us to mangle this symbol } - panic!("Unmangled symbol found: {name}"); + if name.contains(".llvm.") { + // Starting in LLVM 21 we get various implementation-detail functions which + // contain .llvm. that are not a problem. + continue; + } + + panic!("Unmangled symbol found in {path}: {name}"); } }