diff --git a/Cargo.lock b/Cargo.lock index 07de5d2216855..1cd998a0bd2f2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3613,6 +3613,7 @@ dependencies = [ "gimli 0.31.1", "itertools", "libc", + "libloading 0.9.0", "measureme", "object 0.37.3", "rustc-demangle", diff --git a/bootstrap.example.toml b/bootstrap.example.toml index 4e850810a30a9..63bf50722ca09 100644 --- a/bootstrap.example.toml +++ b/bootstrap.example.toml @@ -191,6 +191,31 @@ # Currently, this is only supported for the `x86_64-unknown-linux-gnu` target. #gcc.download-ci-gcc = false +# Provide a directory of prebuilt libgccjit.so dylibs for given (host, target) compilation pairs. +# This is useful when you want to cross-compile `rustc` to another target since GCC is not a +# multi-target compiler. +# You have to use a directory structure that looks like this: +# `///libgccjit.so`. +# For example: +# +# ``` +# +# ├── m68k-unknown-linux-gnu +# │ └── m68k-unknown-linux-gnu +# │ └── libgccjit.so +# └── x86_64-unknown-linux-gnu +# ├── m68k-unknown-linux-gnu +# │ └── libgccjit.so +# └── x86_64-unknown-linux-gnu +# └── libgccjit.so +# ``` +# The directory above would allow you to cross-compile rustc from x64 to m68k +# +# Note that this option has priority over `gcc.download-ci-gcc`. +# If you set both, bootstrap will first try to load libgccjit.so from this directory. +# Only if it isn't found, it will try to download it from CI or build it locally. +#gcc.libgccjit-libs-dir = "/path/to/libgccjit-libs-dir" + # ============================================================================= # General build configuration options # ============================================================================= diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 10093da97fe34..d0871b0b98f45 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -237,25 +237,27 @@ impl SpanLowerer { #[extension(trait ResolverAstLoweringExt)] impl ResolverAstLowering { fn legacy_const_generic_args(&self, expr: &Expr) -> Option> { - if let ExprKind::Path(None, path) = &expr.kind { - // Don't perform legacy const generics rewriting if the path already - // has generic arguments. - if path.segments.last().unwrap().args.is_some() { - return None; - } + let ExprKind::Path(None, path) = &expr.kind else { + return None; + }; - if let Res::Def(DefKind::Fn, def_id) = self.partial_res_map.get(&expr.id)?.full_res()? { - // We only support cross-crate argument rewriting. Uses - // within the same crate should be updated to use the new - // const generics style. - if def_id.is_local() { - return None; - } + // Don't perform legacy const generics rewriting if the path already + // has generic arguments. + if path.segments.last().unwrap().args.is_some() { + return None; + } - if let Some(v) = self.legacy_const_generic_args.get(&def_id) { - return v.clone(); - } - } + let def_id = self.partial_res_map.get(&expr.id)?.full_res()?.opt_def_id()?; + + // We only support cross-crate argument rewriting. Uses + // within the same crate should be updated to use the new + // const generics style. + if def_id.is_local() { + return None; + } + + if let Some(v) = self.legacy_const_generic_args.get(&def_id) { + return v.clone(); } None diff --git a/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs b/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs index 79f7171cc0c86..7323db06a8f1f 100644 --- a/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs +++ b/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs @@ -61,7 +61,6 @@ impl CombineAttributeParser for AllowConstFnUnstableParser { const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), - Allow(Target::Method(MethodKind::Trait { body: false })), Allow(Target::Method(MethodKind::Trait { body: true })), Allow(Target::Method(MethodKind::TraitImpl)), ]); diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs index 1ace3bf7cbf90..e59f70877c948 100644 --- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs @@ -57,7 +57,6 @@ impl NoArgsAttributeParser for ColdParser { Allow(Target::Fn), Allow(Target::Method(MethodKind::Trait { body: true })), Allow(Target::Method(MethodKind::TraitImpl)), - Allow(Target::Method(MethodKind::Trait { body: false })), Allow(Target::Method(MethodKind::Inherent)), Allow(Target::ForeignFn), Allow(Target::Closure), @@ -343,7 +342,7 @@ impl NoArgsAttributeParser for TrackCallerParser { Allow(Target::Method(MethodKind::Inherent)), Allow(Target::Method(MethodKind::Trait { body: true })), Allow(Target::Method(MethodKind::TraitImpl)), - Allow(Target::Method(MethodKind::Trait { body: false })), + Allow(Target::Method(MethodKind::Trait { body: false })), // `#[track_caller]` is inherited from trait methods Allow(Target::ForeignFn), Allow(Target::Closure), Warn(Target::MacroDef), diff --git a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs index 388553c8fd9b6..61f975555884e 100644 --- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs @@ -469,7 +469,6 @@ impl SingleAttributeParser for LinkSectionParser { Allow(Target::Static), Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), - Allow(Target::Method(MethodKind::Trait { body: false })), Allow(Target::Method(MethodKind::Trait { body: true })), Allow(Target::Method(MethodKind::TraitImpl)), ]); @@ -587,12 +586,12 @@ impl SingleAttributeParser for LinkageParser { const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ Allow(Target::Fn), Allow(Target::Method(MethodKind::Inherent)), - Allow(Target::Method(MethodKind::Trait { body: false })), Allow(Target::Method(MethodKind::Trait { body: true })), Allow(Target::Method(MethodKind::TraitImpl)), Allow(Target::Static), Allow(Target::ForeignStatic), Allow(Target::ForeignFn), + Warn(Target::Method(MethodKind::Trait { body: false })), // Not inherited ]); const TEMPLATE: AttributeTemplate = template!(NameValueStr: [ diff --git a/compiler/rustc_attr_parsing/src/attributes/repr.rs b/compiler/rustc_attr_parsing/src/attributes/repr.rs index 9ad103f3bb8ee..34d4957edc70e 100644 --- a/compiler/rustc_attr_parsing/src/attributes/repr.rs +++ b/compiler/rustc_attr_parsing/src/attributes/repr.rs @@ -315,7 +315,7 @@ impl AttributeParser for AlignParser { Allow(Target::Method(MethodKind::Inherent)), Allow(Target::Method(MethodKind::Trait { body: true })), Allow(Target::Method(MethodKind::TraitImpl)), - Allow(Target::Method(MethodKind::Trait { body: false })), + Allow(Target::Method(MethodKind::Trait { body: false })), // `#[align]` is inherited from trait methods Allow(Target::ForeignFn), ]); diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index d51fa2510b936..8cfe812f0c274 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -1,3 +1,5 @@ +use rustc_ast::{LitIntType, LitKind, MetaItemLit}; + use super::prelude::*; use super::util::parse_single_integer; @@ -76,3 +78,47 @@ impl SingleAttributeParser for RustcSimdMonomorphizeLaneLimitParser Some(AttributeKind::RustcSimdMonomorphizeLaneLimit(cx.parse_limit_int(nv)?)) } } + +pub(crate) struct RustcLegacyConstGenericsParser; + +impl SingleAttributeParser for RustcLegacyConstGenericsParser { + const PATH: &[Symbol] = &[sym::rustc_legacy_const_generics]; + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error; + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]); + const TEMPLATE: AttributeTemplate = template!(List: &["N"]); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option { + let ArgParser::List(meta_items) = args else { + cx.expected_list(cx.attr_span, args); + return None; + }; + + let mut parsed_indexes = ThinVec::new(); + let mut errored = false; + + for possible_index in meta_items.mixed() { + if let MetaItemOrLitParser::Lit(MetaItemLit { + kind: LitKind::Int(index, LitIntType::Unsuffixed), + .. + }) = possible_index + { + parsed_indexes.push((index.0 as usize, possible_index.span())); + } else { + cx.expected_integer_literal(possible_index.span()); + errored = true; + } + } + if errored { + return None; + } else if parsed_indexes.is_empty() { + cx.expected_at_least_one_argument(args.span()?); + return None; + } + + Some(AttributeKind::RustcLegacyConstGenerics { + fn_indexes: parsed_indexes, + attr_span: cx.attr_span, + }) + } +} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 8f5f5c55dcd59..fb9cb8fa42773 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -59,8 +59,9 @@ use crate::attributes::proc_macro_attrs::{ use crate::attributes::prototype::CustomMirParser; use crate::attributes::repr::{AlignParser, AlignStaticParser, ReprParser}; use crate::attributes::rustc_internal::{ - RustcLayoutScalarValidRangeEndParser, RustcLayoutScalarValidRangeStartParser, RustcMainParser, - RustcObjectLifetimeDefaultParser, RustcSimdMonomorphizeLaneLimitParser, + RustcLayoutScalarValidRangeEndParser, RustcLayoutScalarValidRangeStartParser, + RustcLegacyConstGenericsParser, RustcMainParser, RustcObjectLifetimeDefaultParser, + RustcSimdMonomorphizeLaneLimitParser, }; use crate::attributes::semantics::MayDangleParser; use crate::attributes::stability::{ @@ -208,6 +209,7 @@ attribute_parsers!( Single, Single, Single, + Single, Single, Single, Single, diff --git a/compiler/rustc_codegen_cranelift/src/inline_asm.rs b/compiler/rustc_codegen_cranelift/src/inline_asm.rs index 08cabe9d695c3..ac0da06cbb8e3 100644 --- a/compiler/rustc_codegen_cranelift/src/inline_asm.rs +++ b/compiler/rustc_codegen_cranelift/src/inline_asm.rs @@ -857,19 +857,9 @@ fn call_inline_asm<'tcx>( fn asm_clif_type<'tcx>(fx: &FunctionCx<'_, '_, 'tcx>, ty: Ty<'tcx>) -> Option { match ty.kind() { - // Adapted from https://github.com/rust-lang/rust/blob/f3c66088610c1b80110297c2d9a8b5f9265b013f/compiler/rustc_hir_analysis/src/check/intrinsicck.rs#L136-L151 + // Adapted from https://github.com/rust-lang/rust/blob/df44a57fd29fca899ce473f85ed64efd0708dd7c/compiler/rustc_hir_typeck/src/inline_asm.rs#L180-L183 ty::Adt(adt, args) if fx.tcx.is_lang_item(adt.did(), LangItem::MaybeUninit) => { - let fields = &adt.non_enum_variant().fields; - let ty = fields[FieldIdx::ONE].ty(fx.tcx, args); - let ty::Adt(ty, args) = ty.kind() else { - unreachable!("expected first field of `MaybeUninit` to be an ADT") - }; - assert!( - ty.is_manually_drop(), - "expected first field of `MaybeUninit` to be `ManuallyDrop`" - ); - let fields = &ty.non_enum_variant().fields; - let ty = fields[FieldIdx::ZERO].ty(fx.tcx, args); + let ty = args.type_at(0); fx.clif_type(ty) } _ => fx.clif_type(ty), diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index a77239e23b4e5..96d3a0024f418 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -98,7 +98,6 @@ use rustc_middle::ty::TyCtxt; use rustc_middle::util::Providers; use rustc_session::Session; use rustc_session::config::{OptLevel, OutputFilenames}; -use rustc_session::filesearch::make_target_lib_path; use rustc_span::Symbol; use rustc_target::spec::{Arch, RelocModel}; use tempfile::TempDir; @@ -207,18 +206,38 @@ impl CodegenBackend for GccCodegenBackend { } fn init(&self, sess: &Session) { + fn file_path(sysroot_path: &Path, sess: &Session) -> PathBuf { + let rustlib_path = + rustc_target::relative_target_rustlib_path(sysroot_path, &sess.host.llvm_target); + sysroot_path + .join(rustlib_path) + .join("codegen-backends") + .join("lib") + .join(sess.target.llvm_target.as_ref()) + .join("libgccjit.so") + } + // We use all_paths() instead of only path() in case the path specified by --sysroot is // invalid. // This is the case for instance in Rust for Linux where they specify --sysroot=/dev/null. for path in sess.opts.sysroot.all_paths() { - let libgccjit_target_lib_file = - make_target_lib_path(path, &sess.target.llvm_target).join("libgccjit.so"); + let libgccjit_target_lib_file = file_path(path, sess); if let Ok(true) = fs::exists(&libgccjit_target_lib_file) { load_libgccjit_if_needed(&libgccjit_target_lib_file); break; } } + if !gccjit::is_loaded() { + let mut paths = vec![]; + for path in sess.opts.sysroot.all_paths() { + let libgccjit_target_lib_file = file_path(path, sess); + paths.push(libgccjit_target_lib_file); + } + + panic!("Could not load libgccjit.so. Attempted paths: {:#?}", paths); + } + #[cfg(feature = "master")] { let target_cpu = target_cpu(sess); diff --git a/compiler/rustc_codegen_llvm/Cargo.toml b/compiler/rustc_codegen_llvm/Cargo.toml index 0544a94fd59fe..076ec5e59eb6b 100644 --- a/compiler/rustc_codegen_llvm/Cargo.toml +++ b/compiler/rustc_codegen_llvm/Cargo.toml @@ -14,6 +14,7 @@ bitflags = "2.4.1" gimli = "0.31" itertools = "0.12" libc = "0.2" +libloading = { version = "0.9.0", optional = true } measureme = "12.0.1" object = { version = "0.37.0", default-features = false, features = ["std", "read"] } rustc-demangle = "0.1.21" @@ -46,7 +47,7 @@ tracing = "0.1" [features] # tidy-alphabetical-start check_only = ["rustc_llvm/check_only"] -llvm_enzyme = [] +llvm_enzyme = ["dep:libloading"] llvm_offload = [] # tidy-alphabetical-end diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index 482e954138553..314e64272ffea 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -528,31 +528,34 @@ fn thin_lto( } } -fn enable_autodiff_settings(ad: &[config::AutoDiff]) { +#[cfg(feature = "llvm_enzyme")] +pub(crate) fn enable_autodiff_settings(ad: &[config::AutoDiff]) { + let mut enzyme = llvm::EnzymeWrapper::get_instance(); + for val in ad { // We intentionally don't use a wildcard, to not forget handling anything new. match val { config::AutoDiff::PrintPerf => { - llvm::set_print_perf(true); + enzyme.set_print_perf(true); } config::AutoDiff::PrintAA => { - llvm::set_print_activity(true); + enzyme.set_print_activity(true); } config::AutoDiff::PrintTA => { - llvm::set_print_type(true); + enzyme.set_print_type(true); } config::AutoDiff::PrintTAFn(fun) => { - llvm::set_print_type(true); // Enable general type printing - llvm::set_print_type_fun(&fun); // Set specific function to analyze + enzyme.set_print_type(true); // Enable general type printing + enzyme.set_print_type_fun(&fun); // Set specific function to analyze } config::AutoDiff::Inline => { - llvm::set_inline(true); + enzyme.set_inline(true); } config::AutoDiff::LooseTypes => { - llvm::set_loose_types(true); + enzyme.set_loose_types(true); } config::AutoDiff::PrintSteps => { - llvm::set_print(true); + enzyme.set_print(true); } // We handle this in the PassWrapper.cpp config::AutoDiff::PrintPasses => {} @@ -571,9 +574,9 @@ fn enable_autodiff_settings(ad: &[config::AutoDiff]) { } } // This helps with handling enums for now. - llvm::set_strict_aliasing(false); + enzyme.set_strict_aliasing(false); // FIXME(ZuseZ4): Test this, since it was added a long time ago. - llvm::set_rust_rules(true); + enzyme.set_rust_rules(true); } pub(crate) fn run_pass_manager( @@ -607,10 +610,6 @@ pub(crate) fn run_pass_manager( if enable_ad { write::AutodiffStage::DuringAD } else { write::AutodiffStage::PostAD } }; - if enable_ad { - enable_autodiff_settings(&config.autodiff); - } - unsafe { write::llvm_optimize(cgcx, dcx, module, None, config, opt_level, opt_stage, stage); } diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 2c4943e835a66..18da945f5a318 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -730,6 +730,13 @@ pub(crate) unsafe fn llvm_optimize( let llvm_plugins = config.llvm_plugins.join(","); + let enzyme_fn = if consider_ad { + let wrapper = llvm::EnzymeWrapper::get_instance(); + wrapper.registerEnzymeAndPassPipeline + } else { + std::ptr::null() + }; + let result = unsafe { llvm::LLVMRustOptimize( module.module_llvm.llmod(), @@ -749,7 +756,7 @@ pub(crate) unsafe fn llvm_optimize( vectorize_loop, config.no_builtins, config.emit_lifetime_markers, - run_enzyme, + enzyme_fn, print_before_enzyme, print_after_enzyme, print_passes, diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 0da5810518c5c..c51b334d95e16 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -240,6 +240,17 @@ impl CodegenBackend for LlvmCodegenBackend { fn init(&self, sess: &Session) { llvm_util::init(sess); // Make sure llvm is inited + + #[cfg(feature = "llvm_enzyme")] + { + use rustc_session::config::AutoDiff; + + use crate::back::lto::enable_autodiff_settings; + if sess.opts.unstable_opts.autodiff.contains(&AutoDiff::Enable) { + drop(llvm::EnzymeWrapper::get_or_init(&sess.opts.sysroot)); + enable_autodiff_settings(&sess.opts.unstable_opts.autodiff); + } + } } fn provide(&self, providers: &mut Providers) { diff --git a/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs index e63043b21227f..28923bf2743e4 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/enzyme_ffi.rs @@ -91,102 +91,363 @@ pub(crate) use self::Enzyme_AD::*; #[cfg(feature = "llvm_enzyme")] pub(crate) mod Enzyme_AD { - use std::ffi::{CString, c_char}; + use std::ffi::{c_char, c_void}; + use std::sync::{Mutex, MutexGuard, OnceLock}; - use libc::c_void; + use rustc_middle::bug; + use rustc_session::config::{Sysroot, host_tuple}; + use rustc_session::filesearch; use super::{CConcreteType, CTypeTreeRef, Context}; - - unsafe extern "C" { - pub(crate) fn EnzymeSetCLBool(arg1: *mut ::std::os::raw::c_void, arg2: u8); - pub(crate) fn EnzymeSetCLString(arg1: *mut ::std::os::raw::c_void, arg2: *const c_char); + use crate::llvm::{EnzymeTypeTree, LLVMRustVersionMajor}; + + type EnzymeSetCLBoolFn = unsafe extern "C" fn(*mut c_void, u8); + type EnzymeSetCLStringFn = unsafe extern "C" fn(*mut c_void, *const c_char); + + type EnzymeNewTypeTreeFn = unsafe extern "C" fn() -> CTypeTreeRef; + type EnzymeNewTypeTreeCTFn = unsafe extern "C" fn(CConcreteType, &Context) -> CTypeTreeRef; + type EnzymeNewTypeTreeTRFn = unsafe extern "C" fn(CTypeTreeRef) -> CTypeTreeRef; + type EnzymeFreeTypeTreeFn = unsafe extern "C" fn(CTypeTreeRef); + type EnzymeMergeTypeTreeFn = unsafe extern "C" fn(CTypeTreeRef, CTypeTreeRef) -> bool; + type EnzymeTypeTreeOnlyEqFn = unsafe extern "C" fn(CTypeTreeRef, i64); + type EnzymeTypeTreeData0EqFn = unsafe extern "C" fn(CTypeTreeRef); + type EnzymeTypeTreeShiftIndiciesEqFn = + unsafe extern "C" fn(CTypeTreeRef, *const c_char, i64, i64, u64); + type EnzymeTypeTreeInsertEqFn = + unsafe extern "C" fn(CTypeTreeRef, *const i64, usize, CConcreteType, &Context); + type EnzymeTypeTreeToStringFn = unsafe extern "C" fn(CTypeTreeRef) -> *const c_char; + type EnzymeTypeTreeToStringFreeFn = unsafe extern "C" fn(*const c_char); + + #[allow(non_snake_case)] + pub(crate) struct EnzymeWrapper { + EnzymeNewTypeTree: EnzymeNewTypeTreeFn, + EnzymeNewTypeTreeCT: EnzymeNewTypeTreeCTFn, + EnzymeNewTypeTreeTR: EnzymeNewTypeTreeTRFn, + EnzymeFreeTypeTree: EnzymeFreeTypeTreeFn, + EnzymeMergeTypeTree: EnzymeMergeTypeTreeFn, + EnzymeTypeTreeOnlyEq: EnzymeTypeTreeOnlyEqFn, + EnzymeTypeTreeData0Eq: EnzymeTypeTreeData0EqFn, + EnzymeTypeTreeShiftIndiciesEq: EnzymeTypeTreeShiftIndiciesEqFn, + EnzymeTypeTreeInsertEq: EnzymeTypeTreeInsertEqFn, + EnzymeTypeTreeToString: EnzymeTypeTreeToStringFn, + EnzymeTypeTreeToStringFree: EnzymeTypeTreeToStringFreeFn, + + EnzymePrintPerf: *mut c_void, + EnzymePrintActivity: *mut c_void, + EnzymePrintType: *mut c_void, + EnzymeFunctionToAnalyze: *mut c_void, + EnzymePrint: *mut c_void, + EnzymeStrictAliasing: *mut c_void, + EnzymeInline: *mut c_void, + EnzymeMaxTypeDepth: *mut c_void, + RustTypeRules: *mut c_void, + looseTypeAnalysis: *mut c_void, + + EnzymeSetCLBool: EnzymeSetCLBoolFn, + EnzymeSetCLString: EnzymeSetCLStringFn, + pub registerEnzymeAndPassPipeline: *const c_void, + lib: libloading::Library, + } + + unsafe impl Sync for EnzymeWrapper {} + unsafe impl Send for EnzymeWrapper {} + + fn load_ptr_by_symbol_mut_void( + lib: &libloading::Library, + bytes: &[u8], + ) -> Result<*mut c_void, Box> { + unsafe { + let s: libloading::Symbol<'_, *mut c_void> = lib.get(bytes)?; + // libloading = 0.9.0: try_as_raw_ptr always succeeds and returns Some + let s = s.try_as_raw_ptr().unwrap(); + Ok(s) + } } - // TypeTree functions - unsafe extern "C" { - pub(crate) fn EnzymeNewTypeTree() -> CTypeTreeRef; - pub(crate) fn EnzymeNewTypeTreeCT(arg1: CConcreteType, ctx: &Context) -> CTypeTreeRef; - pub(crate) fn EnzymeNewTypeTreeTR(arg1: CTypeTreeRef) -> CTypeTreeRef; - pub(crate) fn EnzymeFreeTypeTree(CTT: CTypeTreeRef); - pub(crate) fn EnzymeMergeTypeTree(arg1: CTypeTreeRef, arg2: CTypeTreeRef) -> bool; - pub(crate) fn EnzymeTypeTreeOnlyEq(arg1: CTypeTreeRef, pos: i64); - pub(crate) fn EnzymeTypeTreeData0Eq(arg1: CTypeTreeRef); - pub(crate) fn EnzymeTypeTreeShiftIndiciesEq( - arg1: CTypeTreeRef, + // e.g. + // load_ptrs_by_symbols_mut_void(ABC, XYZ); + // => + // let ABC = load_ptr_mut_void(&lib, b"ABC")?; + // let XYZ = load_ptr_mut_void(&lib, b"XYZ")?; + macro_rules! load_ptrs_by_symbols_mut_void { + ($lib:expr, $($name:ident),* $(,)?) => { + $( + #[allow(non_snake_case)] + let $name = load_ptr_by_symbol_mut_void(&$lib, stringify!($name).as_bytes())?; + )* + }; + } + + // e.g. + // load_ptrs_by_symbols_fn(ABC: ABCFn, XYZ: XYZFn); + // => + // let ABC: libloading::Symbol<'_, ABCFn> = unsafe { lib.get(b"ABC")? }; + // let XYZ: libloading::Symbol<'_, XYZFn> = unsafe { lib.get(b"XYZ")? }; + macro_rules! load_ptrs_by_symbols_fn { + ($lib:expr, $($name:ident : $ty:ty),* $(,)?) => { + $( + #[allow(non_snake_case)] + let $name: $ty = *unsafe { $lib.get::<$ty>(stringify!($name).as_bytes())? }; + )* + }; + } + + static ENZYME_INSTANCE: OnceLock> = OnceLock::new(); + + impl EnzymeWrapper { + /// Initialize EnzymeWrapper with the given sysroot if not already initialized. + /// Safe to call multiple times - subsequent calls are no-ops due to OnceLock. + pub(crate) fn get_or_init( + sysroot: &rustc_session::config::Sysroot, + ) -> MutexGuard<'static, Self> { + ENZYME_INSTANCE + .get_or_init(|| { + Self::call_dynamic(sysroot) + .unwrap_or_else(|e| bug!("failed to load Enzyme: {e}")) + .into() + }) + .lock() + .unwrap() + } + + /// Get the EnzymeWrapper instance. Panics if not initialized. + pub(crate) fn get_instance() -> MutexGuard<'static, Self> { + ENZYME_INSTANCE + .get() + .expect("EnzymeWrapper not initialized. Call get_or_init with sysroot first.") + .lock() + .unwrap() + } + + pub(crate) fn new_type_tree(&self) -> CTypeTreeRef { + unsafe { (self.EnzymeNewTypeTree)() } + } + + pub(crate) fn new_type_tree_ct( + &self, + t: CConcreteType, + ctx: &Context, + ) -> *mut EnzymeTypeTree { + unsafe { (self.EnzymeNewTypeTreeCT)(t, ctx) } + } + + pub(crate) fn new_type_tree_tr(&self, tree: CTypeTreeRef) -> CTypeTreeRef { + unsafe { (self.EnzymeNewTypeTreeTR)(tree) } + } + + pub(crate) fn free_type_tree(&self, tree: CTypeTreeRef) { + unsafe { (self.EnzymeFreeTypeTree)(tree) } + } + + pub(crate) fn merge_type_tree(&self, tree1: CTypeTreeRef, tree2: CTypeTreeRef) -> bool { + unsafe { (self.EnzymeMergeTypeTree)(tree1, tree2) } + } + + pub(crate) fn tree_only_eq(&self, tree: CTypeTreeRef, num: i64) { + unsafe { (self.EnzymeTypeTreeOnlyEq)(tree, num) } + } + + pub(crate) fn tree_data0_eq(&self, tree: CTypeTreeRef) { + unsafe { (self.EnzymeTypeTreeData0Eq)(tree) } + } + + pub(crate) fn shift_indicies_eq( + &self, + tree: CTypeTreeRef, data_layout: *const c_char, offset: i64, max_size: i64, add_offset: u64, - ); - pub(crate) fn EnzymeTypeTreeInsertEq( - CTT: CTypeTreeRef, + ) { + unsafe { + (self.EnzymeTypeTreeShiftIndiciesEq)( + tree, + data_layout, + offset, + max_size, + add_offset, + ) + } + } + + pub(crate) fn tree_insert_eq( + &self, + tree: CTypeTreeRef, indices: *const i64, len: usize, ct: CConcreteType, ctx: &Context, - ); - pub(crate) fn EnzymeTypeTreeToString(arg1: CTypeTreeRef) -> *const c_char; - pub(crate) fn EnzymeTypeTreeToStringFree(arg1: *const c_char); - } + ) { + unsafe { (self.EnzymeTypeTreeInsertEq)(tree, indices, len, ct, ctx) } + } - unsafe extern "C" { - static mut EnzymePrintPerf: c_void; - static mut EnzymePrintActivity: c_void; - static mut EnzymePrintType: c_void; - static mut EnzymeFunctionToAnalyze: c_void; - static mut EnzymePrint: c_void; - static mut EnzymeStrictAliasing: c_void; - static mut looseTypeAnalysis: c_void; - static mut EnzymeInline: c_void; - static mut RustTypeRules: c_void; - } - pub(crate) fn set_print_perf(print: bool) { - unsafe { - EnzymeSetCLBool(std::ptr::addr_of_mut!(EnzymePrintPerf), print as u8); + pub(crate) fn tree_to_string(&self, tree: *mut EnzymeTypeTree) -> *const c_char { + unsafe { (self.EnzymeTypeTreeToString)(tree) } } - } - pub(crate) fn set_print_activity(print: bool) { - unsafe { - EnzymeSetCLBool(std::ptr::addr_of_mut!(EnzymePrintActivity), print as u8); + + pub(crate) fn tree_to_string_free(&self, ch: *const c_char) { + unsafe { (self.EnzymeTypeTreeToStringFree)(ch) } } - } - pub(crate) fn set_print_type(print: bool) { - unsafe { - EnzymeSetCLBool(std::ptr::addr_of_mut!(EnzymePrintType), print as u8); + + pub(crate) fn get_max_type_depth(&self) -> usize { + unsafe { std::ptr::read::(self.EnzymeMaxTypeDepth as *const u32) as usize } } - } - pub(crate) fn set_print_type_fun(fun_name: &str) { - let c_fun_name = CString::new(fun_name).unwrap(); - unsafe { - EnzymeSetCLString( - std::ptr::addr_of_mut!(EnzymeFunctionToAnalyze), - c_fun_name.as_ptr() as *const c_char, - ); + + pub(crate) fn set_print_perf(&mut self, print: bool) { + unsafe { + (self.EnzymeSetCLBool)(self.EnzymePrintPerf, print as u8); + } } - } - pub(crate) fn set_print(print: bool) { - unsafe { - EnzymeSetCLBool(std::ptr::addr_of_mut!(EnzymePrint), print as u8); + + pub(crate) fn set_print_activity(&mut self, print: bool) { + unsafe { + (self.EnzymeSetCLBool)(self.EnzymePrintActivity, print as u8); + } } - } - pub(crate) fn set_strict_aliasing(strict: bool) { - unsafe { - EnzymeSetCLBool(std::ptr::addr_of_mut!(EnzymeStrictAliasing), strict as u8); + + pub(crate) fn set_print_type(&mut self, print: bool) { + unsafe { + (self.EnzymeSetCLBool)(self.EnzymePrintType, print as u8); + } } - } - pub(crate) fn set_loose_types(loose: bool) { - unsafe { - EnzymeSetCLBool(std::ptr::addr_of_mut!(looseTypeAnalysis), loose as u8); + + pub(crate) fn set_print_type_fun(&mut self, fun_name: &str) { + let c_fun_name = std::ffi::CString::new(fun_name) + .unwrap_or_else(|err| bug!("failed to set_print_type_fun: {err}")); + unsafe { + (self.EnzymeSetCLString)( + self.EnzymeFunctionToAnalyze, + c_fun_name.as_ptr() as *const c_char, + ); + } } - } - pub(crate) fn set_inline(val: bool) { - unsafe { - EnzymeSetCLBool(std::ptr::addr_of_mut!(EnzymeInline), val as u8); + + pub(crate) fn set_print(&mut self, print: bool) { + unsafe { + (self.EnzymeSetCLBool)(self.EnzymePrint, print as u8); + } } - } - pub(crate) fn set_rust_rules(val: bool) { - unsafe { - EnzymeSetCLBool(std::ptr::addr_of_mut!(RustTypeRules), val as u8); + + pub(crate) fn set_strict_aliasing(&mut self, strict: bool) { + unsafe { + (self.EnzymeSetCLBool)(self.EnzymeStrictAliasing, strict as u8); + } + } + + pub(crate) fn set_loose_types(&mut self, loose: bool) { + unsafe { + (self.EnzymeSetCLBool)(self.looseTypeAnalysis, loose as u8); + } + } + + pub(crate) fn set_inline(&mut self, val: bool) { + unsafe { + (self.EnzymeSetCLBool)(self.EnzymeInline, val as u8); + } + } + + pub(crate) fn set_rust_rules(&mut self, val: bool) { + unsafe { + (self.EnzymeSetCLBool)(self.RustTypeRules, val as u8); + } + } + + #[allow(non_snake_case)] + fn call_dynamic( + sysroot: &rustc_session::config::Sysroot, + ) -> Result> { + let enzyme_path = Self::get_enzyme_path(sysroot)?; + let lib = unsafe { libloading::Library::new(enzyme_path)? }; + + load_ptrs_by_symbols_fn!( + lib, + EnzymeNewTypeTree: EnzymeNewTypeTreeFn, + EnzymeNewTypeTreeCT: EnzymeNewTypeTreeCTFn, + EnzymeNewTypeTreeTR: EnzymeNewTypeTreeTRFn, + EnzymeFreeTypeTree: EnzymeFreeTypeTreeFn, + EnzymeMergeTypeTree: EnzymeMergeTypeTreeFn, + EnzymeTypeTreeOnlyEq: EnzymeTypeTreeOnlyEqFn, + EnzymeTypeTreeData0Eq: EnzymeTypeTreeData0EqFn, + EnzymeTypeTreeShiftIndiciesEq: EnzymeTypeTreeShiftIndiciesEqFn, + EnzymeTypeTreeInsertEq: EnzymeTypeTreeInsertEqFn, + EnzymeTypeTreeToString: EnzymeTypeTreeToStringFn, + EnzymeTypeTreeToStringFree: EnzymeTypeTreeToStringFreeFn, + EnzymeSetCLBool: EnzymeSetCLBoolFn, + EnzymeSetCLString: EnzymeSetCLStringFn, + ); + + load_ptrs_by_symbols_mut_void!( + lib, + registerEnzymeAndPassPipeline, + EnzymePrintPerf, + EnzymePrintActivity, + EnzymePrintType, + EnzymeFunctionToAnalyze, + EnzymePrint, + EnzymeStrictAliasing, + EnzymeInline, + EnzymeMaxTypeDepth, + RustTypeRules, + looseTypeAnalysis, + ); + + Ok(Self { + EnzymeNewTypeTree, + EnzymeNewTypeTreeCT, + EnzymeNewTypeTreeTR, + EnzymeFreeTypeTree, + EnzymeMergeTypeTree, + EnzymeTypeTreeOnlyEq, + EnzymeTypeTreeData0Eq, + EnzymeTypeTreeShiftIndiciesEq, + EnzymeTypeTreeInsertEq, + EnzymeTypeTreeToString, + EnzymeTypeTreeToStringFree, + EnzymePrintPerf, + EnzymePrintActivity, + EnzymePrintType, + EnzymeFunctionToAnalyze, + EnzymePrint, + EnzymeStrictAliasing, + EnzymeInline, + EnzymeMaxTypeDepth, + RustTypeRules, + looseTypeAnalysis, + EnzymeSetCLBool, + EnzymeSetCLString, + registerEnzymeAndPassPipeline, + lib, + }) + } + + fn get_enzyme_path(sysroot: &Sysroot) -> Result { + let llvm_version_major = unsafe { LLVMRustVersionMajor() }; + + let path_buf = sysroot + .all_paths() + .map(|sysroot_path| { + filesearch::make_target_lib_path(sysroot_path, host_tuple()) + .join("lib") + .with_file_name(format!("libEnzyme-{llvm_version_major}")) + .with_extension(std::env::consts::DLL_EXTENSION) + }) + .find(|f| f.exists()) + .ok_or_else(|| { + let candidates = sysroot + .all_paths() + .map(|p| p.join("lib").display().to_string()) + .collect::>() + .join("\n* "); + format!( + "failed to find a `libEnzyme-{llvm_version_major}` folder \ + in the sysroot candidates:\n* {candidates}" + ) + })?; + + Ok(path_buf + .to_str() + .ok_or_else(|| format!("invalid UTF-8 in path: {}", path_buf.display()))? + .to_string()) } } } @@ -198,111 +459,156 @@ pub(crate) use self::Fallback_AD::*; pub(crate) mod Fallback_AD { #![allow(unused_variables)] + use std::ffi::c_void; + use std::sync::{Mutex, MutexGuard}; + use libc::c_char; + use rustc_codegen_ssa::back::write::CodegenContext; + use rustc_codegen_ssa::traits::WriteBackendMethods; - use super::{CConcreteType, CTypeTreeRef, Context}; + use super::{CConcreteType, CTypeTreeRef, Context, EnzymeTypeTree}; - // TypeTree function fallbacks - pub(crate) unsafe fn EnzymeNewTypeTree() -> CTypeTreeRef { - unimplemented!() + pub(crate) struct EnzymeWrapper { + pub registerEnzymeAndPassPipeline: *const c_void, } - pub(crate) unsafe fn EnzymeNewTypeTreeCT(arg1: CConcreteType, ctx: &Context) -> CTypeTreeRef { - unimplemented!() - } + impl EnzymeWrapper { + pub(crate) fn get_or_init( + _sysroot: &rustc_session::config::Sysroot, + ) -> MutexGuard<'static, Self> { + unimplemented!("Enzyme not available: build with llvm_enzyme feature") + } - pub(crate) unsafe fn EnzymeNewTypeTreeTR(arg1: CTypeTreeRef) -> CTypeTreeRef { - unimplemented!() - } + pub(crate) fn init<'a, B: WriteBackendMethods>( + _cgcx: &'a CodegenContext, + ) -> &'static Mutex { + unimplemented!("Enzyme not available: build with llvm_enzyme feature") + } - pub(crate) unsafe fn EnzymeFreeTypeTree(CTT: CTypeTreeRef) { - unimplemented!() - } + pub(crate) fn get_instance() -> MutexGuard<'static, Self> { + unimplemented!("Enzyme not available: build with llvm_enzyme feature") + } - pub(crate) unsafe fn EnzymeMergeTypeTree(arg1: CTypeTreeRef, arg2: CTypeTreeRef) -> bool { - unimplemented!() - } + pub(crate) fn new_type_tree(&self) -> CTypeTreeRef { + unimplemented!() + } - pub(crate) unsafe fn EnzymeTypeTreeOnlyEq(arg1: CTypeTreeRef, pos: i64) { - unimplemented!() - } + pub(crate) fn new_type_tree_ct( + &self, + t: CConcreteType, + ctx: &Context, + ) -> *mut EnzymeTypeTree { + unimplemented!() + } - pub(crate) unsafe fn EnzymeTypeTreeData0Eq(arg1: CTypeTreeRef) { - unimplemented!() - } + pub(crate) fn new_type_tree_tr(&self, tree: CTypeTreeRef) -> CTypeTreeRef { + unimplemented!() + } - pub(crate) unsafe fn EnzymeTypeTreeShiftIndiciesEq( - arg1: CTypeTreeRef, - data_layout: *const c_char, - offset: i64, - max_size: i64, - add_offset: u64, - ) { - unimplemented!() - } + pub(crate) fn free_type_tree(&self, tree: CTypeTreeRef) { + unimplemented!() + } - pub(crate) unsafe fn EnzymeTypeTreeInsertEq( - CTT: CTypeTreeRef, - indices: *const i64, - len: usize, - ct: CConcreteType, - ctx: &Context, - ) { - unimplemented!() - } + pub(crate) fn merge_type_tree(&self, tree1: CTypeTreeRef, tree2: CTypeTreeRef) -> bool { + unimplemented!() + } - pub(crate) unsafe fn EnzymeTypeTreeToString(arg1: CTypeTreeRef) -> *const c_char { - unimplemented!() - } + pub(crate) fn tree_only_eq(&self, tree: CTypeTreeRef, num: i64) { + unimplemented!() + } - pub(crate) unsafe fn EnzymeTypeTreeToStringFree(arg1: *const c_char) { - unimplemented!() - } + pub(crate) fn tree_data0_eq(&self, tree: CTypeTreeRef) { + unimplemented!() + } - pub(crate) fn set_inline(val: bool) { - unimplemented!() - } - pub(crate) fn set_print_perf(print: bool) { - unimplemented!() - } - pub(crate) fn set_print_activity(print: bool) { - unimplemented!() - } - pub(crate) fn set_print_type(print: bool) { - unimplemented!() - } - pub(crate) fn set_print_type_fun(fun_name: &str) { - unimplemented!() - } - pub(crate) fn set_print(print: bool) { - unimplemented!() - } - pub(crate) fn set_strict_aliasing(strict: bool) { - unimplemented!() - } - pub(crate) fn set_loose_types(loose: bool) { - unimplemented!() - } - pub(crate) fn set_rust_rules(val: bool) { - unimplemented!() + pub(crate) fn shift_indicies_eq( + &self, + tree: CTypeTreeRef, + data_layout: *const c_char, + offset: i64, + max_size: i64, + add_offset: u64, + ) { + unimplemented!() + } + + pub(crate) fn tree_insert_eq( + &self, + tree: CTypeTreeRef, + indices: *const i64, + len: usize, + ct: CConcreteType, + ctx: &Context, + ) { + unimplemented!() + } + + pub(crate) fn tree_to_string(&self, tree: *mut EnzymeTypeTree) -> *const c_char { + unimplemented!() + } + + pub(crate) fn tree_to_string_free(&self, ch: *const c_char) { + unimplemented!() + } + + pub(crate) fn get_max_type_depth(&self) -> usize { + unimplemented!() + } + + pub(crate) fn set_inline(&mut self, val: bool) { + unimplemented!() + } + + pub(crate) fn set_print_perf(&mut self, print: bool) { + unimplemented!() + } + + pub(crate) fn set_print_activity(&mut self, print: bool) { + unimplemented!() + } + + pub(crate) fn set_print_type(&mut self, print: bool) { + unimplemented!() + } + + pub(crate) fn set_print_type_fun(&mut self, fun_name: &str) { + unimplemented!() + } + + pub(crate) fn set_print(&mut self, print: bool) { + unimplemented!() + } + + pub(crate) fn set_strict_aliasing(&mut self, strict: bool) { + unimplemented!() + } + + pub(crate) fn set_loose_types(&mut self, loose: bool) { + unimplemented!() + } + + pub(crate) fn set_rust_rules(&mut self, val: bool) { + unimplemented!() + } } } impl TypeTree { pub(crate) fn new() -> TypeTree { - let inner = unsafe { EnzymeNewTypeTree() }; + let wrapper = EnzymeWrapper::get_instance(); + let inner = wrapper.new_type_tree(); TypeTree { inner } } pub(crate) fn from_type(t: CConcreteType, ctx: &Context) -> TypeTree { - let inner = unsafe { EnzymeNewTypeTreeCT(t, ctx) }; + let wrapper = EnzymeWrapper::get_instance(); + let inner = wrapper.new_type_tree_ct(t, ctx); TypeTree { inner } } pub(crate) fn merge(self, other: Self) -> Self { - unsafe { - EnzymeMergeTypeTree(self.inner, other.inner); - } + let wrapper = EnzymeWrapper::get_instance(); + wrapper.merge_type_tree(self.inner, other.inner); drop(other); self } @@ -316,37 +622,36 @@ impl TypeTree { add_offset: usize, ) -> Self { let layout = std::ffi::CString::new(layout).unwrap(); - - unsafe { - EnzymeTypeTreeShiftIndiciesEq( - self.inner, - layout.as_ptr(), - offset as i64, - max_size as i64, - add_offset as u64, - ); - } + let wrapper = EnzymeWrapper::get_instance(); + wrapper.shift_indicies_eq( + self.inner, + layout.as_ptr(), + offset as i64, + max_size as i64, + add_offset as u64, + ); self } pub(crate) fn insert(&mut self, indices: &[i64], ct: CConcreteType, ctx: &Context) { - unsafe { - EnzymeTypeTreeInsertEq(self.inner, indices.as_ptr(), indices.len(), ct, ctx); - } + let wrapper = EnzymeWrapper::get_instance(); + wrapper.tree_insert_eq(self.inner, indices.as_ptr(), indices.len(), ct, ctx); } } impl Clone for TypeTree { fn clone(&self) -> Self { - let inner = unsafe { EnzymeNewTypeTreeTR(self.inner) }; + let wrapper = EnzymeWrapper::get_instance(); + let inner = wrapper.new_type_tree_tr(self.inner); TypeTree { inner } } } impl std::fmt::Display for TypeTree { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let ptr = unsafe { EnzymeTypeTreeToString(self.inner) }; + let wrapper = EnzymeWrapper::get_instance(); + let ptr = wrapper.tree_to_string(self.inner); let cstr = unsafe { std::ffi::CStr::from_ptr(ptr) }; match cstr.to_str() { Ok(x) => write!(f, "{}", x)?, @@ -354,9 +659,7 @@ impl std::fmt::Display for TypeTree { } // delete C string pointer - unsafe { - EnzymeTypeTreeToStringFree(ptr); - } + wrapper.tree_to_string_free(ptr); Ok(()) } @@ -370,6 +673,7 @@ impl std::fmt::Debug for TypeTree { impl Drop for TypeTree { fn drop(&mut self) { - unsafe { EnzymeFreeTypeTree(self.inner) } + let wrapper = EnzymeWrapper::get_instance(); + wrapper.free_type_tree(self.inner) } } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 8abf8b24d9d6f..7835319f5c1d0 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2411,7 +2411,7 @@ unsafe extern "C" { LoopVectorize: bool, DisableSimplifyLibCalls: bool, EmitLifetimeMarkers: bool, - RunEnzyme: bool, + RunEnzyme: *const c_void, PrintBeforeEnzyme: bool, PrintAfterEnzyme: bool, PrintPasses: bool, diff --git a/compiler/rustc_codegen_llvm/src/typetree.rs b/compiler/rustc_codegen_llvm/src/typetree.rs index 7e2635037008e..513a832e7fe8f 100644 --- a/compiler/rustc_codegen_llvm/src/typetree.rs +++ b/compiler/rustc_codegen_llvm/src/typetree.rs @@ -2,6 +2,7 @@ use rustc_ast::expand::typetree::FncTree; #[cfg(feature = "llvm_enzyme")] use { crate::attributes, + crate::llvm::EnzymeWrapper, rustc_ast::expand::typetree::TypeTree as RustTypeTree, std::ffi::{CString, c_char, c_uint}, }; @@ -77,7 +78,8 @@ pub(crate) fn add_tt<'ll>( for (i, input) in inputs.iter().enumerate() { unsafe { let enzyme_tt = to_enzyme_typetree(input.clone(), llvm_data_layout, llcx); - let c_str = llvm::EnzymeTypeTreeToString(enzyme_tt.inner); + let enzyme_wrapper = EnzymeWrapper::get_instance(); + let c_str = enzyme_wrapper.tree_to_string(enzyme_tt.inner); let c_str = std::ffi::CStr::from_ptr(c_str); let attr = llvm::LLVMCreateStringAttribute( @@ -89,13 +91,14 @@ pub(crate) fn add_tt<'ll>( ); attributes::apply_to_llfn(fn_def, llvm::AttributePlace::Argument(i as u32), &[attr]); - llvm::EnzymeTypeTreeToStringFree(c_str.as_ptr()); + enzyme_wrapper.tree_to_string_free(c_str.as_ptr()); } } unsafe { let enzyme_tt = to_enzyme_typetree(ret_tt, llvm_data_layout, llcx); - let c_str = llvm::EnzymeTypeTreeToString(enzyme_tt.inner); + let enzyme_wrapper = EnzymeWrapper::get_instance(); + let c_str = enzyme_wrapper.tree_to_string(enzyme_tt.inner); let c_str = std::ffi::CStr::from_ptr(c_str); let ret_attr = llvm::LLVMCreateStringAttribute( @@ -107,7 +110,7 @@ pub(crate) fn add_tt<'ll>( ); attributes::apply_to_llfn(fn_def, llvm::AttributePlace::ReturnValue, &[ret_attr]); - llvm::EnzymeTypeTreeToStringFree(c_str.as_ptr()); + enzyme_wrapper.tree_to_string_free(c_str.as_ptr()); } } diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 9abd7c1dd9c68..9b789d9e62b70 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -2792,11 +2792,9 @@ fn add_upstream_rust_crates( // We must always link crates `compiler_builtins` and `profiler_builtins` statically. // Even if they were already included into a dylib // (e.g. `libstd` when `-C prefer-dynamic` is used). - // FIXME: `dependency_formats` can report `profiler_builtins` as `NotLinked` for some - // reason, it shouldn't do that because `profiler_builtins` should indeed be linked. let linkage = data[cnum]; let link_static_crate = linkage == Linkage::Static - || (linkage == Linkage::IncludedFromDylib || linkage == Linkage::NotLinked) + || linkage == Linkage::IncludedFromDylib && (codegen_results.crate_info.compiler_builtins == Some(cnum) || codegen_results.crate_info.profiler_runtime == Some(cnum)); diff --git a/compiler/rustc_hir/src/attrs/data_structures.rs b/compiler/rustc_hir/src/attrs/data_structures.rs index 34d78afca9b2c..83fa70b74b444 100644 --- a/compiler/rustc_hir/src/attrs/data_structures.rs +++ b/compiler/rustc_hir/src/attrs/data_structures.rs @@ -869,6 +869,9 @@ pub enum AttributeKind { /// Represents `#[rustc_layout_scalar_valid_range_start]`. RustcLayoutScalarValidRangeStart(Box, Span), + /// Represents `#[rustc_legacy_const_generics]` + RustcLegacyConstGenerics { fn_indexes: ThinVec<(usize, Span)>, attr_span: Span }, + /// Represents `#[rustc_main]`. RustcMain, diff --git a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs index 4cb786f59bfe4..2dbb0e42149cd 100644 --- a/compiler/rustc_hir/src/attrs/encode_cross_crate.rs +++ b/compiler/rustc_hir/src/attrs/encode_cross_crate.rs @@ -92,6 +92,7 @@ impl AttributeKind { RustcCoherenceIsCore(..) => No, RustcLayoutScalarValidRangeEnd(..) => Yes, RustcLayoutScalarValidRangeStart(..) => Yes, + RustcLegacyConstGenerics { .. } => Yes, RustcMain => No, RustcObjectLifetimeDefault => No, RustcPassIndirectlyInNonRusticAbis(..) => No, diff --git a/compiler/rustc_hir/src/attrs/pretty_printing.rs b/compiler/rustc_hir/src/attrs/pretty_printing.rs index 0ad486cef43d0..9d42c005d5dab 100644 --- a/compiler/rustc_hir/src/attrs/pretty_printing.rs +++ b/compiler/rustc_hir/src/attrs/pretty_printing.rs @@ -159,7 +159,7 @@ macro_rules! print_tup { print_tup!(A B C D E F G H); print_skip!(Span, (), ErrorGuaranteed); -print_disp!(u16, u128, bool, NonZero, Limit); +print_disp!(u16, u128, usize, bool, NonZero, Limit); print_debug!( Symbol, Ident, diff --git a/compiler/rustc_hir_typeck/src/inline_asm.rs b/compiler/rustc_hir_typeck/src/inline_asm.rs index 6626c3edb5466..7c1655f8201d7 100644 --- a/compiler/rustc_hir_typeck/src/inline_asm.rs +++ b/compiler/rustc_hir_typeck/src/inline_asm.rs @@ -178,19 +178,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { ty::Never if is_input => return None, _ if ty.references_error() => return None, ty::Adt(adt, args) if self.tcx().is_lang_item(adt.did(), LangItem::MaybeUninit) => { - let fields = &adt.non_enum_variant().fields; - let ty = fields[FieldIdx::ONE].ty(self.tcx(), args); - // FIXME: Are we just trying to map to the `T` in `MaybeUninit`? - // If so, just get it from the args. - let ty::Adt(ty, args) = ty.kind() else { - unreachable!("expected first field of `MaybeUninit` to be an ADT") - }; - assert!( - ty.is_manually_drop(), - "expected first field of `MaybeUninit` to be `ManuallyDrop`" - ); - let fields = &ty.non_enum_variant().fields; - let ty = fields[FieldIdx::ZERO].ty(self.tcx(), args); + let ty = args.type_at(0); self.get_asm_ty(expr.span, ty) } _ => self.get_asm_ty(expr.span, ty), diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 714ba0f177a8f..95cbec1b37b4f 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -550,17 +550,8 @@ struct LLVMRustSanitizerOptions { bool SanitizeKernelAddressRecover; }; -// This symbol won't be available or used when Enzyme is not enabled. -// Always set AugmentPassBuilder to true, since it registers optimizations which -// will improve the performance for Enzyme. -#ifdef ENZYME -extern "C" void registerEnzymeAndPassPipeline(llvm::PassBuilder &PB, - /* augmentPassBuilder */ bool); - -extern "C" { -extern llvm::cl::opt EnzymeFunctionToAnalyze; -} -#endif +extern "C" typedef void (*registerEnzymeAndPassPipelineFn)( + llvm::PassBuilder &PB, bool augment); extern "C" LLVMRustResult LLVMRustOptimize( LLVMModuleRef ModuleRef, LLVMTargetMachineRef TMRef, @@ -569,8 +560,8 @@ extern "C" LLVMRustResult LLVMRustOptimize( bool LintIR, LLVMRustThinLTOBuffer **ThinLTOBufferRef, bool EmitThinLTO, bool EmitThinLTOSummary, bool MergeFunctions, bool UnrollLoops, bool SLPVectorize, bool LoopVectorize, bool DisableSimplifyLibCalls, - bool EmitLifetimeMarkers, bool RunEnzyme, bool PrintBeforeEnzyme, - bool PrintAfterEnzyme, bool PrintPasses, + bool EmitLifetimeMarkers, registerEnzymeAndPassPipelineFn EnzymePtr, + bool PrintBeforeEnzyme, bool PrintAfterEnzyme, bool PrintPasses, LLVMRustSanitizerOptions *SanitizerOptions, const char *PGOGenPath, const char *PGOUsePath, bool InstrumentCoverage, const char *InstrProfileOutput, const char *PGOSampleUsePath, @@ -907,8 +898,8 @@ extern "C" LLVMRustResult LLVMRustOptimize( } // now load "-enzyme" pass: -#ifdef ENZYME - if (RunEnzyme) { + // With dlopen, ENZYME macro may not be defined, so check EnzymePtr directly + if (EnzymePtr) { if (PrintBeforeEnzyme) { // Handle the Rust flag `-Zautodiff=PrintModBefore`. @@ -916,29 +907,19 @@ extern "C" LLVMRustResult LLVMRustOptimize( MPM.addPass(PrintModulePass(outs(), Banner, true, false)); } - registerEnzymeAndPassPipeline(PB, false); + EnzymePtr(PB, false); if (auto Err = PB.parsePassPipeline(MPM, "enzyme")) { std::string ErrMsg = toString(std::move(Err)); LLVMRustSetLastError(ErrMsg.c_str()); return LLVMRustResult::Failure; } - // Check if PrintTAFn was used and add type analysis pass if needed - if (!EnzymeFunctionToAnalyze.empty()) { - if (auto Err = PB.parsePassPipeline(MPM, "print-type-analysis")) { - std::string ErrMsg = toString(std::move(Err)); - LLVMRustSetLastError(ErrMsg.c_str()); - return LLVMRustResult::Failure; - } - } - if (PrintAfterEnzyme) { // Handle the Rust flag `-Zautodiff=PrintModAfter`. std::string Banner = "Module after EnzymeNewPM"; MPM.addPass(PrintModulePass(outs(), Banner, true, false)); } } -#endif if (PrintPasses) { // Print all passes from the PM: std::string Pipeline; diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index dda06e9b2bf68..0720af0eb7e0c 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -1791,18 +1791,6 @@ extern "C" void LLVMRustSetNoSanitizeHWAddress(LLVMValueRef Global) { GV.setSanitizerMetadata(MD); } -#ifdef ENZYME -extern "C" { -extern llvm::cl::opt EnzymeMaxTypeDepth; -} - -extern "C" size_t LLVMRustEnzymeGetMaxTypeDepth() { return EnzymeMaxTypeDepth; } -#else -extern "C" size_t LLVMRustEnzymeGetMaxTypeDepth() { - return 6; // Default fallback depth -} -#endif - // Statically assert that the fixed metadata kind IDs declared in // `metadata_kind.rs` match the ones actually used by LLVM. #define FIXED_MD_KIND(VARIANT, VALUE) \ diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index b02029cd9a19b..4000f12459a90 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -156,8 +156,8 @@ impl<'a> std::fmt::Debug for CrateDump<'a> { enum CrateOrigin<'a> { /// This crate was a dependency of another crate. IndirectDependency { - /// Where this dependency was included from. - dep_root: &'a CratePaths, + /// Where this dependency was included from. Should only be used in error messages. + dep_root_for_errors: &'a CratePaths, /// True if the parent is private, meaning the dependent should also be private. parent_private: bool, /// Dependency info about this crate. @@ -171,9 +171,11 @@ enum CrateOrigin<'a> { impl<'a> CrateOrigin<'a> { /// Return the dependency root, if any. - fn dep_root(&self) -> Option<&'a CratePaths> { + fn dep_root_for_errors(&self) -> Option<&'a CratePaths> { match self { - CrateOrigin::IndirectDependency { dep_root, .. } => Some(dep_root), + CrateOrigin::IndirectDependency { dep_root_for_errors, .. } => { + Some(dep_root_for_errors) + } _ => None, } } @@ -193,6 +195,7 @@ impl<'a> CrateOrigin<'a> { CrateOrigin::IndirectDependency { parent_private, dep, .. } => { Some(dep.is_private || *parent_private) } + CrateOrigin::Injected => Some(true), _ => None, } } @@ -544,17 +547,7 @@ impl CStore { /// Sometimes the directly dependent crate is not specified by `--extern`, in this case, /// `private-dep` is none during loading. This is equivalent to the scenario where the /// command parameter is set to `public-dependency` - fn is_private_dep( - &self, - externs: &Externs, - name: Symbol, - private_dep: Option, - origin: CrateOrigin<'_>, - ) -> bool { - if matches!(origin, CrateOrigin::Injected) { - return true; - } - + fn is_private_dep(&self, externs: &Externs, name: Symbol, private_dep: Option) -> bool { let extern_private = externs.get(name.as_str()).map(|e| e.is_private_dep); match (extern_private, private_dep) { // Explicit non-private via `--extern`, explicit non-private from metadata, or @@ -581,7 +574,7 @@ impl CStore { let Library { source, metadata } = lib; let crate_root = metadata.get_root(); let host_hash = host_lib.as_ref().map(|lib| lib.metadata.get_root().hash()); - let private_dep = self.is_private_dep(&tcx.sess.opts.externs, name, private_dep, origin); + let private_dep = self.is_private_dep(&tcx.sess.opts.externs, name, private_dep); // Claim this crate number and cache it let feed = self.intern_stable_crate_id(tcx, &crate_root)?; @@ -597,8 +590,8 @@ impl CStore { // Maintain a reference to the top most crate. // Stash paths for top-most crate locally if necessary. let crate_paths; - let dep_root = if let Some(dep_root) = origin.dep_root() { - dep_root + let dep_root_for_errors = if let Some(dep_root_for_errors) = origin.dep_root_for_errors() { + dep_root_for_errors } else { crate_paths = CratePaths::new(crate_root.name(), source.clone()); &crate_paths @@ -606,7 +599,7 @@ impl CStore { let cnum_map = self.resolve_crate_deps( tcx, - dep_root, + dep_root_for_errors, &crate_root, &metadata, cnum, @@ -726,7 +719,7 @@ impl CStore { self.used_extern_options.insert(name); match self.maybe_resolve_crate(tcx, name, dep_kind, origin) { Ok(cnum) => { - self.set_used_recursively(tcx, cnum); + self.set_used_recursively(cnum); Some(cnum) } Err(err) => { @@ -735,7 +728,7 @@ impl CStore { .maybe_resolve_crate( tcx, sym::core, - CrateDepKind::Explicit, + CrateDepKind::Unconditional, CrateOrigin::Extern, ) .is_err(); @@ -757,7 +750,7 @@ impl CStore { return Err(CrateError::NonAsciiName(name)); } - let dep_root = origin.dep_root(); + let dep_root_for_errors = origin.dep_root_for_errors(); let dep = origin.dep(); let hash = dep.map(|d| d.hash); let host_hash = dep.map(|d| d.host_hash).flatten(); @@ -795,7 +788,11 @@ impl CStore { host_hash, )? { Some(res) => res, - None => return Err(locator.into_error(crate_rejections, dep_root.cloned())), + None => { + return Err( + locator.into_error(crate_rejections, dep_root_for_errors.cloned()) + ); + } } } } @@ -808,8 +805,7 @@ impl CStore { // not specified by `--extern` on command line parameters, it may be // `private-dependency` when `register_crate` is called for the first time. Then it must be updated to // `public-dependency` here. - let private_dep = - self.is_private_dep(&tcx.sess.opts.externs, name, private_dep, origin); + let private_dep = self.is_private_dep(&tcx.sess.opts.externs, name, private_dep); let data = self.get_crate_data_mut(cnum); if data.is_proc_macro_crate() { dep_kind = CrateDepKind::MacrosOnly; @@ -856,7 +852,7 @@ impl CStore { fn resolve_crate_deps( &mut self, tcx: TyCtxt<'_>, - dep_root: &CratePaths, + dep_root_for_errors: &CratePaths, crate_root: &CrateRoot, metadata: &MetadataBlob, krate: CrateNum, @@ -866,7 +862,7 @@ impl CStore { debug!( "resolving deps of external crate `{}` with dep root `{}`", crate_root.name(), - dep_root.name + dep_root_for_errors.name ); if crate_root.is_proc_macro_crate() { return Ok(CrateNumMap::new()); @@ -896,7 +892,7 @@ impl CStore { dep.name, dep_kind, CrateOrigin::IndirectDependency { - dep_root, + dep_root_for_errors, parent_private: parent_is_private, dep: &dep, }, @@ -979,9 +975,15 @@ impl CStore { }; info!("panic runtime not found -- loading {}", name); - let Some(cnum) = - self.resolve_crate(tcx, name, DUMMY_SP, CrateDepKind::Implicit, CrateOrigin::Injected) - else { + // This has to be conditional as both panic_unwind and panic_abort may be present in the + // crate graph at the same time. One of them will later be activated in dependency_formats. + let Some(cnum) = self.resolve_crate( + tcx, + name, + DUMMY_SP, + CrateDepKind::Conditional, + CrateOrigin::Injected, + ) else { return; }; let data = self.get_crate_data(cnum); @@ -1009,9 +1011,13 @@ impl CStore { info!("loading profiler"); let name = Symbol::intern(&tcx.sess.opts.unstable_opts.profiler_runtime); - let Some(cnum) = - self.resolve_crate(tcx, name, DUMMY_SP, CrateDepKind::Implicit, CrateOrigin::Injected) - else { + let Some(cnum) = self.resolve_crate( + tcx, + name, + DUMMY_SP, + CrateDepKind::Unconditional, + CrateOrigin::Injected, + ) else { return; }; let data = self.get_crate_data(cnum); @@ -1131,7 +1137,7 @@ impl CStore { tcx, name_interned, DUMMY_SP, - CrateDepKind::Explicit, + CrateDepKind::Unconditional, CrateOrigin::Extern, ); } @@ -1163,7 +1169,7 @@ impl CStore { tcx, sym::compiler_builtins, krate.spans.inner_span.shrink_to_lo(), - CrateDepKind::Explicit, + CrateDepKind::Unconditional, CrateOrigin::Injected, ) else { info!("`compiler_builtins` not resolved"); @@ -1280,7 +1286,7 @@ impl CStore { let dep_kind = if attr::contains_name(&item.attrs, sym::no_link) { CrateDepKind::MacrosOnly } else { - CrateDepKind::Explicit + CrateDepKind::Unconditional }; let cnum = @@ -1310,7 +1316,7 @@ impl CStore { span: Span, ) -> Option { let cnum = - self.resolve_crate(tcx, name, span, CrateDepKind::Explicit, CrateOrigin::Extern)?; + self.resolve_crate(tcx, name, span, CrateDepKind::Unconditional, CrateOrigin::Extern)?; self.update_extern_crate( cnum, @@ -1328,7 +1334,7 @@ impl CStore { } pub fn maybe_process_path_extern(&mut self, tcx: TyCtxt<'_>, name: Symbol) -> Option { - self.maybe_resolve_crate(tcx, name, CrateDepKind::Explicit, CrateOrigin::Extern).ok() + self.maybe_resolve_crate(tcx, name, CrateDepKind::Unconditional, CrateOrigin::Extern).ok() } } diff --git a/compiler/rustc_metadata/src/dependency_format.rs b/compiler/rustc_metadata/src/dependency_format.rs index 8054a48d37af1..7b8e8cb42e536 100644 --- a/compiler/rustc_metadata/src/dependency_format.rs +++ b/compiler/rustc_metadata/src/dependency_format.rs @@ -242,7 +242,7 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { let src = tcx.used_crate_source(cnum); if src.dylib.is_none() && !formats.contains_key(&cnum) - && tcx.dep_kind(cnum) == CrateDepKind::Explicit + && tcx.dep_kind(cnum) == CrateDepKind::Unconditional { assert!(src.rlib.is_some() || src.rmeta.is_some()); info!("adding staticlib: {}", tcx.crate_name(cnum)); @@ -355,8 +355,8 @@ fn attempt_static(tcx: TyCtxt<'_>, unavailable: &mut Vec) -> Option Linkage::Static, - CrateDepKind::MacrosOnly | CrateDepKind::Implicit => Linkage::NotLinked, + CrateDepKind::Unconditional => Linkage::Static, + CrateDepKind::MacrosOnly | CrateDepKind::Conditional => Linkage::NotLinked, }), cnum ); diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 5f7bda9c9064f..e3c2113fe71c6 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -116,8 +116,6 @@ pub(crate) struct CrateMetadata { /// Maps crate IDs as they are were seen from this crate's compilation sessions into /// IDs as they are seen from the current compilation session. cnum_map: CrateNumMap, - /// Same ID set as `cnum_map` plus maybe some injected crates like panic runtime. - dependencies: Vec, /// How to link (or not link) this crate to the currently compiled crate. dep_kind: CrateDepKind, /// Filesystem location of this crate. @@ -1897,7 +1895,6 @@ impl CrateMetadata { .collect(); let alloc_decoding_state = AllocDecodingState::new(root.interpret_alloc_index.decode(&blob).collect()); - let dependencies = cnum_map.iter().copied().collect(); // Pre-decode the DefPathHash->DefIndex table. This is a cheap operation // that does not copy any data. It just does some data verification. @@ -1915,7 +1912,6 @@ impl CrateMetadata { alloc_decoding_state, cnum, cnum_map, - dependencies, dep_kind, source: Arc::new(source), private_dep, @@ -1941,7 +1937,7 @@ impl CrateMetadata { } pub(crate) fn dependencies(&self) -> impl Iterator { - self.dependencies.iter().copied() + self.cnum_map.iter().copied() } pub(crate) fn target_modifiers(&self) -> TargetModifiers { diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index f441788fdcb6a..36fe7f380069c 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -623,15 +623,15 @@ impl CStore { self.get_crate_data(cnum).get_proc_macro_quoted_span(tcx, id) } - pub fn set_used_recursively(&mut self, tcx: TyCtxt<'_>, cnum: CrateNum) { + pub fn set_used_recursively(&mut self, cnum: CrateNum) { let cmeta = self.get_crate_data_mut(cnum); if !cmeta.used { cmeta.used = true; - let dependencies = mem::take(&mut cmeta.dependencies); - for &dep_cnum in &dependencies { - self.set_used_recursively(tcx, dep_cnum); + let cnum_map = mem::take(&mut cmeta.cnum_map); + for &dep_cnum in cnum_map.iter() { + self.set_used_recursively(dep_cnum); } - self.get_crate_data_mut(cnum).dependencies = dependencies; + self.get_crate_data_mut(cnum).cnum_map = cnum_map; } } @@ -663,11 +663,11 @@ impl CStore { if cmeta.update_extern_crate_diagnostics(extern_crate) { // Propagate the extern crate info to dependencies if it was updated. let extern_crate = ExternCrate { dependency_of: cnum, ..extern_crate }; - let dependencies = mem::take(&mut cmeta.dependencies); - for &dep_cnum in &dependencies { + let cnum_map = mem::take(&mut cmeta.cnum_map); + for &dep_cnum in cnum_map.iter() { self.update_transitive_extern_crate_diagnostics(dep_cnum, extern_crate); } - self.get_crate_data_mut(cnum).dependencies = dependencies; + self.get_crate_data_mut(cnum).cnum_map = cnum_map; } } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index b91176e3d4862..79f3f935ecd92 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -195,7 +195,6 @@ pub struct ResolverGlobalCtxt { #[derive(Debug)] pub struct ResolverAstLowering { pub legacy_const_generic_args: FxHashMap>>, - /// Resolutions for nodes that have a single resolution. pub partial_res_map: NodeMap, /// Resolutions for import nodes, which have multiple resolutions in different namespaces. diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 21191085253bd..0f206edcc7758 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -478,9 +478,6 @@ passes_rustc_legacy_const_generics_index_exceed = *[other] arguments } -passes_rustc_legacy_const_generics_index_negative = - arguments should be non-negative integers - passes_rustc_legacy_const_generics_only = #[rustc_legacy_const_generics] functions must only have const generics .label = non-const generic parameter diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 34f73212e90bd..0506728f6afc0 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -10,9 +10,10 @@ use std::collections::hash_map::Entry; use std::slice; use rustc_abi::{Align, ExternAbi, Size}; -use rustc_ast::{AttrStyle, LitKind, MetaItemKind, ast}; +use rustc_ast::{AttrStyle, MetaItemKind, ast}; use rustc_attr_parsing::{AttributeParser, Late}; use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::thin_vec::ThinVec; use rustc_errors::{DiagCtxtHandle, IntoDiagArg, MultiSpan, StashKey}; use rustc_feature::{ ACCEPTED_LANG_FEATURES, AttributeDuplicates, AttributeType, BUILTIN_ATTRIBUTE_MAP, @@ -211,6 +212,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { Attribute::Parsed(AttributeKind::MacroExport { span, .. }) => { self.check_macro_export(hir_id, *span, target) }, + Attribute::Parsed(AttributeKind::RustcLegacyConstGenerics{attr_span, fn_indexes}) => { + self.check_rustc_legacy_const_generics(item, *attr_span, fn_indexes) + }, Attribute::Parsed(AttributeKind::Doc(attr)) => self.check_doc_attrs(attr, hir_id, target), Attribute::Parsed(AttributeKind::EiiImpls(impls)) => { self.check_eii_impl(impls, target) @@ -305,9 +309,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { [sym::rustc_never_returns_null_ptr, ..] => { self.check_applied_to_fn_or_method(hir_id, attr.span(), span, target) } - [sym::rustc_legacy_const_generics, ..] => { - self.check_rustc_legacy_const_generics(hir_id, attr, span, target, item) - } [sym::rustc_lint_query_instability, ..] => { self.check_applied_to_fn_or_method(hir_id, attr.span(), span, target) } @@ -1217,33 +1218,17 @@ impl<'tcx> CheckAttrVisitor<'tcx> { /// Checks if `#[rustc_legacy_const_generics]` is applied to a function and has a valid argument. fn check_rustc_legacy_const_generics( &self, - hir_id: HirId, - attr: &Attribute, - span: Span, - target: Target, item: Option>, + attr_span: Span, + index_list: &ThinVec<(usize, Span)>, ) { - let is_function = matches!(target, Target::Fn); - if !is_function { - self.dcx().emit_err(errors::AttrShouldBeAppliedToFn { - attr_span: attr.span(), - defn_span: span, - on_crate: hir_id == CRATE_HIR_ID, - }); - return; - } - - let Some(list) = attr.meta_item_list() else { - // The attribute form is validated on AST. - return; - }; - let Some(ItemLike::Item(Item { kind: ItemKind::Fn { sig: FnSig { decl, .. }, generics, .. }, .. })) = item else { - bug!("should be a function item"); + // No error here, since it's already given by the parser + return; }; for param in generics.params { @@ -1251,7 +1236,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { hir::GenericParamKind::Const { .. } => {} _ => { self.dcx().emit_err(errors::RustcLegacyConstGenericsOnly { - attr_span: attr.span(), + attr_span, param_span: param.span, }); return; @@ -1259,34 +1244,23 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - if list.len() != generics.params.len() { + if index_list.len() != generics.params.len() { self.dcx().emit_err(errors::RustcLegacyConstGenericsIndex { - attr_span: attr.span(), + attr_span, generics_span: generics.span, }); return; } - let arg_count = decl.inputs.len() as u128 + generics.params.len() as u128; - let mut invalid_args = vec![]; - for meta in list { - if let Some(LitKind::Int(val, _)) = meta.lit().map(|lit| &lit.kind) { - if *val >= arg_count { - let span = meta.span(); - self.dcx().emit_err(errors::RustcLegacyConstGenericsIndexExceed { - span, - arg_count: arg_count as usize, - }); - return; - } - } else { - invalid_args.push(meta.span()); + let arg_count = decl.inputs.len() + generics.params.len(); + for (index, span) in index_list { + if *index >= arg_count { + self.dcx().emit_err(errors::RustcLegacyConstGenericsIndexExceed { + span: *span, + arg_count, + }); } } - - if !invalid_args.is_empty() { - self.dcx().emit_err(errors::RustcLegacyConstGenericsIndexNegative { invalid_args }); - } } /// Helper function for checking that the provided attribute is only applied to a function or diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 7abd2c703aeb4..8ead69da9916c 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -290,13 +290,6 @@ pub(crate) struct RustcLegacyConstGenericsIndexExceed { pub arg_count: usize, } -#[derive(Diagnostic)] -#[diag(passes_rustc_legacy_const_generics_index_negative)] -pub(crate) struct RustcLegacyConstGenericsIndexNegative { - #[primary_span] - pub invalid_args: Vec, -} - #[derive(Diagnostic)] #[diag(passes_rustc_dirty_clean)] pub(crate) struct RustcDirtyClean { diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index b3141406e467e..d373d6136b523 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -44,7 +44,7 @@ use rustc_arena::{DroplessArena, TypedArena}; use rustc_ast::node_id::NodeMap; use rustc_ast::{ self as ast, AngleBracketedArg, CRATE_NODE_ID, Crate, Expr, ExprKind, GenericArg, GenericArgs, - LitKind, NodeId, Path, attr, + NodeId, Path, attr, }; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::intern::Interned; @@ -54,7 +54,7 @@ use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_errors::{Applicability, Diag, ErrCode, ErrorGuaranteed, LintBuffer}; use rustc_expand::base::{DeriveResolution, SyntaxExtension, SyntaxExtensionKind}; use rustc_feature::BUILTIN_ATTRIBUTES; -use rustc_hir::attrs::StrippedCfgItem; +use rustc_hir::attrs::{AttributeKind, StrippedCfgItem}; use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{ self, CtorOf, DefKind, DocLinkResMap, LifetimeRes, MacroKinds, NonMacroAttrKind, PartialRes, @@ -62,7 +62,7 @@ use rustc_hir::def::{ }; use rustc_hir::def_id::{CRATE_DEF_ID, CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalDefIdMap}; use rustc_hir::definitions::DisambiguatorState; -use rustc_hir::{PrimTy, TraitCandidate}; +use rustc_hir::{PrimTy, TraitCandidate, find_attr}; use rustc_index::bit_set::DenseBitSet; use rustc_metadata::creader::CStore; use rustc_middle::metadata::{AmbigModChild, ModChild, Reexport}; @@ -1676,8 +1676,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { node_id_to_def_id, disambiguator: DisambiguatorState::new(), placeholder_field_indices: Default::default(), - invocation_parents, legacy_const_generic_args: Default::default(), + invocation_parents, item_generics_num_lifetimes: Default::default(), trait_impls: Default::default(), confused_type_with_std_module: Default::default(), @@ -2396,40 +2396,33 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { /// `#[rustc_legacy_const_generics]` and returns the argument index list /// from the attribute. fn legacy_const_generic_args(&mut self, expr: &Expr) -> Option> { - if let ExprKind::Path(None, path) = &expr.kind { - // Don't perform legacy const generics rewriting if the path already - // has generic arguments. - if path.segments.last().unwrap().args.is_some() { - return None; - } - - let res = self.partial_res_map.get(&expr.id)?.full_res()?; - if let Res::Def(def::DefKind::Fn, def_id) = res { - // We only support cross-crate argument rewriting. Uses - // within the same crate should be updated to use the new - // const generics style. - if def_id.is_local() { - return None; - } + let ExprKind::Path(None, path) = &expr.kind else { + return None; + }; + // Don't perform legacy const generics rewriting if the path already + // has generic arguments. + if path.segments.last().unwrap().args.is_some() { + return None; + } - if let Some(v) = self.legacy_const_generic_args.get(&def_id) { - return v.clone(); - } + let def_id = self.partial_res_map.get(&expr.id)?.full_res()?.opt_def_id()?; - let attr = self.tcx.get_attr(def_id, sym::rustc_legacy_const_generics)?; - let mut ret = Vec::new(); - for meta in attr.meta_item_list()? { - match meta.lit()?.kind { - LitKind::Int(a, _) => ret.push(a.get() as usize), - _ => panic!("invalid arg index"), - } - } - // Cache the lookup to avoid parsing attributes for an item multiple times. - self.legacy_const_generic_args.insert(def_id, Some(ret.clone())); - return Some(ret); - } + // We only support cross-crate argument rewriting. Uses + // within the same crate should be updated to use the new + // const generics style. + if def_id.is_local() { + return None; } - None + + let indexes = find_attr!( + // we can use parsed attrs here since for other crates they're already available + self.tcx.get_all_attrs(def_id), + AttributeKind::RustcLegacyConstGenerics{fn_indexes,..} => fn_indexes + ) + .map(|fn_indexes| fn_indexes.iter().map(|(num, _)| *num).collect()); + + self.legacy_const_generic_args.insert(def_id, indexes.clone()); + indexes } fn resolve_main(&mut self) { diff --git a/compiler/rustc_session/src/cstore.rs b/compiler/rustc_session/src/cstore.rs index 9d000bc28edd2..2f969aefda182 100644 --- a/compiler/rustc_session/src/cstore.rs +++ b/compiler/rustc_session/src/cstore.rs @@ -39,12 +39,13 @@ impl CrateSource { pub enum CrateDepKind { /// A dependency that is only used for its macros. MacrosOnly, - /// A dependency that is always injected into the dependency list and so - /// doesn't need to be linked to an rlib, e.g., the injected panic runtime. - Implicit, + /// A dependency that is injected into the crate graph but which only + /// sometimes needs to actually be linked in, e.g., the injected panic runtime. + Conditional, /// A dependency that is required by an rlib version of this crate. - /// Ordinary `extern crate`s result in `Explicit` dependencies. - Explicit, + /// Ordinary `extern crate`s as well as most injected dependencies result + /// in `Unconditional` dependencies. + Unconditional, } impl CrateDepKind { @@ -52,7 +53,7 @@ impl CrateDepKind { pub fn macros_only(self) -> bool { match self { CrateDepKind::MacrosOnly => true, - CrateDepKind::Implicit | CrateDepKind::Explicit => false, + CrateDepKind::Conditional | CrateDepKind::Unconditional => false, } } } diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index c76e345bb7b64..3d500694c978b 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1686,6 +1686,7 @@ supported_targets! { ("riscv32imac-unknown-xous-elf", riscv32imac_unknown_xous_elf), ("riscv32gc-unknown-linux-gnu", riscv32gc_unknown_linux_gnu), ("riscv32gc-unknown-linux-musl", riscv32gc_unknown_linux_musl), + ("riscv64im-unknown-none-elf", riscv64im_unknown_none_elf), ("riscv64imac-unknown-none-elf", riscv64imac_unknown_none_elf), ("riscv64gc-unknown-none-elf", riscv64gc_unknown_none_elf), ("riscv64gc-unknown-linux-gnu", riscv64gc_unknown_linux_gnu), diff --git a/compiler/rustc_target/src/spec/targets/riscv64im_unknown_none_elf.rs b/compiler/rustc_target/src/spec/targets/riscv64im_unknown_none_elf.rs new file mode 100644 index 0000000000000..6aae40a3f90de --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/riscv64im_unknown_none_elf.rs @@ -0,0 +1,35 @@ +use crate::spec::{ + Arch, Cc, CodeModel, LinkerFlavor, Lld, PanicStrategy, RelocModel, Target, TargetMetadata, + TargetOptions, +}; + +pub(crate) fn target() -> Target { + Target { + data_layout: "e-m:e-p:64:64-i64:64-i128:128-n32:64-S128".into(), + llvm_target: "riscv64".into(), + metadata: TargetMetadata { + description: Some("Bare RISC-V (RV64IM ISA)".into()), + tier: Some(3), + host_tools: Some(false), + std: Some(false), + }, + pointer_width: 64, + arch: Arch::RiscV64, + + options: TargetOptions { + linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), + linker: Some("rust-lld".into()), + cpu: "generic-rv64".into(), + max_atomic_width: Some(64), + atomic_cas: false, + features: "+m,+forced-atomics".into(), + llvm_abiname: "lp64".into(), + panic_strategy: PanicStrategy::Abort, + relocation_model: RelocModel::Static, + code_model: Some(CodeModel::Medium), + emit_debug_gdb_scripts: false, + eh_frame_header: false, + ..Default::default() + }, + } +} diff --git a/library/std/src/sync/mpmc/mod.rs b/library/std/src/sync/mpmc/mod.rs index 673033034eff5..ee9795a528127 100644 --- a/library/std/src/sync/mpmc/mod.rs +++ b/library/std/src/sync/mpmc/mod.rs @@ -6,9 +6,10 @@ //! * [`Sender`] //! * [`Receiver`] //! -//! [`Sender`]s are used to send data to a set of [`Receiver`]s. Both -//! sender and receiver are cloneable (multi-producer) such that many threads can send -//! simultaneously to receivers (multi-consumer). +//! [`Sender`]s are used to send data to a set of [`Receiver`]s where each item +//! sent is delivered to (at most) one receiver. Both sender and receiver are +//! cloneable (multi-producer) such that many threads can send simultaneously +//! to receivers (multi-consumer). //! //! These channels come in two flavors: //! diff --git a/library/std/src/sys/fs/uefi.rs b/library/std/src/sys/fs/uefi.rs index 44f8b6e80f903..21ef70b43dcd6 100644 --- a/library/std/src/sys/fs/uefi.rs +++ b/library/std/src/sys/fs/uefi.rs @@ -9,7 +9,6 @@ use crate::path::{Path, PathBuf}; use crate::sys::time::SystemTime; use crate::sys::{helpers, unsupported}; -#[expect(dead_code)] const FILE_PERMISSIONS_MASK: u64 = r_efi::protocols::file::READ_ONLY; pub struct File(!); @@ -109,7 +108,6 @@ impl FilePermissions { Self(attr & r_efi::protocols::file::READ_ONLY != 0) } - #[expect(dead_code)] const fn to_attr(&self) -> u64 { if self.0 { r_efi::protocols::file::READ_ONLY } else { 0 } } @@ -366,16 +364,40 @@ pub fn rename(_old: &Path, _new: &Path) -> io::Result<()> { unsupported() } -pub fn set_perm(_p: &Path, _perm: FilePermissions) -> io::Result<()> { - unsupported() +pub fn set_perm(p: &Path, perm: FilePermissions) -> io::Result<()> { + let f = uefi_fs::File::from_path(p, file::MODE_READ | file::MODE_WRITE, 0)?; + let mut file_info = f.file_info()?; + + unsafe { + (*file_info.as_mut_ptr()).attribute = + ((*file_info.as_ptr()).attribute & !FILE_PERMISSIONS_MASK) | perm.to_attr() + }; + + f.set_file_info(file_info) } -pub fn set_times(_p: &Path, _times: FileTimes) -> io::Result<()> { - unsupported() +pub fn set_times(p: &Path, times: FileTimes) -> io::Result<()> { + // UEFI does not support symlinks + set_times_nofollow(p, times) } -pub fn set_times_nofollow(_p: &Path, _times: FileTimes) -> io::Result<()> { - unsupported() +pub fn set_times_nofollow(p: &Path, times: FileTimes) -> io::Result<()> { + let f = uefi_fs::File::from_path(p, file::MODE_READ | file::MODE_WRITE, 0)?; + let mut file_info = f.file_info()?; + + if let Some(x) = times.accessed { + unsafe { + (*file_info.as_mut_ptr()).last_access_time = uefi_fs::systemtime_to_uefi(x); + } + } + + if let Some(x) = times.modified { + unsafe { + (*file_info.as_mut_ptr()).modification_time = uefi_fs::systemtime_to_uefi(x); + } + } + + f.set_file_info(file_info) } pub fn rmdir(p: &Path) -> io::Result<()> { @@ -560,6 +582,17 @@ mod uefi_fs { if r.is_error() { Err(io::Error::from_raw_os_error(r.as_usize())) } else { Ok(info) } } + pub(crate) fn set_file_info(&self, mut info: UefiBox) -> io::Result<()> { + let file_ptr = self.0.as_ptr(); + let mut info_id = file::INFO_ID; + + let r = unsafe { + ((*file_ptr).set_info)(file_ptr, &mut info_id, info.len(), info.as_mut_ptr().cast()) + }; + + if r.is_error() { Err(io::Error::from_raw_os_error(r.as_usize())) } else { Ok(()) } + } + pub(crate) fn delete(self) -> io::Result<()> { let file_ptr = self.0.as_ptr(); let r = unsafe { ((*file_ptr).delete)(file_ptr) }; @@ -643,8 +676,7 @@ mod uefi_fs { } /// Convert to UEFI Time with the current timezone. - #[expect(dead_code)] - fn systemtime_to_uefi(time: SystemTime) -> r_efi::efi::Time { + pub(crate) fn systemtime_to_uefi(time: SystemTime) -> r_efi::efi::Time { let now = time::system_time_internal::now(); time.to_uefi_loose(now.timezone, now.daylight) } diff --git a/library/std/src/sys/pal/uefi/helpers.rs b/library/std/src/sys/pal/uefi/helpers.rs index bfad6491e3219..d059be010e98b 100644 --- a/library/std/src/sys/pal/uefi/helpers.rs +++ b/library/std/src/sys/pal/uefi/helpers.rs @@ -802,6 +802,10 @@ impl UefiBox { pub(crate) fn as_ptr(&self) -> *const T { self.inner.as_ptr().cast() } + + pub(crate) const fn len(&self) -> usize { + self.size + } } impl Drop for UefiBox { diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 82cc25f123bc9..ed154133dec2e 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -7,7 +7,7 @@ //! goes along from the output of the previous stage. use std::borrow::Cow; -use std::collections::{HashMap, HashSet}; +use std::collections::{BTreeMap, HashMap, HashSet}; use std::ffi::OsStr; use std::io::BufReader; use std::io::prelude::*; @@ -19,7 +19,7 @@ use serde_derive::Deserialize; #[cfg(feature = "tracing")] use tracing::span; -use crate::core::build_steps::gcc::{Gcc, GccOutput, add_cg_gcc_cargo_flags}; +use crate::core::build_steps::gcc::{Gcc, GccOutput, GccTargetPair, add_cg_gcc_cargo_flags}; use crate::core::build_steps::tool::{RustcPrivateCompilers, SourceType, copy_lld_artifacts}; use crate::core::build_steps::{dist, llvm}; use crate::core::builder; @@ -1232,19 +1232,6 @@ pub fn rustc_cargo( // . cargo.rustflag("-Zon-broken-pipe=kill"); - // We want to link against registerEnzyme and in the future we want to use additional - // functionality from Enzyme core. For that we need to link against Enzyme. - if builder.config.llvm_enzyme { - let arch = builder.build.host_target; - let enzyme_dir = builder.build.out.join(arch).join("enzyme").join("lib"); - cargo.rustflag("-L").rustflag(enzyme_dir.to_str().expect("Invalid path")); - - if let Some(llvm_config) = builder.llvm_config(builder.config.host_target) { - let llvm_version_major = llvm::get_llvm_version_major(builder, &llvm_config); - cargo.rustflag("-l").rustflag(&format!("Enzyme-{llvm_version_major}")); - } - } - // Building with protected visibility reduces the number of dynamic relocations needed, giving // us a faster startup time. However GNU ld < 2.40 will error if we try to link a shared object // with direct references to protected symbols, so for now we only use protected symbols if @@ -1576,17 +1563,98 @@ impl Step for RustcLink { } } +/// Set of `libgccjit` dylibs that can be used by `cg_gcc` to compile code for a set of targets. +#[derive(Clone)] +pub struct GccDylibSet { + dylibs: BTreeMap, + host_pair: GccTargetPair, +} + +impl GccDylibSet { + /// Returns the libgccjit.so dylib that corresponds to a host target on which `cg_gcc` will be + /// executed, and which will target the host. So e.g. if `cg_gcc` will be executed on + /// x86_64-unknown-linux-gnu, the host dylib will be for compilation pair + /// `(x86_64-unknown-linux-gnu, x86_64-unknown-linux-gnu)`. + fn host_dylib(&self) -> &GccOutput { + self.dylibs.get(&self.host_pair).unwrap_or_else(|| { + panic!("libgccjit.so was not built for host target {}", self.host_pair) + }) + } + + /// Install the libgccjit dylibs to the corresponding target directories of the given compiler. + /// cg_gcc know how to search for the libgccjit dylibs in these directories, according to the + /// (host, target) pair that is being compiled by rustc and cg_gcc. + pub fn install_to(&self, builder: &Builder<'_>, compiler: Compiler) { + if builder.config.dry_run() { + return; + } + + // /lib//codegen-backends + let cg_sysroot = builder.sysroot_codegen_backends(compiler); + + for (target_pair, libgccjit) in &self.dylibs { + assert_eq!( + target_pair.host(), + compiler.host, + "Trying to install libgccjit ({target_pair}) to a compiler with a different host ({})", + compiler.host + ); + let libgccjit = libgccjit.libgccjit(); + let target_filename = libgccjit.file_name().unwrap().to_str().unwrap(); + + // If we build libgccjit ourselves, then `libgccjit` can actually be a symlink. + // In that case, we have to resolve it first, otherwise we'd create a symlink to a + // symlink, which wouldn't work. + let actual_libgccjit_path = t!( + libgccjit.canonicalize(), + format!("Cannot find libgccjit at {}", libgccjit.display()) + ); + + // /lib//libgccjit.so + let dest_dir = cg_sysroot.join("lib").join(target_pair.target()); + t!(fs::create_dir_all(&dest_dir)); + let dst = dest_dir.join(target_filename); + builder.copy_link(&actual_libgccjit_path, &dst, FileType::NativeLibrary); + } + } +} + /// Output of the `compile::GccCodegenBackend` step. -/// It includes the path to the libgccjit library on which this backend depends. +/// +/// It contains paths to all built libgccjit libraries on which this backend depends here. #[derive(Clone)] pub struct GccCodegenBackendOutput { stamp: BuildStamp, - gcc: GccOutput, + dylib_set: GccDylibSet, } +/// Builds the GCC codegen backend (`cg_gcc`). +/// The `cg_gcc` backend uses `libgccjit`, which requires a separate build for each +/// `host -> target` pair. So if you are on linux-x64 and build for linux-aarch64, +/// you will need at least: +/// - linux-x64 -> linux-x64 libgccjit (for building host code like proc macros) +/// - linux-x64 -> linux-aarch64 libgccjit (for the aarch64 target code) +/// +/// We model this by having a single cg_gcc for a given host target, which contains one +/// libgccjit per (host, target) pair. +/// Note that the host target is taken from `self.compilers.target_compiler.host`. #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct GccCodegenBackend { compilers: RustcPrivateCompilers, + targets: Vec, +} + +impl GccCodegenBackend { + /// Build `cg_gcc` that will run on host `H` (`compilers.target_compiler.host`) and will be + /// able to produce code target pairs (`H`, `T`) for all `T` from `targets`. + pub fn for_targets( + compilers: RustcPrivateCompilers, + mut targets: Vec, + ) -> Self { + // Sort targets to improve step cache hits + targets.sort(); + Self { compilers, targets } + } } impl Step for GccCodegenBackend { @@ -1599,23 +1667,34 @@ impl Step for GccCodegenBackend { } fn make_run(run: RunConfig<'_>) { - run.builder.ensure(GccCodegenBackend { - compilers: RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target), - }); + // By default, build cg_gcc that will only be able to compile native code for the given + // host target. + let compilers = RustcPrivateCompilers::new(run.builder, run.builder.top_stage, run.target); + run.builder.ensure(GccCodegenBackend { compilers, targets: vec![run.target] }); } fn run(self, builder: &Builder<'_>) -> Self::Output { - let target = self.compilers.target(); + let host = self.compilers.target(); let build_compiler = self.compilers.build_compiler(); let stamp = build_stamp::codegen_backend_stamp( builder, build_compiler, - target, + host, &CodegenBackendKind::Gcc, ); - let gcc = builder.ensure(Gcc { target }); + let dylib_set = GccDylibSet { + dylibs: self + .targets + .iter() + .map(|&target| { + let target_pair = GccTargetPair::for_target_pair(host, target); + (target_pair, builder.ensure(Gcc { target_pair })) + }) + .collect(), + host_pair: GccTargetPair::for_native_build(host), + }; if builder.config.keep_stage.contains(&build_compiler.stage) { trace!("`keep-stage` requested"); @@ -1625,7 +1704,7 @@ impl Step for GccCodegenBackend { ); // Codegen backends are linked separately from this step today, so we don't do // anything here. - return GccCodegenBackendOutput { stamp, gcc }; + return GccCodegenBackendOutput { stamp, dylib_set }; } let mut cargo = builder::Cargo::new( @@ -1633,21 +1712,21 @@ impl Step for GccCodegenBackend { build_compiler, Mode::Codegen, SourceType::InTree, - target, + host, Kind::Build, ); cargo.arg("--manifest-path").arg(builder.src.join("compiler/rustc_codegen_gcc/Cargo.toml")); - rustc_cargo_env(builder, &mut cargo, target); + rustc_cargo_env(builder, &mut cargo, host); - add_cg_gcc_cargo_flags(&mut cargo, &gcc); + add_cg_gcc_cargo_flags(&mut cargo, dylib_set.host_dylib()); let _guard = - builder.msg(Kind::Build, "codegen backend gcc", Mode::Codegen, build_compiler, target); + builder.msg(Kind::Build, "codegen backend gcc", Mode::Codegen, build_compiler, host); let files = run_cargo(builder, cargo, vec![], &stamp, vec![], false, false); GccCodegenBackendOutput { stamp: write_codegen_backend_stamp(stamp, files, builder.config.dry_run()), - gcc, + dylib_set, } } @@ -2324,12 +2403,65 @@ impl Step for Assemble { copy_codegen_backends_to_sysroot(builder, stamp, target_compiler); } CodegenBackendKind::Gcc => { - let output = - builder.ensure(GccCodegenBackend { compilers: prepare_compilers() }); + // We need to build cg_gcc for the host target of the compiler which we + // build here, which is `target_compiler`. + // But we also need to build libgccjit for some additional targets, in + // the most general case. + // 1. We need to build (target_compiler.host, stdlib target) libgccjit + // for all stdlibs that we build, so that cg_gcc can be used to build code + // for all those targets. + // 2. We need to build (target_compiler.host, target_compiler.host) + // libgccjit, so that the target compiler can compile host code (e.g. proc + // macros). + // 3. We need to build (target_compiler.host, host target) libgccjit + // for all *host targets* that we build, so that cg_gcc can be used to + // build a (possibly cross-compiled) stage 2+ rustc. + // + // Assume that we are on host T1 and we do a stage2 build of rustc for T2. + // We want the T2 rustc compiler to be able to use cg_gcc and build code + // for T2 (host) and T3 (target). We also want to build the stage2 compiler + // itself using cg_gcc. + // This could correspond to the following bootstrap invocation: + // `x build rustc --build T1 --host T2 --target T3 --set codegen-backends=['gcc', 'llvm']` + // + // For that, we will need the following GCC target pairs: + // 1. T1 -> T2 (to cross-compile a T2 rustc using cg_gcc running on T1) + // 2. T2 -> T2 (to build host code with the stage 2 rustc running on T2) + // 3. T2 -> T3 (to cross-compile code with the stage 2 rustc running on T2) + // + // FIXME: this set of targets is *maximal*, in reality we might need + // less libgccjits at this current build stage. Try to reduce the set of + // GCC dylibs built below by taking a look at the current stage and whether + // cg_gcc is used as the default codegen backend. + + let compilers = prepare_compilers(); + + // The left side of the target pairs below is implied. It has to match the + // host target on which cg_gcc will run, which is the host target of + // `target_compiler`. We only pass the right side of the target pairs to + // the `GccCodegenBackend` constructor. + let mut targets = HashSet::new(); + // Add all host targets, so that we are able to build host code in this + // bootstrap invocation using cg_gcc. + for target in &builder.hosts { + targets.insert(*target); + } + // Add all stdlib targets, so that the built rustc can produce code for them + for target in &builder.targets { + targets.insert(*target); + } + // Add the host target of the built rustc itself, so that it can build + // host code (e.g. proc macros) using cg_gcc. + targets.insert(compilers.target_compiler().host); + + let output = builder.ensure(GccCodegenBackend::for_targets( + compilers, + targets.into_iter().collect(), + )); copy_codegen_backends_to_sysroot(builder, output.stamp, target_compiler); - // Also copy libgccjit to the library sysroot, so that it is available for - // the codegen backend. - output.gcc.install_to(builder, &rustc_libdir); + // Also copy all requires libgccjit dylibs to the corresponding + // library sysroots, so that they are available for the codegen backend. + output.dylib_set.install_to(builder, target_compiler); } CodegenBackendKind::Llvm | CodegenBackendKind::Custom(_) => continue, } diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index caf0af35e401d..cbbdc7e024195 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -21,6 +21,7 @@ use tracing::instrument; use crate::core::build_steps::compile::{get_codegen_backend_file, normalize_codegen_backend_name}; use crate::core::build_steps::doc::DocumentationFormat; +use crate::core::build_steps::gcc::GccTargetPair; use crate::core::build_steps::tool::{ self, RustcPrivateCompilers, ToolTargetBuildMode, get_tool_target_compiler, }; @@ -2856,8 +2857,9 @@ impl Step for Gcc { fn run(self, builder: &Builder<'_>) -> Self::Output { let tarball = Tarball::new(builder, "gcc", &self.target.triple); - let output = builder.ensure(super::gcc::Gcc { target: self.target }); - tarball.add_file(&output.libgccjit, "lib", FileType::NativeLibrary); + let output = builder + .ensure(super::gcc::Gcc { target_pair: GccTargetPair::for_native_build(self.target) }); + tarball.add_file(output.libgccjit(), "lib", FileType::NativeLibrary); tarball.generate() } diff --git a/src/bootstrap/src/core/build_steps/gcc.rs b/src/bootstrap/src/core/build_steps/gcc.rs index fc87c48f17b68..648a2bea41819 100644 --- a/src/bootstrap/src/core/build_steps/gcc.rs +++ b/src/bootstrap/src/core/build_steps/gcc.rs @@ -8,49 +8,69 @@ //! GCC and compiler-rt are essentially just wired up to everything else to //! ensure that they're always in place if needed. +use std::fmt::{Display, Formatter}; use std::fs; use std::path::{Path, PathBuf}; use std::sync::OnceLock; -use crate::FileType; use crate::core::builder::{Builder, Cargo, Kind, RunConfig, ShouldRun, Step}; use crate::core::config::TargetSelection; use crate::utils::build_stamp::{BuildStamp, generate_smart_stamp_hash}; use crate::utils::exec::command; use crate::utils::helpers::{self, t}; +/// GCC cannot cross-compile from a single binary to multiple targets. +/// So we need to have a separate GCC dylib for each (host, target) pair. +/// We represent this explicitly using this struct. +#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] +pub struct GccTargetPair { + /// Target on which the libgccjit.so dylib will be executed. + host: TargetSelection, + /// Target for which the libgccjit.so dylib will generate assembly. + target: TargetSelection, +} + +impl GccTargetPair { + /// Create a target pair for a GCC that will run on `target` and generate assembly for `target`. + pub fn for_native_build(target: TargetSelection) -> Self { + Self { host: target, target } + } + + /// Create a target pair for a GCC that will run on `host` and generate assembly for `target`. + /// This may be cross-compilation if `host != target`. + pub fn for_target_pair(host: TargetSelection, target: TargetSelection) -> Self { + Self { host, target } + } + + pub fn host(&self) -> TargetSelection { + self.host + } + + pub fn target(&self) -> TargetSelection { + self.target + } +} + +impl Display for GccTargetPair { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "{} -> {}", self.host, self.target) + } +} + #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct Gcc { - pub target: TargetSelection, + pub target_pair: GccTargetPair, } #[derive(Clone)] pub struct GccOutput { - pub libgccjit: PathBuf, - target: TargetSelection, + /// Path to a built or downloaded libgccjit. + libgccjit: PathBuf, } impl GccOutput { - /// Install the required libgccjit library file(s) to the specified `path`. - pub fn install_to(&self, builder: &Builder<'_>, directory: &Path) { - if builder.config.dry_run() { - return; - } - - let target_filename = self.libgccjit.file_name().unwrap().to_str().unwrap().to_string(); - - // If we build libgccjit ourselves, then `self.libgccjit` can actually be a symlink. - // In that case, we have to resolve it first, otherwise we'd create a symlink to a symlink, - // which wouldn't work. - let actual_libgccjit_path = t!( - self.libgccjit.canonicalize(), - format!("Cannot find libgccjit at {}", self.libgccjit.display()) - ); - - let dest_dir = directory.join("rustlib").join(self.target).join("lib"); - t!(fs::create_dir_all(&dest_dir)); - let dst = dest_dir.join(target_filename); - builder.copy_link(&actual_libgccjit_path, &dst, FileType::NativeLibrary); + pub fn libgccjit(&self) -> &Path { + &self.libgccjit } } @@ -64,33 +84,38 @@ impl Step for Gcc { } fn make_run(run: RunConfig<'_>) { - run.builder.ensure(Gcc { target: run.target }); + // By default, we build libgccjit that can do native compilation (no cross-compilation) + // on a given target. + run.builder + .ensure(Gcc { target_pair: GccTargetPair { host: run.target, target: run.target } }); } /// Compile GCC (specifically `libgccjit`) for `target`. fn run(self, builder: &Builder<'_>) -> Self::Output { - let target = self.target; + let target_pair = self.target_pair; // If GCC has already been built, we avoid building it again. - let metadata = match get_gcc_build_status(builder, target) { - GccBuildStatus::AlreadyBuilt(path) => return GccOutput { libgccjit: path, target }, + let metadata = match get_gcc_build_status(builder, target_pair) { + GccBuildStatus::AlreadyBuilt(path) => return GccOutput { libgccjit: path }, GccBuildStatus::ShouldBuild(m) => m, }; - let _guard = builder.msg_unstaged(Kind::Build, "GCC", target); + let action = Kind::Build.description(); + let msg = format!("{action} GCC for {target_pair}"); + let _guard = builder.group(&msg); t!(metadata.stamp.remove()); let _time = helpers::timeit(builder); let libgccjit_path = libgccjit_built_path(&metadata.install_dir); if builder.config.dry_run() { - return GccOutput { libgccjit: libgccjit_path, target }; + return GccOutput { libgccjit: libgccjit_path }; } - build_gcc(&metadata, builder, target); + build_gcc(&metadata, builder, target_pair); t!(metadata.stamp.write()); - GccOutput { libgccjit: libgccjit_path, target } + GccOutput { libgccjit: libgccjit_path } } } @@ -111,15 +136,27 @@ pub enum GccBuildStatus { /// are available for the given target. /// Returns a path to the libgccjit.so file. #[cfg(not(test))] -fn try_download_gcc(builder: &Builder<'_>, target: TargetSelection) -> Option { +fn try_download_gcc(builder: &Builder<'_>, target_pair: GccTargetPair) -> Option { use build_helper::git::PathFreshness; // Try to download GCC from CI if configured and available if !matches!(builder.config.gcc_ci_mode, crate::core::config::GccCiMode::DownloadFromCi) { return None; } - if target != "x86_64-unknown-linux-gnu" { - eprintln!("GCC CI download is only available for the `x86_64-unknown-linux-gnu` target"); + + // We currently do not support downloading CI GCC if the host/target pair doesn't match. + if target_pair.host != target_pair.target { + eprintln!( + "GCC CI download is not available when the host ({}) does not equal the compilation target ({}).", + target_pair.host, target_pair.target + ); + return None; + } + + if target_pair.host != "x86_64-unknown-linux-gnu" { + eprintln!( + "GCC CI download is only available for the `x86_64-unknown-linux-gnu` host/target" + ); return None; } let source = detect_gcc_freshness( @@ -132,7 +169,7 @@ fn try_download_gcc(builder: &Builder<'_>, target: TargetSelection) -> Option { // Download from upstream CI - let root = ci_gcc_root(&builder.config, target); + let root = ci_gcc_root(&builder.config, target_pair.target); let gcc_stamp = BuildStamp::new(&root).with_prefix("gcc").add_stamp(&upstream); if !gcc_stamp.is_up_to_date() && !builder.config.dry_run() { builder.config.download_ci_gcc(&upstream, &root); @@ -158,7 +195,7 @@ fn try_download_gcc(builder: &Builder<'_>, target: TargetSelection) -> Option, _target: TargetSelection) -> Option { +fn try_download_gcc(_builder: &Builder<'_>, _target_pair: GccTargetPair) -> Option { None } @@ -167,11 +204,37 @@ fn try_download_gcc(_builder: &Builder<'_>, _target: TargetSelection) -> Option< /// /// It's used to avoid busting caches during x.py check -- if we've already built /// GCC, it's fine for us to not try to avoid doing so. -pub fn get_gcc_build_status(builder: &Builder<'_>, target: TargetSelection) -> GccBuildStatus { - if let Some(path) = try_download_gcc(builder, target) { +pub fn get_gcc_build_status(builder: &Builder<'_>, target_pair: GccTargetPair) -> GccBuildStatus { + // Prefer taking externally provided prebuilt libgccjit dylib + if let Some(dir) = &builder.config.libgccjit_libs_dir { + // The dir structure should be ///libgccjit.so + let host_dir = dir.join(target_pair.host); + let path = host_dir.join(target_pair.target).join("libgccjit.so"); + if path.exists() { + return GccBuildStatus::AlreadyBuilt(path); + } else { + builder.info(&format!( + "libgccjit.so for `{target_pair}` was not found at `{}`", + path.display() + )); + + if target_pair.host != target_pair.target || target_pair.host != builder.host_target { + eprintln!( + "info: libgccjit.so for `{target_pair}` was not found at `{}`", + path.display() + ); + eprintln!("error: we do not support downloading or building a GCC cross-compiler"); + std::process::exit(1); + } + } + } + + // If not available, try to download from CI + if let Some(path) = try_download_gcc(builder, target_pair) { return GccBuildStatus::AlreadyBuilt(path); } + // If not available, try to build (or use already built libgccjit from disk) static STAMP_HASH_MEMO: OnceLock = OnceLock::new(); let smart_stamp_hash = STAMP_HASH_MEMO.get_or_init(|| { generate_smart_stamp_hash( @@ -185,8 +248,8 @@ pub fn get_gcc_build_status(builder: &Builder<'_>, target: TargetSelection) -> G builder.config.update_submodule("src/gcc"); let root = builder.src.join("src/gcc"); - let out_dir = builder.gcc_out(target).join("build"); - let install_dir = builder.gcc_out(target).join("install"); + let out_dir = gcc_out(builder, target_pair).join("build"); + let install_dir = gcc_out(builder, target_pair).join("install"); let stamp = BuildStamp::new(&out_dir).with_prefix("gcc").add_stamp(smart_stamp_hash); @@ -215,15 +278,20 @@ pub fn get_gcc_build_status(builder: &Builder<'_>, target: TargetSelection) -> G GccBuildStatus::ShouldBuild(Meta { stamp, out_dir, install_dir, root }) } +fn gcc_out(builder: &Builder<'_>, pair: GccTargetPair) -> PathBuf { + builder.out.join(pair.host).join("gcc").join(pair.target) +} + /// Returns the path to a libgccjit.so file in the install directory of GCC. fn libgccjit_built_path(install_dir: &Path) -> PathBuf { install_dir.join("lib/libgccjit.so") } -fn build_gcc(metadata: &Meta, builder: &Builder<'_>, target: TargetSelection) { - if builder.build.cc_tool(target).is_like_clang() - || builder.build.cxx_tool(target).is_like_clang() - { +fn build_gcc(metadata: &Meta, builder: &Builder<'_>, target_pair: GccTargetPair) { + // Target on which libgccjit.so will be executed. Here we will generate a dylib with + // instructions for that target. + let host = target_pair.host; + if builder.build.cc_tool(host).is_like_clang() || builder.build.cxx_tool(host).is_like_clang() { panic!( "Attempting to build GCC using Clang, which is known to misbehave. Please use GCC as the host C/C++ compiler. " ); @@ -241,7 +309,7 @@ fn build_gcc(metadata: &Meta, builder: &Builder<'_>, target: TargetSelection) { // builds. // Therefore, we first copy the whole source directory to the build directory, and perform the // build from there. - let src_dir = builder.gcc_out(target).join("src"); + let src_dir = gcc_out(builder, target_pair).join("src"); if src_dir.exists() { builder.remove_dir(&src_dir); } @@ -259,7 +327,7 @@ fn build_gcc(metadata: &Meta, builder: &Builder<'_>, target: TargetSelection) { .arg("--disable-multilib") .arg(format!("--prefix={}", install_dir.display())); - let cc = builder.build.cc(target).display().to_string(); + let cc = builder.build.cc(host).display().to_string(); let cc = builder .build .config @@ -268,7 +336,7 @@ fn build_gcc(metadata: &Meta, builder: &Builder<'_>, target: TargetSelection) { .map_or_else(|| cc.clone(), |ccache| format!("{ccache} {cc}")); configure_cmd.env("CC", cc); - if let Ok(ref cxx) = builder.build.cxx(target) { + if let Ok(ref cxx) = builder.build.cxx(host) { let cxx = cxx.display().to_string(); let cxx = builder .build diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 67214d832444c..0abf5eff7f2fb 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -16,7 +16,7 @@ use build_helper::exit; use crate::core::build_steps::compile::{Std, run_cargo}; use crate::core::build_steps::doc::{DocumentationFormat, prepare_doc_compiler}; -use crate::core::build_steps::gcc::{Gcc, add_cg_gcc_cargo_flags}; +use crate::core::build_steps::gcc::{Gcc, GccTargetPair, add_cg_gcc_cargo_flags}; use crate::core::build_steps::llvm::get_llvm_version; use crate::core::build_steps::run::{get_completion_paths, get_help_path}; use crate::core::build_steps::synthetic_targets::MirOptPanicAbortSyntheticTarget; @@ -3960,7 +3960,7 @@ impl Step for CodegenGCC { let compilers = self.compilers; let target = self.target; - let gcc = builder.ensure(Gcc { target }); + let gcc = builder.ensure(Gcc { target_pair: GccTargetPair::for_native_build(target) }); builder.ensure( compile::Std::new(compilers.build_compiler(), target) @@ -4001,12 +4001,13 @@ impl Step for CodegenGCC { .arg("--use-backend") .arg("gcc") .arg("--gcc-path") - .arg(gcc.libgccjit.parent().unwrap()) + .arg(gcc.libgccjit().parent().unwrap()) .arg("--out-dir") .arg(builder.stage_out(compilers.build_compiler(), Mode::Codegen).join("cg_gcc")) .arg("--release") .arg("--mini-tests") .arg("--std-tests"); + cargo.args(builder.config.test_args()); cargo.into_cmd().run(builder); diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index 2f493658ec0ec..a81b8ccb9140a 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -188,6 +188,7 @@ pub struct Config { // gcc codegen options pub gcc_ci_mode: GccCiMode, + pub libgccjit_libs_dir: Option, // rust codegen options pub rust_optimize: RustOptimize, @@ -620,7 +621,10 @@ impl Config { vendor: dist_vendor, } = toml.dist.unwrap_or_default(); - let Gcc { download_ci_gcc: gcc_download_ci_gcc } = toml.gcc.unwrap_or_default(); + let Gcc { + download_ci_gcc: gcc_download_ci_gcc, + libgccjit_libs_dir: gcc_libgccjit_libs_dir, + } = toml.gcc.unwrap_or_default(); if rust_bootstrap_override_lld.is_some() && rust_bootstrap_override_lld_legacy.is_some() { panic!( @@ -1346,6 +1350,7 @@ impl Config { keep_stage: flags_keep_stage, keep_stage_std: flags_keep_stage_std, libdir: install_libdir.map(PathBuf::from), + libgccjit_libs_dir: gcc_libgccjit_libs_dir, library_docs_private_items: build_library_docs_private_items.unwrap_or(false), lld_enabled, lldb: build_lldb.map(PathBuf::from), diff --git a/src/bootstrap/src/core/config/toml/gcc.rs b/src/bootstrap/src/core/config/toml/gcc.rs index 9ea697edf159e..94d15a9baaff9 100644 --- a/src/bootstrap/src/core/config/toml/gcc.rs +++ b/src/bootstrap/src/core/config/toml/gcc.rs @@ -15,5 +15,6 @@ define_config! { #[derive(Default)] struct Gcc { download_ci_gcc: Option = "download-ci-gcc", + libgccjit_libs_dir: Option = "libgccjit-libs-dir", } } diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs index 50d8154014bbc..d1f706fd9c3e8 100644 --- a/src/bootstrap/src/core/sanity.rs +++ b/src/bootstrap/src/core/sanity.rs @@ -41,6 +41,7 @@ const STAGE0_MISSING_TARGETS: &[&str] = &[ "sparc64-unknown-helenos", // just a dummy comment so the list doesn't get onelined "riscv64gc-unknown-redox", + "riscv64im-unknown-none-elf", "hexagon-unknown-qurt", ]; diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index a31eb0c1c8012..adae9a1b8b081 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -975,10 +975,6 @@ impl Build { self.out.join(&*target.triple).join("enzyme") } - fn gcc_out(&self, target: TargetSelection) -> PathBuf { - self.out.join(&*target.triple).join("gcc") - } - fn lld_out(&self, target: TargetSelection) -> PathBuf { self.out.join(target).join("lld") } diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index 37ad5f09897fa..d7990c2316d15 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -601,4 +601,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[ severity: ChangeSeverity::Info, summary: "New options `rust.rustflags` for all targets and per-target `rustflags` that will pass specified flags to rustc for all stages. Target-specific flags override global `rust.rustflags` ones.", }, + ChangeInfo { + change_id: 149354, + severity: ChangeSeverity::Info, + summary: "New option `gcc.libgccjit-libs-dir` to specify which libgccjit.so to use per target.", + }, ]; diff --git a/src/doc/rustc-dev-guide/src/tests/codegen-backend-tests/cg_gcc.md b/src/doc/rustc-dev-guide/src/tests/codegen-backend-tests/cg_gcc.md index 4325cc58797f8..7a1c5b9a98c03 100644 --- a/src/doc/rustc-dev-guide/src/tests/codegen-backend-tests/cg_gcc.md +++ b/src/doc/rustc-dev-guide/src/tests/codegen-backend-tests/cg_gcc.md @@ -77,6 +77,26 @@ will be downloaded from CI or built locally. The default value is `true`, which will download GCC from CI if there are no local changes to the GCC sources and the given host target is available on CI. +## Providing your own GCC + +There are cases where you will want to provide yourself the `libgccjit.so` file. +One such case is when you want to cross-compile `rustc` to another target since GCC is not a multi-target compiler. +To support this use case, there is the bootstrap option `gcc.libgccjit-libs-dir`. +This option override `gcc.download-ci-gcc`, meaning `libgccjit.so` won't be downloaded or built locally by bootstrap. +The directory structure of this directory is `//libgccjit.so`, for instance: + +``` +. +├── m68k-unknown-linux-gnu +│ └── m68k-unknown-linux-gnu +│ └── libgccjit.so +└── x86_64-unknown-linux-gnu + ├── m68k-unknown-linux-gnu + │ └── libgccjit.so + └── x86_64-unknown-linux-gnu + └── libgccjit.so +``` + ## Running tests of the backend itself In addition to running the compiler's test suites using the GCC codegen backend, you can also run the test suite of the backend itself. diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index 832b5a69d47c4..3b8852f8ff9f7 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -112,6 +112,7 @@ - [riscv32i\*-unknown-none-elf](platform-support/riscv32-unknown-none-elf.md) - [riscv32im-risc0-zkvm-elf](platform-support/riscv32im-risc0-zkvm-elf.md) - [riscv32imac-unknown-xous-elf](platform-support/riscv32imac-unknown-xous-elf.md) + - [riscv64im-unknown-none-elf](platform-support/riscv64im-unknown-none-elf.md) - [riscv64gc-unknown-linux-gnu](platform-support/riscv64gc-unknown-linux-gnu.md) - [riscv64gc-unknown-linux-musl](platform-support/riscv64gc-unknown-linux-musl.md) - [riscv64a23-unknown-linux-gnu](platform-support/riscv64a23-unknown-linux-gnu.md) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index d772702df76e2..5164ab69d3531 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -184,6 +184,7 @@ target | std | notes [`riscv32imc-unknown-none-elf`](platform-support/riscv32-unknown-none-elf.md) | * | Bare RISC-V (RV32IMC ISA) [`riscv64gc-unknown-linux-musl`](platform-support/riscv64gc-unknown-linux-musl.md) | ✓ |RISC-V Linux (kernel 4.20+, musl 1.2.5) `riscv64gc-unknown-none-elf` | * | Bare RISC-V (RV64IMAFDC ISA) +[`riscv64im-unknown-none-elf`](platform-support/riscv64im-unknown-none-elf.md) | * | Bare RISC-V (RV64IM ISA) `riscv64imac-unknown-none-elf` | * | Bare RISC-V (RV64IMAC ISA) `sparc64-unknown-linux-gnu` | ✓ | SPARC Linux (kernel 4.4+, glibc 2.23) [`thumbv6m-none-eabi`](platform-support/thumbv6m-none-eabi.md) | * | Bare Armv6-M diff --git a/src/doc/rustc/src/platform-support/riscv64im-unknown-none-elf.md b/src/doc/rustc/src/platform-support/riscv64im-unknown-none-elf.md new file mode 100644 index 0000000000000..505810caa4254 --- /dev/null +++ b/src/doc/rustc/src/platform-support/riscv64im-unknown-none-elf.md @@ -0,0 +1,47 @@ +# `riscv64im-unknown-none-elf` + +**Tier: 3** + +Bare-metal target for RISC-V CPUs with the RV64IM ISA. + +## Target maintainers + +* Rust Embedded Working Group, [RISC-V team](https://github.com/rust-embedded/wg#the-risc-v-team) + +## Requirements + +This target is cross-compiled and uses static linking. The target supports `core` and `alloc`, but not `std`. + +As the RV64IM ISA lacks the "A" (Atomics) extension, atomic operations are emulated using the `+forced-atomics` feature. + +No external toolchain is required and the default `rust-lld` linker works, but you must specify a linker script. The [`riscv-rt`] crate provides suitable linker scripts. The [`riscv-rust-quickstart`] repository gives examples of RISC-V bare-metal projects. + +[`riscv-rt`]: https://crates.io/crates/riscv-rt +[`riscv-rust-quickstart`]: https://github.com/riscv-rust/riscv-rust-quickstart + +## Building the target + +You can build Rust with support for the target by adding it to the `target` list in `bootstrap.toml`: + +```toml +[build] +target = ["riscv64im-unknown-none-elf"] +``` + +Alternatively, you can use the `-Z build-std` flag to build the standard library on-demand: + +```bash +cargo build -Z build-std=core,alloc --target riscv64im-unknown-none-elf +``` + +## Building Rust programs + +Rust does not yet ship pre-compiled artifacts for this target. To compile for this target (see "Building the target" above) + +## Testing + +This is a cross-compiled `no-std` target, which must be run either in a simulator or by programming onto suitable hardware. It is not possible to run the Rust test-suite on this target. + +## Cross-compilation toolchains and C code + +This target supports C code. If interlinking with C or C++, you may need to use `riscv64-unknown-elf-gcc` with the appropriate `-march=rv64im -mabi=lp64` flags as a linker instead of `rust-lld`. diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index dd5c50d2ba37c..3696f0ca5fd7a 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -38,6 +38,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet, In use rustc_data_structures::thin_vec::ThinVec; use rustc_errors::codes::*; use rustc_errors::{FatalError, struct_span_code_err}; +use rustc_hir as hir; use rustc_hir::attrs::{AttributeKind, DocAttribute, DocInline}; use rustc_hir::def::{CtorKind, DefKind, MacroKinds, Res}; use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LOCAL_CRATE, LocalDefId}; @@ -54,7 +55,6 @@ use rustc_span::symbol::{Ident, Symbol, kw, sym}; use rustc_trait_selection::traits::wf::object_region_bounds; use tracing::{debug, instrument}; use utils::*; -use {rustc_ast as ast, rustc_hir as hir}; pub(crate) use self::cfg::{CfgInfo, extract_cfg_from_attrs}; pub(crate) use self::types::*; @@ -1026,26 +1026,20 @@ fn clean_fn_or_proc_macro<'tcx>( /// `rustc_legacy_const_generics`. More information in /// . fn clean_fn_decl_legacy_const_generics(func: &mut Function, attrs: &[hir::Attribute]) { - for meta_item_list in attrs - .iter() - .filter(|a| a.has_name(sym::rustc_legacy_const_generics)) - .filter_map(|a| a.meta_item_list()) - { - for (pos, literal) in meta_item_list.iter().filter_map(|meta| meta.lit()).enumerate() { - match literal.kind { - ast::LitKind::Int(a, _) => { - let GenericParamDef { name, kind, .. } = func.generics.params.remove(0); - if let GenericParamDefKind::Const { ty, .. } = kind { - func.decl.inputs.insert( - a.get() as _, - Parameter { name: Some(name), type_: *ty, is_const: true }, - ); - } else { - panic!("unexpected non const in position {pos}"); - } - } - _ => panic!("invalid arg index"), - } + let Some(indexes) = + find_attr!(attrs, AttributeKind::RustcLegacyConstGenerics{fn_indexes,..} => fn_indexes) + else { + return; + }; + + for (pos, (index, _)) in indexes.iter().enumerate() { + let GenericParamDef { name, kind, .. } = func.generics.params.remove(0); + if let GenericParamDefKind::Const { ty, .. } = kind { + func.decl + .inputs + .insert(*index, Parameter { name: Some(name), type_: *ty, is_const: true }); + } else { + panic!("unexpected non const in position {pos}"); } } } diff --git a/tests/assembly-llvm/targets/targets-elf.rs b/tests/assembly-llvm/targets/targets-elf.rs index 324c7fc9da4ee..c8b81cc858d6a 100644 --- a/tests/assembly-llvm/targets/targets-elf.rs +++ b/tests/assembly-llvm/targets/targets-elf.rs @@ -520,6 +520,9 @@ //@ revisions: riscv64gc_unknown_redox //@ [riscv64gc_unknown_redox] compile-flags: --target riscv64gc-unknown-redox //@ [riscv64gc_unknown_redox] needs-llvm-components: riscv +//@ revisions: riscv64im_unknown_none_elf +//@ [riscv64im_unknown_none_elf] compile-flags: --target riscv64im-unknown-none-elf +//@ [riscv64im_unknown_none_elf] needs-llvm-components: riscv //@ revisions: riscv64imac_unknown_none_elf //@ [riscv64imac_unknown_none_elf] compile-flags: --target riscv64imac-unknown-none-elf //@ [riscv64imac_unknown_none_elf] needs-llvm-components: riscv diff --git a/tests/ui/attributes/codegen_attr_on_required_trait_method.rs b/tests/ui/attributes/codegen_attr_on_required_trait_method.rs new file mode 100644 index 0000000000000..6301a5a8ebf70 --- /dev/null +++ b/tests/ui/attributes/codegen_attr_on_required_trait_method.rs @@ -0,0 +1,24 @@ +#![deny(unused_attributes)] +#![feature(linkage)] +#![feature(fn_align)] + +trait Test { + #[cold] + //~^ ERROR cannot be used on required trait methods [unused_attributes] + //~| WARN previously accepted + fn method1(&self); + #[link_section = ".text"] + //~^ ERROR cannot be used on required trait methods [unused_attributes] + //~| WARN previously accepted + fn method2(&self); + #[linkage = "common"] + //~^ ERROR cannot be used on required trait methods [unused_attributes] + //~| WARN previously accepted + fn method3(&self); + #[track_caller] + fn method4(&self); + #[rustc_align(1)] + fn method5(&self); +} + +fn main() {} diff --git a/tests/ui/attributes/codegen_attr_on_required_trait_method.stderr b/tests/ui/attributes/codegen_attr_on_required_trait_method.stderr new file mode 100644 index 0000000000000..0770ccae41469 --- /dev/null +++ b/tests/ui/attributes/codegen_attr_on_required_trait_method.stderr @@ -0,0 +1,34 @@ +error: `#[cold]` attribute cannot be used on required trait methods + --> $DIR/codegen_attr_on_required_trait_method.rs:6:5 + | +LL | #[cold] + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[cold]` can be applied to closures, foreign functions, functions, inherent methods, provided trait methods, and trait methods in impl blocks +note: the lint level is defined here + --> $DIR/codegen_attr_on_required_trait_method.rs:1:9 + | +LL | #![deny(unused_attributes)] + | ^^^^^^^^^^^^^^^^^ + +error: `#[link_section]` attribute cannot be used on required trait methods + --> $DIR/codegen_attr_on_required_trait_method.rs:10:5 + | +LL | #[link_section = ".text"] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[link_section]` can be applied to functions, inherent methods, provided trait methods, statics, and trait methods in impl blocks + +error: `#[linkage]` attribute cannot be used on required trait methods + --> $DIR/codegen_attr_on_required_trait_method.rs:14:5 + | +LL | #[linkage = "common"] + | ^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[linkage]` can be applied to foreign functions, foreign statics, functions, inherent methods, provided trait methods, statics, and trait methods in impl blocks + +error: aborting due to 3 previous errors + diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs index 4b5420a2ff8b4..6716e78a7197a 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs +++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.rs @@ -680,6 +680,10 @@ mod link_section { //~| HELP remove the attribute trait Tr { #[link_section = "1800"] + //~^ WARN attribute cannot be used on + //~| WARN previously accepted + //~| HELP can be applied to + //~| HELP remove the attribute fn inside_tr_no_default(&self); #[link_section = "1800"] diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr index 676372ad85e05..8ed39a0079ba5 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr +++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr @@ -203,7 +203,7 @@ LL | #![reexport_test_harness_main = "2900"] | + warning: attribute should be applied to an `extern` block with non-Rust ABI - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:706:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:710:1 | LL | #[link(name = "x")] | ^^^^^^^^^^^^^^^^^^^ @@ -219,7 +219,7 @@ LL | | } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: crate-level attribute should be an inner attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:832:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:836:1 | LL | #[crate_type = "0800"] | ^^^^^^^^^^^^^^^^^^^^^^ @@ -230,7 +230,7 @@ LL | #![crate_type = "0800"] | + warning: crate-level attribute should be an inner attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:856:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:860:1 | LL | #[feature(x0600)] | ^^^^^^^^^^^^^^^^^ @@ -241,7 +241,7 @@ LL | #![feature(x0600)] | + warning: crate-level attribute should be an inner attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:881:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:885:1 | LL | #[no_main] | ^^^^^^^^^^ @@ -252,7 +252,7 @@ LL | #![no_main] | + warning: crate-level attribute should be an inner attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:905:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:909:1 | LL | #[no_builtins] | ^^^^^^^^^^^^^^ @@ -329,7 +329,7 @@ LL | #![reexport_test_harness_main = "2900"] impl S { } | + warning: attribute should be applied to an `extern` block with non-Rust ABI - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:712:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:716:17 | LL | mod inner { #![link(name = "x")] } | ------------^^^^^^^^^^^^^^^^^^^^-- not an `extern` block @@ -337,7 +337,7 @@ LL | mod inner { #![link(name = "x")] } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to an `extern` block with non-Rust ABI - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:717:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:721:5 | LL | #[link(name = "x")] fn f() { } | ^^^^^^^^^^^^^^^^^^^ ---------- not an `extern` block @@ -345,7 +345,7 @@ LL | #[link(name = "x")] fn f() { } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to an `extern` block with non-Rust ABI - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:722:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:726:5 | LL | #[link(name = "x")] struct S; | ^^^^^^^^^^^^^^^^^^^ --------- not an `extern` block @@ -353,7 +353,7 @@ LL | #[link(name = "x")] struct S; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to an `extern` block with non-Rust ABI - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:727:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:731:5 | LL | #[link(name = "x")] type T = S; | ^^^^^^^^^^^^^^^^^^^ ----------- not an `extern` block @@ -361,7 +361,7 @@ LL | #[link(name = "x")] type T = S; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to an `extern` block with non-Rust ABI - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:732:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:736:5 | LL | #[link(name = "x")] impl S { } | ^^^^^^^^^^^^^^^^^^^ ---------- not an `extern` block @@ -369,7 +369,7 @@ LL | #[link(name = "x")] impl S { } = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: attribute should be applied to an `extern` block with non-Rust ABI - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:737:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:741:5 | LL | #[link(name = "x")] extern "Rust" {} | ^^^^^^^^^^^^^^^^^^^ @@ -377,13 +377,13 @@ LL | #[link(name = "x")] extern "Rust" {} = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:836:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:840:17 | LL | mod inner { #![crate_type="0800"] } | ^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:839:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:843:5 | LL | #[crate_type = "0800"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^ @@ -394,7 +394,7 @@ LL | #![crate_type = "0800"] fn f() { } | + warning: crate-level attribute should be an inner attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:843:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:847:5 | LL | #[crate_type = "0800"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^ @@ -405,7 +405,7 @@ LL | #![crate_type = "0800"] struct S; | + warning: crate-level attribute should be an inner attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:847:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:851:5 | LL | #[crate_type = "0800"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^ @@ -416,7 +416,7 @@ LL | #![crate_type = "0800"] type T = S; | + warning: crate-level attribute should be an inner attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:851:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:855:5 | LL | #[crate_type = "0800"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^ @@ -427,13 +427,13 @@ LL | #![crate_type = "0800"] impl S { } | + warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:860:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:864:17 | LL | mod inner { #![feature(x0600)] } | ^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:863:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:867:5 | LL | #[feature(x0600)] fn f() { } | ^^^^^^^^^^^^^^^^^ @@ -444,7 +444,7 @@ LL | #![feature(x0600)] fn f() { } | + warning: crate-level attribute should be an inner attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:867:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:871:5 | LL | #[feature(x0600)] struct S; | ^^^^^^^^^^^^^^^^^ @@ -455,7 +455,7 @@ LL | #![feature(x0600)] struct S; | + warning: crate-level attribute should be an inner attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:871:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:875:5 | LL | #[feature(x0600)] type T = S; | ^^^^^^^^^^^^^^^^^ @@ -466,7 +466,7 @@ LL | #![feature(x0600)] type T = S; | + warning: crate-level attribute should be an inner attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:875:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:879:5 | LL | #[feature(x0600)] impl S { } | ^^^^^^^^^^^^^^^^^ @@ -477,13 +477,13 @@ LL | #![feature(x0600)] impl S { } | + warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:885:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:889:17 | LL | mod inner { #![no_main] } | ^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:888:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:892:5 | LL | #[no_main] fn f() { } | ^^^^^^^^^^ @@ -494,7 +494,7 @@ LL | #![no_main] fn f() { } | + warning: crate-level attribute should be an inner attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:892:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:896:5 | LL | #[no_main] struct S; | ^^^^^^^^^^ @@ -505,7 +505,7 @@ LL | #![no_main] struct S; | + warning: crate-level attribute should be an inner attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:896:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:900:5 | LL | #[no_main] type T = S; | ^^^^^^^^^^ @@ -516,7 +516,7 @@ LL | #![no_main] type T = S; | + warning: crate-level attribute should be an inner attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:900:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:904:5 | LL | #[no_main] impl S { } | ^^^^^^^^^^ @@ -527,13 +527,13 @@ LL | #![no_main] impl S { } | + warning: crate-level attribute should be in the root module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:909:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:913:17 | LL | mod inner { #![no_builtins] } | ^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:912:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:916:5 | LL | #[no_builtins] fn f() { } | ^^^^^^^^^^^^^^ @@ -544,7 +544,7 @@ LL | #![no_builtins] fn f() { } | + warning: crate-level attribute should be an inner attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:916:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:920:5 | LL | #[no_builtins] struct S; | ^^^^^^^^^^^^^^ @@ -555,7 +555,7 @@ LL | #![no_builtins] struct S; | + warning: crate-level attribute should be an inner attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:920:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:924:5 | LL | #[no_builtins] type T = S; | ^^^^^^^^^^^^^^ @@ -566,7 +566,7 @@ LL | #![no_builtins] type T = S; | + warning: crate-level attribute should be an inner attribute - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:924:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:928:5 | LL | #[no_builtins] impl S { } | ^^^^^^^^^^^^^^ @@ -1222,8 +1222,17 @@ LL | #[link_section = "1800"] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = help: `#[link_section]` can be applied to functions and statics +warning: `#[link_section]` attribute cannot be used on required trait methods + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:682:9 + | +LL | #[link_section = "1800"] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = help: `#[link_section]` can be applied to functions, inherent methods, provided trait methods, statics, and trait methods in impl blocks + warning: `#[must_use]` attribute cannot be used on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:757:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:761:1 | LL | #[must_use] | ^^^^^^^^^^^ @@ -1232,7 +1241,7 @@ LL | #[must_use] = help: `#[must_use]` can be applied to data types, functions, traits, and unions warning: `#[must_use]` attribute cannot be used on modules - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:762:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:766:17 | LL | mod inner { #![must_use] } | ^^^^^^^^^^^^ @@ -1241,7 +1250,7 @@ LL | mod inner { #![must_use] } = help: `#[must_use]` can be applied to data types, functions, traits, and unions warning: `#[must_use]` attribute cannot be used on type aliases - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:771:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:775:5 | LL | #[must_use] type T = S; | ^^^^^^^^^^^ @@ -1250,7 +1259,7 @@ LL | #[must_use] type T = S; = help: `#[must_use]` can be applied to data types, functions, traits, and unions warning: `#[must_use]` attribute cannot be used on inherent impl blocks - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:776:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:780:5 | LL | #[must_use] impl S { } | ^^^^^^^^^^^ @@ -1259,13 +1268,13 @@ LL | #[must_use] impl S { } = help: `#[must_use]` can be applied to data types, functions, traits, and unions warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![windows_subsystem]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:782:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:786:1 | LL | #[windows_subsystem = "windows"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: This attribute does not have an `!`, which means it is applied to this module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:784:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:788:1 | LL | / mod windows_subsystem { LL | | @@ -1275,67 +1284,67 @@ LL | | } | |_^ warning: the `#![windows_subsystem]` attribute can only be used at the crate root - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:786:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:790:17 | LL | mod inner { #![windows_subsystem="windows"] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![windows_subsystem]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:789:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:793:5 | LL | #[windows_subsystem = "windows"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: This attribute does not have an `!`, which means it is applied to this function - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:789:38 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:793:38 | LL | #[windows_subsystem = "windows"] fn f() { } | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![windows_subsystem]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:793:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:797:5 | LL | #[windows_subsystem = "windows"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: This attribute does not have an `!`, which means it is applied to this struct - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:793:38 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:797:38 | LL | #[windows_subsystem = "windows"] struct S; | ^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![windows_subsystem]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:797:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:801:5 | LL | #[windows_subsystem = "windows"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: This attribute does not have an `!`, which means it is applied to this type alias - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:797:38 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:801:38 | LL | #[windows_subsystem = "windows"] type T = S; | ^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![windows_subsystem]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:801:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:805:5 | LL | #[windows_subsystem = "windows"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: This attribute does not have an `!`, which means it is applied to this implementation block - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:801:38 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:805:38 | LL | #[windows_subsystem = "windows"] impl S { } | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_name]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:808:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:812:1 | LL | #[crate_name = "0900"] | ^^^^^^^^^^^^^^^^^^^^^^ | note: This attribute does not have an `!`, which means it is applied to this module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:810:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:814:1 | LL | / mod crate_name { LL | | @@ -1345,67 +1354,67 @@ LL | | } | |_^ warning: the `#![crate_name]` attribute can only be used at the crate root - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:812:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:816:17 | LL | mod inner { #![crate_name="0900"] } | ^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_name]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:815:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:819:5 | LL | #[crate_name = "0900"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^ | note: This attribute does not have an `!`, which means it is applied to this function - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:815:28 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:819:28 | LL | #[crate_name = "0900"] fn f() { } | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_name]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:819:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:823:5 | LL | #[crate_name = "0900"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^ | note: This attribute does not have an `!`, which means it is applied to this struct - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:819:28 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:823:28 | LL | #[crate_name = "0900"] struct S; | ^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_name]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:823:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:827:5 | LL | #[crate_name = "0900"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^ | note: This attribute does not have an `!`, which means it is applied to this type alias - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:823:28 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:827:28 | LL | #[crate_name = "0900"] type T = S; | ^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_name]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:827:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:831:5 | LL | #[crate_name = "0900"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^ | note: This attribute does not have an `!`, which means it is applied to this implementation block - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:827:28 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:831:28 | LL | #[crate_name = "0900"] impl S { } | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![recursion_limit]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:929:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:933:1 | LL | #[recursion_limit="0200"] | ^^^^^^^^^^^^^^^^^^^^^^^^^ | note: This attribute does not have an `!`, which means it is applied to this module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:931:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:935:1 | LL | / mod recursion_limit { LL | | @@ -1415,67 +1424,67 @@ LL | | } | |_^ warning: the `#![recursion_limit]` attribute can only be used at the crate root - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:933:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:937:17 | LL | mod inner { #![recursion_limit="0200"] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![recursion_limit]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:936:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:940:5 | LL | #[recursion_limit="0200"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^^ | note: This attribute does not have an `!`, which means it is applied to this function - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:936:31 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:940:31 | LL | #[recursion_limit="0200"] fn f() { } | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![recursion_limit]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:940:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:944:5 | LL | #[recursion_limit="0200"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^^ | note: This attribute does not have an `!`, which means it is applied to this struct - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:940:31 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:944:31 | LL | #[recursion_limit="0200"] struct S; | ^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![recursion_limit]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:944:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:948:5 | LL | #[recursion_limit="0200"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^^ | note: This attribute does not have an `!`, which means it is applied to this type alias - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:944:31 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:948:31 | LL | #[recursion_limit="0200"] type T = S; | ^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![recursion_limit]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:948:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:952:5 | LL | #[recursion_limit="0200"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^^ | note: This attribute does not have an `!`, which means it is applied to this implementation block - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:948:31 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:952:31 | LL | #[recursion_limit="0200"] impl S { } | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![type_length_limit]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:953:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:957:1 | LL | #[type_length_limit="0100"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: This attribute does not have an `!`, which means it is applied to this module - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:955:1 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:959:1 | LL | / mod type_length_limit { LL | | @@ -1485,55 +1494,55 @@ LL | | } | |_^ warning: the `#![type_length_limit]` attribute can only be used at the crate root - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:957:17 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:961:17 | LL | mod inner { #![type_length_limit="0100"] } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![type_length_limit]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:960:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:964:5 | LL | #[type_length_limit="0100"] fn f() { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: This attribute does not have an `!`, which means it is applied to this function - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:960:33 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:964:33 | LL | #[type_length_limit="0100"] fn f() { } | ^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![type_length_limit]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:964:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:968:5 | LL | #[type_length_limit="0100"] struct S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: This attribute does not have an `!`, which means it is applied to this struct - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:964:33 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:968:33 | LL | #[type_length_limit="0100"] struct S; | ^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![type_length_limit]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:968:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:972:5 | LL | #[type_length_limit="0100"] type T = S; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: This attribute does not have an `!`, which means it is applied to this type alias - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:968:33 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:972:33 | LL | #[type_length_limit="0100"] type T = S; | ^^^^^^^^^^^ warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![type_length_limit]` - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:972:5 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:976:5 | LL | #[type_length_limit="0100"] impl S { } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: This attribute does not have an `!`, which means it is applied to this implementation block - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:972:33 + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:976:33 | LL | #[type_length_limit="0100"] impl S { } | ^^^^^^^^^^ @@ -1601,5 +1610,5 @@ LL | #![must_use] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = help: `#[must_use]` can be applied to data types, functions, traits, and unions -warning: 174 warnings emitted +warning: 175 warnings emitted diff --git a/tests/ui/invalid/invalid-rustc_legacy_const_generics-arguments.rs b/tests/ui/invalid/invalid-rustc_legacy_const_generics-arguments.rs index 73a0363904aeb..03a28fac95def 100644 --- a/tests/ui/invalid/invalid-rustc_legacy_const_generics-arguments.rs +++ b/tests/ui/invalid/invalid-rustc_legacy_const_generics-arguments.rs @@ -9,20 +9,24 @@ fn foo2() {} #[rustc_legacy_const_generics(2)] //~ ERROR index exceeds number of arguments fn foo3(_: u8) {} -#[rustc_legacy_const_generics(a)] //~ ERROR arguments should be non-negative integers +#[rustc_legacy_const_generics(a)] //~ ERROR malformed `rustc_legacy_const_generics` attribute input fn foo4() {} -#[rustc_legacy_const_generics(1, a, 2, b)] //~ ERROR arguments should be non-negative integers +#[rustc_legacy_const_generics(1, a, 2, b)] +//~^ ERROR malformed `rustc_legacy_const_generics` attribute input +//~^^ ERROR malformed `rustc_legacy_const_generics` attribute input fn foo5() {} -#[rustc_legacy_const_generics(0)] //~ ERROR attribute should be applied to a function +#[rustc_legacy_const_generics(0)] //~ ERROR `#[rustc_legacy_const_generics]` attribute cannot be used on structs struct S; -#[rustc_legacy_const_generics(0usize)] //~ ERROR suffixed literals are not allowed in attributes +#[rustc_legacy_const_generics(0usize)] +//~^ ERROR suffixed literals are not allowed in attributes +//~^^ ERROR malformed `rustc_legacy_const_generics` attribute input fn foo6() {} extern "C" { - #[rustc_legacy_const_generics(1)] //~ ERROR attribute should be applied to a function + #[rustc_legacy_const_generics(1)] //~ ERROR `#[rustc_legacy_const_generics]` attribute cannot be used on foreign functions fn foo7(); //~ ERROR foreign items may not have const parameters } @@ -30,14 +34,14 @@ extern "C" { fn foo8() {} impl S { - #[rustc_legacy_const_generics(0)] //~ ERROR attribute should be applied to a function + #[rustc_legacy_const_generics(0)] //~ ERROR `#[rustc_legacy_const_generics]` attribute cannot be used on inherent methods fn foo9() {} } -#[rustc_legacy_const_generics] //~ ERROR malformed `rustc_legacy_const_generics` attribute +#[rustc_legacy_const_generics] //~ ERROR malformed `rustc_legacy_const_generics` attribute input fn bar1() {} -#[rustc_legacy_const_generics = 1] //~ ERROR malformed `rustc_legacy_const_generics` attribute +#[rustc_legacy_const_generics = 1] //~ ERROR malformed `rustc_legacy_const_generics` attribute input fn bar2() {} fn main() {} diff --git a/tests/ui/invalid/invalid-rustc_legacy_const_generics-arguments.stderr b/tests/ui/invalid/invalid-rustc_legacy_const_generics-arguments.stderr index 1ced1433fe955..e4da6c86c83e5 100644 --- a/tests/ui/invalid/invalid-rustc_legacy_const_generics-arguments.stderr +++ b/tests/ui/invalid/invalid-rustc_legacy_const_generics-arguments.stderr @@ -1,22 +1,88 @@ +error[E0539]: malformed `rustc_legacy_const_generics` attribute input + --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:12:1 + | +LL | #[rustc_legacy_const_generics(a)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^^ + | | | + | | expected an integer literal here + | help: must be of the form: `#[rustc_legacy_const_generics(N)]` + +error[E0539]: malformed `rustc_legacy_const_generics` attribute input + --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:15:1 + | +LL | #[rustc_legacy_const_generics(1, a, 2, b)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^^^^^^^^ + | | | + | | expected an integer literal here + | help: must be of the form: `#[rustc_legacy_const_generics(N)]` + +error[E0539]: malformed `rustc_legacy_const_generics` attribute input + --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:15:1 + | +LL | #[rustc_legacy_const_generics(1, a, 2, b)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^^ + | | | + | | expected an integer literal here + | help: must be of the form: `#[rustc_legacy_const_generics(N)]` + +error: `#[rustc_legacy_const_generics]` attribute cannot be used on structs + --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:20:1 + | +LL | #[rustc_legacy_const_generics(0)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[rustc_legacy_const_generics]` can only be applied to functions + error: suffixed literals are not allowed in attributes - --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:21:31 + --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:23:31 | LL | #[rustc_legacy_const_generics(0usize)] | ^^^^^^ | = help: instead of using a suffixed literal (`1u8`, `1.0f32`, etc.), use an unsuffixed version (`1`, `1.0`, etc.) -error: malformed `rustc_legacy_const_generics` attribute input - --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:37:1 +error[E0539]: malformed `rustc_legacy_const_generics` attribute input + --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:23:1 + | +LL | #[rustc_legacy_const_generics(0usize)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^------^^ + | | | + | | expected an integer literal here + | help: must be of the form: `#[rustc_legacy_const_generics(N)]` + +error: `#[rustc_legacy_const_generics]` attribute cannot be used on foreign functions + --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:29:5 + | +LL | #[rustc_legacy_const_generics(1)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[rustc_legacy_const_generics]` can only be applied to functions + +error: `#[rustc_legacy_const_generics]` attribute cannot be used on inherent methods + --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:37:5 + | +LL | #[rustc_legacy_const_generics(0)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[rustc_legacy_const_generics]` can only be applied to functions + +error[E0539]: malformed `rustc_legacy_const_generics` attribute input + --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:41:1 | LL | #[rustc_legacy_const_generics] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[rustc_legacy_const_generics(N)]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected this to be a list + | help: must be of the form: `#[rustc_legacy_const_generics(N)]` -error: malformed `rustc_legacy_const_generics` attribute input - --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:40:1 +error[E0539]: malformed `rustc_legacy_const_generics` attribute input + --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:44:1 | LL | #[rustc_legacy_const_generics = 1] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[rustc_legacy_const_generics(N)]` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^---^ + | | | + | | expected this to be a list + | help: must be of the form: `#[rustc_legacy_const_generics(N)]` error: #[rustc_legacy_const_generics] must have one index for each generic parameter --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:3:1 @@ -38,58 +104,23 @@ error: index exceeds number of arguments LL | #[rustc_legacy_const_generics(2)] | ^ there are only 2 arguments -error: arguments should be non-negative integers - --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:12:31 - | -LL | #[rustc_legacy_const_generics(a)] - | ^ - -error: arguments should be non-negative integers - --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:15:34 - | -LL | #[rustc_legacy_const_generics(1, a, 2, b)] - | ^ ^ - -error: attribute should be applied to a function definition - --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:18:1 - | -LL | #[rustc_legacy_const_generics(0)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | struct S; - | --------- not a function definition - error: #[rustc_legacy_const_generics] functions must only have const generics - --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:29:1 + --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:33:1 | LL | #[rustc_legacy_const_generics(0)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LL | fn foo8() {} | - non-const generic parameter -error: attribute should be applied to a function definition - --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:33:5 - | -LL | #[rustc_legacy_const_generics(0)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | fn foo9() {} - | ---------------------------- not a function definition - -error: attribute should be applied to a function definition - --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:25:5 - | -LL | #[rustc_legacy_const_generics(1)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | fn foo7(); - | -------------------------- not a function definition - error[E0044]: foreign items may not have const parameters - --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:26:5 + --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:30:5 | LL | fn foo7(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ can't have const parameters | = help: replace the const parameters with concrete consts -error: aborting due to 13 previous errors +error: aborting due to 15 previous errors -For more information about this error, try `rustc --explain E0044`. +Some errors have detailed explanations: E0044, E0539. +For more information about an error, try `rustc --explain E0044`. diff --git a/typos.toml b/typos.toml index 758239ffe751c..b9d9c6c3522cf 100644 --- a/typos.toml +++ b/typos.toml @@ -50,6 +50,8 @@ unstalled = "unstalled" debug_aranges = "debug_aranges" DNS_ERROR_INVAILD_VIRTUALIZATION_INSTANCE_NAME = "DNS_ERROR_INVAILD_VIRTUALIZATION_INSTANCE_NAME" EnzymeTypeTreeShiftIndiciesEq = "EnzymeTypeTreeShiftIndiciesEq" +EnzymeTypeTreeShiftIndiciesEqFn = "EnzymeTypeTreeShiftIndiciesEqFn" +shift_indicies_eq = "shift_indicies_eq" ERRNO_ACCES = "ERRNO_ACCES" ERROR_DS_FILTER_USES_CONTRUCTED_ATTRS = "ERROR_DS_FILTER_USES_CONTRUCTED_ATTRS" ERROR_DS_NOT_AUTHORITIVE_FOR_DST_NC = "ERROR_DS_NOT_AUTHORITIVE_FOR_DST_NC"