From 2445dd794e4e24d62ab8d79ba8924baba44865ae Mon Sep 17 00:00:00 2001 From: kulst Date: Sun, 9 Feb 2025 11:50:06 +0100 Subject: Persist target features used for codegen beyond tcx Bitcode linkers like llvm-bitcode-linker or bpf linker hand over the target features to llvm during link stage. During link stage the `TyCtxt` is already gone so it is not possible to create a query for the global backend features any longer. The features preserved in `Session.target_features` only incorporate target features known to rustc. This would contradict with the behaviour during codegen stage which also passes target features to llvm which are unknown to rustc. This commit adds target features as a field to the `CrateInfo` struct and queries the target features in its new function. This way the target features are preserved beyond tcx and available at link stage. To make sure the `global_backend_features` query is always registered even if the CodegenBackend does not register it, this registration is added to the `provide`function of the `rustc_codegen_ssa` crate. --- compiler/rustc_codegen_ssa/src/base.rs | 1 + compiler/rustc_codegen_ssa/src/lib.rs | 2 ++ 2 files changed, 3 insertions(+) (limited to 'compiler/rustc_codegen_ssa/src') diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index e800492dad0..0b420fcfaae 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -921,6 +921,7 @@ impl CrateInfo { let n_crates = crates.len(); let mut info = CrateInfo { target_cpu, + target_features: tcx.global_backend_features(()).clone(), crate_types, exported_symbols, linked_symbols, diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 428a45975f1..9d2ac219d59 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -190,6 +190,7 @@ impl From<&cstore::NativeLib> for NativeLib { #[derive(Debug, Encodable, Decodable)] pub struct CrateInfo { pub target_cpu: String, + pub target_features: Vec, pub crate_types: Vec, pub exported_symbols: UnordMap>, pub linked_symbols: FxIndexMap>, @@ -230,6 +231,7 @@ pub fn provide(providers: &mut Providers) { crate::base::provide(providers); crate::target_features::provide(providers); crate::codegen_attrs::provide(providers); + providers.queries.global_backend_features = |_tcx: TyCtxt<'_>, ()| vec![]; } /// Checks if the given filename ends with the `.rcgu.o` extension that `rustc` -- cgit 1.4.1-3-g733a5 From 831d9f39e9c330934b7c4f35010477ba4a738d96 Mon Sep 17 00:00:00 2001 From: kulst Date: Wed, 5 Feb 2025 21:33:58 +0100 Subject: Pass through of target features to llvm-bitcode-linker and handling them The .ptx version produced by llc can be specified by passing it with --mattr. Currently it is not possible to specify the .ptx version with -Ctarget-feature because these are not passed through to llvm-bitcode-linker and handled by it. This commit adds both. --target-feature and -mattr are passed with equals to mitigate issues when the value starts with a - (minus). --- compiler/rustc_codegen_ssa/src/back/link.rs | 6 ++++++ .../llvm-bitcode-linker/src/bin/llvm-bitcode-linker.rs | 6 +++++- src/tools/llvm-bitcode-linker/src/linker.rs | 13 ++++++++++++- 3 files changed, 23 insertions(+), 2 deletions(-) (limited to 'compiler/rustc_codegen_ssa/src') diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 105a4cb81f0..dceef52e81a 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -2518,6 +2518,12 @@ fn add_order_independent_options( "--target-cpu", &codegen_results.crate_info.target_cpu, ]); + if codegen_results.crate_info.target_features.len() > 0 { + cmd.link_arg(&format!( + "--target-feature={}", + &codegen_results.crate_info.target_features.join(",") + )); + } } else if flavor == LinkerFlavor::Ptx { cmd.link_args(&["--fallback-arch", &codegen_results.crate_info.target_cpu]); } else if flavor == LinkerFlavor::Bpf { diff --git a/src/tools/llvm-bitcode-linker/src/bin/llvm-bitcode-linker.rs b/src/tools/llvm-bitcode-linker/src/bin/llvm-bitcode-linker.rs index fdbf6171c53..608c6605304 100644 --- a/src/tools/llvm-bitcode-linker/src/bin/llvm-bitcode-linker.rs +++ b/src/tools/llvm-bitcode-linker/src/bin/llvm-bitcode-linker.rs @@ -27,6 +27,10 @@ pub struct Args { #[arg(long)] target_cpu: Option, + /// The target features + #[arg(long)] + target_feature: Option, + /// Write output to the filename #[arg(short, long)] output: PathBuf, @@ -49,7 +53,7 @@ fn main() -> anyhow::Result<()> { let args = Args::parse(); - let mut linker = Session::new(args.target, args.target_cpu, args.output); + let mut linker = Session::new(args.target, args.target_cpu, args.target_feature, args.output); linker.add_exported_symbols(args.export_symbol); diff --git a/src/tools/llvm-bitcode-linker/src/linker.rs b/src/tools/llvm-bitcode-linker/src/linker.rs index 9f579d10094..dafd847e768 100644 --- a/src/tools/llvm-bitcode-linker/src/linker.rs +++ b/src/tools/llvm-bitcode-linker/src/linker.rs @@ -8,6 +8,7 @@ use crate::{Optimization, Target}; pub struct Session { target: Target, cpu: Option, + feature: Option, symbols: Vec, /// A file that `llvm-link` supports, like a bitcode file or an archive. @@ -21,7 +22,12 @@ pub struct Session { } impl Session { - pub fn new(target: crate::Target, cpu: Option, out_path: PathBuf) -> Self { + pub fn new( + target: crate::Target, + cpu: Option, + feature: Option, + out_path: PathBuf, + ) -> Self { let link_path = out_path.with_extension("o"); let opt_path = out_path.with_extension("optimized.o"); let sym_path = out_path.with_extension("symbols.txt"); @@ -29,6 +35,7 @@ impl Session { Session { target, cpu, + feature, symbols: Vec::new(), files: Vec::new(), link_path, @@ -134,6 +141,10 @@ impl Session { lcc_command.arg("--mcpu").arg(mcpu); } + if let Some(mattr) = &self.feature { + lcc_command.arg(&format!("--mattr={}", mattr)); + } + let lcc_output = lcc_command .arg(&self.opt_path) .arg("-o").arg(&self.out_path) -- cgit 1.4.1-3-g733a5 From 78ddabf31d3147a19be77c3b38b49fe60915d75a Mon Sep 17 00:00:00 2001 From: Patryk Wychowaniec Date: Sun, 13 Oct 2024 14:58:44 +0200 Subject: Create a generic AVR target: avr-none This commit removes the `avr-unknown-gnu-atmega328` target and replaces it with a more generic `avr-none` variant that must be specialized with the `-C target-cpu` flag (e.g. `-C target-cpu=atmega328p`). --- compiler/rustc_codegen_ssa/src/back/link.rs | 1 + compiler/rustc_codegen_ssa/src/back/linker.rs | 12 + compiler/rustc_target/src/spec/base/avr.rs | 337 ++++++++++++++++++ compiler/rustc_target/src/spec/base/avr_gnu.rs | 377 --------------------- compiler/rustc_target/src/spec/base/mod.rs | 2 +- compiler/rustc_target/src/spec/mod.rs | 9 +- compiler/rustc_target/src/spec/targets/avr_none.rs | 32 ++ .../src/spec/targets/avr_unknown_gnu_atmega328.rs | 5 - src/doc/rustc/src/platform-support.md | 2 +- src/doc/rustc/src/platform-support/avr-none.md | 81 +++++ src/tools/compiletest/src/header/tests.rs | 3 + .../run-make-support/src/external_deps/rustc.rs | 7 + tests/assembly/asm/avr-modifiers.rs | 2 +- tests/assembly/asm/avr-types.rs | 2 +- tests/assembly/targets/targets-pe.rs | 6 +- tests/codegen/asm/avr-clobbers.rs | 2 +- tests/codegen/avr/avr-func-addrspace.rs | 2 +- tests/run-make/avr-rjmp-offset/rmake.rs | 4 +- .../feature-gate-abi-avr-interrupt.rs | 2 +- tests/ui/repr/16-bit-repr-c-enum.rs | 2 +- 20 files changed, 493 insertions(+), 397 deletions(-) create mode 100644 compiler/rustc_target/src/spec/base/avr.rs delete mode 100644 compiler/rustc_target/src/spec/base/avr_gnu.rs create mode 100644 compiler/rustc_target/src/spec/targets/avr_none.rs delete mode 100644 compiler/rustc_target/src/spec/targets/avr_unknown_gnu_atmega328.rs create mode 100644 src/doc/rustc/src/platform-support/avr-none.md (limited to 'compiler/rustc_codegen_ssa/src') diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 105a4cb81f0..0399ea77c72 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1990,6 +1990,7 @@ fn add_pre_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) if let Some(args) = sess.target.pre_link_args.get(&flavor) { cmd.verbatim_args(args.iter().map(Deref::deref)); } + cmd.verbatim_args(&sess.opts.unstable_opts.pre_link_args); } diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index e3ace01c1eb..8900405c1b8 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -153,6 +153,7 @@ pub(crate) fn get_linker<'a>( hinted_static: None, is_ld: cc == Cc::No, is_gnu: flavor.is_gnu(), + uses_lld: flavor.uses_lld(), }) as Box, LinkerFlavor::Msvc(..) => Box::new(MsvcLinker { cmd, sess }) as Box, LinkerFlavor::EmCc => Box::new(EmLinker { cmd, sess }) as Box, @@ -361,6 +362,7 @@ struct GccLinker<'a> { // Link as ld is_ld: bool, is_gnu: bool, + uses_lld: bool, } impl<'a> GccLinker<'a> { @@ -552,6 +554,7 @@ impl<'a> Linker for GccLinker<'a> { self.link_args(&["--entry", "_initialize"]); } } + // VxWorks compiler driver introduced `--static-crt` flag specifically for rustc, // it switches linking for libc and similar system libraries to static without using // any `#[link]` attributes in the `libc` crate, see #72782 for details. @@ -567,6 +570,15 @@ impl<'a> Linker for GccLinker<'a> { { self.cc_arg("--static-crt"); } + + // avr-none doesn't have default ISA, users must specify which specific + // CPU (well, microcontroller) they are targetting using `-Ctarget-cpu`. + // + // Currently this makes sense only when using avr-gcc as a linker, since + // it brings a couple of hand-written important intrinsics from libgcc. + if self.sess.target.arch == "avr" && !self.uses_lld { + self.verbatim_arg(format!("-mmcu={}", self.target_cpu)); + } } fn link_dylib_by_name(&mut self, name: &str, verbatim: bool, as_needed: bool) { diff --git a/compiler/rustc_target/src/spec/base/avr.rs b/compiler/rustc_target/src/spec/base/avr.rs new file mode 100644 index 00000000000..85b73e61e52 --- /dev/null +++ b/compiler/rustc_target/src/spec/base/avr.rs @@ -0,0 +1,337 @@ +use object::elf; + +/// Resolve the value of the EF_AVR_ARCH field for AVR ELF files, given the +/// name of the target CPU / MCU. +/// +/// In ELF files using the AVR architecture, the lower 7 bits of the e_flags +/// field is a code that identifies the "ISA revision" of the object code. +/// +/// This flag is generally set by AVR compilers in their output ELF files, +/// and linkers like avr-ld check this flag in all of their input files to +/// make sure they are compiled with the same ISA revision. +pub fn ef_avr_arch(target_cpu: &str) -> u32 { + // Adapted from llvm-project/llvm/lib/target/AVR/AVRDevices.td + match target_cpu { + // Generic MCUs + "avr1" => elf::EF_AVR_ARCH_AVR1, + "avr2" => elf::EF_AVR_ARCH_AVR2, + "avr25" => elf::EF_AVR_ARCH_AVR25, + "avr3" => elf::EF_AVR_ARCH_AVR3, + "avr31" => elf::EF_AVR_ARCH_AVR31, + "avr35" => elf::EF_AVR_ARCH_AVR35, + "avr4" => elf::EF_AVR_ARCH_AVR4, + "avr5" => elf::EF_AVR_ARCH_AVR5, + "avr51" => elf::EF_AVR_ARCH_AVR51, + "avr6" => elf::EF_AVR_ARCH_AVR6, + "avrxmega1" => elf::EF_AVR_ARCH_XMEGA1, + "avrxmega2" => elf::EF_AVR_ARCH_XMEGA2, + "avrxmega3" => elf::EF_AVR_ARCH_XMEGA3, + "avrxmega4" => elf::EF_AVR_ARCH_XMEGA4, + "avrxmega5" => elf::EF_AVR_ARCH_XMEGA5, + "avrxmega6" => elf::EF_AVR_ARCH_XMEGA6, + "avrxmega7" => elf::EF_AVR_ARCH_XMEGA7, + "avrtiny" => elf::EF_AVR_ARCH_AVRTINY, + + // Specific MCUs + "at90s1200" => elf::EF_AVR_ARCH_AVR1, + "attiny11" => elf::EF_AVR_ARCH_AVR1, + "attiny12" => elf::EF_AVR_ARCH_AVR1, + "attiny15" => elf::EF_AVR_ARCH_AVR1, + "attiny28" => elf::EF_AVR_ARCH_AVR1, + "at90s2313" => elf::EF_AVR_ARCH_AVR2, + "at90s2323" => elf::EF_AVR_ARCH_AVR2, + "at90s2333" => elf::EF_AVR_ARCH_AVR2, + "at90s2343" => elf::EF_AVR_ARCH_AVR2, + "attiny22" => elf::EF_AVR_ARCH_AVR2, + "attiny26" => elf::EF_AVR_ARCH_AVR2, + "at86rf401" => elf::EF_AVR_ARCH_AVR25, + "at90s4414" => elf::EF_AVR_ARCH_AVR2, + "at90s4433" => elf::EF_AVR_ARCH_AVR2, + "at90s4434" => elf::EF_AVR_ARCH_AVR2, + "at90s8515" => elf::EF_AVR_ARCH_AVR2, + "at90c8534" => elf::EF_AVR_ARCH_AVR2, + "at90s8535" => elf::EF_AVR_ARCH_AVR2, + "ata5272" => elf::EF_AVR_ARCH_AVR25, + "ata6616c" => elf::EF_AVR_ARCH_AVR25, + "attiny13" => elf::EF_AVR_ARCH_AVR25, + "attiny13a" => elf::EF_AVR_ARCH_AVR25, + "attiny2313" => elf::EF_AVR_ARCH_AVR25, + "attiny2313a" => elf::EF_AVR_ARCH_AVR25, + "attiny24" => elf::EF_AVR_ARCH_AVR25, + "attiny24a" => elf::EF_AVR_ARCH_AVR25, + "attiny4313" => elf::EF_AVR_ARCH_AVR25, + "attiny44" => elf::EF_AVR_ARCH_AVR25, + "attiny44a" => elf::EF_AVR_ARCH_AVR25, + "attiny84" => elf::EF_AVR_ARCH_AVR25, + "attiny84a" => elf::EF_AVR_ARCH_AVR25, + "attiny25" => elf::EF_AVR_ARCH_AVR25, + "attiny45" => elf::EF_AVR_ARCH_AVR25, + "attiny85" => elf::EF_AVR_ARCH_AVR25, + "attiny261" => elf::EF_AVR_ARCH_AVR25, + "attiny261a" => elf::EF_AVR_ARCH_AVR25, + "attiny441" => elf::EF_AVR_ARCH_AVR25, + "attiny461" => elf::EF_AVR_ARCH_AVR25, + "attiny461a" => elf::EF_AVR_ARCH_AVR25, + "attiny841" => elf::EF_AVR_ARCH_AVR25, + "attiny861" => elf::EF_AVR_ARCH_AVR25, + "attiny861a" => elf::EF_AVR_ARCH_AVR25, + "attiny87" => elf::EF_AVR_ARCH_AVR25, + "attiny43u" => elf::EF_AVR_ARCH_AVR25, + "attiny48" => elf::EF_AVR_ARCH_AVR25, + "attiny88" => elf::EF_AVR_ARCH_AVR25, + "attiny828" => elf::EF_AVR_ARCH_AVR25, + "at43usb355" => elf::EF_AVR_ARCH_AVR3, + "at76c711" => elf::EF_AVR_ARCH_AVR3, + "atmega103" => elf::EF_AVR_ARCH_AVR31, + "at43usb320" => elf::EF_AVR_ARCH_AVR31, + "attiny167" => elf::EF_AVR_ARCH_AVR35, + "at90usb82" => elf::EF_AVR_ARCH_AVR35, + "at90usb162" => elf::EF_AVR_ARCH_AVR35, + "ata5505" => elf::EF_AVR_ARCH_AVR35, + "ata6617c" => elf::EF_AVR_ARCH_AVR35, + "ata664251" => elf::EF_AVR_ARCH_AVR35, + "atmega8u2" => elf::EF_AVR_ARCH_AVR35, + "atmega16u2" => elf::EF_AVR_ARCH_AVR35, + "atmega32u2" => elf::EF_AVR_ARCH_AVR35, + "attiny1634" => elf::EF_AVR_ARCH_AVR35, + "atmega8" => elf::EF_AVR_ARCH_AVR4, + "ata6289" => elf::EF_AVR_ARCH_AVR4, + "atmega8a" => elf::EF_AVR_ARCH_AVR4, + "ata6285" => elf::EF_AVR_ARCH_AVR4, + "ata6286" => elf::EF_AVR_ARCH_AVR4, + "ata6612c" => elf::EF_AVR_ARCH_AVR4, + "atmega48" => elf::EF_AVR_ARCH_AVR4, + "atmega48a" => elf::EF_AVR_ARCH_AVR4, + "atmega48pa" => elf::EF_AVR_ARCH_AVR4, + "atmega48pb" => elf::EF_AVR_ARCH_AVR4, + "atmega48p" => elf::EF_AVR_ARCH_AVR4, + "atmega88" => elf::EF_AVR_ARCH_AVR4, + "atmega88a" => elf::EF_AVR_ARCH_AVR4, + "atmega88p" => elf::EF_AVR_ARCH_AVR4, + "atmega88pa" => elf::EF_AVR_ARCH_AVR4, + "atmega88pb" => elf::EF_AVR_ARCH_AVR4, + "atmega8515" => elf::EF_AVR_ARCH_AVR4, + "atmega8535" => elf::EF_AVR_ARCH_AVR4, + "atmega8hva" => elf::EF_AVR_ARCH_AVR4, + "at90pwm1" => elf::EF_AVR_ARCH_AVR4, + "at90pwm2" => elf::EF_AVR_ARCH_AVR4, + "at90pwm2b" => elf::EF_AVR_ARCH_AVR4, + "at90pwm3" => elf::EF_AVR_ARCH_AVR4, + "at90pwm3b" => elf::EF_AVR_ARCH_AVR4, + "at90pwm81" => elf::EF_AVR_ARCH_AVR4, + "ata5702m322" => elf::EF_AVR_ARCH_AVR5, + "ata5782" => elf::EF_AVR_ARCH_AVR5, + "ata5790" => elf::EF_AVR_ARCH_AVR5, + "ata5790n" => elf::EF_AVR_ARCH_AVR5, + "ata5791" => elf::EF_AVR_ARCH_AVR5, + "ata5795" => elf::EF_AVR_ARCH_AVR5, + "ata5831" => elf::EF_AVR_ARCH_AVR5, + "ata6613c" => elf::EF_AVR_ARCH_AVR5, + "ata6614q" => elf::EF_AVR_ARCH_AVR5, + "ata8210" => elf::EF_AVR_ARCH_AVR5, + "ata8510" => elf::EF_AVR_ARCH_AVR5, + "atmega16" => elf::EF_AVR_ARCH_AVR5, + "atmega16a" => elf::EF_AVR_ARCH_AVR5, + "atmega161" => elf::EF_AVR_ARCH_AVR5, + "atmega162" => elf::EF_AVR_ARCH_AVR5, + "atmega163" => elf::EF_AVR_ARCH_AVR5, + "atmega164a" => elf::EF_AVR_ARCH_AVR5, + "atmega164p" => elf::EF_AVR_ARCH_AVR5, + "atmega164pa" => elf::EF_AVR_ARCH_AVR5, + "atmega165" => elf::EF_AVR_ARCH_AVR5, + "atmega165a" => elf::EF_AVR_ARCH_AVR5, + "atmega165p" => elf::EF_AVR_ARCH_AVR5, + "atmega165pa" => elf::EF_AVR_ARCH_AVR5, + "atmega168" => elf::EF_AVR_ARCH_AVR5, + "atmega168a" => elf::EF_AVR_ARCH_AVR5, + "atmega168p" => elf::EF_AVR_ARCH_AVR5, + "atmega168pa" => elf::EF_AVR_ARCH_AVR5, + "atmega168pb" => elf::EF_AVR_ARCH_AVR5, + "atmega169" => elf::EF_AVR_ARCH_AVR5, + "atmega169a" => elf::EF_AVR_ARCH_AVR5, + "atmega169p" => elf::EF_AVR_ARCH_AVR5, + "atmega169pa" => elf::EF_AVR_ARCH_AVR5, + "atmega32" => elf::EF_AVR_ARCH_AVR5, + "atmega32a" => elf::EF_AVR_ARCH_AVR5, + "atmega323" => elf::EF_AVR_ARCH_AVR5, + "atmega324a" => elf::EF_AVR_ARCH_AVR5, + "atmega324p" => elf::EF_AVR_ARCH_AVR5, + "atmega324pa" => elf::EF_AVR_ARCH_AVR5, + "atmega324pb" => elf::EF_AVR_ARCH_AVR5, + "atmega325" => elf::EF_AVR_ARCH_AVR5, + "atmega325a" => elf::EF_AVR_ARCH_AVR5, + "atmega325p" => elf::EF_AVR_ARCH_AVR5, + "atmega325pa" => elf::EF_AVR_ARCH_AVR5, + "atmega3250" => elf::EF_AVR_ARCH_AVR5, + "atmega3250a" => elf::EF_AVR_ARCH_AVR5, + "atmega3250p" => elf::EF_AVR_ARCH_AVR5, + "atmega3250pa" => elf::EF_AVR_ARCH_AVR5, + "atmega328" => elf::EF_AVR_ARCH_AVR5, + "atmega328p" => elf::EF_AVR_ARCH_AVR5, + "atmega328pb" => elf::EF_AVR_ARCH_AVR5, + "atmega329" => elf::EF_AVR_ARCH_AVR5, + "atmega329a" => elf::EF_AVR_ARCH_AVR5, + "atmega329p" => elf::EF_AVR_ARCH_AVR5, + "atmega329pa" => elf::EF_AVR_ARCH_AVR5, + "atmega3290" => elf::EF_AVR_ARCH_AVR5, + "atmega3290a" => elf::EF_AVR_ARCH_AVR5, + "atmega3290p" => elf::EF_AVR_ARCH_AVR5, + "atmega3290pa" => elf::EF_AVR_ARCH_AVR5, + "atmega406" => elf::EF_AVR_ARCH_AVR5, + "atmega64" => elf::EF_AVR_ARCH_AVR5, + "atmega64a" => elf::EF_AVR_ARCH_AVR5, + "atmega640" => elf::EF_AVR_ARCH_AVR5, + "atmega644" => elf::EF_AVR_ARCH_AVR5, + "atmega644a" => elf::EF_AVR_ARCH_AVR5, + "atmega644p" => elf::EF_AVR_ARCH_AVR5, + "atmega644pa" => elf::EF_AVR_ARCH_AVR5, + "atmega645" => elf::EF_AVR_ARCH_AVR5, + "atmega645a" => elf::EF_AVR_ARCH_AVR5, + "atmega645p" => elf::EF_AVR_ARCH_AVR5, + "atmega649" => elf::EF_AVR_ARCH_AVR5, + "atmega649a" => elf::EF_AVR_ARCH_AVR5, + "atmega649p" => elf::EF_AVR_ARCH_AVR5, + "atmega6450" => elf::EF_AVR_ARCH_AVR5, + "atmega6450a" => elf::EF_AVR_ARCH_AVR5, + "atmega6450p" => elf::EF_AVR_ARCH_AVR5, + "atmega6490" => elf::EF_AVR_ARCH_AVR5, + "atmega6490a" => elf::EF_AVR_ARCH_AVR5, + "atmega6490p" => elf::EF_AVR_ARCH_AVR5, + "atmega64rfr2" => elf::EF_AVR_ARCH_AVR5, + "atmega644rfr2" => elf::EF_AVR_ARCH_AVR5, + "atmega16hva" => elf::EF_AVR_ARCH_AVR5, + "atmega16hva2" => elf::EF_AVR_ARCH_AVR5, + "atmega16hvb" => elf::EF_AVR_ARCH_AVR5, + "atmega16hvbrevb" => elf::EF_AVR_ARCH_AVR5, + "atmega32hvb" => elf::EF_AVR_ARCH_AVR5, + "atmega32hvbrevb" => elf::EF_AVR_ARCH_AVR5, + "atmega64hve" => elf::EF_AVR_ARCH_AVR5, + "atmega64hve2" => elf::EF_AVR_ARCH_AVR5, + "at90can32" => elf::EF_AVR_ARCH_AVR5, + "at90can64" => elf::EF_AVR_ARCH_AVR5, + "at90pwm161" => elf::EF_AVR_ARCH_AVR5, + "at90pwm216" => elf::EF_AVR_ARCH_AVR5, + "at90pwm316" => elf::EF_AVR_ARCH_AVR5, + "atmega32c1" => elf::EF_AVR_ARCH_AVR5, + "atmega64c1" => elf::EF_AVR_ARCH_AVR5, + "atmega16m1" => elf::EF_AVR_ARCH_AVR5, + "atmega32m1" => elf::EF_AVR_ARCH_AVR5, + "atmega64m1" => elf::EF_AVR_ARCH_AVR5, + "atmega16u4" => elf::EF_AVR_ARCH_AVR5, + "atmega32u4" => elf::EF_AVR_ARCH_AVR5, + "atmega32u6" => elf::EF_AVR_ARCH_AVR5, + "at90usb646" => elf::EF_AVR_ARCH_AVR5, + "at90usb647" => elf::EF_AVR_ARCH_AVR5, + "at90scr100" => elf::EF_AVR_ARCH_AVR5, + "at94k" => elf::EF_AVR_ARCH_AVR5, + "m3000" => elf::EF_AVR_ARCH_AVR5, + "atmega128" => elf::EF_AVR_ARCH_AVR51, + "atmega128a" => elf::EF_AVR_ARCH_AVR51, + "atmega1280" => elf::EF_AVR_ARCH_AVR51, + "atmega1281" => elf::EF_AVR_ARCH_AVR51, + "atmega1284" => elf::EF_AVR_ARCH_AVR51, + "atmega1284p" => elf::EF_AVR_ARCH_AVR51, + "atmega128rfa1" => elf::EF_AVR_ARCH_AVR51, + "atmega128rfr2" => elf::EF_AVR_ARCH_AVR51, + "atmega1284rfr2" => elf::EF_AVR_ARCH_AVR51, + "at90can128" => elf::EF_AVR_ARCH_AVR51, + "at90usb1286" => elf::EF_AVR_ARCH_AVR51, + "at90usb1287" => elf::EF_AVR_ARCH_AVR51, + "atmega2560" => elf::EF_AVR_ARCH_AVR6, + "atmega2561" => elf::EF_AVR_ARCH_AVR6, + "atmega256rfr2" => elf::EF_AVR_ARCH_AVR6, + "atmega2564rfr2" => elf::EF_AVR_ARCH_AVR6, + "atxmega16a4" => elf::EF_AVR_ARCH_XMEGA2, + "atxmega16a4u" => elf::EF_AVR_ARCH_XMEGA2, + "atxmega16c4" => elf::EF_AVR_ARCH_XMEGA2, + "atxmega16d4" => elf::EF_AVR_ARCH_XMEGA2, + "atxmega32a4" => elf::EF_AVR_ARCH_XMEGA2, + "atxmega32a4u" => elf::EF_AVR_ARCH_XMEGA2, + "atxmega32c3" => elf::EF_AVR_ARCH_XMEGA2, + "atxmega32c4" => elf::EF_AVR_ARCH_XMEGA2, + "atxmega32d3" => elf::EF_AVR_ARCH_XMEGA2, + "atxmega32d4" => elf::EF_AVR_ARCH_XMEGA2, + "atxmega32e5" => elf::EF_AVR_ARCH_XMEGA2, + "atxmega16e5" => elf::EF_AVR_ARCH_XMEGA2, + "atxmega8e5" => elf::EF_AVR_ARCH_XMEGA2, + "atxmega64a3" => elf::EF_AVR_ARCH_XMEGA4, + "atxmega64a3u" => elf::EF_AVR_ARCH_XMEGA4, + "atxmega64a4u" => elf::EF_AVR_ARCH_XMEGA4, + "atxmega64b1" => elf::EF_AVR_ARCH_XMEGA4, + "atxmega64b3" => elf::EF_AVR_ARCH_XMEGA4, + "atxmega64c3" => elf::EF_AVR_ARCH_XMEGA4, + "atxmega64d3" => elf::EF_AVR_ARCH_XMEGA4, + "atxmega64d4" => elf::EF_AVR_ARCH_XMEGA4, + "atxmega64a1" => elf::EF_AVR_ARCH_XMEGA5, + "atxmega64a1u" => elf::EF_AVR_ARCH_XMEGA5, + "atxmega128a3" => elf::EF_AVR_ARCH_XMEGA6, + "atxmega128a3u" => elf::EF_AVR_ARCH_XMEGA6, + "atxmega128b1" => elf::EF_AVR_ARCH_XMEGA6, + "atxmega128b3" => elf::EF_AVR_ARCH_XMEGA6, + "atxmega128c3" => elf::EF_AVR_ARCH_XMEGA6, + "atxmega128d3" => elf::EF_AVR_ARCH_XMEGA6, + "atxmega128d4" => elf::EF_AVR_ARCH_XMEGA6, + "atxmega192a3" => elf::EF_AVR_ARCH_XMEGA6, + "atxmega192a3u" => elf::EF_AVR_ARCH_XMEGA6, + "atxmega192c3" => elf::EF_AVR_ARCH_XMEGA6, + "atxmega192d3" => elf::EF_AVR_ARCH_XMEGA6, + "atxmega256a3" => elf::EF_AVR_ARCH_XMEGA6, + "atxmega256a3u" => elf::EF_AVR_ARCH_XMEGA6, + "atxmega256a3b" => elf::EF_AVR_ARCH_XMEGA6, + "atxmega256a3bu" => elf::EF_AVR_ARCH_XMEGA6, + "atxmega256c3" => elf::EF_AVR_ARCH_XMEGA6, + "atxmega256d3" => elf::EF_AVR_ARCH_XMEGA6, + "atxmega384c3" => elf::EF_AVR_ARCH_XMEGA6, + "atxmega384d3" => elf::EF_AVR_ARCH_XMEGA6, + "atxmega128a1" => elf::EF_AVR_ARCH_XMEGA7, + "atxmega128a1u" => elf::EF_AVR_ARCH_XMEGA7, + "atxmega128a4u" => elf::EF_AVR_ARCH_XMEGA7, + "attiny4" => elf::EF_AVR_ARCH_AVRTINY, + "attiny5" => elf::EF_AVR_ARCH_AVRTINY, + "attiny9" => elf::EF_AVR_ARCH_AVRTINY, + "attiny10" => elf::EF_AVR_ARCH_AVRTINY, + "attiny20" => elf::EF_AVR_ARCH_AVRTINY, + "attiny40" => elf::EF_AVR_ARCH_AVRTINY, + "attiny102" => elf::EF_AVR_ARCH_AVRTINY, + "attiny104" => elf::EF_AVR_ARCH_AVRTINY, + "attiny202" => elf::EF_AVR_ARCH_XMEGA3, + "attiny402" => elf::EF_AVR_ARCH_XMEGA3, + "attiny204" => elf::EF_AVR_ARCH_XMEGA3, + "attiny404" => elf::EF_AVR_ARCH_XMEGA3, + "attiny804" => elf::EF_AVR_ARCH_XMEGA3, + "attiny1604" => elf::EF_AVR_ARCH_XMEGA3, + "attiny406" => elf::EF_AVR_ARCH_XMEGA3, + "attiny806" => elf::EF_AVR_ARCH_XMEGA3, + "attiny1606" => elf::EF_AVR_ARCH_XMEGA3, + "attiny807" => elf::EF_AVR_ARCH_XMEGA3, + "attiny1607" => elf::EF_AVR_ARCH_XMEGA3, + "attiny212" => elf::EF_AVR_ARCH_XMEGA3, + "attiny412" => elf::EF_AVR_ARCH_XMEGA3, + "attiny214" => elf::EF_AVR_ARCH_XMEGA3, + "attiny414" => elf::EF_AVR_ARCH_XMEGA3, + "attiny814" => elf::EF_AVR_ARCH_XMEGA3, + "attiny1614" => elf::EF_AVR_ARCH_XMEGA3, + "attiny416" => elf::EF_AVR_ARCH_XMEGA3, + "attiny816" => elf::EF_AVR_ARCH_XMEGA3, + "attiny1616" => elf::EF_AVR_ARCH_XMEGA3, + "attiny3216" => elf::EF_AVR_ARCH_XMEGA3, + "attiny417" => elf::EF_AVR_ARCH_XMEGA3, + "attiny817" => elf::EF_AVR_ARCH_XMEGA3, + "attiny1617" => elf::EF_AVR_ARCH_XMEGA3, + "attiny3217" => elf::EF_AVR_ARCH_XMEGA3, + "attiny1624" => elf::EF_AVR_ARCH_XMEGA3, + "attiny1626" => elf::EF_AVR_ARCH_XMEGA3, + "attiny1627" => elf::EF_AVR_ARCH_XMEGA3, + "atmega808" => elf::EF_AVR_ARCH_XMEGA3, + "atmega809" => elf::EF_AVR_ARCH_XMEGA3, + "atmega1608" => elf::EF_AVR_ARCH_XMEGA3, + "atmega1609" => elf::EF_AVR_ARCH_XMEGA3, + "atmega3208" => elf::EF_AVR_ARCH_XMEGA3, + "atmega3209" => elf::EF_AVR_ARCH_XMEGA3, + "atmega4808" => elf::EF_AVR_ARCH_XMEGA3, + "atmega4809" => elf::EF_AVR_ARCH_XMEGA3, + + // Unknown target CPU => Unspecified/generic code + _ => 0, + } +} diff --git a/compiler/rustc_target/src/spec/base/avr_gnu.rs b/compiler/rustc_target/src/spec/base/avr_gnu.rs deleted file mode 100644 index 3554dcfcb4a..00000000000 --- a/compiler/rustc_target/src/spec/base/avr_gnu.rs +++ /dev/null @@ -1,377 +0,0 @@ -use object::elf; - -use crate::spec::{Cc, LinkerFlavor, Lld, RelocModel, Target, TargetOptions}; - -/// A base target for AVR devices using the GNU toolchain. -/// -/// Requires GNU avr-gcc and avr-binutils on the host system. -/// FIXME: Remove the second parameter when const string concatenation is possible. -pub(crate) fn target(target_cpu: &'static str, mmcu: &'static str) -> Target { - Target { - arch: "avr".into(), - metadata: crate::spec::TargetMetadata { - description: None, - tier: None, - host_tools: None, - std: None, - }, - data_layout: "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8".into(), - llvm_target: "avr-unknown-unknown".into(), - pointer_width: 16, - options: TargetOptions { - env: "gnu".into(), - - c_int_width: "16".into(), - cpu: target_cpu.into(), - exe_suffix: ".elf".into(), - - linker: Some("avr-gcc".into()), - eh_frame_header: false, - pre_link_args: TargetOptions::link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &[mmcu]), - late_link_args: TargetOptions::link_args( - LinkerFlavor::Gnu(Cc::Yes, Lld::No), - &["-lgcc"], - ), - max_atomic_width: Some(16), - atomic_cas: false, - relocation_model: RelocModel::Static, - ..TargetOptions::default() - }, - } -} - -/// Resolve the value of the EF_AVR_ARCH field for AVR ELF files, given the -/// name of the target CPU / MCU. -/// -/// In ELF files using the AVR architecture, the lower 7 bits of the e_flags -/// field is a code that identifies the "ISA revision" of the object code. -/// -/// This flag is generally set by AVR compilers in their output ELF files, -/// and linkers like avr-ld check this flag in all of their input files to -/// make sure they are compiled with the same ISA revision. -pub fn ef_avr_arch(target_cpu: &str) -> u32 { - // Adapted from llvm-project/llvm/lib/target/AVR/AVRDevices.td - match target_cpu { - // Generic MCUs - "avr1" => elf::EF_AVR_ARCH_AVR1, - "avr2" => elf::EF_AVR_ARCH_AVR2, - "avr25" => elf::EF_AVR_ARCH_AVR25, - "avr3" => elf::EF_AVR_ARCH_AVR3, - "avr31" => elf::EF_AVR_ARCH_AVR31, - "avr35" => elf::EF_AVR_ARCH_AVR35, - "avr4" => elf::EF_AVR_ARCH_AVR4, - "avr5" => elf::EF_AVR_ARCH_AVR5, - "avr51" => elf::EF_AVR_ARCH_AVR51, - "avr6" => elf::EF_AVR_ARCH_AVR6, - "avrxmega1" => elf::EF_AVR_ARCH_XMEGA1, - "avrxmega2" => elf::EF_AVR_ARCH_XMEGA2, - "avrxmega3" => elf::EF_AVR_ARCH_XMEGA3, - "avrxmega4" => elf::EF_AVR_ARCH_XMEGA4, - "avrxmega5" => elf::EF_AVR_ARCH_XMEGA5, - "avrxmega6" => elf::EF_AVR_ARCH_XMEGA6, - "avrxmega7" => elf::EF_AVR_ARCH_XMEGA7, - "avrtiny" => elf::EF_AVR_ARCH_AVRTINY, - - // Specific MCUs - "at90s1200" => elf::EF_AVR_ARCH_AVR1, - "attiny11" => elf::EF_AVR_ARCH_AVR1, - "attiny12" => elf::EF_AVR_ARCH_AVR1, - "attiny15" => elf::EF_AVR_ARCH_AVR1, - "attiny28" => elf::EF_AVR_ARCH_AVR1, - "at90s2313" => elf::EF_AVR_ARCH_AVR2, - "at90s2323" => elf::EF_AVR_ARCH_AVR2, - "at90s2333" => elf::EF_AVR_ARCH_AVR2, - "at90s2343" => elf::EF_AVR_ARCH_AVR2, - "attiny22" => elf::EF_AVR_ARCH_AVR2, - "attiny26" => elf::EF_AVR_ARCH_AVR2, - "at86rf401" => elf::EF_AVR_ARCH_AVR25, - "at90s4414" => elf::EF_AVR_ARCH_AVR2, - "at90s4433" => elf::EF_AVR_ARCH_AVR2, - "at90s4434" => elf::EF_AVR_ARCH_AVR2, - "at90s8515" => elf::EF_AVR_ARCH_AVR2, - "at90c8534" => elf::EF_AVR_ARCH_AVR2, - "at90s8535" => elf::EF_AVR_ARCH_AVR2, - "ata5272" => elf::EF_AVR_ARCH_AVR25, - "ata6616c" => elf::EF_AVR_ARCH_AVR25, - "attiny13" => elf::EF_AVR_ARCH_AVR25, - "attiny13a" => elf::EF_AVR_ARCH_AVR25, - "attiny2313" => elf::EF_AVR_ARCH_AVR25, - "attiny2313a" => elf::EF_AVR_ARCH_AVR25, - "attiny24" => elf::EF_AVR_ARCH_AVR25, - "attiny24a" => elf::EF_AVR_ARCH_AVR25, - "attiny4313" => elf::EF_AVR_ARCH_AVR25, - "attiny44" => elf::EF_AVR_ARCH_AVR25, - "attiny44a" => elf::EF_AVR_ARCH_AVR25, - "attiny84" => elf::EF_AVR_ARCH_AVR25, - "attiny84a" => elf::EF_AVR_ARCH_AVR25, - "attiny25" => elf::EF_AVR_ARCH_AVR25, - "attiny45" => elf::EF_AVR_ARCH_AVR25, - "attiny85" => elf::EF_AVR_ARCH_AVR25, - "attiny261" => elf::EF_AVR_ARCH_AVR25, - "attiny261a" => elf::EF_AVR_ARCH_AVR25, - "attiny441" => elf::EF_AVR_ARCH_AVR25, - "attiny461" => elf::EF_AVR_ARCH_AVR25, - "attiny461a" => elf::EF_AVR_ARCH_AVR25, - "attiny841" => elf::EF_AVR_ARCH_AVR25, - "attiny861" => elf::EF_AVR_ARCH_AVR25, - "attiny861a" => elf::EF_AVR_ARCH_AVR25, - "attiny87" => elf::EF_AVR_ARCH_AVR25, - "attiny43u" => elf::EF_AVR_ARCH_AVR25, - "attiny48" => elf::EF_AVR_ARCH_AVR25, - "attiny88" => elf::EF_AVR_ARCH_AVR25, - "attiny828" => elf::EF_AVR_ARCH_AVR25, - "at43usb355" => elf::EF_AVR_ARCH_AVR3, - "at76c711" => elf::EF_AVR_ARCH_AVR3, - "atmega103" => elf::EF_AVR_ARCH_AVR31, - "at43usb320" => elf::EF_AVR_ARCH_AVR31, - "attiny167" => elf::EF_AVR_ARCH_AVR35, - "at90usb82" => elf::EF_AVR_ARCH_AVR35, - "at90usb162" => elf::EF_AVR_ARCH_AVR35, - "ata5505" => elf::EF_AVR_ARCH_AVR35, - "ata6617c" => elf::EF_AVR_ARCH_AVR35, - "ata664251" => elf::EF_AVR_ARCH_AVR35, - "atmega8u2" => elf::EF_AVR_ARCH_AVR35, - "atmega16u2" => elf::EF_AVR_ARCH_AVR35, - "atmega32u2" => elf::EF_AVR_ARCH_AVR35, - "attiny1634" => elf::EF_AVR_ARCH_AVR35, - "atmega8" => elf::EF_AVR_ARCH_AVR4, - "ata6289" => elf::EF_AVR_ARCH_AVR4, - "atmega8a" => elf::EF_AVR_ARCH_AVR4, - "ata6285" => elf::EF_AVR_ARCH_AVR4, - "ata6286" => elf::EF_AVR_ARCH_AVR4, - "ata6612c" => elf::EF_AVR_ARCH_AVR4, - "atmega48" => elf::EF_AVR_ARCH_AVR4, - "atmega48a" => elf::EF_AVR_ARCH_AVR4, - "atmega48pa" => elf::EF_AVR_ARCH_AVR4, - "atmega48pb" => elf::EF_AVR_ARCH_AVR4, - "atmega48p" => elf::EF_AVR_ARCH_AVR4, - "atmega88" => elf::EF_AVR_ARCH_AVR4, - "atmega88a" => elf::EF_AVR_ARCH_AVR4, - "atmega88p" => elf::EF_AVR_ARCH_AVR4, - "atmega88pa" => elf::EF_AVR_ARCH_AVR4, - "atmega88pb" => elf::EF_AVR_ARCH_AVR4, - "atmega8515" => elf::EF_AVR_ARCH_AVR4, - "atmega8535" => elf::EF_AVR_ARCH_AVR4, - "atmega8hva" => elf::EF_AVR_ARCH_AVR4, - "at90pwm1" => elf::EF_AVR_ARCH_AVR4, - "at90pwm2" => elf::EF_AVR_ARCH_AVR4, - "at90pwm2b" => elf::EF_AVR_ARCH_AVR4, - "at90pwm3" => elf::EF_AVR_ARCH_AVR4, - "at90pwm3b" => elf::EF_AVR_ARCH_AVR4, - "at90pwm81" => elf::EF_AVR_ARCH_AVR4, - "ata5702m322" => elf::EF_AVR_ARCH_AVR5, - "ata5782" => elf::EF_AVR_ARCH_AVR5, - "ata5790" => elf::EF_AVR_ARCH_AVR5, - "ata5790n" => elf::EF_AVR_ARCH_AVR5, - "ata5791" => elf::EF_AVR_ARCH_AVR5, - "ata5795" => elf::EF_AVR_ARCH_AVR5, - "ata5831" => elf::EF_AVR_ARCH_AVR5, - "ata6613c" => elf::EF_AVR_ARCH_AVR5, - "ata6614q" => elf::EF_AVR_ARCH_AVR5, - "ata8210" => elf::EF_AVR_ARCH_AVR5, - "ata8510" => elf::EF_AVR_ARCH_AVR5, - "atmega16" => elf::EF_AVR_ARCH_AVR5, - "atmega16a" => elf::EF_AVR_ARCH_AVR5, - "atmega161" => elf::EF_AVR_ARCH_AVR5, - "atmega162" => elf::EF_AVR_ARCH_AVR5, - "atmega163" => elf::EF_AVR_ARCH_AVR5, - "atmega164a" => elf::EF_AVR_ARCH_AVR5, - "atmega164p" => elf::EF_AVR_ARCH_AVR5, - "atmega164pa" => elf::EF_AVR_ARCH_AVR5, - "atmega165" => elf::EF_AVR_ARCH_AVR5, - "atmega165a" => elf::EF_AVR_ARCH_AVR5, - "atmega165p" => elf::EF_AVR_ARCH_AVR5, - "atmega165pa" => elf::EF_AVR_ARCH_AVR5, - "atmega168" => elf::EF_AVR_ARCH_AVR5, - "atmega168a" => elf::EF_AVR_ARCH_AVR5, - "atmega168p" => elf::EF_AVR_ARCH_AVR5, - "atmega168pa" => elf::EF_AVR_ARCH_AVR5, - "atmega168pb" => elf::EF_AVR_ARCH_AVR5, - "atmega169" => elf::EF_AVR_ARCH_AVR5, - "atmega169a" => elf::EF_AVR_ARCH_AVR5, - "atmega169p" => elf::EF_AVR_ARCH_AVR5, - "atmega169pa" => elf::EF_AVR_ARCH_AVR5, - "atmega32" => elf::EF_AVR_ARCH_AVR5, - "atmega32a" => elf::EF_AVR_ARCH_AVR5, - "atmega323" => elf::EF_AVR_ARCH_AVR5, - "atmega324a" => elf::EF_AVR_ARCH_AVR5, - "atmega324p" => elf::EF_AVR_ARCH_AVR5, - "atmega324pa" => elf::EF_AVR_ARCH_AVR5, - "atmega324pb" => elf::EF_AVR_ARCH_AVR5, - "atmega325" => elf::EF_AVR_ARCH_AVR5, - "atmega325a" => elf::EF_AVR_ARCH_AVR5, - "atmega325p" => elf::EF_AVR_ARCH_AVR5, - "atmega325pa" => elf::EF_AVR_ARCH_AVR5, - "atmega3250" => elf::EF_AVR_ARCH_AVR5, - "atmega3250a" => elf::EF_AVR_ARCH_AVR5, - "atmega3250p" => elf::EF_AVR_ARCH_AVR5, - "atmega3250pa" => elf::EF_AVR_ARCH_AVR5, - "atmega328" => elf::EF_AVR_ARCH_AVR5, - "atmega328p" => elf::EF_AVR_ARCH_AVR5, - "atmega328pb" => elf::EF_AVR_ARCH_AVR5, - "atmega329" => elf::EF_AVR_ARCH_AVR5, - "atmega329a" => elf::EF_AVR_ARCH_AVR5, - "atmega329p" => elf::EF_AVR_ARCH_AVR5, - "atmega329pa" => elf::EF_AVR_ARCH_AVR5, - "atmega3290" => elf::EF_AVR_ARCH_AVR5, - "atmega3290a" => elf::EF_AVR_ARCH_AVR5, - "atmega3290p" => elf::EF_AVR_ARCH_AVR5, - "atmega3290pa" => elf::EF_AVR_ARCH_AVR5, - "atmega406" => elf::EF_AVR_ARCH_AVR5, - "atmega64" => elf::EF_AVR_ARCH_AVR5, - "atmega64a" => elf::EF_AVR_ARCH_AVR5, - "atmega640" => elf::EF_AVR_ARCH_AVR5, - "atmega644" => elf::EF_AVR_ARCH_AVR5, - "atmega644a" => elf::EF_AVR_ARCH_AVR5, - "atmega644p" => elf::EF_AVR_ARCH_AVR5, - "atmega644pa" => elf::EF_AVR_ARCH_AVR5, - "atmega645" => elf::EF_AVR_ARCH_AVR5, - "atmega645a" => elf::EF_AVR_ARCH_AVR5, - "atmega645p" => elf::EF_AVR_ARCH_AVR5, - "atmega649" => elf::EF_AVR_ARCH_AVR5, - "atmega649a" => elf::EF_AVR_ARCH_AVR5, - "atmega649p" => elf::EF_AVR_ARCH_AVR5, - "atmega6450" => elf::EF_AVR_ARCH_AVR5, - "atmega6450a" => elf::EF_AVR_ARCH_AVR5, - "atmega6450p" => elf::EF_AVR_ARCH_AVR5, - "atmega6490" => elf::EF_AVR_ARCH_AVR5, - "atmega6490a" => elf::EF_AVR_ARCH_AVR5, - "atmega6490p" => elf::EF_AVR_ARCH_AVR5, - "atmega64rfr2" => elf::EF_AVR_ARCH_AVR5, - "atmega644rfr2" => elf::EF_AVR_ARCH_AVR5, - "atmega16hva" => elf::EF_AVR_ARCH_AVR5, - "atmega16hva2" => elf::EF_AVR_ARCH_AVR5, - "atmega16hvb" => elf::EF_AVR_ARCH_AVR5, - "atmega16hvbrevb" => elf::EF_AVR_ARCH_AVR5, - "atmega32hvb" => elf::EF_AVR_ARCH_AVR5, - "atmega32hvbrevb" => elf::EF_AVR_ARCH_AVR5, - "atmega64hve" => elf::EF_AVR_ARCH_AVR5, - "atmega64hve2" => elf::EF_AVR_ARCH_AVR5, - "at90can32" => elf::EF_AVR_ARCH_AVR5, - "at90can64" => elf::EF_AVR_ARCH_AVR5, - "at90pwm161" => elf::EF_AVR_ARCH_AVR5, - "at90pwm216" => elf::EF_AVR_ARCH_AVR5, - "at90pwm316" => elf::EF_AVR_ARCH_AVR5, - "atmega32c1" => elf::EF_AVR_ARCH_AVR5, - "atmega64c1" => elf::EF_AVR_ARCH_AVR5, - "atmega16m1" => elf::EF_AVR_ARCH_AVR5, - "atmega32m1" => elf::EF_AVR_ARCH_AVR5, - "atmega64m1" => elf::EF_AVR_ARCH_AVR5, - "atmega16u4" => elf::EF_AVR_ARCH_AVR5, - "atmega32u4" => elf::EF_AVR_ARCH_AVR5, - "atmega32u6" => elf::EF_AVR_ARCH_AVR5, - "at90usb646" => elf::EF_AVR_ARCH_AVR5, - "at90usb647" => elf::EF_AVR_ARCH_AVR5, - "at90scr100" => elf::EF_AVR_ARCH_AVR5, - "at94k" => elf::EF_AVR_ARCH_AVR5, - "m3000" => elf::EF_AVR_ARCH_AVR5, - "atmega128" => elf::EF_AVR_ARCH_AVR51, - "atmega128a" => elf::EF_AVR_ARCH_AVR51, - "atmega1280" => elf::EF_AVR_ARCH_AVR51, - "atmega1281" => elf::EF_AVR_ARCH_AVR51, - "atmega1284" => elf::EF_AVR_ARCH_AVR51, - "atmega1284p" => elf::EF_AVR_ARCH_AVR51, - "atmega128rfa1" => elf::EF_AVR_ARCH_AVR51, - "atmega128rfr2" => elf::EF_AVR_ARCH_AVR51, - "atmega1284rfr2" => elf::EF_AVR_ARCH_AVR51, - "at90can128" => elf::EF_AVR_ARCH_AVR51, - "at90usb1286" => elf::EF_AVR_ARCH_AVR51, - "at90usb1287" => elf::EF_AVR_ARCH_AVR51, - "atmega2560" => elf::EF_AVR_ARCH_AVR6, - "atmega2561" => elf::EF_AVR_ARCH_AVR6, - "atmega256rfr2" => elf::EF_AVR_ARCH_AVR6, - "atmega2564rfr2" => elf::EF_AVR_ARCH_AVR6, - "atxmega16a4" => elf::EF_AVR_ARCH_XMEGA2, - "atxmega16a4u" => elf::EF_AVR_ARCH_XMEGA2, - "atxmega16c4" => elf::EF_AVR_ARCH_XMEGA2, - "atxmega16d4" => elf::EF_AVR_ARCH_XMEGA2, - "atxmega32a4" => elf::EF_AVR_ARCH_XMEGA2, - "atxmega32a4u" => elf::EF_AVR_ARCH_XMEGA2, - "atxmega32c3" => elf::EF_AVR_ARCH_XMEGA2, - "atxmega32c4" => elf::EF_AVR_ARCH_XMEGA2, - "atxmega32d3" => elf::EF_AVR_ARCH_XMEGA2, - "atxmega32d4" => elf::EF_AVR_ARCH_XMEGA2, - "atxmega32e5" => elf::EF_AVR_ARCH_XMEGA2, - "atxmega16e5" => elf::EF_AVR_ARCH_XMEGA2, - "atxmega8e5" => elf::EF_AVR_ARCH_XMEGA2, - "atxmega64a3" => elf::EF_AVR_ARCH_XMEGA4, - "atxmega64a3u" => elf::EF_AVR_ARCH_XMEGA4, - "atxmega64a4u" => elf::EF_AVR_ARCH_XMEGA4, - "atxmega64b1" => elf::EF_AVR_ARCH_XMEGA4, - "atxmega64b3" => elf::EF_AVR_ARCH_XMEGA4, - "atxmega64c3" => elf::EF_AVR_ARCH_XMEGA4, - "atxmega64d3" => elf::EF_AVR_ARCH_XMEGA4, - "atxmega64d4" => elf::EF_AVR_ARCH_XMEGA4, - "atxmega64a1" => elf::EF_AVR_ARCH_XMEGA5, - "atxmega64a1u" => elf::EF_AVR_ARCH_XMEGA5, - "atxmega128a3" => elf::EF_AVR_ARCH_XMEGA6, - "atxmega128a3u" => elf::EF_AVR_ARCH_XMEGA6, - "atxmega128b1" => elf::EF_AVR_ARCH_XMEGA6, - "atxmega128b3" => elf::EF_AVR_ARCH_XMEGA6, - "atxmega128c3" => elf::EF_AVR_ARCH_XMEGA6, - "atxmega128d3" => elf::EF_AVR_ARCH_XMEGA6, - "atxmega128d4" => elf::EF_AVR_ARCH_XMEGA6, - "atxmega192a3" => elf::EF_AVR_ARCH_XMEGA6, - "atxmega192a3u" => elf::EF_AVR_ARCH_XMEGA6, - "atxmega192c3" => elf::EF_AVR_ARCH_XMEGA6, - "atxmega192d3" => elf::EF_AVR_ARCH_XMEGA6, - "atxmega256a3" => elf::EF_AVR_ARCH_XMEGA6, - "atxmega256a3u" => elf::EF_AVR_ARCH_XMEGA6, - "atxmega256a3b" => elf::EF_AVR_ARCH_XMEGA6, - "atxmega256a3bu" => elf::EF_AVR_ARCH_XMEGA6, - "atxmega256c3" => elf::EF_AVR_ARCH_XMEGA6, - "atxmega256d3" => elf::EF_AVR_ARCH_XMEGA6, - "atxmega384c3" => elf::EF_AVR_ARCH_XMEGA6, - "atxmega384d3" => elf::EF_AVR_ARCH_XMEGA6, - "atxmega128a1" => elf::EF_AVR_ARCH_XMEGA7, - "atxmega128a1u" => elf::EF_AVR_ARCH_XMEGA7, - "atxmega128a4u" => elf::EF_AVR_ARCH_XMEGA7, - "attiny4" => elf::EF_AVR_ARCH_AVRTINY, - "attiny5" => elf::EF_AVR_ARCH_AVRTINY, - "attiny9" => elf::EF_AVR_ARCH_AVRTINY, - "attiny10" => elf::EF_AVR_ARCH_AVRTINY, - "attiny20" => elf::EF_AVR_ARCH_AVRTINY, - "attiny40" => elf::EF_AVR_ARCH_AVRTINY, - "attiny102" => elf::EF_AVR_ARCH_AVRTINY, - "attiny104" => elf::EF_AVR_ARCH_AVRTINY, - "attiny202" => elf::EF_AVR_ARCH_XMEGA3, - "attiny402" => elf::EF_AVR_ARCH_XMEGA3, - "attiny204" => elf::EF_AVR_ARCH_XMEGA3, - "attiny404" => elf::EF_AVR_ARCH_XMEGA3, - "attiny804" => elf::EF_AVR_ARCH_XMEGA3, - "attiny1604" => elf::EF_AVR_ARCH_XMEGA3, - "attiny406" => elf::EF_AVR_ARCH_XMEGA3, - "attiny806" => elf::EF_AVR_ARCH_XMEGA3, - "attiny1606" => elf::EF_AVR_ARCH_XMEGA3, - "attiny807" => elf::EF_AVR_ARCH_XMEGA3, - "attiny1607" => elf::EF_AVR_ARCH_XMEGA3, - "attiny212" => elf::EF_AVR_ARCH_XMEGA3, - "attiny412" => elf::EF_AVR_ARCH_XMEGA3, - "attiny214" => elf::EF_AVR_ARCH_XMEGA3, - "attiny414" => elf::EF_AVR_ARCH_XMEGA3, - "attiny814" => elf::EF_AVR_ARCH_XMEGA3, - "attiny1614" => elf::EF_AVR_ARCH_XMEGA3, - "attiny416" => elf::EF_AVR_ARCH_XMEGA3, - "attiny816" => elf::EF_AVR_ARCH_XMEGA3, - "attiny1616" => elf::EF_AVR_ARCH_XMEGA3, - "attiny3216" => elf::EF_AVR_ARCH_XMEGA3, - "attiny417" => elf::EF_AVR_ARCH_XMEGA3, - "attiny817" => elf::EF_AVR_ARCH_XMEGA3, - "attiny1617" => elf::EF_AVR_ARCH_XMEGA3, - "attiny3217" => elf::EF_AVR_ARCH_XMEGA3, - "attiny1624" => elf::EF_AVR_ARCH_XMEGA3, - "attiny1626" => elf::EF_AVR_ARCH_XMEGA3, - "attiny1627" => elf::EF_AVR_ARCH_XMEGA3, - "atmega808" => elf::EF_AVR_ARCH_XMEGA3, - "atmega809" => elf::EF_AVR_ARCH_XMEGA3, - "atmega1608" => elf::EF_AVR_ARCH_XMEGA3, - "atmega1609" => elf::EF_AVR_ARCH_XMEGA3, - "atmega3208" => elf::EF_AVR_ARCH_XMEGA3, - "atmega3209" => elf::EF_AVR_ARCH_XMEGA3, - "atmega4808" => elf::EF_AVR_ARCH_XMEGA3, - "atmega4809" => elf::EF_AVR_ARCH_XMEGA3, - - // Unknown target CPU => Unspecified/generic code - _ => 0, - } -} diff --git a/compiler/rustc_target/src/spec/base/mod.rs b/compiler/rustc_target/src/spec/base/mod.rs index b9139c8452c..6f88be5d37f 100644 --- a/compiler/rustc_target/src/spec/base/mod.rs +++ b/compiler/rustc_target/src/spec/base/mod.rs @@ -1,7 +1,7 @@ pub(crate) mod aix; pub(crate) mod android; pub(crate) mod apple; -pub(crate) mod avr_gnu; +pub(crate) mod avr; pub(crate) mod bpf; pub(crate) mod cygwin; pub(crate) mod dragonfly; diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index f7e467b0c11..3b943fc178f 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -60,7 +60,7 @@ pub mod crt_objects; mod base; mod json; -pub use base::avr_gnu::ef_avr_arch; +pub use base::avr::ef_avr_arch; /// Linker is called through a C/C++ compiler. #[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)] @@ -1797,7 +1797,7 @@ supported_targets! { ("riscv64gc-unknown-fuchsia", riscv64gc_unknown_fuchsia), ("x86_64-unknown-fuchsia", x86_64_unknown_fuchsia), - ("avr-unknown-gnu-atmega328", avr_unknown_gnu_atmega328), + ("avr-none", avr_none), ("x86_64-unknown-l4re-uclibc", x86_64_unknown_l4re_uclibc), @@ -3062,7 +3062,10 @@ impl Target { &self.post_link_args, ] { for (&flavor, flavor_args) in args { - check!(!flavor_args.is_empty(), "linker flavor args must not be empty"); + check!( + !flavor_args.is_empty() || self.arch == "avr", + "linker flavor args must not be empty" + ); // Check that flavors mentioned in link args are compatible with the default flavor. match self.linker_flavor { LinkerFlavor::Gnu(..) => { diff --git a/compiler/rustc_target/src/spec/targets/avr_none.rs b/compiler/rustc_target/src/spec/targets/avr_none.rs new file mode 100644 index 00000000000..91d3197d099 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/avr_none.rs @@ -0,0 +1,32 @@ +use crate::spec::{Cc, LinkerFlavor, Lld, RelocModel, Target, TargetOptions}; + +pub(crate) fn target() -> Target { + Target { + arch: "avr".into(), + metadata: crate::spec::TargetMetadata { + description: None, + tier: None, + host_tools: None, + std: None, + }, + data_layout: "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8".into(), + llvm_target: "avr-unknown-unknown".into(), + pointer_width: 16, + options: TargetOptions { + c_int_width: "16".into(), + exe_suffix: ".elf".into(), + linker: Some("avr-gcc".into()), + eh_frame_header: false, + pre_link_args: TargetOptions::link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &[]), + late_link_args: TargetOptions::link_args( + LinkerFlavor::Gnu(Cc::Yes, Lld::No), + &["-lgcc"], + ), + max_atomic_width: Some(16), + atomic_cas: false, + relocation_model: RelocModel::Static, + need_explicit_cpu: true, + ..TargetOptions::default() + }, + } +} diff --git a/compiler/rustc_target/src/spec/targets/avr_unknown_gnu_atmega328.rs b/compiler/rustc_target/src/spec/targets/avr_unknown_gnu_atmega328.rs deleted file mode 100644 index c3d6fb72273..00000000000 --- a/compiler/rustc_target/src/spec/targets/avr_unknown_gnu_atmega328.rs +++ /dev/null @@ -1,5 +0,0 @@ -use crate::spec::{Target, base}; - -pub(crate) fn target() -> Target { - base::avr_gnu::target("atmega328", "-mmcu=atmega328") -} diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index b5cd3864620..c7f4ab48ab1 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -301,7 +301,7 @@ target | std | host | notes [`armv8r-none-eabihf`](platform-support/armv8r-none-eabihf.md) | * | | Bare Armv8-R, hardfloat [`armv7a-nuttx-eabi`](platform-support/nuttx.md) | ✓ | | ARMv7-A with NuttX [`armv7a-nuttx-eabihf`](platform-support/nuttx.md) | ✓ | | ARMv7-A with NuttX, hardfloat -`avr-unknown-gnu-atmega328` | * | | AVR. Requires `-Z build-std=core` +`avr-none` | * | | AVR; requires `-Zbuild-std=core` and `-Ctarget-cpu=...` `bpfeb-unknown-none` | * | | BPF (big endian) `bpfel-unknown-none` | * | | BPF (little endian) `csky-unknown-linux-gnuabiv2` | ✓ | | C-SKY abiv2 Linux (little endian) diff --git a/src/doc/rustc/src/platform-support/avr-none.md b/src/doc/rustc/src/platform-support/avr-none.md new file mode 100644 index 00000000000..9c1836222c1 --- /dev/null +++ b/src/doc/rustc/src/platform-support/avr-none.md @@ -0,0 +1,81 @@ +# `avr-none` + +Series of microcontrollers from Atmel: ATmega8, ATmega328p etc. + +**Tier: 3** + +## Target maintainers + +- [Patryk Wychowaniec](https://github.com/Patryk27) + +## Requirements + +This target is only cross-compiled; x86-64 Linux, x86-64 macOS and aarch64 macOS +hosts are confirmed to work, but in principle any machine able to run rustc and +avr-gcc should be good. + +Compiling for this target requires `avr-gcc` installed, because a couple of +intrinsics (like 32-bit multiplication) rely on [`libgcc`](https://github.com/gcc-mirror/gcc/blob/3269a722b7a03613e9c4e2862bc5088c4a17cc11/libgcc/config/avr/lib1funcs.S) +and can't be provided through `compiler-builtins` yet. This is a limitation that +[we hope to lift in the future](https://github.com/rust-lang/compiler-builtins/issues/711). + +You'll also need to setup the `.cargo/config` file - see below for details. + +## Building the target + +Rust comes with AVR support enabled, you don't have to rebuild the compiler. + +## Building Rust programs + +Install `avr-gcc`: + +```console +# Ubuntu: +$ sudo apt-get install gcc-avr + +# Mac: +$ brew tap osx-cross/avr && brew install avr-gcc + +# NixOS (takes a couple of minutes, since it's not provided through Hydra): +$ nix shell nixpkgs#pkgsCross.avr.buildPackages.gcc11 +``` + +... setup `.cargo/config` for your project: + +```toml +[build] +target = "avr-none" +rustflags = ["-C", "target-cpu=atmega328p"] + +[unstable] +build-std = ["core"] +``` + +... and then simply run: + +```console +$ cargo build --release +``` + +The final binary will be placed into +`./target/avr-none/release/your-project.elf`. + +Note that since AVRs have rather small amounts of registers, ROM and RAM, it's +recommended to always use `--release` to avoid running out of space. + +Also, please note that specifying `-C target-cpu` is required - here's a list of +the possible variants: + +https://github.com/llvm/llvm-project/blob/093d4db2f3c874d4683fb01194b00dbb20e5c713/clang/lib/Basic/Targets/AVR.cpp#L32 + +## Testing + +You can use [`simavr`](https://github.com/buserror/simavr) to emulate the +resulting firmware on your machine: + +```console +$ simavr -m atmega328p ./target/avr-none/release/your-project.elf +``` + +Alternatively, if you want to write a couple of actual `#[test]`s, you can use +[`avr-tester`](https://github.com/Patryk27/avr-tester). diff --git a/src/tools/compiletest/src/header/tests.rs b/src/tools/compiletest/src/header/tests.rs index 55292c46bba..c65f10a52bd 100644 --- a/src/tools/compiletest/src/header/tests.rs +++ b/src/tools/compiletest/src/header/tests.rs @@ -465,7 +465,10 @@ fn profiler_runtime() { #[test] fn asm_support() { let asms = [ + #[cfg(bootstrap)] ("avr-unknown-gnu-atmega328", false), + #[cfg(not(bootstrap))] + ("avr-none", false), ("i686-unknown-netbsd", true), ("riscv32gc-unknown-linux-gnu", true), ("riscv64imac-unknown-none-elf", true), diff --git a/src/tools/run-make-support/src/external_deps/rustc.rs b/src/tools/run-make-support/src/external_deps/rustc.rs index fd4a20278ad..710ba025830 100644 --- a/src/tools/run-make-support/src/external_deps/rustc.rs +++ b/src/tools/run-make-support/src/external_deps/rustc.rs @@ -253,6 +253,13 @@ impl Rustc { self } + /// Specify the target CPU. + pub fn target_cpu>(&mut self, target_cpu: S) -> &mut Self { + let target_cpu = target_cpu.as_ref(); + self.cmd.arg(format!("-Ctarget-cpu={target_cpu}")); + self + } + /// Specify the crate type. pub fn crate_type(&mut self, crate_type: &str) -> &mut Self { self.cmd.arg("--crate-type"); diff --git a/tests/assembly/asm/avr-modifiers.rs b/tests/assembly/asm/avr-modifiers.rs index 585fdd7b725..124cad9bef6 100644 --- a/tests/assembly/asm/avr-modifiers.rs +++ b/tests/assembly/asm/avr-modifiers.rs @@ -1,6 +1,6 @@ //@ add-core-stubs //@ assembly-output: emit-asm -//@ compile-flags: --target avr-unknown-gnu-atmega328 +//@ compile-flags: --target avr-none -C target-cpu=atmega328p //@ needs-llvm-components: avr #![feature(no_core, asm_experimental_arch)] diff --git a/tests/assembly/asm/avr-types.rs b/tests/assembly/asm/avr-types.rs index 25cf3ec3b4b..309405f4d51 100644 --- a/tests/assembly/asm/avr-types.rs +++ b/tests/assembly/asm/avr-types.rs @@ -1,6 +1,6 @@ //@ add-core-stubs //@ assembly-output: emit-asm -//@ compile-flags: --target avr-unknown-gnu-atmega328 +//@ compile-flags: --target avr-none -C target-cpu=atmega328p //@ needs-llvm-components: avr #![feature(no_core, asm_experimental_arch)] diff --git a/tests/assembly/targets/targets-pe.rs b/tests/assembly/targets/targets-pe.rs index 1fa4dc821dd..b74d0181c4d 100644 --- a/tests/assembly/targets/targets-pe.rs +++ b/tests/assembly/targets/targets-pe.rs @@ -15,9 +15,9 @@ //@ revisions: arm64ec_pc_windows_msvc //@ [arm64ec_pc_windows_msvc] compile-flags: --target arm64ec-pc-windows-msvc //@ [arm64ec_pc_windows_msvc] needs-llvm-components: aarch64 -//@ revisions: avr_unknown_gnu_atmega328 -//@ [avr_unknown_gnu_atmega328] compile-flags: --target avr-unknown-gnu-atmega328 -//@ [avr_unknown_gnu_atmega328] needs-llvm-components: avr +//@ revisions: avr_none +//@ [avr_none] compile-flags: --target avr-none -C target-cpu=atmega328p +//@ [avr_none] needs-llvm-components: avr //@ revisions: bpfeb_unknown_none //@ [bpfeb_unknown_none] compile-flags: --target bpfeb-unknown-none //@ [bpfeb_unknown_none] needs-llvm-components: bpf diff --git a/tests/codegen/asm/avr-clobbers.rs b/tests/codegen/asm/avr-clobbers.rs index 56218cd7bcf..9451127bf04 100644 --- a/tests/codegen/asm/avr-clobbers.rs +++ b/tests/codegen/asm/avr-clobbers.rs @@ -1,6 +1,6 @@ //@ add-core-stubs //@ assembly-output: emit-asm -//@ compile-flags: --target avr-unknown-gnu-atmega328 +//@ compile-flags: --target avr-none -C target-cpu=atmega328p //@ needs-llvm-components: avr #![crate_type = "rlib"] diff --git a/tests/codegen/avr/avr-func-addrspace.rs b/tests/codegen/avr/avr-func-addrspace.rs index ed8acccb1ad..2ec7c86b5f4 100644 --- a/tests/codegen/avr/avr-func-addrspace.rs +++ b/tests/codegen/avr/avr-func-addrspace.rs @@ -1,4 +1,4 @@ -//@ compile-flags: -Copt-level=3 --target=avr-unknown-gnu-atmega328 --crate-type=rlib -C panic=abort +//@ compile-flags: -Copt-level=3 --target=avr-none -C target-cpu=atmega328p --crate-type=rlib -C panic=abort //@ needs-llvm-components: avr // This test validates that function pointers can be stored in global variables diff --git a/tests/run-make/avr-rjmp-offset/rmake.rs b/tests/run-make/avr-rjmp-offset/rmake.rs index de64b724eed..73b6ab3977e 100644 --- a/tests/run-make/avr-rjmp-offset/rmake.rs +++ b/tests/run-make/avr-rjmp-offset/rmake.rs @@ -22,7 +22,8 @@ fn main() { .input("avr-rjmp-offsets.rs") .opt_level("s") .panic("abort") - .target("avr-unknown-gnu-atmega328") + .target("avr-none") + .target_cpu("avr") // normally one links with `avr-gcc`, but this is not available in CI, // hence this test diverges from the default behavior to enable linking // at all, which is necessary for the test (to resolve the labels). To @@ -49,6 +50,7 @@ fn main() { // of the Rust compiler did produce a label `rjmp .-4` (misses the first // instruction in the loop). assert!(disassembly.contains("
"), "no main function in output"); + disassembly .trim() .lines() diff --git a/tests/ui/feature-gates/feature-gate-abi-avr-interrupt.rs b/tests/ui/feature-gates/feature-gate-abi-avr-interrupt.rs index 5386628a8e0..ce3d3fc645d 100644 --- a/tests/ui/feature-gates/feature-gate-abi-avr-interrupt.rs +++ b/tests/ui/feature-gates/feature-gate-abi-avr-interrupt.rs @@ -1,5 +1,5 @@ //@ needs-llvm-components: avr -//@ compile-flags: --target=avr-unknown-gnu-atmega328 --crate-type=rlib +//@ compile-flags: --target=avr-none -C target-cpu=atmega328p --crate-type=rlib #![no_core] #![feature(no_core, lang_items)] #[lang="sized"] diff --git a/tests/ui/repr/16-bit-repr-c-enum.rs b/tests/ui/repr/16-bit-repr-c-enum.rs index 2b6bbf12650..011076882d2 100644 --- a/tests/ui/repr/16-bit-repr-c-enum.rs +++ b/tests/ui/repr/16-bit-repr-c-enum.rs @@ -2,7 +2,7 @@ //@ revisions: avr msp430 // //@ [avr] needs-llvm-components: avr -//@ [avr] compile-flags: --target=avr-unknown-gnu-atmega328 --crate-type=rlib +//@ [avr] compile-flags: --target=avr-none -C target-cpu=atmega328p --crate-type=rlib //@ [msp430] needs-llvm-components: msp430 //@ [msp430] compile-flags: --target=msp430-none-elf --crate-type=rlib #![feature(no_core, lang_items, intrinsics, staged_api, rustc_attrs)] -- cgit 1.4.1-3-g733a5 From 7ba3d7b54e7688f6f1a0fd22fe274ee7b06fea3e Mon Sep 17 00:00:00 2001 From: Zachary S Date: Sat, 25 Jan 2025 20:15:24 -0600 Subject: Remove `BackendRepr::Uninhabited`, replaced with an `uninhabited: bool` field in `LayoutData`. Also update comments that refered to BackendRepr::Uninhabited. --- compiler/rustc_abi/src/callconv.rs | 2 -- compiler/rustc_abi/src/layout.rs | 23 +++++++------- compiler/rustc_abi/src/lib.rs | 35 ++++++++++------------ .../rustc_codegen_cranelift/src/value_and_place.rs | 4 +-- compiler/rustc_codegen_gcc/src/intrinsic/mod.rs | 2 +- compiler/rustc_codegen_gcc/src/type_of.rs | 13 ++++---- compiler/rustc_codegen_llvm/src/intrinsic.rs | 2 +- compiler/rustc_codegen_llvm/src/type_of.rs | 13 ++++---- compiler/rustc_codegen_ssa/src/mir/operand.rs | 4 +-- compiler/rustc_const_eval/src/interpret/operand.rs | 2 +- .../rustc_const_eval/src/interpret/validity.rs | 8 ++--- .../src/util/check_validity_requirement.rs | 16 +++++----- compiler/rustc_middle/src/ty/layout.rs | 3 +- compiler/rustc_mir_transform/src/gvn.rs | 5 +++- compiler/rustc_smir/src/rustc_smir/convert/abi.rs | 1 - compiler/rustc_target/src/callconv/loongarch.rs | 2 +- compiler/rustc_target/src/callconv/mod.rs | 3 +- compiler/rustc_target/src/callconv/riscv.rs | 2 +- compiler/rustc_target/src/callconv/x86.rs | 4 +-- compiler/rustc_target/src/callconv/x86_64.rs | 2 -- compiler/rustc_target/src/callconv/x86_win64.rs | 2 +- compiler/rustc_ty_utils/src/abi.rs | 4 +-- compiler/rustc_ty_utils/src/layout.rs | 21 ++++++------- compiler/rustc_ty_utils/src/layout/invariant.rs | 15 ++++++---- compiler/stable_mir/src/abi.rs | 6 +--- .../rust-analyzer/crates/hir-ty/src/layout.rs | 12 ++++---- 26 files changed, 93 insertions(+), 113 deletions(-) (limited to 'compiler/rustc_codegen_ssa/src') diff --git a/compiler/rustc_abi/src/callconv.rs b/compiler/rustc_abi/src/callconv.rs index 9fb70b80c9e..4529ab8058e 100644 --- a/compiler/rustc_abi/src/callconv.rs +++ b/compiler/rustc_abi/src/callconv.rs @@ -65,8 +65,6 @@ impl<'a, Ty> TyAndLayout<'a, Ty> { Ty: TyAbiInterface<'a, C> + Copy, { match self.backend_repr { - BackendRepr::Uninhabited => Err(Heterogeneous), - // The primitive for this algorithm. BackendRepr::Scalar(scalar) => { let kind = match scalar.primitive() { diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index 45cd0b517f6..53243266f99 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -130,6 +130,7 @@ impl LayoutCalculator { }, backend_repr: BackendRepr::ScalarPair(a, b), largest_niche, + uninhabited: false, align, size, max_repr_align: None, @@ -221,8 +222,9 @@ impl LayoutCalculator { LayoutData { variants: Variants::Empty, fields: FieldsShape::Primitive, - backend_repr: BackendRepr::Uninhabited, + backend_repr: BackendRepr::Memory { sized: true }, largest_niche: None, + uninhabited: true, align: dl.i8_align, size: Size::ZERO, max_repr_align: None, @@ -400,6 +402,7 @@ impl LayoutCalculator { fields: FieldsShape::Union(union_field_count), backend_repr: abi, largest_niche: None, + uninhabited: false, align, size: size.align_to(align.abi), max_repr_align, @@ -447,7 +450,6 @@ impl LayoutCalculator { Scalar::Union { .. } => {} }; match &mut st.backend_repr { - BackendRepr::Uninhabited => {} BackendRepr::Scalar(scalar) => hide_niches(scalar), BackendRepr::ScalarPair(a, b) => { hide_niches(a); @@ -639,9 +641,8 @@ impl LayoutCalculator { let same_size = size == variant_layouts[largest_variant_index].size; let same_align = align == variant_layouts[largest_variant_index].align; - let abi = if variant_layouts.iter().all(|v| v.is_uninhabited()) { - BackendRepr::Uninhabited - } else if same_size && same_align && others_zst { + let uninhabited = variant_layouts.iter().all(|v| v.is_uninhabited()); + let abi = if same_size && same_align && others_zst { match variant_layouts[largest_variant_index].backend_repr { // When the total alignment and size match, we can use the // same ABI as the scalar variant with the reserved niche. @@ -683,6 +684,7 @@ impl LayoutCalculator { }, backend_repr: abi, largest_niche, + uninhabited, size, align, max_repr_align, @@ -853,9 +855,8 @@ impl LayoutCalculator { }; let mut abi = BackendRepr::Memory { sized: true }; - if layout_variants.iter().all(|v| v.is_uninhabited()) { - abi = BackendRepr::Uninhabited; - } else if tag.size(dl) == size { + let uninhabited = layout_variants.iter().all(|v| v.is_uninhabited()); + if tag.size(dl) == size { // Make sure we only use scalar layout when the enum is entirely its // own tag (i.e. it has no padding nor any non-ZST variant fields). abi = BackendRepr::Scalar(tag); @@ -995,6 +996,7 @@ impl LayoutCalculator { memory_index: [0].into(), }, largest_niche, + uninhabited, backend_repr: abi, align, size, @@ -1355,9 +1357,7 @@ impl LayoutCalculator { _ => {} } } - if fields.iter().any(|f| f.is_uninhabited()) { - abi = BackendRepr::Uninhabited; - } + let uninhabited = fields.iter().any(|f| f.is_uninhabited()); let unadjusted_abi_align = if repr.transparent() { match layout_of_single_non_zst_field { @@ -1378,6 +1378,7 @@ impl LayoutCalculator { fields: FieldsShape::Arbitrary { offsets, memory_index }, backend_repr: abi, largest_niche, + uninhabited, align, size, max_repr_align, diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index dbb4bed5cdd..14a8a579200 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1404,7 +1404,6 @@ impl AddressSpace { #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] #[cfg_attr(feature = "nightly", derive(HashStable_Generic))] pub enum BackendRepr { - Uninhabited, Scalar(Scalar), ScalarPair(Scalar, Scalar), Vector { @@ -1423,10 +1422,9 @@ impl BackendRepr { #[inline] pub fn is_unsized(&self) -> bool { match *self { - BackendRepr::Uninhabited - | BackendRepr::Scalar(_) - | BackendRepr::ScalarPair(..) - | BackendRepr::Vector { .. } => false, + BackendRepr::Scalar(_) | BackendRepr::ScalarPair(..) | BackendRepr::Vector { .. } => { + false + } BackendRepr::Memory { sized } => !sized, } } @@ -1445,12 +1443,6 @@ impl BackendRepr { } } - /// Returns `true` if this is an uninhabited type - #[inline] - pub fn is_uninhabited(&self) -> bool { - matches!(*self, BackendRepr::Uninhabited) - } - /// Returns `true` if this is a scalar type #[inline] pub fn is_scalar(&self) -> bool { @@ -1471,7 +1463,7 @@ impl BackendRepr { BackendRepr::Vector { element, count } => { cx.data_layout().vector_align(element.size(cx) * count) } - BackendRepr::Uninhabited | BackendRepr::Memory { .. } => return None, + BackendRepr::Memory { .. } => return None, }) } @@ -1492,7 +1484,7 @@ impl BackendRepr { // to make the size a multiple of align (e.g. for vectors of size 3). (element.size(cx) * count).align_to(self.inherent_align(cx)?.abi) } - BackendRepr::Uninhabited | BackendRepr::Memory { .. } => return None, + BackendRepr::Memory { .. } => return None, }) } @@ -1506,9 +1498,7 @@ impl BackendRepr { BackendRepr::Vector { element, count } => { BackendRepr::Vector { element: element.to_union(), count } } - BackendRepr::Uninhabited | BackendRepr::Memory { .. } => { - BackendRepr::Memory { sized: true } - } + BackendRepr::Memory { .. } => BackendRepr::Memory { sized: true }, } } @@ -1704,6 +1694,11 @@ pub struct LayoutData { /// The leaf scalar with the largest number of invalid values /// (i.e. outside of its `valid_range`), if it exists. pub largest_niche: Option, + /// Is this type known to be uninhabted? + /// + /// This is separate from BackendRepr, because an uninhabited return type may require special + /// consideration based on its size or other attributes. + pub uninhabited: bool, pub align: AbiAndPrefAlign, pub size: Size, @@ -1735,14 +1730,14 @@ impl LayoutData { /// Returns `true` if this is an aggregate type (including a ScalarPair!) pub fn is_aggregate(&self) -> bool { match self.backend_repr { - BackendRepr::Uninhabited | BackendRepr::Scalar(_) | BackendRepr::Vector { .. } => false, + BackendRepr::Scalar(_) | BackendRepr::Vector { .. } => false, BackendRepr::ScalarPair(..) | BackendRepr::Memory { .. } => true, } } /// Returns `true` if this is an uninhabited type pub fn is_uninhabited(&self) -> bool { - self.backend_repr.is_uninhabited() + self.uninhabited } pub fn scalar(cx: &C, scalar: Scalar) -> Self { @@ -1778,6 +1773,7 @@ impl LayoutData { fields: FieldsShape::Primitive, backend_repr: BackendRepr::Scalar(scalar), largest_niche, + uninhabited: false, size, align, max_repr_align: None, @@ -1802,6 +1798,7 @@ where backend_repr, fields, largest_niche, + uninhabited, variants, max_repr_align, unadjusted_abi_align, @@ -1813,6 +1810,7 @@ where .field("abi", backend_repr) .field("fields", fields) .field("largest_niche", largest_niche) + .field("uninhabited", uninhabited) .field("variants", variants) .field("max_repr_align", max_repr_align) .field("unadjusted_abi_align", unadjusted_abi_align) @@ -1877,7 +1875,6 @@ impl LayoutData { BackendRepr::Scalar(_) | BackendRepr::ScalarPair(..) | BackendRepr::Vector { .. } => { false } - BackendRepr::Uninhabited => self.size.bytes() == 0, BackendRepr::Memory { sized } => sized && self.size.bytes() == 0, } } diff --git a/compiler/rustc_codegen_cranelift/src/value_and_place.rs b/compiler/rustc_codegen_cranelift/src/value_and_place.rs index a9b8e1bd393..1b3f86c8405 100644 --- a/compiler/rustc_codegen_cranelift/src/value_and_place.rs +++ b/compiler/rustc_codegen_cranelift/src/value_and_place.rs @@ -638,9 +638,7 @@ impl<'tcx> CPlace<'tcx> { } CPlaceInner::Addr(_, Some(_)) => bug!("Can't write value to unsized place {:?}", self), CPlaceInner::Addr(to_ptr, None) => { - if dst_layout.size == Size::ZERO - || dst_layout.backend_repr == BackendRepr::Uninhabited - { + if dst_layout.size == Size::ZERO { return; } diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs index 5322b731d8b..433868e238a 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs @@ -315,7 +315,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc let layout = self.layout_of(tp_ty).layout; let _use_integer_compare = match layout.backend_repr() { Scalar(_) | ScalarPair(_, _) => true, - Uninhabited | Vector { .. } => false, + Vector { .. } => false, Memory { .. } => { // For rusty ABIs, small aggregates are actually passed // as `RegKind::Integer` (see `FnAbi::adjust_for_abi`), diff --git a/compiler/rustc_codegen_gcc/src/type_of.rs b/compiler/rustc_codegen_gcc/src/type_of.rs index 8b8b54753e7..bac4fc51300 100644 --- a/compiler/rustc_codegen_gcc/src/type_of.rs +++ b/compiler/rustc_codegen_gcc/src/type_of.rs @@ -84,7 +84,7 @@ fn uncached_gcc_type<'gcc, 'tcx>( false, ); } - BackendRepr::Uninhabited | BackendRepr::Memory { .. } => {} + BackendRepr::Memory { .. } => {} } let name = match *layout.ty.kind() { @@ -179,19 +179,16 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> { fn is_gcc_immediate(&self) -> bool { match self.backend_repr { BackendRepr::Scalar(_) | BackendRepr::Vector { .. } => true, - BackendRepr::ScalarPair(..) | BackendRepr::Uninhabited | BackendRepr::Memory { .. } => { - false - } + BackendRepr::ScalarPair(..) | BackendRepr::Memory { .. } => false, } } fn is_gcc_scalar_pair(&self) -> bool { match self.backend_repr { BackendRepr::ScalarPair(..) => true, - BackendRepr::Uninhabited - | BackendRepr::Scalar(_) - | BackendRepr::Vector { .. } - | BackendRepr::Memory { .. } => false, + BackendRepr::Scalar(_) | BackendRepr::Vector { .. } | BackendRepr::Memory { .. } => { + false + } } } diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 7e1a9d361e6..f68365f6c69 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -476,7 +476,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { let layout = self.layout_of(tp_ty).layout; let use_integer_compare = match layout.backend_repr() { Scalar(_) | ScalarPair(_, _) => true, - Uninhabited | Vector { .. } => false, + Vector { .. } => false, Memory { .. } => { // For rusty ABIs, small aggregates are actually passed // as `RegKind::Integer` (see `FnAbi::adjust_for_abi`), diff --git a/compiler/rustc_codegen_llvm/src/type_of.rs b/compiler/rustc_codegen_llvm/src/type_of.rs index b0b6da869da..ba01fbff385 100644 --- a/compiler/rustc_codegen_llvm/src/type_of.rs +++ b/compiler/rustc_codegen_llvm/src/type_of.rs @@ -23,7 +23,7 @@ fn uncached_llvm_type<'a, 'tcx>( let element = layout.scalar_llvm_type_at(cx, element); return cx.type_vector(element, count); } - BackendRepr::Uninhabited | BackendRepr::Memory { .. } | BackendRepr::ScalarPair(..) => {} + BackendRepr::Memory { .. } | BackendRepr::ScalarPair(..) => {} } let name = match layout.ty.kind() { @@ -172,19 +172,16 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyAndLayout<'tcx> { fn is_llvm_immediate(&self) -> bool { match self.backend_repr { BackendRepr::Scalar(_) | BackendRepr::Vector { .. } => true, - BackendRepr::ScalarPair(..) | BackendRepr::Uninhabited | BackendRepr::Memory { .. } => { - false - } + BackendRepr::ScalarPair(..) | BackendRepr::Memory { .. } => false, } } fn is_llvm_scalar_pair(&self) -> bool { match self.backend_repr { BackendRepr::ScalarPair(..) => true, - BackendRepr::Uninhabited - | BackendRepr::Scalar(_) - | BackendRepr::Vector { .. } - | BackendRepr::Memory { .. } => false, + BackendRepr::Scalar(_) | BackendRepr::Vector { .. } | BackendRepr::Memory { .. } => { + false + } } } diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index 958a52a2cb1..faf1300e473 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -422,9 +422,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { See ", ); } - BackendRepr::Uninhabited - | BackendRepr::ScalarPair(_, _) - | BackendRepr::Memory { sized: false } => bug!(), + BackendRepr::ScalarPair(_, _) | BackendRepr::Memory { sized: false } => bug!(), }) }; diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 5d905cff1f2..36da9037e43 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -385,7 +385,7 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> { (Immediate::Uninit, _) => Immediate::Uninit, // If the field is uninhabited, we can forget the data (can happen in ConstProp). // `enum S { A(!), B, C }` is an example of an enum with Scalar layout that - // has an `Uninhabited` variant, which means this case is possible. + // has an uninhabited variant, which means this case is possible. _ if layout.is_uninhabited() => Immediate::Uninit, // the field contains no information, can be left uninit // (Scalar/ScalarPair can contain even aligned ZST, not just 1-ZST) diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 0ac34f4633b..3667cc84d70 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -1274,11 +1274,11 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt, // FIXME: We could avoid some redundant checks here. For newtypes wrapping // scalars, we do the same check on every "level" (e.g., first we check // MyNewtype and then the scalar in there). + if val.layout.is_uninhabited() { + let ty = val.layout.ty; + throw_validation_failure!(self.path, UninhabitedVal { ty }); + } match val.layout.backend_repr { - BackendRepr::Uninhabited => { - let ty = val.layout.ty; - throw_validation_failure!(self.path, UninhabitedVal { ty }); - } BackendRepr::Scalar(scalar_layout) => { if !scalar_layout.is_uninit_valid() { // There is something to check here. diff --git a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs index 79baf91c3ce..6426bca2332 100644 --- a/compiler/rustc_const_eval/src/util/check_validity_requirement.rs +++ b/compiler/rustc_const_eval/src/util/check_validity_requirement.rs @@ -111,13 +111,15 @@ fn check_validity_requirement_lax<'tcx>( }; // Check the ABI. - let valid = match this.backend_repr { - BackendRepr::Uninhabited => false, // definitely UB - BackendRepr::Scalar(s) => scalar_allows_raw_init(s), - BackendRepr::ScalarPair(s1, s2) => scalar_allows_raw_init(s1) && scalar_allows_raw_init(s2), - BackendRepr::Vector { element: s, count } => count == 0 || scalar_allows_raw_init(s), - BackendRepr::Memory { .. } => true, // Fields are checked below. - }; + let valid = !this.is_uninhabited() // definitely UB if uninhabited + && match this.backend_repr { + BackendRepr::Scalar(s) => scalar_allows_raw_init(s), + BackendRepr::ScalarPair(s1, s2) => { + scalar_allows_raw_init(s1) && scalar_allows_raw_init(s2) + } + BackendRepr::Vector { element: s, count } => count == 0 || scalar_allows_raw_init(s), + BackendRepr::Memory { .. } => true, // Fields are checked below. + }; if !valid { // This is definitely not okay. return Ok(false); diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 19fa8323574..eb14ed20fba 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -794,8 +794,9 @@ where Some(fields) => FieldsShape::Union(fields), None => FieldsShape::Arbitrary { offsets: IndexVec::new(), memory_index: IndexVec::new() }, }, - backend_repr: BackendRepr::Uninhabited, + backend_repr: BackendRepr::Memory { sized: true }, largest_niche: None, + uninhabited: true, align: tcx.data_layout.i8_align, size: Size::ZERO, max_repr_align: None, diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 77a3854ebde..2f8a3050199 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -1558,8 +1558,11 @@ impl<'body, 'tcx> VnState<'body, 'tcx> { return true; }; + if layout.uninhabited { + return true; + } + match layout.backend_repr { - BackendRepr::Uninhabited => true, BackendRepr::Scalar(a) => !a.is_always_valid(&self.ecx), BackendRepr::ScalarPair(a, b) => { !a.is_always_valid(&self.ecx) || !b.is_always_valid(&self.ecx) diff --git a/compiler/rustc_smir/src/rustc_smir/convert/abi.rs b/compiler/rustc_smir/src/rustc_smir/convert/abi.rs index fb2e838cdc9..a627e0e69b6 100644 --- a/compiler/rustc_smir/src/rustc_smir/convert/abi.rs +++ b/compiler/rustc_smir/src/rustc_smir/convert/abi.rs @@ -202,7 +202,6 @@ impl<'tcx> Stable<'tcx> for rustc_abi::BackendRepr { fn stable(&self, tables: &mut Tables<'_>) -> Self::T { match *self { - rustc_abi::BackendRepr::Uninhabited => ValueAbi::Uninhabited, rustc_abi::BackendRepr::Scalar(scalar) => ValueAbi::Scalar(scalar.stable(tables)), rustc_abi::BackendRepr::ScalarPair(first, second) => { ValueAbi::ScalarPair(first.stable(tables), second.stable(tables)) diff --git a/compiler/rustc_target/src/callconv/loongarch.rs b/compiler/rustc_target/src/callconv/loongarch.rs index 47566bde6b4..3fa67c624a7 100644 --- a/compiler/rustc_target/src/callconv/loongarch.rs +++ b/compiler/rustc_target/src/callconv/loongarch.rs @@ -80,7 +80,7 @@ where } } }, - BackendRepr::Vector { .. } | BackendRepr::Uninhabited => return Err(CannotUseFpConv), + BackendRepr::Vector { .. } => return Err(CannotUseFpConv), BackendRepr::ScalarPair(..) | BackendRepr::Memory { .. } => match arg_layout.fields { FieldsShape::Primitive => { unreachable!("aggregates can't have `FieldsShape::Primitive`") diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs index c2a176facdf..e5f986269dd 100644 --- a/compiler/rustc_target/src/callconv/mod.rs +++ b/compiler/rustc_target/src/callconv/mod.rs @@ -38,7 +38,7 @@ mod xtensa; pub enum PassMode { /// Ignore the argument. /// - /// The argument is either uninhabited or a ZST. + /// The argument is a ZST. Ignore, /// Pass the argument directly. /// @@ -350,7 +350,6 @@ impl<'a, Ty> ArgAbi<'a, Ty> { scalar_attrs: impl Fn(&TyAndLayout<'a, Ty>, Scalar, Size) -> ArgAttributes, ) -> Self { let mode = match layout.backend_repr { - BackendRepr::Uninhabited => PassMode::Ignore, BackendRepr::Scalar(scalar) => { PassMode::Direct(scalar_attrs(&layout, scalar, Size::ZERO)) } diff --git a/compiler/rustc_target/src/callconv/riscv.rs b/compiler/rustc_target/src/callconv/riscv.rs index 265ae20f991..785175229b0 100644 --- a/compiler/rustc_target/src/callconv/riscv.rs +++ b/compiler/rustc_target/src/callconv/riscv.rs @@ -86,7 +86,7 @@ where } } }, - BackendRepr::Vector { .. } | BackendRepr::Uninhabited => return Err(CannotUseFpConv), + BackendRepr::Vector { .. } => return Err(CannotUseFpConv), BackendRepr::ScalarPair(..) | BackendRepr::Memory { .. } => match arg_layout.fields { FieldsShape::Primitive => { unreachable!("aggregates can't have `FieldsShape::Primitive`") diff --git a/compiler/rustc_target/src/callconv/x86.rs b/compiler/rustc_target/src/callconv/x86.rs index 5f4f4cd57f6..7e5aab0201b 100644 --- a/compiler/rustc_target/src/callconv/x86.rs +++ b/compiler/rustc_target/src/callconv/x86.rs @@ -108,9 +108,7 @@ where Ty: TyAbiInterface<'a, C> + Copy, { match layout.backend_repr { - BackendRepr::Uninhabited - | BackendRepr::Scalar(_) - | BackendRepr::ScalarPair(..) => false, + BackendRepr::Scalar(_) | BackendRepr::ScalarPair(..) => false, BackendRepr::Vector { .. } => true, BackendRepr::Memory { .. } => { for i in 0..layout.fields.count() { diff --git a/compiler/rustc_target/src/callconv/x86_64.rs b/compiler/rustc_target/src/callconv/x86_64.rs index b15d82c26da..ab306e20239 100644 --- a/compiler/rustc_target/src/callconv/x86_64.rs +++ b/compiler/rustc_target/src/callconv/x86_64.rs @@ -51,8 +51,6 @@ where } let mut c = match layout.backend_repr { - BackendRepr::Uninhabited => return Ok(()), - BackendRepr::Scalar(scalar) => match scalar.primitive() { Primitive::Int(..) | Primitive::Pointer(_) => Class::Int, Primitive::Float(_) => Class::Sse, diff --git a/compiler/rustc_target/src/callconv/x86_win64.rs b/compiler/rustc_target/src/callconv/x86_win64.rs index 2ef5127de04..4d99a9f9ba0 100644 --- a/compiler/rustc_target/src/callconv/x86_win64.rs +++ b/compiler/rustc_target/src/callconv/x86_win64.rs @@ -8,7 +8,7 @@ use crate::spec::{HasTargetSpec, RustcAbi}; pub(crate) fn compute_abi_info(cx: &impl HasTargetSpec, fn_abi: &mut FnAbi<'_, Ty>) { let fixup = |a: &mut ArgAbi<'_, Ty>, is_ret: bool| { match a.layout.backend_repr { - BackendRepr::Uninhabited | BackendRepr::Memory { sized: false } => {} + BackendRepr::Memory { sized: false } => {} BackendRepr::ScalarPair(..) | BackendRepr::Memory { sized: true } => { match a.layout.size.bits() { 8 => a.cast_to(Reg::i8()), diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index c5d2d0afbfa..2d20ef3d690 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -472,9 +472,7 @@ fn fn_abi_sanity_check<'tcx>( // `layout.backend_repr` and ignore everything else. We should just reject //`Aggregate` entirely here, but some targets need to be fixed first. match arg.layout.backend_repr { - BackendRepr::Uninhabited - | BackendRepr::Scalar(_) - | BackendRepr::Vector { .. } => {} + BackendRepr::Scalar(_) | BackendRepr::Vector { .. } => {} BackendRepr::ScalarPair(..) => { panic!("`PassMode::Direct` used for ScalarPair type {}", arg.layout.ty) } diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 556512e0236..b6a14d147ca 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -348,19 +348,17 @@ fn layout_of_uncached<'tcx>( .checked_mul(count, dl) .ok_or_else(|| error(cx, LayoutError::SizeOverflow(ty)))?; - let abi = if count != 0 && ty.is_privately_uninhabited(tcx, cx.typing_env) { - BackendRepr::Uninhabited - } else { - BackendRepr::Memory { sized: true } - }; + let abi = BackendRepr::Memory { sized: true }; let largest_niche = if count != 0 { element.largest_niche } else { None }; + let uninhabited = if count != 0 { element.uninhabited } else { false }; tcx.mk_layout(LayoutData { variants: Variants::Single { index: FIRST_VARIANT }, fields: FieldsShape::Array { stride: element.size, count }, backend_repr: abi, largest_niche, + uninhabited, align: element.align, size, max_repr_align: None, @@ -375,6 +373,7 @@ fn layout_of_uncached<'tcx>( fields: FieldsShape::Array { stride: element.size, count: 0 }, backend_repr: BackendRepr::Memory { sized: false }, largest_niche: None, + uninhabited: false, align: element.align, size: Size::ZERO, max_repr_align: None, @@ -390,6 +389,7 @@ fn layout_of_uncached<'tcx>( fields: FieldsShape::Array { stride: Size::from_bytes(1), count: 0 }, backend_repr: BackendRepr::Memory { sized: false }, largest_niche: None, + uninhabited: false, align: dl.i8_align, size: Size::ZERO, max_repr_align: None, @@ -555,6 +555,7 @@ fn layout_of_uncached<'tcx>( fields, backend_repr: abi, largest_niche: e_ly.largest_niche, + uninhabited: false, size, align, max_repr_align: None, @@ -1014,13 +1015,8 @@ fn coroutine_layout<'tcx>( size = size.align_to(align.abi); - let abi = if prefix.backend_repr.is_uninhabited() - || variants.iter().all(|v| v.backend_repr.is_uninhabited()) - { - BackendRepr::Uninhabited - } else { - BackendRepr::Memory { sized: true } - }; + let uninhabited = prefix.uninhabited || variants.iter().all(|v| v.is_uninhabited()); + let abi = BackendRepr::Memory { sized: true }; // this is similar to how ReprOptions populates its field_shuffle_seed let def_hash = tcx.def_path_hash(def_id).0.to_smaller_hash(); @@ -1041,6 +1037,7 @@ fn coroutine_layout<'tcx>( // See , . // FIXME: Remove when is implemented and aliased coroutine fields are wrapped in `UnsafePinned`. largest_niche: None, + uninhabited, size, align, max_repr_align: None, diff --git a/compiler/rustc_ty_utils/src/layout/invariant.rs b/compiler/rustc_ty_utils/src/layout/invariant.rs index 8d5403ed324..5ea6716c5ca 100644 --- a/compiler/rustc_ty_utils/src/layout/invariant.rs +++ b/compiler/rustc_ty_utils/src/layout/invariant.rs @@ -10,7 +10,11 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou // Type-level uninhabitedness should always imply ABI uninhabitedness. if layout.ty.is_privately_uninhabited(tcx, cx.typing_env) { - assert!(layout.is_uninhabited()); + assert!( + layout.is_uninhabited(), + "{:?} is type-level uninhabited but not ABI-uninhabited?", + layout.ty + ); } if layout.size.bytes() % layout.align.abi.bytes() != 0 { @@ -71,7 +75,7 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou let Some((align, size)) = align.zip(size) else { assert_matches!( layout.layout.backend_repr(), - BackendRepr::Uninhabited | BackendRepr::Memory { .. }, + BackendRepr::Memory { .. }, "ABI unexpectedly missing alignment and/or size in {layout:#?}" ); return; @@ -235,7 +239,7 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou assert!(align >= element.align(cx).abi); // just sanity-checking `vector_align`. // FIXME: Do some kind of check of the inner type, like for Scalar and ScalarPair. } - BackendRepr::Uninhabited | BackendRepr::Memory { .. } => {} // Nothing to check. + BackendRepr::Memory { .. } => {} // Nothing to check. } } @@ -291,8 +295,8 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou || variant.is_uninhabited() { // These are never actually accessed anyway, so we can skip the coherence check - // for them. They also fail that check, since they have - // `Aggregate`/`Uninhabited` ABI even when the main type is + // for them. They also fail that check, since they may have + // a different ABI even when the main type is // `Scalar`/`ScalarPair`. (Note that sometimes, variants with fields have size // 0, and sometimes, variants without fields have non-0 size.) continue; @@ -306,7 +310,6 @@ pub(super) fn layout_sanity_check<'tcx>(cx: &LayoutCx<'tcx>, layout: &TyAndLayou (BackendRepr::ScalarPair(a1, b1), BackendRepr::ScalarPair(a2, b2)) => { scalar_coherent(a1, a2) && scalar_coherent(b1, b2) } - (BackendRepr::Uninhabited, _) => true, (BackendRepr::Memory { .. }, _) => true, _ => false, }; diff --git a/compiler/stable_mir/src/abi.rs b/compiler/stable_mir/src/abi.rs index 861b6692b53..091f3e1a95e 100644 --- a/compiler/stable_mir/src/abi.rs +++ b/compiler/stable_mir/src/abi.rs @@ -227,7 +227,6 @@ pub enum TagEncoding { /// in terms of categories of C types there are ABI rules for. #[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize)] pub enum ValueAbi { - Uninhabited, Scalar(Scalar), ScalarPair(Scalar, Scalar), Vector { @@ -244,10 +243,7 @@ impl ValueAbi { /// Returns `true` if the layout corresponds to an unsized type. pub fn is_unsized(&self) -> bool { match *self { - ValueAbi::Uninhabited - | ValueAbi::Scalar(_) - | ValueAbi::ScalarPair(..) - | ValueAbi::Vector { .. } => false, + ValueAbi::Scalar(_) | ValueAbi::ScalarPair(..) | ValueAbi::Vector { .. } => false, ValueAbi::Aggregate { sized } => !sized, } } diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs index b6f7c44c2ae..f5a7b658123 100644 --- a/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs +++ b/src/tools/rust-analyzer/crates/hir-ty/src/layout.rs @@ -194,6 +194,7 @@ fn layout_of_simd_ty( fields, backend_repr: BackendRepr::Vector { element: e_abi, count: e_len }, largest_niche: e_ly.largest_niche, + uninhabited: false, size, align, max_repr_align: None, @@ -297,20 +298,17 @@ pub fn layout_of_ty_query( .checked_mul(count, dl) .ok_or(LayoutError::BadCalc(LayoutCalculatorError::SizeOverflow))?; - let backend_repr = - if count != 0 && matches!(element.backend_repr, BackendRepr::Uninhabited) { - BackendRepr::Uninhabited - } else { - BackendRepr::Memory { sized: true } - }; + let backend_repr = BackendRepr::Memory { sized: true }; let largest_niche = if count != 0 { element.largest_niche } else { None }; + let uninhabited = if count != 0 { element.uninhabited } else { false }; Layout { variants: Variants::Single { index: struct_variant_idx() }, fields: FieldsShape::Array { stride: element.size, count }, backend_repr, largest_niche, + uninhabited, align: element.align, size, max_repr_align: None, @@ -325,6 +323,7 @@ pub fn layout_of_ty_query( fields: FieldsShape::Array { stride: element.size, count: 0 }, backend_repr: BackendRepr::Memory { sized: false }, largest_niche: None, + uninhabited: false, align: element.align, size: Size::ZERO, max_repr_align: None, @@ -337,6 +336,7 @@ pub fn layout_of_ty_query( fields: FieldsShape::Array { stride: Size::from_bytes(1), count: 0 }, backend_repr: BackendRepr::Memory { sized: false }, largest_niche: None, + uninhabited: false, align: dl.i8_align, size: Size::ZERO, max_repr_align: None, -- cgit 1.4.1-3-g733a5 From 58ebf6afdd01d32f9f6d22d2e788c0dc10bc65a5 Mon Sep 17 00:00:00 2001 From: Zachary S Date: Thu, 13 Feb 2025 13:17:39 -0600 Subject: Add test that uninhabited repr(transparent) type has same function return ABI as wrapped type. Fix codegen of uninhabited PassMode::Indirect return types. Add codegen test for uninhabited PassMode::Indirect return types. Enable optimizations for uninhabited return type codegen test --- compiler/rustc_codegen_ssa/src/mir/block.rs | 28 ++++---------- .../codegen/uninhabited-transparent-return-abi.rs | 44 ++++++++++++++++++++++ .../uninhabited-transparent-return-abi.rs | 33 ++++++++++++++++ 3 files changed, 84 insertions(+), 21 deletions(-) create mode 100644 tests/codegen/uninhabited-transparent-return-abi.rs create mode 100644 tests/ui/uninhabited/uninhabited-transparent-return-abi.rs (limited to 'compiler/rustc_codegen_ssa/src') diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 0620f08fc73..49074996174 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -4,9 +4,7 @@ use rustc_abi::{BackendRepr, ExternAbi, HasDataLayout, Reg, WrappingRange}; use rustc_ast as ast; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_hir::lang_items::LangItem; -use rustc_middle::mir::{ - self, AssertKind, BasicBlock, InlineAsmMacro, SwitchTargets, UnwindTerminateReason, -}; +use rustc_middle::mir::{self, AssertKind, InlineAsmMacro, SwitchTargets, UnwindTerminateReason}; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf, ValidityRequirement}; use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; use rustc_middle::ty::{self, Instance, Ty}; @@ -942,7 +940,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { &fn_abi.ret, &mut llargs, Some(intrinsic), - target, ); let dest = match ret_dest { _ if fn_abi.ret.is_indirect() => llargs[0], @@ -998,19 +995,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }; let mut llargs = Vec::with_capacity(arg_count); - let destination = target.as_ref().map(|&target| { - ( - self.make_return_dest( - bx, - destination, - &fn_abi.ret, - &mut llargs, - None, - Some(target), - ), - target, - ) - }); + + // We still need to call `make_return_dest` even if there's no `target`, since + // `fn_abi.ret` could be `PassMode::Indirect`, even if it is uninhabited, + // and `make_return_dest` adds the return-place indirect pointer to `llargs`. + let return_dest = self.make_return_dest(bx, destination, &fn_abi.ret, &mut llargs, None); + let destination = target.map(|target| (return_dest, target)); // Split the rust-call tupled arguments off. let (first_args, untuple) = if abi == ExternAbi::RustCall && !args.is_empty() { @@ -1813,11 +1803,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { fn_ret: &ArgAbi<'tcx, Ty<'tcx>>, llargs: &mut Vec, intrinsic: Option, - target: Option, ) -> ReturnDest<'tcx, Bx::Value> { - if target.is_none() { - return ReturnDest::Nothing; - } // If the return is ignored, we can just return a do-nothing `ReturnDest`. if fn_ret.is_ignore() { return ReturnDest::Nothing; diff --git a/tests/codegen/uninhabited-transparent-return-abi.rs b/tests/codegen/uninhabited-transparent-return-abi.rs new file mode 100644 index 00000000000..6e8b1683163 --- /dev/null +++ b/tests/codegen/uninhabited-transparent-return-abi.rs @@ -0,0 +1,44 @@ +//@ compile-flags: -Copt-level=3 + +// See https://github.com/rust-lang/rust/issues/135802 + +#![crate_type = "lib"] + +enum Void {} + +// Should be ABI-compatible with T, but wasn't prior to the PR adding this test. +#[repr(transparent)] +struct NoReturn(T, Void); + +// Returned by invisible reference (in most ABIs) +#[allow(dead_code)] +struct Large(u64, u64, u64); + +extern "Rust" { + fn opaque() -> NoReturn; + fn opaque_with_arg(rsi: u32) -> NoReturn; +} + +// CHECK-LABEL: @test_uninhabited_ret_by_ref +#[no_mangle] +pub fn test_uninhabited_ret_by_ref() { + // CHECK: %_1 = alloca [24 x i8], align {{8|4}} + // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %_1) + // CHECK-NEXT: call void @opaque(ptr noalias nocapture noundef nonnull sret([24 x i8]) align {{8|4}} dereferenceable(24) %_1) #2 + // CHECK-NEXT: unreachable + unsafe { + opaque(); + } +} + +// CHECK-LABEL: @test_uninhabited_ret_by_ref_with_arg +#[no_mangle] +pub fn test_uninhabited_ret_by_ref_with_arg(rsi: u32) { + // CHECK: %_2 = alloca [24 x i8], align {{8|4}} + // CHECK-NEXT: call void @llvm.lifetime.start.p0(i64 24, ptr nonnull %_2) + // CHECK-NEXT: call void @opaque_with_arg(ptr noalias nocapture noundef nonnull sret([24 x i8]) align {{8|4}} dereferenceable(24) %_2, i32 noundef %rsi) #2 + // CHECK-NEXT: unreachable + unsafe { + opaque_with_arg(rsi); + } +} diff --git a/tests/ui/uninhabited/uninhabited-transparent-return-abi.rs b/tests/ui/uninhabited/uninhabited-transparent-return-abi.rs new file mode 100644 index 00000000000..2c2788a3e56 --- /dev/null +++ b/tests/ui/uninhabited/uninhabited-transparent-return-abi.rs @@ -0,0 +1,33 @@ +//@ run-pass +//@ needs-unwind +// See https://github.com/rust-lang/rust/issues/135802 + +enum Void {} + +// Should be ABI-compatible with T, but wasn't prior to the PR adding this test. +#[repr(transparent)] +struct NoReturn(T, Void); + +// Returned by invisible reference (in most ABIs) +#[allow(dead_code)] +struct Large(u64, u64, u64); + +// Prior to the PR adding this test, this function had a different ABI than +// `fn() -> Large` (on `x86_64-unknown-linux-gnu` at least), so calling it as `fn() -> Large` +// would pass the return place pointer in rdi and `correct` in rsi, but the function +// would expect `correct` in rdi. +fn never(correct: &mut bool) -> NoReturn { + *correct = true; + panic!("catch this") +} + +fn main() { + let mut correct = false; + let never: fn(&mut bool) -> NoReturn = never; + // Safety: `NoReturn` is a `repr(transparent)` wrapper around `Large`, + // so they should be ABI-compatible. + let never: fn(&mut bool) -> Large = unsafe { std::mem::transmute(never) }; + let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| never(&mut correct))); + assert!(result.is_err(), "function should have panicked"); + assert!(correct, "function should have stored `true` into `correct`"); +} -- cgit 1.4.1-3-g733a5