add x86-sse2 (32bit) ABI that requires SSE2 target feature · rust-lang/rust@2eff215 (original) (raw)
25 files changed
lines changed
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -2,8 +2,8 @@ use std::borrow::Cow; | ||
2 | 2 | use std::env; |
3 | 3 | |
4 | 4 | use crate::spec::{ |
5 | -Cc, DebuginfoKind, FloatAbi, FramePointer, LinkerFlavor, Lld, SplitDebuginfo, StackProbeType, | |
6 | -StaticCow, TargetOptions, cvs, | |
5 | +Cc, DebuginfoKind, FloatAbi, FramePointer, LinkerFlavor, Lld, RustcAbi, SplitDebuginfo, | |
6 | +StackProbeType, StaticCow, TargetOptions, cvs, | |
7 | 7 | }; |
8 | 8 | |
9 | 9 | #[cfg(test)] |
@@ -103,7 +103,7 @@ pub(crate) fn base( | ||
103 | 103 | arch: Arch, |
104 | 104 | abi: TargetAbi, |
105 | 105 | ) -> (TargetOptions, StaticCow<str>, StaticCow<str>) { |
106 | -let opts = TargetOptions { | |
106 | +let mut opts = TargetOptions { | |
107 | 107 | abi: abi.target_abi().into(), |
108 | 108 | llvm_floatabi: Some(FloatAbi::Hard), |
109 | 109 | os: os.into(), |
@@ -154,6 +154,10 @@ pub(crate) fn base( | ||
154 | 154 | |
155 | 155 | ..Default::default() |
156 | 156 | }; |
157 | +if matches!(arch, Arch::I386 | Arch::I686) { | |
158 | +// All Apple x86-32 targets have SSE2. | |
159 | + opts.rustc_abi = Some(RustcAbi::X86Sse2); | |
160 | +} | |
157 | 161 | (opts, unversioned_llvm_target(os, arch, abi), arch.target_arch()) |
158 | 162 | } |
159 | 163 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1109,6 +1109,8 @@ impl ToJson for FloatAbi { | ||
1109 | 1109 | /// The Rustc-specific variant of the ABI used for this target. |
1110 | 1110 | #[derive(Clone, Copy, PartialEq, Hash, Debug)] |
1111 | 1111 | pub enum RustcAbi { |
1112 | +/// On x86-32 only: make use of SSE and SSE2 for ABI purposes. | |
1113 | + X86Sse2, | |
1112 | 1114 | /// On x86-32/64 only: do not use any FPU or SIMD registers for the ABI. |
1113 | 1115 | X86Softfloat, |
1114 | 1116 | } |
@@ -1118,6 +1120,7 @@ impl FromStr for RustcAbi { | ||
1118 | 1120 | |
1119 | 1121 | fn from_str(s: &str) -> Result<RustcAbi, ()> { |
1120 | 1122 | Ok(match s { |
1123 | +"x86-sse2" => RustcAbi::X86Sse2, | |
1121 | 1124 | "x86-softfloat" => RustcAbi::X86Softfloat, |
1122 | 1125 | _ => return Err(()), |
1123 | 1126 | }) |
@@ -1127,6 +1130,7 @@ impl FromStr for RustcAbi { | ||
1127 | 1130 | impl ToJson for RustcAbi { |
1128 | 1131 | fn to_json(&self) -> Json { |
1129 | 1132 | match *self { |
1133 | +RustcAbi::X86Sse2 => "x86-sse2", | |
1130 | 1134 | RustcAbi::X86Softfloat => "x86-softfloat", |
1131 | 1135 | } |
1132 | 1136 | .to_json() |
@@ -3264,6 +3268,11 @@ impl Target { | ||
3264 | 3268 | // Check consistency of Rust ABI declaration. |
3265 | 3269 | if let Some(rust_abi) = self.rustc_abi { |
3266 | 3270 | match rust_abi { |
3271 | +RustcAbi::X86Sse2 => check_matches!( | |
3272 | +&*self.arch, | |
3273 | +"x86", | |
3274 | +"`x86-sse2` ABI is only valid for x86-32 targets" | |
3275 | +), | |
3267 | 3276 | RustcAbi::X86Softfloat => check_matches!( |
3268 | 3277 | &*self.arch, |
3269 | 3278 | "x86" | "x86_64", |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,5 @@ | ||
1 | 1 | use crate::spec::base::nto_qnx; |
2 | -use crate::spec::{StackProbeType, Target, TargetOptions, base}; | |
2 | +use crate::spec::{RustcAbi, StackProbeType, Target, TargetOptions, base}; | |
3 | 3 | |
4 | 4 | pub(crate) fn target() -> Target { |
5 | 5 | let mut meta = nto_qnx::meta(); |
@@ -14,6 +14,7 @@ pub(crate) fn target() -> Target { | ||
14 | 14 | .into(), |
15 | 15 | arch: "x86".into(), |
16 | 16 | options: TargetOptions { |
17 | +rustc_abi: Some(RustcAbi::X86Sse2), | |
17 | 18 | cpu: "pentium4".into(), |
18 | 19 | max_atomic_width: Some(64), |
19 | 20 | pre_link_args: nto_qnx::pre_link_args( |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -2,6 +2,7 @@ use crate::spec::Target; | ||
2 | 2 | |
3 | 3 | pub(crate) fn target() -> Target { |
4 | 4 | let mut base = super::i686_unknown_linux_gnu::target(); |
5 | + base.rustc_abi = None; // overwrite the SSE2 ABI set by the base target | |
5 | 6 | base.cpu = "pentium".into(); |
6 | 7 | base.llvm_target = "i586-unknown-linux-gnu".into(); |
7 | 8 | base |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -2,6 +2,7 @@ use crate::spec::Target; | ||
2 | 2 | |
3 | 3 | pub(crate) fn target() -> Target { |
4 | 4 | let mut base = super::i686_unknown_linux_musl::target(); |
5 | + base.rustc_abi = None; // overwrite the SSE2 ABI set by the base target | |
5 | 6 | base.cpu = "pentium".into(); |
6 | 7 | base.llvm_target = "i586-unknown-linux-musl".into(); |
7 | 8 | // FIXME(compiler-team#422): musl targets should be dynamically linked by default. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
1 | -use crate::spec::{SanitizerSet, StackProbeType, Target, TargetOptions, base}; | |
1 | +use crate::spec::{RustcAbi, SanitizerSet, StackProbeType, Target, TargetOptions, base}; | |
2 | 2 | |
3 | 3 | // See https://developer.android.com/ndk/guides/abis.html#x86 |
4 | 4 | // for target ABI requirements. |
@@ -8,6 +8,7 @@ pub(crate) fn target() -> Target { | ||
8 | 8 | |
9 | 9 | base.max_atomic_width = Some(64); |
10 | 10 | |
11 | + base.rustc_abi = Some(RustcAbi::X86Sse2); | |
11 | 12 | // https://developer.android.com/ndk/guides/abis.html#x86 |
12 | 13 | base.cpu = "pentium4".into(); |
13 | 14 | base.features = "+mmx,+sse,+sse2,+sse3,+ssse3".into(); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,8 @@ | ||
1 | -use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target, base}; | |
1 | +use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, RustcAbi, Target, base}; | |
2 | 2 | |
3 | 3 | pub(crate) fn target() -> Target { |
4 | 4 | let mut base = base::windows_gnu::opts(); |
5 | + base.rustc_abi = Some(RustcAbi::X86Sse2); | |
5 | 6 | base.cpu = "pentium4".into(); |
6 | 7 | base.max_atomic_width = Some(64); |
7 | 8 | base.frame_pointer = FramePointer::Always; // Required for backtraces |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,8 @@ | ||
1 | -use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target, base}; | |
1 | +use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, RustcAbi, Target, base}; | |
2 | 2 | |
3 | 3 | pub(crate) fn target() -> Target { |
4 | 4 | let mut base = base::windows_gnullvm::opts(); |
5 | + base.rustc_abi = Some(RustcAbi::X86Sse2); | |
5 | 6 | base.cpu = "pentium4".into(); |
6 | 7 | base.max_atomic_width = Some(64); |
7 | 8 | base.frame_pointer = FramePointer::Always; // Required for backtraces |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,8 @@ | ||
1 | -use crate::spec::{LinkerFlavor, Lld, SanitizerSet, Target, base}; | |
1 | +use crate::spec::{LinkerFlavor, Lld, RustcAbi, SanitizerSet, Target, base}; | |
2 | 2 | |
3 | 3 | pub(crate) fn target() -> Target { |
4 | 4 | let mut base = base::windows_msvc::opts(); |
5 | + base.rustc_abi = Some(RustcAbi::X86Sse2); | |
5 | 6 | base.cpu = "pentium4".into(); |
6 | 7 | base.max_atomic_width = Some(64); |
7 | 8 | base.supported_sanitizers = SanitizerSet::ADDRESS; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,8 @@ | ||
1 | -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, base}; | |
1 | +use crate::spec::{Cc, LinkerFlavor, Lld, RustcAbi, StackProbeType, Target, base}; | |
2 | 2 | |
3 | 3 | pub(crate) fn target() -> Target { |
4 | 4 | let mut base = base::freebsd::opts(); |
5 | + base.rustc_abi = Some(RustcAbi::X86Sse2); | |
5 | 6 | base.cpu = "pentium4".into(); |
6 | 7 | base.max_atomic_width = Some(64); |
7 | 8 | base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32", "-Wl,-znotext"]); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,8 @@ | ||
1 | -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, base}; | |
1 | +use crate::spec::{Cc, LinkerFlavor, Lld, RustcAbi, StackProbeType, Target, base}; | |
2 | 2 | |
3 | 3 | pub(crate) fn target() -> Target { |
4 | 4 | let mut base = base::haiku::opts(); |
5 | + base.rustc_abi = Some(RustcAbi::X86Sse2); | |
5 | 6 | base.cpu = "pentium4".into(); |
6 | 7 | base.max_atomic_width = Some(64); |
7 | 8 | base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32"]); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,19 @@ | ||
1 | -use crate::spec::{Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target, base}; | |
1 | +use crate::spec::{Cc, LinkerFlavor, Lld, RustcAbi, SanitizerSet, StackProbeType, Target, base}; | |
2 | 2 | |
3 | 3 | pub(crate) fn target() -> Target { |
4 | 4 | let mut base = base::linux_gnu::opts(); |
5 | + base.rustc_abi = Some(RustcAbi::X86Sse2); | |
6 | +// Dear distribution packager, if you are changing the base CPU model with the goal of removing | |
7 | +// the SSE2 requirement, make sure to also set the `rustc_abi` to `None` above or else the compiler | |
8 | +// will complain that the chosen ABI cannot be realized with the given CPU features. | |
9 | +// Also note that x86 without SSE2 is *not* considered a Tier 1 target by the Rust project, and | |
10 | +// it has some known floating-point correctness issues mostly caused by a lack of people caring | |
11 | +// for LLVM's x87 support (double-rounding, value truncation; see | |
12 | +// https://github.com/rust-lang/rust/issues/114479 for details). This can lead to incorrect | |
13 | +// math (Rust generally promises exact math, so this can break code in unexpected ways) and it | |
14 | +// can lead to memory safety violations if floating-point values are used e.g. to access an | |
15 | +// array. If users run into such issues and report bugs upstream and then it turns out that the | |
16 | +// bugs are caused by distribution patches, that leads to confusion and frustration. | |
5 | 17 | base.cpu = "pentium4".into(); |
6 | 18 | base.max_atomic_width = Some(64); |
7 | 19 | base.supported_sanitizers = SanitizerSet::ADDRESS; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,10 @@ | ||
1 | -use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, StackProbeType, Target, base}; | |
1 | +use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, RustcAbi, StackProbeType, Target, base}; | |
2 | 2 | |
3 | 3 | pub(crate) fn target() -> Target { |
4 | 4 | let mut base = base::linux_musl::opts(); |
5 | + base.rustc_abi = Some(RustcAbi::X86Sse2); | |
6 | +// If you want to change the base CPU, please see `i686_unknown_linux_gnu.rs` | |
7 | +// for an important comment. | |
5 | 8 | base.cpu = "pentium4".into(); |
6 | 9 | base.max_atomic_width = Some(64); |
7 | 10 | base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32", "-Wl,-melf_i386"]); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,8 @@ | ||
1 | -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions, base}; | |
1 | +use crate::spec::{Cc, LinkerFlavor, Lld, RustcAbi, StackProbeType, Target, TargetOptions, base}; | |
2 | 2 | |
3 | 3 | pub(crate) fn target() -> Target { |
4 | 4 | let mut base = base::netbsd::opts(); |
5 | + base.rustc_abi = Some(RustcAbi::X86Sse2); | |
5 | 6 | base.cpu = "pentium4".into(); |
6 | 7 | base.max_atomic_width = Some(64); |
7 | 8 | base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32"]); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,8 @@ | ||
1 | -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, base}; | |
1 | +use crate::spec::{Cc, LinkerFlavor, Lld, RustcAbi, StackProbeType, Target, base}; | |
2 | 2 | |
3 | 3 | pub(crate) fn target() -> Target { |
4 | 4 | let mut base = base::openbsd::opts(); |
5 | + base.rustc_abi = Some(RustcAbi::X86Sse2); | |
5 | 6 | base.cpu = "pentium4".into(); |
6 | 7 | base.max_atomic_width = Some(64); |
7 | 8 | base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32", "-fuse-ld=lld"]); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,8 @@ | ||
1 | -use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target, base}; | |
1 | +use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, RustcAbi, Target, base}; | |
2 | 2 | |
3 | 3 | pub(crate) fn target() -> Target { |
4 | 4 | let mut base = base::windows_uwp_gnu::opts(); |
5 | + base.rustc_abi = Some(RustcAbi::X86Sse2); | |
5 | 6 | base.cpu = "pentium4".into(); |
6 | 7 | base.max_atomic_width = Some(64); |
7 | 8 | base.frame_pointer = FramePointer::Always; // Required for backtraces |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,8 @@ | ||
1 | -use crate::spec::{Target, base}; | |
1 | +use crate::spec::{RustcAbi, Target, base}; | |
2 | 2 | |
3 | 3 | pub(crate) fn target() -> Target { |
4 | 4 | let mut base = base::windows_uwp_msvc::opts(); |
5 | + base.rustc_abi = Some(RustcAbi::X86Sse2); | |
5 | 6 | base.cpu = "pentium4".into(); |
6 | 7 | base.max_atomic_width = Some(64); |
7 | 8 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,9 @@ | ||
1 | -use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target, base}; | |
1 | +use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, RustcAbi, Target, base}; | |
2 | 2 | |
3 | 3 | pub(crate) fn target() -> Target { |
4 | 4 | let mut base = base::windows_gnu::opts(); |
5 | 5 | base.vendor = "win7".into(); |
6 | + base.rustc_abi = Some(RustcAbi::X86Sse2); | |
6 | 7 | base.cpu = "pentium4".into(); |
7 | 8 | base.max_atomic_width = Some(64); |
8 | 9 | base.frame_pointer = FramePointer::Always; // Required for backtraces |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,9 @@ | ||
1 | -use crate::spec::{LinkerFlavor, Lld, SanitizerSet, Target, base}; | |
1 | +use crate::spec::{LinkerFlavor, Lld, RustcAbi, SanitizerSet, Target, base}; | |
2 | 2 | |
3 | 3 | pub(crate) fn target() -> Target { |
4 | 4 | let mut base = base::windows_msvc::opts(); |
5 | 5 | base.vendor = "win7".into(); |
6 | + base.rustc_abi = Some(RustcAbi::X86Sse2); | |
6 | 7 | base.cpu = "pentium4".into(); |
7 | 8 | base.max_atomic_width = Some(64); |
8 | 9 | base.supported_sanitizers = SanitizerSet::ADDRESS; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,8 @@ | ||
1 | -use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, base}; | |
1 | +use crate::spec::{Cc, LinkerFlavor, Lld, RustcAbi, StackProbeType, Target, base}; | |
2 | 2 | |
3 | 3 | pub(crate) fn target() -> Target { |
4 | 4 | let mut base = base::vxworks::opts(); |
5 | + base.rustc_abi = Some(RustcAbi::X86Sse2); | |
5 | 6 | base.cpu = "pentium4".into(); |
6 | 7 | base.max_atomic_width = Some(64); |
7 | 8 | base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m32"]); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -790,6 +790,13 @@ impl Target { | ||
790 | 790 | // x87 must be enabled, soft-float must be disabled. |
791 | 791 | FeatureConstraints { required: &["x87"], incompatible: &["soft-float"] } |
792 | 792 | } |
793 | +Some(RustcAbi::X86Sse2) => { | |
794 | +// Extended hardfloat ABI. x87 and SSE2 must be enabled, soft-float must be disabled. | |
795 | +FeatureConstraints { | |
796 | +required: &["x87", "sse2"], | |
797 | +incompatible: &["soft-float"], | |
798 | +} | |
799 | +} | |
793 | 800 | Some(RustcAbi::X86Softfloat) => { |
794 | 801 | // Softfloat ABI, requires corresponding target feature. That feature trumps |
795 | 802 | // `x87` and all other FPU features so those do not matter. |
@@ -817,6 +824,7 @@ impl Target { | ||
817 | 824 | // LLVM handles the rest. |
818 | 825 | FeatureConstraints { required: &["soft-float"], incompatible: &[] } |
819 | 826 | } |
827 | +Some(r) => panic!("invalid Rust ABI for x86_64: {r:?}"), | |
820 | 828 | } |
821 | 829 | } |
822 | 830 | "arm" => { |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
1 | +warning: target feature `sse2` must be enabled to ensure that the ABI of the current target can be implemented correctly | |
2 | + | | |
3 | + = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
4 | + = note: for more information, see issue #116344 https://github.com/rust-lang/rust/issues/116344 | |
5 | + |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
1 | 1 | //! Ensure we trigger abi_unsupported_vector_types for target features that are usually enabled |
2 | 2 | //! on a target, but disabled in this file via a `-C` flag. |
3 | -//@ compile-flags: --crate-type=rlib --target=i686-unknown-linux-gnu -C target-feature=-sse,-sse2 | |
3 | +//@ compile-flags: --crate-type=rlib --target=i586-unknown-linux-gnu -C target-feature=-sse,-sse2 | |
4 | 4 | //@ build-pass |
5 | 5 | //@ ignore-pass (test emits codegen-time warnings) |
6 | 6 | //@ needs-llvm-components: x86 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
1 | +//@ compile-flags: --target=i686-unknown-linux-gnu --crate-type=lib | |
2 | +//@ needs-llvm-components: x86 | |
3 | +//@ compile-flags: -Ctarget-cpu=pentium | |
4 | +// For now this is just a warning. | |
5 | +//@ build-pass | |
6 | +//@error-pattern: must be enabled | |
7 | + | |
8 | +#![feature(no_core, lang_items)] | |
9 | +#![no_core] | |
10 | + | |
11 | +#[lang = "sized"] | |
12 | +pub trait Sized {} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
1 | +warning: target feature `sse2` must be enabled to ensure that the ABI of the current target can be implemented correctly | |
2 | + | | |
3 | + = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! | |
4 | + = note: for more information, see issue #116344 https://github.com/rust-lang/rust/issues/116344 | |
5 | + | |
6 | +warning: 1 warning emitted | |
7 | + |