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_builtin_macros/src/autodiff.rs b/compiler/rustc_builtin_macros/src/autodiff.rs index dcd3c1ce8d917..6591ed151cf6e 100644 --- a/compiler/rustc_builtin_macros/src/autodiff.rs +++ b/compiler/rustc_builtin_macros/src/autodiff.rs @@ -26,6 +26,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 { @@ -224,20 +234,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]); @@ -270,36 +268,39 @@ 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 { + 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) @@ -314,13 +315,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 { @@ -361,30 +356,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, @@ -433,6 +425,51 @@ 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 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( + ecx: &ExtCtxt<'_>, + x: &AutoDiffAttrs, + n_active: u32, + sig: &ast::FnSig, + d_sig: &ast::FnSig, + primal: Ident, + new_names: &[String], + span: Span, + sig_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; @@ -444,7 +481,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; } @@ -536,11 +573,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)); @@ -553,7 +590,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 { diff --git a/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch b/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch index 754025ff49db3..34249ea483451 100644 --- a/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch +++ b/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch @@ -16,8 +16,8 @@ index 7165c3e48af..968552ad435 100644 [dependencies] core = { path = "../core", public = true } --compiler_builtins = { version = "=0.1.151", features = ['rustc-dep-of-std'] } -+compiler_builtins = { version = "=0.1.151", features = ['rustc-dep-of-std', 'no-f16-f128'] } +-compiler_builtins = { version = "=0.1.152", features = ['rustc-dep-of-std'] } ++compiler_builtins = { version = "=0.1.152", features = ['rustc-dep-of-std', 'no-f16-f128'] } [features] compiler-builtins-mem = ['compiler_builtins/mem'] diff --git a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs index 71705ecb4d0f5..7cd4ee539d875 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 @@ -43,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", @@ -132,111 +236,13 @@ 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)); - } - 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)); } - 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, &attrs.input_activity, &outer_args); let call = builder.call(enzyme_ty, ad_fn, &args, None); diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index d5972b5c9e649..d16d4ed228389 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -790,16 +790,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/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! ``` diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 5430bfde78554..fd936458f1115 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_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 3b75c69132c20..4707daea08910 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -566,6 +566,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 dca6f2959d2be..11a42f54b2ce7 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -600,7 +600,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { sym::repr, // code generation sym::cold, - sym::target_feature, // documentation sym::doc, ]; @@ -626,6 +625,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_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index c94846e95d424..c4304a7a6df6a 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,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { edition, ); + // 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; + } + if let Some(builtin_name) = ext.builtin_name { // The macro was marked with `#[rustc_builtin_macro]`. if let Some(builtin_ext_kind) = self.builtin_macros.get(&builtin_name) { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index d83863b1f7a8a..015ddc6e27330 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1376,6 +1376,7 @@ symbols! { naked, naked_asm, naked_functions, + naked_functions_target_feature, name, names, native_link_modifiers, @@ -1794,6 +1795,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/Cargo.lock b/library/Cargo.lock index 104e0a3d01079..6b1a0a080551f 100644 --- a/library/Cargo.lock +++ b/library/Cargo.lock @@ -67,9 +67,9 @@ dependencies = [ [[package]] name = "compiler_builtins" -version = "0.1.151" +version = "0.1.152" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abc30f1766d387c35f2405e586d3e7a88230dc728ff78cd1d0bc59ae0b63154b" +checksum = "2153cf213eb259361567720ce55f6446f17acd0ccca87fb6dc05360578228a58" dependencies = [ "cc", "rustc-std-workspace-core", diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml index 8d0253bd29aa2..b729d5e116d2c 100644 --- a/library/alloc/Cargo.toml +++ b/library/alloc/Cargo.toml @@ -16,7 +16,7 @@ bench = false [dependencies] core = { path = "../core", public = true } -compiler_builtins = { version = "=0.1.151", features = ['rustc-dep-of-std'] } +compiler_builtins = { version = "=0.1.152", features = ['rustc-dep-of-std'] } [features] compiler-builtins-mem = ['compiler_builtins/mem'] 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..a866cf12a3bbf 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)] @@ -81,3 +84,14 @@ mod pin_coerce_unsized { arg } } + +#[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 + match std::pin::pin!(foo(&mut 0)) { + _ => {} + } + async fn foo(_: &mut usize) {} +} diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 9d9601b79a7ed..176da603d58d7 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -18,7 +18,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] } panic_unwind = { path = "../panic_unwind", optional = true } panic_abort = { path = "../panic_abort" } core = { path = "../core", public = true } -compiler_builtins = { version = "=0.1.151" } +compiler_builtins = { version = "=0.1.152" } unwind = { path = "../unwind" } hashbrown = { version = "0.15", default-features = false, features = [ 'rustc-dep-of-std', 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/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. 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) { diff --git a/src/build_helper/src/git.rs b/src/build_helper/src/git.rs index 9f778a2fd7742..8d737450444a0 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"); @@ -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()) @@ -195,7 +198,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/gcc b/src/gcc index 48664a6cab29d..13cc8243226a9 160000 --- a/src/gcc +++ b/src/gcc @@ -1 +1 @@ -Subproject commit 48664a6cab29d48138ffa004b7978d52ef73e3ac +Subproject commit 13cc8243226a9028bb08ab6c5e1c5fe6d533bcdf 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; 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/pretty/autodiff_forward.pp b/tests/pretty/autodiff_forward.pp index 23c3b5b34a82a..dc7a2712f4231 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)); }; @@ -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") } 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!() } 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}"); } } 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 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`.