From 91425f2c85764af92fd2cbae23b22f5d264d150d Mon Sep 17 00:00:00 2001 From: Folkert Date: Thu, 8 Aug 2024 10:20:40 +0200 Subject: [PATCH 01/22] codegen `#[naked]` functions using `global_asm!` --- src/asm.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/asm.rs b/src/asm.rs index a1f9eab10e7..415f8affab9 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -867,6 +867,13 @@ impl<'gcc, 'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { template_str.push_str("\n.popsection"); self.context.add_top_level_asm(None, &template_str); } + + fn mangled_name(&self, instance: Instance<'tcx>) -> String { + // TODO(@Amanieu): Additional mangling is needed on + // some targets to add a leading underscore (Mach-O) + // or byte count suffixes (x86 Windows). + self.tcx.symbol_name(instance).name.to_string() + } } fn modifier_to_gcc( From a1374f5c36e6e97672da6e521eb80a31eab8a8ed Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 16 Nov 2024 10:00:16 +0100 Subject: [PATCH 02/22] generalize 'forbidden feature' concept so that even (un)stable feature can be invalid to toggle Also rename some things for extra clarity --- messages.ftl | 2 +- src/errors.rs | 1 + src/gcc_util.rs | 18 ++++++++++-------- src/lib.rs | 11 ++++++----- 4 files changed, 18 insertions(+), 14 deletions(-) diff --git a/messages.ftl b/messages.ftl index 26ddc5732dd..85fa17a6ba5 100644 --- a/messages.ftl +++ b/messages.ftl @@ -9,7 +9,7 @@ codegen_gcc_lto_not_supported = LTO is not supported. You may get a linker error. codegen_gcc_forbidden_ctarget_feature = - target feature `{$feature}` cannot be toggled with `-Ctarget-feature` + target feature `{$feature}` cannot be toggled with `-Ctarget-feature`: {$reason} codegen_gcc_unwinding_inline_asm = GCC backend does not support unwinding from inline asm diff --git a/src/errors.rs b/src/errors.rs index 7a586b5b04c..56849cc8610 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -28,6 +28,7 @@ pub(crate) struct UnstableCTargetFeature<'a> { #[diag(codegen_gcc_forbidden_ctarget_feature)] pub(crate) struct ForbiddenCTargetFeature<'a> { pub feature: &'a str, + pub reason: &'a str, } #[derive(Subdiagnostic)] diff --git a/src/gcc_util.rs b/src/gcc_util.rs index 65279c9495a..3717e12020f 100644 --- a/src/gcc_util.rs +++ b/src/gcc_util.rs @@ -5,7 +5,7 @@ use rustc_codegen_ssa::errors::TargetFeatureDisableOrEnable; use rustc_data_structures::fx::FxHashMap; use rustc_middle::bug; use rustc_session::Session; -use rustc_target::target_features::{RUSTC_SPECIFIC_FEATURES, Stability}; +use rustc_target::target_features::RUSTC_SPECIFIC_FEATURES; use smallvec::{SmallVec, smallvec}; use crate::errors::{ @@ -94,13 +94,15 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec {} - Some((_, Stability::Unstable(_), _)) => { - // An unstable feature. Warn about using it. - sess.dcx().emit_warn(UnstableCTargetFeature { feature }); - } - Some((_, Stability::Forbidden { .. }, _)) => { - sess.dcx().emit_err(ForbiddenCTargetFeature { feature }); + Some((_, stability, _)) => { + if let Err(reason) = stability.compute(&sess.target).allow_toggle() { + sess.dcx().emit_warn(ForbiddenCTargetFeature { feature, reason }); + } else if stability.requires_nightly().is_some() { + // An unstable feature. Warn about using it. (It makes little sense + // to hard-error here since we just warn about fully unknown + // features above). + sess.dcx().emit_warn(UnstableCTargetFeature { feature }); + } } } diff --git a/src/lib.rs b/src/lib.rs index 452e92bffa2..764e84be1fe 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -260,8 +260,8 @@ impl CodegenBackend for GccCodegenBackend { .join(sess) } - fn target_features(&self, sess: &Session, allow_unstable: bool) -> Vec { - target_features(sess, allow_unstable, &self.target_info) + fn target_features_cfg(&self, sess: &Session, allow_unstable: bool) -> Vec { + target_features_cfg(sess, allow_unstable, &self.target_info) } } @@ -472,7 +472,8 @@ fn to_gcc_opt_level(optlevel: Option) -> OptimizationLevel { } } -pub fn target_features( +/// Returns the features that should be set in `cfg(target_feature)`. +fn target_features_cfg( sess: &Session, allow_unstable: bool, target_info: &LockedTargetInfo, @@ -481,9 +482,9 @@ pub fn target_features( sess.target .rust_target_features() .iter() - .filter(|(_, gate, _)| gate.is_supported()) + .filter(|(_, gate, _)| gate.in_cfg()) .filter_map(|&(feature, gate, _)| { - if sess.is_nightly_build() || allow_unstable || gate.is_stable() { + if sess.is_nightly_build() || allow_unstable || gate.requires_nightly().is_none() { Some(feature) } else { None From d31c5e9c06f674c391bab6b29c263209b555d11e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 2 Dec 2024 11:02:22 +0100 Subject: [PATCH 03/22] apply review feedback --- src/gcc_util.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/gcc_util.rs b/src/gcc_util.rs index 3717e12020f..88e5eefd7a1 100644 --- a/src/gcc_util.rs +++ b/src/gcc_util.rs @@ -95,7 +95,9 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec { - if let Err(reason) = stability.compute(&sess.target).allow_toggle() { + if let Err(reason) = + stability.compute_toggleability(&sess.target).allow_toggle() + { sess.dcx().emit_warn(ForbiddenCTargetFeature { feature, reason }); } else if stability.requires_nightly().is_some() { // An unstable feature. Warn about using it. (It makes little sense From 1ff0558a9455cd0a037da6272815b01952a34d8c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 24 Nov 2024 12:22:01 +0100 Subject: [PATCH 04/22] target_features: control separately whether enabling and disabling a target feature is allowed --- src/gcc_util.rs | 2 +- src/lib.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/gcc_util.rs b/src/gcc_util.rs index 88e5eefd7a1..058a874501b 100644 --- a/src/gcc_util.rs +++ b/src/gcc_util.rs @@ -96,7 +96,7 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec { if let Err(reason) = - stability.compute_toggleability(&sess.target).allow_toggle() + stability.toggle_allowed(&sess.target, enable_disable == '+') { sess.dcx().emit_warn(ForbiddenCTargetFeature { feature, reason }); } else if stability.requires_nightly().is_some() { diff --git a/src/lib.rs b/src/lib.rs index 764e84be1fe..bb0f2fa5b01 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -483,9 +483,9 @@ fn target_features_cfg( .rust_target_features() .iter() .filter(|(_, gate, _)| gate.in_cfg()) - .filter_map(|&(feature, gate, _)| { + .filter_map(|(feature, gate, _)| { if sess.is_nightly_build() || allow_unstable || gate.requires_nightly().is_none() { - Some(feature) + Some(*feature) } else { None } From a845ca75a09e743b9ad07075e5344cf6dbd042ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonathan=20D=C3=B6nszelmann?= Date: Fri, 13 Dec 2024 14:47:11 +0100 Subject: [PATCH 05/22] rename rustc_attr to rustc_attr_parsing and create rustc_attr_data_structures --- src/attributes.rs | 4 ++-- src/lib.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/attributes.rs b/src/attributes.rs index d20e13e15b9..028a5ab5f71 100644 --- a/src/attributes.rs +++ b/src/attributes.rs @@ -2,8 +2,8 @@ use gccjit::FnAttribute; use gccjit::Function; #[cfg(feature = "master")] -use rustc_attr::InlineAttr; -use rustc_attr::InstructionSetAttr; +use rustc_attr_parsing::InlineAttr; +use rustc_attr_parsing::InstructionSetAttr; #[cfg(feature = "master")] use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::ty; diff --git a/src/lib.rs b/src/lib.rs index bb0f2fa5b01..f2efa981f97 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -35,7 +35,7 @@ extern crate tracing; extern crate rustc_abi; extern crate rustc_apfloat; extern crate rustc_ast; -extern crate rustc_attr; +extern crate rustc_attr_parsing; extern crate rustc_codegen_ssa; extern crate rustc_data_structures; extern crate rustc_errors; From 4d1e772f97043c1b327af5ee2cdc3a21efa951c1 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 1 Dec 2024 13:12:43 +0100 Subject: [PATCH 06/22] Variants::Single: do not use invalid VariantIdx for uninhabited enums --- src/type_of.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/type_of.rs b/src/type_of.rs index 0efdf36da48..426d28f4ed7 100644 --- a/src/type_of.rs +++ b/src/type_of.rs @@ -99,14 +99,14 @@ fn uncached_gcc_type<'gcc, 'tcx>( if !cx.sess().fewer_names() => { let mut name = with_no_trimmed_paths!(layout.ty.to_string()); - if let (&ty::Adt(def, _), &Variants::Single { index }) = + if let (&ty::Adt(def, _), &Variants::Single { index: Some(index) }) = (layout.ty.kind(), &layout.variants) { if def.is_enum() && !def.variants().is_empty() { write!(&mut name, "::{}", def.variant(index).name).unwrap(); } } - if let (&ty::Coroutine(_, _), &Variants::Single { index }) = + if let (&ty::Coroutine(_, _), &Variants::Single { index: Some(index) }) = (layout.ty.kind(), &layout.variants) { write!(&mut name, "::{}", ty::CoroutineArgs::variant_name(index)).unwrap(); @@ -230,7 +230,7 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> { // Check the cache. let variant_index = match self.variants { - Variants::Single { index } => Some(index), + Variants::Single { index } => index, _ => None, }; let cached_type = cx.types.borrow().get(&(self.ty, variant_index)).cloned(); From bd26db466465b82546daed7cbf96d872637970c3 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 1 Dec 2024 17:33:01 +0100 Subject: [PATCH 07/22] make no-variant types a dedicated Variants variant --- src/type_of.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/type_of.rs b/src/type_of.rs index 426d28f4ed7..0efdf36da48 100644 --- a/src/type_of.rs +++ b/src/type_of.rs @@ -99,14 +99,14 @@ fn uncached_gcc_type<'gcc, 'tcx>( if !cx.sess().fewer_names() => { let mut name = with_no_trimmed_paths!(layout.ty.to_string()); - if let (&ty::Adt(def, _), &Variants::Single { index: Some(index) }) = + if let (&ty::Adt(def, _), &Variants::Single { index }) = (layout.ty.kind(), &layout.variants) { if def.is_enum() && !def.variants().is_empty() { write!(&mut name, "::{}", def.variant(index).name).unwrap(); } } - if let (&ty::Coroutine(_, _), &Variants::Single { index: Some(index) }) = + if let (&ty::Coroutine(_, _), &Variants::Single { index }) = (layout.ty.kind(), &layout.variants) { write!(&mut name, "::{}", ty::CoroutineArgs::variant_name(index)).unwrap(); @@ -230,7 +230,7 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> { // Check the cache. let variant_index = match self.variants { - Variants::Single { index } => index, + Variants::Single { index } => Some(index), _ => None, }; let cached_type = cx.types.borrow().get(&(self.ty, variant_index)).cloned(); From c3eed20ab1df4ac0b39418f1243accdc45a937c9 Mon Sep 17 00:00:00 2001 From: acceptacross Date: Wed, 18 Dec 2024 23:23:44 +0800 Subject: [PATCH 08/22] chore: fix some typos Signed-off-by: acceptacross --- src/intrinsic/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 69326f409bb..78ec9741f57 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -66,7 +66,7 @@ fn get_simple_intrinsic<'gcc, 'tcx>( sym::log2f64 => "log2", sym::fmaf32 => "fmaf", sym::fmaf64 => "fma", - // FIXME: calling `fma` from libc without FMA target feature uses expensive sofware emulation + // FIXME: calling `fma` from libc without FMA target feature uses expensive software emulation sym::fmuladdf32 => "fmaf", // TODO: use gcc intrinsic analogous to llvm.fmuladd.f32 sym::fmuladdf64 => "fma", // TODO: use gcc intrinsic analogous to llvm.fmuladd.f64 sym::fabsf32 => "fabsf", From e6e72ce158daf8651bef919b4d7de619de1d4737 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 26 Dec 2024 19:08:30 +0100 Subject: [PATCH 09/22] adjust GCC backend --- src/errors.rs | 1 + src/gcc_util.rs | 196 ++++++++++++++++++++++++++++-------------------- 2 files changed, 116 insertions(+), 81 deletions(-) diff --git a/src/errors.rs b/src/errors.rs index 56849cc8610..c896246866b 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -28,6 +28,7 @@ pub(crate) struct UnstableCTargetFeature<'a> { #[diag(codegen_gcc_forbidden_ctarget_feature)] pub(crate) struct ForbiddenCTargetFeature<'a> { pub feature: &'a str, + pub enabled: &'a str, pub reason: &'a str, } diff --git a/src/gcc_util.rs b/src/gcc_util.rs index 058a874501b..b0fd07827d6 100644 --- a/src/gcc_util.rs +++ b/src/gcc_util.rs @@ -1,9 +1,11 @@ +use std::iter::FromIterator; + #[cfg(feature = "master")] use gccjit::Context; use rustc_codegen_ssa::codegen_attrs::check_tied_features; use rustc_codegen_ssa::errors::TargetFeatureDisableOrEnable; -use rustc_data_structures::fx::FxHashMap; -use rustc_middle::bug; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::unord::UnordSet; use rustc_session::Session; use rustc_target::target_features::RUSTC_SPECIFIC_FEATURES; use smallvec::{SmallVec, smallvec}; @@ -37,82 +39,128 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec return None, - Some(c @ ('+' | '-')) => c, - Some(_) => { - if diagnostics { - sess.dcx().emit_warn(UnknownCTargetFeaturePrefix { feature: s }); - } - return None; - } - }; - // Get the backend feature name, if any. - // This excludes rustc-specific features, that do not get passed down to GCC. - let feature = backend_feature_name(s)?; - // Warn against use of GCC specific feature names on the CLI. + // Ensure that all ABI-required features are enabled, and the ABI-forbidden ones + // are disabled. + let (abi_enable, abi_disable) = sess.target.abi_required_features(); + let abi_enable_set = FxHashSet::from_iter(abi_enable.iter().copied()); + let abi_disable_set = FxHashSet::from_iter(abi_disable.iter().copied()); + + // Compute implied features + let mut all_rust_features = vec![]; + for feature in sess.opts.cg.target_feature.split(',') { + if let Some(feature) = feature.strip_prefix('+') { + all_rust_features.extend( + UnordSet::from(sess.target.implied_target_features(std::iter::once(feature))) + .to_sorted_stable_ord() + .iter() + .map(|&&s| (true, s)), + ) + } else if let Some(feature) = feature.strip_prefix('-') { + // FIXME: Why do we not remove implied features on "-" here? + // We do the equivalent above in `target_features_cfg`. + // See . + all_rust_features.push((false, feature)); + } else if !feature.is_empty() { if diagnostics { - let feature_state = known_features.iter().find(|&&(v, _, _)| v == feature); - match feature_state { - None => { - let rust_feature = - known_features.iter().find_map(|&(rust_feature, _, _)| { - let gcc_features = to_gcc_features(sess, rust_feature); - if gcc_features.contains(&feature) - && !gcc_features.contains(&rust_feature) - { - Some(rust_feature) - } else { - None - } - }); - let unknown_feature = if let Some(rust_feature) = rust_feature { - UnknownCTargetFeature { - feature, - rust_feature: PossibleFeature::Some { rust_feature }, - } - } else { - UnknownCTargetFeature { feature, rust_feature: PossibleFeature::None } - }; - sess.dcx().emit_warn(unknown_feature); - } - Some((_, stability, _)) => { - if let Err(reason) = - stability.toggle_allowed(&sess.target, enable_disable == '+') + sess.dcx().emit_warn(UnknownCTargetFeaturePrefix { feature }); + } + } + } + // Remove features that are meant for rustc, not LLVM. + all_rust_features.retain(|(_, feature)| { + // Retain if it is not a rustc feature + !RUSTC_SPECIFIC_FEATURES.contains(feature) + }); + + // Check feature validity. + if diagnostics { + for &(enable, feature) in &all_rust_features { + let feature_state = known_features.iter().find(|&&(v, _, _)| v == feature); + match feature_state { + None => { + let rust_feature = known_features.iter().find_map(|&(rust_feature, _, _)| { + let gcc_features = to_gcc_features(sess, rust_feature); + if gcc_features.contains(&feature) && !gcc_features.contains(&rust_feature) { - sess.dcx().emit_warn(ForbiddenCTargetFeature { feature, reason }); - } else if stability.requires_nightly().is_some() { - // An unstable feature. Warn about using it. (It makes little sense - // to hard-error here since we just warn about fully unknown - // features above). - sess.dcx().emit_warn(UnstableCTargetFeature { feature }); + Some(rust_feature) + } else { + None } + }); + let unknown_feature = if let Some(rust_feature) = rust_feature { + UnknownCTargetFeature { + feature, + rust_feature: PossibleFeature::Some { rust_feature }, + } + } else { + UnknownCTargetFeature { feature, rust_feature: PossibleFeature::None } + }; + sess.dcx().emit_warn(unknown_feature); + } + Some((_, stability, _)) => { + if let Err(reason) = stability.toggle_allowed() { + sess.dcx().emit_warn(ForbiddenCTargetFeature { + feature, + enabled: if enable { "enabled" } else { "disabled" }, + reason, + }); + } else if stability.requires_nightly().is_some() { + // An unstable feature. Warn about using it. (It makes little sense + // to hard-error here since we just warn about fully unknown + // features above). + sess.dcx().emit_warn(UnstableCTargetFeature { feature }); } } + } - // FIXME(nagisa): figure out how to not allocate a full hashset here. - featsmap.insert(feature, enable_disable == '+'); + // Ensure that the features we enable/disable are compatible with the ABI. + if enable { + if abi_disable_set.contains(feature) { + sess.dcx().emit_warn(ForbiddenCTargetFeature { + feature, + enabled: "enabled", + reason: "this feature is incompatible with the target ABI", + }); + } + } else { + if abi_enable_set.contains(feature) { + sess.dcx().emit_warn(ForbiddenCTargetFeature { + feature, + enabled: "disabled", + reason: "this feature is required by the target ABI", + }); + } } - // ... otherwise though we run through `to_gcc_features` when + // FIXME(nagisa): figure out how to not allocate a full hashset here. + featsmap.insert(feature, enable); + } + } + + // To be sure the ABI-relevant features are all in the right state, we explicitly + // (un)set them here. This means if the target spec sets those features wrong, + // we will silently correct them rather than silently producing wrong code. + // (The target sanity check tries to catch this, but we can't know which features are + // enabled in GCC by default so we can't be fully sure about that check.) + for feature in abi_enable { + all_rust_features.push((true, feature)); + } + for feature in abi_disable { + all_rust_features.push((false, feature)); + } + + // Translate this into GCC features. + let feats = all_rust_features + .iter() + .filter_map(|&(enable, feature)| { + let enable_disable = if enable { '+' } else { '-' }; + // We run through `to_gcc_features` when // passing requests down to GCC. This means that all in-language // features also work on the command line instead of having two // different names when the GCC name and the Rust name differ. @@ -146,26 +194,12 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec Option<&str> { - // features must start with a `+` or `-`. - let feature = s.strip_prefix(&['+', '-'][..]).unwrap_or_else(|| { - bug!("target feature `{}` must begin with a `+` or `-`", s); - }); - // Rustc-specific feature requests like `+crt-static` or `-crt-static` - // are not passed down to GCC. - if RUSTC_SPECIFIC_FEATURES.contains(&feature) { - return None; - } - Some(feature) -} - // To find a list of GCC's names, check https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html pub fn to_gcc_features<'a>(sess: &Session, s: &'a str) -> SmallVec<[&'a str; 2]> { let arch = if sess.target.arch == "x86_64" { "x86" } else { &*sess.target.arch }; match (arch, s) { + // FIXME: seems like x87 does not exist? + ("x86", "x87") => smallvec![], ("x86", "sse4.2") => smallvec!["sse4.2", "crc32"], ("x86", "pclmulqdq") => smallvec!["pclmul"], ("x86", "rdrand") => smallvec!["rdrnd"], From f06f5684112ac2de345819b9da513035f253764b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 26 Dec 2024 19:47:41 +0100 Subject: [PATCH 10/22] x86-64 hardfloat actually requires sse2 --- src/gcc_util.rs | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/gcc_util.rs b/src/gcc_util.rs index b0fd07827d6..3e579d75d86 100644 --- a/src/gcc_util.rs +++ b/src/gcc_util.rs @@ -129,12 +129,18 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec Date: Fri, 27 Dec 2024 22:19:55 +0100 Subject: [PATCH 11/22] add ABI target features *before* -Ctarget-features --- src/gcc_util.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/gcc_util.rs b/src/gcc_util.rs index 3e579d75d86..e9dfb4e4cf4 100644 --- a/src/gcc_util.rs +++ b/src/gcc_util.rs @@ -154,12 +154,12 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec Date: Wed, 1 Jan 2025 21:42:45 +0100 Subject: [PATCH 12/22] upstream rustc_codegen_llvm changes for enzyme/autodiff --- src/lib.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index f2efa981f97..7329080ce1f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -93,6 +93,7 @@ use gccjit::{CType, Context, OptimizationLevel}; #[cfg(feature = "master")] use gccjit::{TargetInfo, Version}; use rustc_ast::expand::allocator::AllocatorKind; +use rustc_ast::expand::autodiff_attrs::AutoDiffItem; use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule}; use rustc_codegen_ssa::back::write::{ CodegenContext, FatLtoInput, ModuleConfig, TargetMachineFactoryFn, @@ -439,6 +440,15 @@ impl WriteBackendMethods for GccCodegenBackend { ) -> Result, FatalError> { back::write::link(cgcx, dcx, modules) } + fn autodiff( + _cgcx: &CodegenContext, + _tcx: TyCtxt<'_>, + _module: &ModuleCodegen, + _diff_fncs: Vec, + _config: &ModuleConfig, + ) -> Result<(), FatalError> { + unimplemented!() + } } /// This is the entrypoint for a hot plugged rustc_codegen_gccjit From 3aba2d96d17be4df937be7629da1862d9a838476 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 5 Jan 2025 10:34:33 +0100 Subject: [PATCH 13/22] add dedicated type for ABI target feature constraints --- src/gcc_util.rs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/gcc_util.rs b/src/gcc_util.rs index e9dfb4e4cf4..1994a2a3c53 100644 --- a/src/gcc_util.rs +++ b/src/gcc_util.rs @@ -47,9 +47,9 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec Vec Vec Vec Vec Date: Tue, 7 Jan 2025 00:53:42 +0000 Subject: [PATCH 14/22] llvm: Ignore error value that is always false See llvm/llvm-project#121851 For LLVM 20+, this function (`renameModuleForThinLTO`) has no return value. For prior versions of LLVM, this never failed, but had a signature which allowed an error value people were handling. --- src/back/lto.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/back/lto.rs b/src/back/lto.rs index ed92f9c5241..f7173d4d2ff 100644 --- a/src/back/lto.rs +++ b/src/back/lto.rs @@ -660,9 +660,7 @@ pub unsafe fn optimize_thin_module( { let _timer = cgcx.prof.generic_activity_with_arg("LLVM_thin_lto_rename", thin_module.name()); - if !llvm::LLVMRustPrepareThinLTORename(thin_module.shared.data.0, llmod, target) { - return Err(write::llvm_err(&dcx, LlvmError::PrepareThinLtoModule)); - } + unsafe { llvm::LLVMRustPrepareThinLTORename(thin_module.shared.data.0, llmod, target) }; save_temp_bitcode(cgcx, &module, "thin-lto-after-rename"); } From 90ae2cf4185425c877b7455e26fa14414aa376c5 Mon Sep 17 00:00:00 2001 From: David Wood Date: Mon, 23 Sep 2024 18:46:23 +0100 Subject: [PATCH 15/22] mir_transform: implement forced inlining Adds `#[rustc_force_inline]` which is similar to always inlining but reports an error if the inlining was not possible, and which always attempts to inline annotated items, regardless of optimisation levels. It can only be applied to free functions to guarantee that the MIR inliner will be able to resolve calls. --- src/attributes.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/attributes.rs b/src/attributes.rs index 028a5ab5f71..69b04dd5796 100644 --- a/src/attributes.rs +++ b/src/attributes.rs @@ -20,7 +20,7 @@ fn inline_attr<'gcc, 'tcx>( ) -> Option> { match inline { InlineAttr::Hint => Some(FnAttribute::Inline), - InlineAttr::Always => Some(FnAttribute::AlwaysInline), + InlineAttr::Always | InlineAttr::Force { .. } => Some(FnAttribute::AlwaysInline), InlineAttr::Never => { if cx.sess().target.arch != "amdgpu" { Some(FnAttribute::NoInline) From c6f258d884fdcc037bab2daa604dd9cead0d3838 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Tue, 7 Jan 2025 15:30:54 +0000 Subject: [PATCH 16/22] migrate `rustc_codegen_gcc` to the `DenseBitSet` name --- src/debuginfo.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/debuginfo.rs b/src/debuginfo.rs index 6aeb656c1ab..d3aeb7f3bde 100644 --- a/src/debuginfo.rs +++ b/src/debuginfo.rs @@ -4,7 +4,7 @@ use gccjit::{Location, RValue}; use rustc_codegen_ssa::mir::debuginfo::{DebugScope, FunctionDebugContext, VariableKind}; use rustc_codegen_ssa::traits::{DebugInfoBuilderMethods, DebugInfoCodegenMethods}; use rustc_data_structures::sync::Lrc; -use rustc_index::bit_set::BitSet; +use rustc_index::bit_set::DenseBitSet; use rustc_index::{Idx, IndexVec}; use rustc_middle::mir::{self, Body, SourceScope}; use rustc_middle::ty::{Instance, PolyExistentialTraitRef, Ty}; @@ -69,7 +69,7 @@ fn compute_mir_scopes<'gcc, 'tcx>( ) { // Find all scopes with variables defined in them. let variables = if cx.sess().opts.debuginfo == DebugInfo::Full { - let mut vars = BitSet::new_empty(mir.source_scopes.len()); + let mut vars = DenseBitSet::new_empty(mir.source_scopes.len()); // FIXME(eddyb) take into account that arguments always have debuginfo, // irrespective of their name (assuming full debuginfo is enabled). // NOTE(eddyb) actually, on second thought, those are always in the @@ -82,7 +82,7 @@ fn compute_mir_scopes<'gcc, 'tcx>( // Nothing to emit, of course. None }; - let mut instantiated = BitSet::new_empty(mir.source_scopes.len()); + let mut instantiated = DenseBitSet::new_empty(mir.source_scopes.len()); // Instantiate all scopes. for idx in 0..mir.source_scopes.len() { let scope = SourceScope::new(idx); @@ -101,9 +101,9 @@ fn make_mir_scope<'gcc, 'tcx>( cx: &CodegenCx<'gcc, 'tcx>, _instance: Instance<'tcx>, mir: &Body<'tcx>, - variables: &Option>, + variables: &Option>, debug_context: &mut FunctionDebugContext<'tcx, (), Location<'gcc>>, - instantiated: &mut BitSet, + instantiated: &mut DenseBitSet, scope: SourceScope, ) { if instantiated.contains(scope) { From 59689c43f3e8ac79bd221d1b0617017547bf3bd2 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 12 Jan 2025 19:37:10 -0500 Subject: [PATCH 17/22] Update to nightly-2025-01-12 --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index c4171310577..940b3de9f74 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2024-12-11" +channel = "nightly-2025-01-12" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] From b4418b896c163f935bf0f48e7c1fa62cd2a3baaf Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 12 Jan 2025 19:47:47 -0500 Subject: [PATCH 18/22] Fix clippy warnings --- src/gcc_util.rs | 44 +++++++++++++++++++------------------------ src/intrinsic/llvm.rs | 2 +- src/lib.rs | 6 +++--- 3 files changed, 23 insertions(+), 29 deletions(-) diff --git a/src/gcc_util.rs b/src/gcc_util.rs index 1994a2a3c53..560aff43d65 100644 --- a/src/gcc_util.rs +++ b/src/gcc_util.rs @@ -66,16 +66,14 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec. all_rust_features.push((false, feature)); - } else if !feature.is_empty() { - if diagnostics { - sess.dcx().emit_warn(UnknownCTargetFeaturePrefix { feature }); - } + } else if !feature.is_empty() && diagnostics { + sess.dcx().emit_warn(UnknownCTargetFeaturePrefix { feature }); } } // Remove features that are meant for rustc, not codegen. - all_rust_features.retain(|(_, feature)| { + all_rust_features.retain(|&(_, feature)| { // Retain if it is not a rustc feature - !RUSTC_SPECIFIC_FEATURES.contains(feature) + !RUSTC_SPECIFIC_FEATURES.contains(&feature) }); // Check feature validity. @@ -103,7 +101,7 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec { + Some(&(_, stability, _)) => { if let Err(reason) = stability.toggle_allowed() { sess.dcx().emit_warn(ForbiddenCTargetFeature { feature, @@ -165,29 +163,25 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec>(), - ) - }) - .flatten(); + to_gcc_features(sess, feature) + .iter() + .flat_map(|feat| to_gcc_features(sess, feat).into_iter()) + .map(|feature| { + if enable_disable == '-' { + format!("-{}", feature) + } else { + feature.to_string() + } + }) + .collect::>() + }); features.extend(feats); if diagnostics { diff --git a/src/intrinsic/llvm.rs b/src/intrinsic/llvm.rs index 0a448ded6b1..231307def29 100644 --- a/src/intrinsic/llvm.rs +++ b/src/intrinsic/llvm.rs @@ -421,7 +421,7 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>( | "__builtin_ia32_xsaveopt64" => { let new_args = args.to_vec(); let thirty_two = builder.context.new_rvalue_from_int(new_args[1].get_type(), 32); - let arg2 = new_args[1] << thirty_two | new_args[2]; + let arg2 = (new_args[1] << thirty_two) | new_args[2]; let arg2_type = gcc_func.get_param_type(1); let arg2 = builder.context.new_cast(None, arg2, arg2_type); args = vec![new_args[0], arg2].into(); diff --git a/src/lib.rs b/src/lib.rs index 1dfa598ea67..f6ad0c79de5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -494,10 +494,10 @@ fn target_features_cfg( sess.target .rust_target_features() .iter() - .filter(|(_, gate, _)| gate.in_cfg()) - .filter_map(|(feature, gate, _)| { + .filter(|&&(_, gate, _)| gate.in_cfg()) + .filter_map(|&(feature, gate, _)| { if sess.is_nightly_build() || allow_unstable || gate.requires_nightly().is_none() { - Some(*feature) + Some(feature) } else { None } From 06fdf3df2ce1fdfec057ac3c43f0fc0ea80aec63 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Mon, 13 Jan 2025 08:10:40 -0500 Subject: [PATCH 19/22] Use mini_core in the tests --- .github/workflows/ci.yml | 2 +- .github/workflows/m68k.yml | 2 +- .github/workflows/release.yml | 1 + .github/workflows/stdarch.yml | 5 +- example/mini_core.rs | 8 + tests/lang_tests_common.rs | 2 + tests/run/array.rs | 206 +----------------------- tests/run/closure.rs | 184 +--------------------- tests/run/condition.rs | 288 +--------------------------------- tests/run/fun_ptr.rs | 196 +---------------------- tests/run/ptr_cast.rs | 196 +---------------------- tests/run/slice.rs | 101 +----------- 12 files changed, 26 insertions(+), 1165 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index efb4de5f5fb..73ec6b84a15 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,7 +22,6 @@ jobs: - { gcc: "gcc-13.deb" } - { gcc: "gcc-13-without-int128.deb" } commands: [ - "--mini-tests", "--std-tests", # FIXME: re-enable asm tests when GCC can emit in the right syntax. # "--asm-tests", @@ -79,6 +78,7 @@ jobs: run: | ./y.sh prepare --only-libcore ./y.sh build --sysroot + ./y.sh test --mini-tests cargo test - name: Run y.sh cargo build diff --git a/.github/workflows/m68k.yml b/.github/workflows/m68k.yml index 69549dfeb5f..07bb372b360 100644 --- a/.github/workflows/m68k.yml +++ b/.github/workflows/m68k.yml @@ -23,7 +23,6 @@ jobs: fail-fast: false matrix: commands: [ - "--mini-tests", "--std-tests", # TODO(antoyo): fix those on m68k. #"--test-libcore", @@ -93,6 +92,7 @@ jobs: run: | ./y.sh prepare --only-libcore --cross ./y.sh build --sysroot --features compiler_builtins/no-f16-f128 --target-triple m68k-unknown-linux-gnu + ./y.sh test --mini-tests CG_GCC_TEST_TARGET=m68k-unknown-linux-gnu cargo test ./y.sh clean all diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f1ddb301acc..60e0943c87d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -54,6 +54,7 @@ jobs: run: | ./y.sh prepare --only-libcore EMBED_LTO_BITCODE=1 ./y.sh build --sysroot --release --release-sysroot + ./y.sh test --mini-tests cargo test ./y.sh clean all diff --git a/.github/workflows/stdarch.yml b/.github/workflows/stdarch.yml index d8818eefa96..d5ae6144496 100644 --- a/.github/workflows/stdarch.yml +++ b/.github/workflows/stdarch.yml @@ -73,10 +73,6 @@ jobs: echo "LD_LIBRARY_PATH="$(./y.sh info | grep -v Using) >> $GITHUB_ENV echo "LIBRARY_PATH="$(./y.sh info | grep -v Using) >> $GITHUB_ENV - - name: Build (part 2) - run: | - cargo test - - name: Clean if: ${{ !matrix.cargo_runner }} run: | @@ -92,6 +88,7 @@ jobs: if: ${{ !matrix.cargo_runner }} run: | ./y.sh test --release --clean --release-sysroot --build-sysroot --mini-tests --std-tests --test-libcore + cargo test - name: Run stdarch tests if: ${{ !matrix.cargo_runner }} diff --git a/example/mini_core.rs b/example/mini_core.rs index cdd151613df..bd7a4612a92 100644 --- a/example/mini_core.rs +++ b/example/mini_core.rs @@ -170,6 +170,14 @@ impl Add for usize { } } +impl Add for isize { + type Output = Self; + + fn add(self, rhs: Self) -> Self { + self + rhs + } +} + #[lang = "sub"] pub trait Sub { type Output; diff --git a/tests/lang_tests_common.rs b/tests/lang_tests_common.rs index 433b3d680b5..fafb7be55ce 100644 --- a/tests/lang_tests_common.rs +++ b/tests/lang_tests_common.rs @@ -89,6 +89,8 @@ pub fn main_inner(profile: Profile) { &format!("{}/build/build_sysroot/sysroot/", current_dir), "-C", "link-arg=-lc", + "--extern", + "mini_core=target/out/libmini_core.rlib", "-o", exe.to_str().expect("to_str"), path.to_str().expect("to_str"), diff --git a/tests/run/array.rs b/tests/run/array.rs index 9d04ba10b23..c3c08c29c6d 100644 --- a/tests/run/array.rs +++ b/tests/run/array.rs @@ -7,38 +7,12 @@ // 5 // 10 -#![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs)] -#![allow(internal_features)] +#![feature(no_core, start)] #![no_std] #![no_core] -/* - * Core - */ - -// Because we don't have core yet. -#[lang = "sized"] -pub trait Sized {} - -#[lang = "copy"] -trait Copy { -} - -impl Copy for isize {} -impl Copy for usize {} -impl Copy for i32 {} -impl Copy for u8 {} -impl Copy for i8 {} -impl Copy for i16 {} -impl Copy for *mut T {} - -#[lang = "legacy_receiver"] -trait LegacyReceiver { -} - -#[lang = "freeze"] -pub(crate) unsafe auto trait Freeze {} +extern crate mini_core; mod libc { #[link(name = "c")] @@ -48,182 +22,6 @@ mod libc { } } -#[lang = "index"] -pub trait Index { - type Output: ?Sized; - fn index(&self, index: Idx) -> &Self::Output; -} - -impl Index for [T; 3] { - type Output = T; - - fn index(&self, index: usize) -> &Self::Output { - &self[index] - } -} - -impl Index for [T] { - type Output = T; - - fn index(&self, index: usize) -> &Self::Output { - &self[index] - } -} - -#[lang = "drop_in_place"] -#[allow(unconditional_recursion)] -pub unsafe fn drop_in_place(to_drop: *mut T) { - // Code here does not matter - this is replaced by the - // real drop glue by the compiler. - drop_in_place(to_drop); -} - -#[lang = "panic"] -#[track_caller] -#[no_mangle] -pub fn panic(_msg: &'static str) -> ! { - unsafe { - libc::puts("Panicking\0" as *const str as *const u8); - intrinsics::abort(); - } -} - -#[lang = "panic_location"] -struct PanicLocation { - file: &'static str, - line: u32, - column: u32, -} - -#[lang = "panic_bounds_check"] -#[track_caller] -#[no_mangle] -fn panic_bounds_check(index: usize, len: usize) -> ! { - unsafe { - libc::printf("index out of bounds: the len is %d but the index is %d\n\0" as *const str as *const i8, len, index); - intrinsics::abort(); - } -} - -mod intrinsics { - #[rustc_nounwind] - #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn abort() -> ! { - loop {} - } -} - -#[lang = "add"] -trait Add { - type Output; - - fn add(self, rhs: RHS) -> Self::Output; -} - -impl Add for u8 { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -impl Add for i8 { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -impl Add for i32 { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -impl Add for usize { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -impl Add for isize { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -#[lang = "sub"] -pub trait Sub { - type Output; - - fn sub(self, rhs: RHS) -> Self::Output; -} - -impl Sub for usize { - type Output = Self; - - fn sub(self, rhs: Self) -> Self { - self - rhs - } -} - -impl Sub for isize { - type Output = Self; - - fn sub(self, rhs: Self) -> Self { - self - rhs - } -} - -impl Sub for u8 { - type Output = Self; - - fn sub(self, rhs: Self) -> Self { - self - rhs - } -} - -impl Sub for i8 { - type Output = Self; - - fn sub(self, rhs: Self) -> Self { - self - rhs - } -} - -impl Sub for i16 { - type Output = Self; - - fn sub(self, rhs: Self) -> Self { - self - rhs - } -} - -#[track_caller] -#[lang = "panic_const_add_overflow"] -pub fn panic_const_add_overflow() -> ! { - panic("attempt to add with overflow"); -} - -#[track_caller] -#[lang = "panic_const_sub_overflow"] -pub fn panic_const_sub_overflow() -> ! { - panic("attempt to subtract with overflow"); -} - -/* - * Code - */ - static mut ONE: usize = 1; fn make_array() -> [u8; 3] { diff --git a/tests/run/closure.rs b/tests/run/closure.rs index 6f7210b5d07..46c47bc54ed 100644 --- a/tests/run/closure.rs +++ b/tests/run/closure.rs @@ -8,200 +8,20 @@ // Int argument: 2 // Both args: 11 -#![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics, - unboxed_closures, rustc_attrs)] -#![allow(internal_features)] +#![feature(no_core, start)] #![no_std] #![no_core] -/* - * Core - */ - -// Because we don't have core yet. -#[lang = "sized"] -pub trait Sized {} - -#[lang = "copy"] -trait Copy { -} - -impl Copy for isize {} -impl Copy for usize {} -impl Copy for i32 {} -impl Copy for u32 {} -impl Copy for u8 {} -impl Copy for i8 {} -impl Copy for *mut T {} - -#[lang = "legacy_receiver"] -trait LegacyReceiver { -} - -#[lang = "freeze"] -pub(crate) unsafe auto trait Freeze {} +extern crate mini_core; mod libc { #[link(name = "c")] extern "C" { - pub fn puts(s: *const u8) -> i32; pub fn printf(format: *const i8, ...) -> i32; } } -#[lang = "index"] -pub trait Index { - type Output: ?Sized; - fn index(&self, index: Idx) -> &Self::Output; -} - -impl Index for [T; 3] { - type Output = T; - - fn index(&self, index: usize) -> &Self::Output { - &self[index] - } -} - -impl Index for [T] { - type Output = T; - - fn index(&self, index: usize) -> &Self::Output { - &self[index] - } -} - -#[lang = "drop_in_place"] -#[allow(unconditional_recursion)] -pub unsafe fn drop_in_place(to_drop: *mut T) { - // Code here does not matter - this is replaced by the - // real drop glue by the compiler. - drop_in_place(to_drop); -} - -#[lang = "panic_location"] -struct PanicLocation { - file: &'static str, - line: u32, - column: u32, -} - -#[lang = "panic_bounds_check"] -#[track_caller] -#[no_mangle] -fn panic_bounds_check(index: usize, len: usize) -> ! { - unsafe { - libc::printf("index out of bounds: the len is %d but the index is %d\n\0" as *const str as *const i8, len, index); - intrinsics::abort(); - } -} - -mod intrinsics { - #[rustc_nounwind] - #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn abort() -> ! { - loop {} - } -} - -#[lang = "tuple_trait"] -pub trait Tuple {} - -#[lang = "unsize"] -pub trait Unsize {} - -#[lang = "coerce_unsized"] -pub trait CoerceUnsized {} - -impl<'a, 'b: 'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} -impl<'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<&'a mut U> for &'a mut T {} -impl, U: ?Sized> CoerceUnsized<*const U> for *const T {} -impl, U: ?Sized> CoerceUnsized<*mut U> for *mut T {} - -#[lang = "fn_once"] -#[rustc_paren_sugar] -pub trait FnOnce { - #[lang = "fn_once_output"] - type Output; - - extern "rust-call" fn call_once(self, args: Args) -> Self::Output; -} - -#[lang = "fn_mut"] -#[rustc_paren_sugar] -pub trait FnMut: FnOnce { - extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output; -} - -#[lang = "add"] -trait Add { - type Output; - - fn add(self, rhs: RHS) -> Self::Output; -} - -impl Add for u8 { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -impl Add for i8 { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -impl Add for i32 { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -impl Add for usize { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -impl Add for isize { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -#[lang = "panic"] -#[track_caller] -#[no_mangle] -pub fn panic(_msg: &'static str) -> ! { - unsafe { - libc::puts("Panicking\0" as *const str as *const u8); - intrinsics::abort(); - } -} - -#[track_caller] -#[lang = "panic_const_add_overflow"] -pub fn panic_const_add_overflow() -> ! { - panic("attempt to add with overflow"); -} - -/* - * Code - */ - #[start] fn main(mut argc: isize, _argv: *const *const u8) -> isize { let string = "Arg: %d\n\0"; diff --git a/tests/run/condition.rs b/tests/run/condition.rs index 01af6fa8280..039ef94eaa7 100644 --- a/tests/run/condition.rs +++ b/tests/run/condition.rs @@ -5,304 +5,20 @@ // stdout: true // 1 -#![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs)] -#![allow(internal_features)] +#![feature(no_core, start)] #![no_std] #![no_core] -/* - * Core - */ - -// Because we don't have core yet. -#[lang = "sized"] -pub trait Sized {} - -#[lang = "copy"] -trait Copy { -} - -impl Copy for isize {} -impl Copy for usize {} -impl Copy for u64 {} -impl Copy for i32 {} -impl Copy for u32 {} -impl Copy for bool {} -impl Copy for u16 {} -impl Copy for i16 {} -impl Copy for char {} -impl Copy for i8 {} -impl Copy for u8 {} -impl Copy for *mut T {} - -#[lang = "legacy_receiver"] -trait LegacyReceiver { -} - -#[lang = "freeze"] -pub(crate) unsafe auto trait Freeze {} +extern crate mini_core; mod libc { #[link(name = "c")] extern "C" { pub fn printf(format: *const i8, ...) -> i32; - pub fn puts(s: *const u8) -> i32; - } -} - -#[lang = "index"] -pub trait Index { - type Output: ?Sized; - fn index(&self, index: Idx) -> &Self::Output; -} - -impl Index for [T; 3] { - type Output = T; - - fn index(&self, index: usize) -> &Self::Output { - &self[index] - } -} - -impl Index for [T] { - type Output = T; - - fn index(&self, index: usize) -> &Self::Output { - &self[index] - } -} - -#[lang = "drop_in_place"] -#[allow(unconditional_recursion)] -pub unsafe fn drop_in_place(to_drop: *mut T) { - // Code here does not matter - this is replaced by the - // real drop glue by the compiler. - drop_in_place(to_drop); -} - -#[lang = "panic"] -#[track_caller] -#[no_mangle] -pub fn panic(_msg: &'static str) -> ! { - unsafe { - libc::puts("Panicking\0" as *const str as *const u8); - intrinsics::abort(); - } -} - -#[lang = "panic_location"] -struct PanicLocation { - file: &'static str, - line: u32, - column: u32, -} - -#[lang = "panic_bounds_check"] -#[track_caller] -#[no_mangle] -fn panic_bounds_check(index: usize, len: usize) -> ! { - unsafe { - libc::printf("index out of bounds: the len is %d but the index is %d\n\0" as *const str as *const i8, len, index); - intrinsics::abort(); - } -} - -mod intrinsics { - #[rustc_nounwind] - #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn abort() -> ! { - loop {} - } -} - -#[lang = "add"] -trait Add { - type Output; - - fn add(self, rhs: RHS) -> Self::Output; -} - -impl Add for u8 { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -impl Add for i8 { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -impl Add for i32 { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -impl Add for usize { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -impl Add for isize { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -#[lang = "sub"] -pub trait Sub { - type Output; - - fn sub(self, rhs: RHS) -> Self::Output; -} - -impl Sub for usize { - type Output = Self; - - fn sub(self, rhs: Self) -> Self { - self - rhs - } -} - -impl Sub for isize { - type Output = Self; - - fn sub(self, rhs: Self) -> Self { - self - rhs - } -} - -impl Sub for u8 { - type Output = Self; - - fn sub(self, rhs: Self) -> Self { - self - rhs - } -} - -impl Sub for i8 { - type Output = Self; - - fn sub(self, rhs: Self) -> Self { - self - rhs } } -impl Sub for i16 { - type Output = Self; - - fn sub(self, rhs: Self) -> Self { - self - rhs - } -} - -#[lang = "eq"] -pub trait PartialEq { - fn eq(&self, other: &Rhs) -> bool; - fn ne(&self, other: &Rhs) -> bool; -} - -impl PartialEq for u8 { - fn eq(&self, other: &u8) -> bool { - (*self) == (*other) - } - fn ne(&self, other: &u8) -> bool { - (*self) != (*other) - } -} - -impl PartialEq for u16 { - fn eq(&self, other: &u16) -> bool { - (*self) == (*other) - } - fn ne(&self, other: &u16) -> bool { - (*self) != (*other) - } -} - -impl PartialEq for u32 { - fn eq(&self, other: &u32) -> bool { - (*self) == (*other) - } - fn ne(&self, other: &u32) -> bool { - (*self) != (*other) - } -} - - -impl PartialEq for u64 { - fn eq(&self, other: &u64) -> bool { - (*self) == (*other) - } - fn ne(&self, other: &u64) -> bool { - (*self) != (*other) - } -} - -impl PartialEq for usize { - fn eq(&self, other: &usize) -> bool { - (*self) == (*other) - } - fn ne(&self, other: &usize) -> bool { - (*self) != (*other) - } -} - -impl PartialEq for i8 { - fn eq(&self, other: &i8) -> bool { - (*self) == (*other) - } - fn ne(&self, other: &i8) -> bool { - (*self) != (*other) - } -} - -impl PartialEq for i32 { - fn eq(&self, other: &i32) -> bool { - (*self) == (*other) - } - fn ne(&self, other: &i32) -> bool { - (*self) != (*other) - } -} - -impl PartialEq for isize { - fn eq(&self, other: &isize) -> bool { - (*self) == (*other) - } - fn ne(&self, other: &isize) -> bool { - (*self) != (*other) - } -} - -impl PartialEq for char { - fn eq(&self, other: &char) -> bool { - (*self) == (*other) - } - fn ne(&self, other: &char) -> bool { - (*self) != (*other) - } -} - -/* - * Code - */ - #[start] fn main(argc: isize, _argv: *const *const u8) -> isize { unsafe { diff --git a/tests/run/fun_ptr.rs b/tests/run/fun_ptr.rs index a2e304c1e37..ed1bf72bb27 100644 --- a/tests/run/fun_ptr.rs +++ b/tests/run/fun_ptr.rs @@ -4,212 +4,20 @@ // status: 0 // stdout: 1 -#![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs)] -#![allow(internal_features)] +#![feature(no_core, start)] #![no_std] #![no_core] -/* - * Core - */ - -// Because we don't have core yet. -#[lang = "sized"] -pub trait Sized {} - -#[lang = "copy"] -trait Copy { -} - -impl Copy for isize {} -impl Copy for usize {} -impl Copy for i32 {} -impl Copy for u8 {} -impl Copy for i8 {} -impl Copy for i16 {} -impl Copy for *mut T {} - -#[lang = "legacy_receiver"] -trait LegacyReceiver { -} - -#[lang = "freeze"] -pub(crate) unsafe auto trait Freeze {} +extern crate mini_core; mod libc { #[link(name = "c")] extern "C" { pub fn printf(format: *const i8, ...) -> i32; - pub fn puts(s: *const u8) -> i32; - } -} - -#[lang = "index"] -pub trait Index { - type Output: ?Sized; - fn index(&self, index: Idx) -> &Self::Output; -} - -impl Index for [T; 3] { - type Output = T; - - fn index(&self, index: usize) -> &Self::Output { - &self[index] - } -} - -impl Index for [T] { - type Output = T; - - fn index(&self, index: usize) -> &Self::Output { - &self[index] - } -} - -#[lang = "drop_in_place"] -#[allow(unconditional_recursion)] -pub unsafe fn drop_in_place(to_drop: *mut T) { - // Code here does not matter - this is replaced by the - // real drop glue by the compiler. - drop_in_place(to_drop); -} - -#[lang = "panic"] -#[track_caller] -#[no_mangle] -pub fn panic(_msg: &'static str) -> ! { - unsafe { - libc::puts("Panicking\0" as *const str as *const u8); - intrinsics::abort(); - } -} - -#[lang = "panic_location"] -struct PanicLocation { - file: &'static str, - line: u32, - column: u32, -} - -#[lang = "panic_bounds_check"] -#[track_caller] -#[no_mangle] -fn panic_bounds_check(index: usize, len: usize) -> ! { - unsafe { - libc::printf("index out of bounds: the len is %d but the index is %d\n\0" as *const str as *const i8, len, index); - intrinsics::abort(); - } -} - -mod intrinsics { - #[rustc_nounwind] - #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn abort() -> ! { - loop {} - } -} - -#[lang = "add"] -trait Add { - type Output; - - fn add(self, rhs: RHS) -> Self::Output; -} - -impl Add for u8 { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -impl Add for i8 { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -impl Add for i32 { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -impl Add for usize { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -impl Add for isize { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -#[lang = "sub"] -pub trait Sub { - type Output; - - fn sub(self, rhs: RHS) -> Self::Output; -} - -impl Sub for usize { - type Output = Self; - - fn sub(self, rhs: Self) -> Self { - self - rhs - } -} - -impl Sub for isize { - type Output = Self; - - fn sub(self, rhs: Self) -> Self { - self - rhs - } -} - -impl Sub for u8 { - type Output = Self; - - fn sub(self, rhs: Self) -> Self { - self - rhs } } -impl Sub for i8 { - type Output = Self; - - fn sub(self, rhs: Self) -> Self { - self - rhs - } -} - -impl Sub for i16 { - type Output = Self; - - fn sub(self, rhs: Self) -> Self { - self - rhs - } -} - - -/* - * Code - */ - fn i16_as_i8(a: i16) -> i8 { a as i8 } diff --git a/tests/run/ptr_cast.rs b/tests/run/ptr_cast.rs index d66d5b2a8cb..2b8812ad51c 100644 --- a/tests/run/ptr_cast.rs +++ b/tests/run/ptr_cast.rs @@ -4,212 +4,20 @@ // status: 0 // stdout: 1 -#![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs)] -#![allow(internal_features)] +#![feature(no_core, start)] #![no_std] #![no_core] -/* - * Core - */ - -// Because we don't have core yet. -#[lang = "sized"] -pub trait Sized {} - -#[lang = "copy"] -trait Copy { -} - -impl Copy for isize {} -impl Copy for usize {} -impl Copy for i32 {} -impl Copy for u8 {} -impl Copy for i8 {} -impl Copy for i16 {} -impl Copy for *mut T {} - -#[lang = "legacy_receiver"] -trait LegacyReceiver { -} - -#[lang = "freeze"] -pub(crate) unsafe auto trait Freeze {} +extern crate mini_core; mod libc { #[link(name = "c")] extern "C" { pub fn printf(format: *const i8, ...) -> i32; - pub fn puts(s: *const u8) -> i32; - } -} - -#[lang = "index"] -pub trait Index { - type Output: ?Sized; - fn index(&self, index: Idx) -> &Self::Output; -} - -impl Index for [T; 3] { - type Output = T; - - fn index(&self, index: usize) -> &Self::Output { - &self[index] - } -} - -impl Index for [T] { - type Output = T; - - fn index(&self, index: usize) -> &Self::Output { - &self[index] - } -} - -#[lang = "drop_in_place"] -#[allow(unconditional_recursion)] -pub unsafe fn drop_in_place(to_drop: *mut T) { - // Code here does not matter - this is replaced by the - // real drop glue by the compiler. - drop_in_place(to_drop); -} - -#[lang = "panic"] -#[track_caller] -#[no_mangle] -pub fn panic(_msg: &'static str) -> ! { - unsafe { - libc::puts("Panicking\0" as *const str as *const u8); - intrinsics::abort(); - } -} - -#[lang = "panic_location"] -struct PanicLocation { - file: &'static str, - line: u32, - column: u32, -} - -#[lang = "panic_bounds_check"] -#[track_caller] -#[no_mangle] -fn panic_bounds_check(index: usize, len: usize) -> ! { - unsafe { - libc::printf("index out of bounds: the len is %d but the index is %d\n\0" as *const str as *const i8, len, index); - intrinsics::abort(); - } -} - -mod intrinsics { - #[rustc_nounwind] - #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn abort() -> ! { - loop {} - } -} - -#[lang = "add"] -trait Add { - type Output; - - fn add(self, rhs: RHS) -> Self::Output; -} - -impl Add for u8 { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -impl Add for i8 { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -impl Add for i32 { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -impl Add for usize { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -impl Add for isize { - type Output = Self; - - fn add(self, rhs: Self) -> Self { - self + rhs - } -} - -#[lang = "sub"] -pub trait Sub { - type Output; - - fn sub(self, rhs: RHS) -> Self::Output; -} - -impl Sub for usize { - type Output = Self; - - fn sub(self, rhs: Self) -> Self { - self - rhs - } -} - -impl Sub for isize { - type Output = Self; - - fn sub(self, rhs: Self) -> Self { - self - rhs - } -} - -impl Sub for u8 { - type Output = Self; - - fn sub(self, rhs: Self) -> Self { - self - rhs } } -impl Sub for i8 { - type Output = Self; - - fn sub(self, rhs: Self) -> Self { - self - rhs - } -} - -impl Sub for i16 { - type Output = Self; - - fn sub(self, rhs: Self) -> Self { - self - rhs - } -} - - -/* - * Code - */ - static mut ONE: usize = 1; fn make_array() -> [u8; 3] { diff --git a/tests/run/slice.rs b/tests/run/slice.rs index 32f4c604058..fba93fc1554 100644 --- a/tests/run/slice.rs +++ b/tests/run/slice.rs @@ -4,36 +4,12 @@ // status: 0 // stdout: 5 -#![feature(arbitrary_self_types, auto_traits, lang_items, no_core, start, intrinsics, rustc_attrs)] -#![allow(internal_features)] +#![feature(no_core, start)] #![no_std] #![no_core] -/* - * Core - */ - -// Because we don't have core yet. -#[lang = "sized"] -pub trait Sized {} - -#[lang = "copy"] -trait Copy { -} - -impl Copy for isize {} -impl Copy for usize {} -impl Copy for i32 {} -impl Copy for u32 {} -impl Copy for *mut T {} - -#[lang = "legacy_receiver"] -trait LegacyReceiver { -} - -#[lang = "freeze"] -pub(crate) unsafe auto trait Freeze {} +extern crate mini_core; mod libc { #[link(name = "c")] @@ -42,79 +18,6 @@ mod libc { } } -#[lang = "index"] -pub trait Index { - type Output: ?Sized; - fn index(&self, index: Idx) -> &Self::Output; -} - -impl Index for [T; 3] { - type Output = T; - - fn index(&self, index: usize) -> &Self::Output { - &self[index] - } -} - -impl Index for [T] { - type Output = T; - - fn index(&self, index: usize) -> &Self::Output { - &self[index] - } -} - -#[lang = "unsize"] -pub trait Unsize {} - -#[lang = "coerce_unsized"] -pub trait CoerceUnsized {} - -impl<'a, 'b: 'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<&'a U> for &'b T {} -impl<'a, T: ?Sized + Unsize, U: ?Sized> CoerceUnsized<&'a mut U> for &'a mut T {} -impl, U: ?Sized> CoerceUnsized<*const U> for *const T {} -impl, U: ?Sized> CoerceUnsized<*mut U> for *mut T {} - -#[lang = "drop_in_place"] -#[allow(unconditional_recursion)] -pub unsafe fn drop_in_place(to_drop: *mut T) { - // Code here does not matter - this is replaced by the - // real drop glue by the compiler. - drop_in_place(to_drop); -} - -#[lang = "panic_location"] -struct PanicLocation { - file: &'static str, - line: u32, - column: u32, -} - -#[lang = "panic_bounds_check"] -#[track_caller] -#[no_mangle] -fn panic_bounds_check(index: usize, len: usize) -> ! { - unsafe { - libc::printf("index out of bounds: the len is %d but the index is %d\n\0" as *const str as *const i8, len, index); - intrinsics::abort(); - } -} - -mod intrinsics { - use super::Sized; - - #[rustc_nounwind] - #[rustc_intrinsic] - #[rustc_intrinsic_must_be_overridden] - pub fn abort() -> ! { - loop {} - } -} - -/* - * Code - */ - static mut TWO: usize = 2; fn index_slice(s: &[u32]) -> u32 { From 500fce185cea1fdb259c1e88f2610d463ef63e3d Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Mon, 13 Jan 2025 08:29:28 -0500 Subject: [PATCH 20/22] Add error pattern --- build_system/src/test.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 371fcb4bc30..21286e97271 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -848,9 +848,17 @@ fn contains_ui_error_patterns(file_path: &Path, keep_lto_tests: bool) -> Result< if line.is_empty() { continue; } - if ["//@ error-pattern:", "//@ build-fail", "//@ run-fail", "-Cllvm-args", "//~", "thread"] - .iter() - .any(|check| line.contains(check)) + if [ + "//@ error-pattern:", + "//@ build-fail", + "//@ run-fail", + "//@ known-bug", + "-Cllvm-args", + "//~", + "thread", + ] + .iter() + .any(|check| line.contains(check)) { return Ok(true); } From 10d745c7f7f6dbff7feabc00269c7bcee4c9d680 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Mon, 13 Jan 2025 08:53:59 -0500 Subject: [PATCH 21/22] Do not run UI tests in the error-emitter directory --- build_system/src/test.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 21286e97271..7cc7336612c 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -876,9 +876,14 @@ fn contains_ui_error_patterns(file_path: &Path, keep_lto_tests: bool) -> Result< return Ok(true); } } - if file_path.display().to_string().contains("ambiguous-4-extern.rs") { + let file_path = file_path.display().to_string(); + if file_path.contains("ambiguous-4-extern.rs") { eprintln!("nothing found for {file_path:?}"); } + // The files in this directory contain errors. + if file_path.contains("/error-emitter/") { + return Ok(true); + } Ok(false) } From 17f5a4f4f05579854d0819b38b6391cddb1717ef Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Mon, 13 Jan 2025 09:17:54 -0500 Subject: [PATCH 22/22] Add support for fmaf16 --- src/intrinsic/mod.rs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index d2956bac201..11f9604c6d2 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -13,11 +13,12 @@ use rustc_codegen_ssa::common::IntPredicate; use rustc_codegen_ssa::errors::InvalidMonomorphization; use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue}; use rustc_codegen_ssa::mir::place::{PlaceRef, PlaceValue}; +use rustc_codegen_ssa::traits::BaseTypeCodegenMethods; +#[cfg(feature = "master")] +use rustc_codegen_ssa::traits::MiscCodegenMethods; use rustc_codegen_ssa::traits::{ ArgAbiBuilderMethods, BuilderMethods, ConstCodegenMethods, IntrinsicCallBuilderMethods, }; -#[cfg(feature = "master")] -use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, MiscCodegenMethods}; use rustc_middle::bug; #[cfg(feature = "master")] use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt}; @@ -139,6 +140,18 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc &args.iter().map(|arg| arg.immediate()).collect::>(), ) } + sym::fmaf16 => { + // TODO(antoyo): use the correct builtin for f16. + let func = self.cx.context.get_builtin_function("fmaf"); + let args: Vec<_> = args + .iter() + .map(|arg| { + self.cx.context.new_cast(self.location, arg.immediate(), self.cx.type_f32()) + }) + .collect(); + let result = self.cx.context.new_call(self.location, func, &args); + self.cx.context.new_cast(self.location, result, self.cx.type_f16()) + } sym::is_val_statically_known => { let a = args[0].immediate(); let builtin = self.context.get_builtin_function("__builtin_constant_p");