From 2bf27e09beb4cd1c5f01369e7086e36b3de04f5c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 26 Dec 2024 18:32:22 +0100 Subject: explicitly model that certain ABIs require/forbid certain target features --- tests/codegen/tied-features-strength.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'tests/codegen') diff --git a/tests/codegen/tied-features-strength.rs b/tests/codegen/tied-features-strength.rs index 1b2b63c3d1a..4d96a7cde78 100644 --- a/tests/codegen/tied-features-strength.rs +++ b/tests/codegen/tied-features-strength.rs @@ -1,5 +1,5 @@ // ignore-tidy-linelength -//@ revisions: ENABLE_SVE DISABLE_SVE DISABLE_NEON ENABLE_NEON +//@ revisions: ENABLE_SVE DISABLE_SVE ENABLE_NEON //@ compile-flags: --crate-type=rlib --target=aarch64-unknown-linux-gnu //@ needs-llvm-components: aarch64 @@ -11,9 +11,10 @@ // ENABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+fpmr,?)?|(\+sve,?)|(\+neon,?)|(\+fp-armv8,?))*}}" } //@ [DISABLE_SVE] compile-flags: -C target-feature=-sve -Copt-level=0 -// DISABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+fpmr,?)?|(-sve,?)|(\+neon,?))*}}" } +// DISABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+fpmr,?)?|(-sve,?)|(\+neon,?)|(\+fp-armv8,?))*}}" } -//@ [DISABLE_NEON] compile-flags: -C target-feature=-neon -Copt-level=0 +// The DISABLE_NEON is disabled since neon is a required target feature for this targt, it cannot be disabled. +// it would have: compile-flags: -C target-feature=-neon -Copt-level=0 // DISABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+fpmr,?)?|(-fp-armv8,?)|(-neon,?))*}}" } //@ [ENABLE_NEON] compile-flags: -C target-feature=+neon -Copt-level=0 -- cgit 1.4.1-3-g733a5 From eb527424a5f0206a464d0968387d85636ac9d305 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 26 Dec 2024 19:47:41 +0100 Subject: x86-64 hardfloat actually requires sse2 --- compiler/rustc_codegen_gcc/src/gcc_util.rs | 18 ++++++++++++------ compiler/rustc_codegen_llvm/src/llvm_util.rs | 19 +++++++++++++------ compiler/rustc_target/src/target_features.rs | 11 ++++++++++- tests/codegen/target-feature-overrides.rs | 4 ++-- ...n-hardfloat-target-feature-flag-disable-implied.rs | 10 ++++++++++ ...rdfloat-target-feature-flag-disable-implied.stderr | 7 +++++++ 6 files changed, 54 insertions(+), 15 deletions(-) create mode 100644 tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable-implied.rs create mode 100644 tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable-implied.stderr (limited to 'tests/codegen') diff --git a/compiler/rustc_codegen_gcc/src/gcc_util.rs b/compiler/rustc_codegen_gcc/src/gcc_util.rs index b0fd07827d6..3e579d75d86 100644 --- a/compiler/rustc_codegen_gcc/src/gcc_util.rs +++ b/compiler/rustc_codegen_gcc/src/gcc_util.rs @@ -129,12 +129,18 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec { + "x86" => { // We support 2 ABIs, hardfloat (default) and softfloat. if self.has_feature("soft-float") { NOTHING @@ -762,6 +762,15 @@ impl Target { (&["x87"], &[]) } } + "x86_64" => { + // We support 2 ABIs, hardfloat (default) and softfloat. + if self.has_feature("soft-float") { + NOTHING + } else { + // Hardfloat ABI. x87 and SSE2 must be enabled. + (&["x87", "sse2"], &[]) + } + } "arm" => { // We support 2 ABIs, hardfloat (default) and softfloat. if self.has_feature("soft-float") { diff --git a/tests/codegen/target-feature-overrides.rs b/tests/codegen/target-feature-overrides.rs index f38a1ae72de..c4f9a8898a1 100644 --- a/tests/codegen/target-feature-overrides.rs +++ b/tests/codegen/target-feature-overrides.rs @@ -40,7 +40,7 @@ pub unsafe fn banana() -> u32 { // CHECK: attributes [[APPLEATTRS]] // COMPAT-SAME: "target-features"="+avx,+avx2,{{.*}}" -// INCOMPAT-SAME: "target-features"="-avx2,-avx,+avx,{{.*}}" +// INCOMPAT-SAME: "target-features"="-avx2,-avx,+x87,+sse2,+avx,{{.*}}" // CHECK: attributes [[BANANAATTRS]] // COMPAT-SAME: "target-features"="+avx,+avx2,{{.*}}" -// INCOMPAT-SAME: "target-features"="-avx2,-avx" +// INCOMPAT-SAME: "target-features"="-avx2,-avx,+x87,+sse2" diff --git a/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable-implied.rs b/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable-implied.rs new file mode 100644 index 00000000000..3d09217327a --- /dev/null +++ b/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable-implied.rs @@ -0,0 +1,10 @@ +//@ compile-flags: --target=x86_64-unknown-linux-gnu --crate-type=lib +//@ needs-llvm-components: x86 +//@ compile-flags: -Ctarget-feature=-sse +// For now this is just a warning. +//@ build-pass +#![feature(no_core, lang_items)] +#![no_core] + +#[lang = "sized"] +pub trait Sized {} diff --git a/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable-implied.stderr b/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable-implied.stderr new file mode 100644 index 00000000000..72b2d03fe20 --- /dev/null +++ b/tests/ui/target-feature/forbidden-hardfloat-target-feature-flag-disable-implied.stderr @@ -0,0 +1,7 @@ +warning: target feature `sse` cannot be disabled with `-Ctarget-feature`: this feature is required by the target ABI + | + = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116344 + +warning: 1 warning emitted + -- cgit 1.4.1-3-g733a5 From 912b7291d0f8f477388282a04ccf085d1b3715b0 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 27 Dec 2024 22:19:55 +0100 Subject: add ABI target features *before* -Ctarget-features --- compiler/rustc_codegen_gcc/src/gcc_util.rs | 12 ++++++------ compiler/rustc_codegen_llvm/src/llvm_util.rs | 12 ++++++------ compiler/rustc_target/src/target_features.rs | 3 +++ tests/codegen/target-feature-overrides.rs | 8 ++++---- 4 files changed, 19 insertions(+), 16 deletions(-) (limited to 'tests/codegen') diff --git a/compiler/rustc_codegen_gcc/src/gcc_util.rs b/compiler/rustc_codegen_gcc/src/gcc_util.rs index 3e579d75d86..e9dfb4e4cf4 100644 --- a/compiler/rustc_codegen_gcc/src/gcc_util.rs +++ b/compiler/rustc_codegen_gcc/src/gcc_util.rs @@ -154,12 +154,12 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec u32 { } // CHECK: attributes [[APPLEATTRS]] -// COMPAT-SAME: "target-features"="+avx,+avx2,{{.*}}" -// INCOMPAT-SAME: "target-features"="-avx2,-avx,+x87,+sse2,+avx,{{.*}}" +// COMPAT-SAME: "target-features"="+x87,+sse2,+avx,+avx2,{{.*}}" +// INCOMPAT-SAME: "target-features"="+x87,+sse2,-avx2,-avx,+avx,{{.*}}" // CHECK: attributes [[BANANAATTRS]] -// COMPAT-SAME: "target-features"="+avx,+avx2,{{.*}}" -// INCOMPAT-SAME: "target-features"="-avx2,-avx,+x87,+sse2" +// COMPAT-SAME: "target-features"="+x87,+sse2,+avx,+avx2,{{.*}}" +// INCOMPAT-SAME: "target-features"="+x87,+sse2,-avx2,-avx" -- cgit 1.4.1-3-g733a5 From 43ede97ebf7d874c9076723840c945b051b10ee2 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 31 Dec 2024 12:20:30 +0100 Subject: arm: use target.llvm_floatabi over soft-float target feature --- compiler/rustc_target/src/target_features.rs | 29 +++++++++++++++++++--------- tests/codegen/tied-features-strength.rs | 8 ++++---- tests/run-make/simd-ffi/rmake.rs | 2 +- 3 files changed, 25 insertions(+), 14 deletions(-) (limited to 'tests/codegen') diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index b5e30c4d5c9..142ac0ff3d3 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -5,7 +5,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_span::{Symbol, sym}; -use crate::spec::Target; +use crate::spec::{FloatAbi, Target}; /// Features that control behaviour of rustc, rather than the codegen. /// These exist globally and are not in the target-specific lists below. @@ -148,7 +148,6 @@ const ARM_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("neon", Unstable(sym::arm_target_feature), &["vfp3"]), ("rclass", Unstable(sym::arm_target_feature), &[]), ("sha2", Unstable(sym::arm_target_feature), &["neon"]), - ("soft-float", Stability::Forbidden { reason: "unsound because it changes float ABI" }, &[]), // This is needed for inline assembly, but shouldn't be stabilized as-is // since it should be enabled per-function using #[instruction_set], not // #[target_feature]. @@ -204,6 +203,7 @@ const AARCH64_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("flagm", Stable, &[]), // FEAT_FLAGM2 ("flagm2", Unstable(sym::aarch64_unstable_target_feature), &[]), + // We forbid directly toggling just `fp-armv8`; it must be toggled with `neon`. ("fp-armv8", Stability::Forbidden { reason: "Rust ties `fp-armv8` to `neon`" }, &[]), // FEAT_FP16 // Rust ties FP and Neon: https://github.com/rust-lang/rust/pull/91608 @@ -758,6 +758,7 @@ impl Target { match &*self.arch { "x86" => { // We support 2 ABIs, hardfloat (default) and softfloat. + // x86 has no sane ABI indicator so we have to use the target feature. if self.has_feature("soft-float") { NOTHING } else { @@ -767,6 +768,7 @@ impl Target { } "x86_64" => { // We support 2 ABIs, hardfloat (default) and softfloat. + // x86 has no sane ABI indicator so we have to use the target feature. if self.has_feature("soft-float") { NOTHING } else { @@ -775,20 +777,27 @@ impl Target { } } "arm" => { - // We support 2 ABIs, hardfloat (default) and softfloat. - if self.has_feature("soft-float") { - NOTHING - } else { - // Hardfloat ABI. x87 must be enabled. - (&["fpregs"], &[]) + // On ARM, ABI handling is reasonably sane; we use `llvm_floatabi` to indicate + // to LLVM which ABI we are going for. + match self.llvm_floatabi.unwrap() { + FloatAbi::Soft => { + // Nothing special required, will use soft-float ABI throughout. + NOTHING + } + FloatAbi::Hard => { + // Must have `fpregs` and must not have `soft-float`. + (&["fpregs"], &["soft-float"]) + } } } "aarch64" | "arm64ec" => { + // Aarch64 has no sane ABI specifier, and LLVM doesn't even have a way to force + // the use of soft-float, so all we can do here is some crude hacks. match &*self.abi { "softfloat" => { // This is not fully correct, LLVM actually doesn't let us enforce the softfloat // ABI properly... see . - // FIXME: should be forbid "neon" here? But that would be a breaking change. + // FIXME: should we forbid "neon" here? But that would be a breaking change. NOTHING } _ => { @@ -799,6 +808,8 @@ impl Target { } } "riscv32" | "riscv64" => { + // RISC-V handles ABI in a very sane way, being fully explicit via `llvm_abiname` + // about what the intended ABI is. match &*self.llvm_abiname { "ilp32d" | "lp64d" => { // Requires d (which implies f), incompatible with e. diff --git a/tests/codegen/tied-features-strength.rs b/tests/codegen/tied-features-strength.rs index 4d96a7cde78..6daa5cd7d5e 100644 --- a/tests/codegen/tied-features-strength.rs +++ b/tests/codegen/tied-features-strength.rs @@ -1,5 +1,5 @@ // ignore-tidy-linelength -//@ revisions: ENABLE_SVE DISABLE_SVE ENABLE_NEON +//@ revisions: ENABLE_SVE DISABLE_SVE DISABLE_NEON ENABLE_NEON //@ compile-flags: --crate-type=rlib --target=aarch64-unknown-linux-gnu //@ needs-llvm-components: aarch64 @@ -13,9 +13,9 @@ //@ [DISABLE_SVE] compile-flags: -C target-feature=-sve -Copt-level=0 // DISABLE_SVE: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+fpmr,?)?|(-sve,?)|(\+neon,?)|(\+fp-armv8,?))*}}" } -// The DISABLE_NEON is disabled since neon is a required target feature for this targt, it cannot be disabled. -// it would have: compile-flags: -C target-feature=-neon -Copt-level=0 -// DISABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+fpmr,?)?|(-fp-armv8,?)|(-neon,?))*}}" } +//@ [DISABLE_NEON] compile-flags: -C target-feature=-neon -Copt-level=0 +// `neon` and `fp-armv8` get enabled as target base features, but then disabled again at the end of the list. +// DISABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+fp-armv8,?)|(\+neon,?))*}},-neon,-fp-armv8{{(,\+fpmr)?}}" } //@ [ENABLE_NEON] compile-flags: -C target-feature=+neon -Copt-level=0 // ENABLE_NEON: attributes #0 = { {{.*}} "target-features"="{{((\+outline-atomics,?)|(\+v8a,?)|(\+fpmr,?)?|(\+fp-armv8,?)|(\+neon,?))*}}" } diff --git a/tests/run-make/simd-ffi/rmake.rs b/tests/run-make/simd-ffi/rmake.rs index 04990c8bdf4..ef71dfa4c30 100644 --- a/tests/run-make/simd-ffi/rmake.rs +++ b/tests/run-make/simd-ffi/rmake.rs @@ -56,7 +56,7 @@ fn main() { .target(&target) .emit("llvm-ir,asm") .input("simd.rs") - .arg("-Ctarget-feature=+neon,+sse") + .arg("-Ctarget-feature=-soft-float,+neon,+sse") .arg(&format!("-Cextra-filename=-{target}")) .run(); } -- cgit 1.4.1-3-g733a5 From d42c3ae02f4c54fe3bdac7e0cc49c3c51e8fb517 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sun, 5 Jan 2025 01:17:07 +0000 Subject: Merge the intrinsic and user tests for `select_unpredictable` [1] mentions that having a single test with `-Zmerge-functions=disabled` is preferable to having two separate tests. Apply that to the new `select_unpredicatble` test here. [1]: https://github.com/rust-lang/rust/pull/133964#issuecomment-2569693325 --- tests/codegen/bool-select-unpredictable.rs | 35 ------------------------ tests/codegen/intrinsics/select_unpredictable.rs | 34 ++++++++++++++++++++++- 2 files changed, 33 insertions(+), 36 deletions(-) delete mode 100644 tests/codegen/bool-select-unpredictable.rs (limited to 'tests/codegen') diff --git a/tests/codegen/bool-select-unpredictable.rs b/tests/codegen/bool-select-unpredictable.rs deleted file mode 100644 index 1562b177542..00000000000 --- a/tests/codegen/bool-select-unpredictable.rs +++ /dev/null @@ -1,35 +0,0 @@ -//@ compile-flags: -O - -#![feature(select_unpredictable)] -#![crate_type = "lib"] - -#[no_mangle] -pub fn test_int(p: bool, a: u64, b: u64) -> u64 { - // CHECK-LABEL: define{{.*}} @test_int - // CHECK: select i1 %p, i64 %a, i64 %b, !unpredictable - p.select_unpredictable(a, b) -} - -#[no_mangle] -pub fn test_pair(p: bool, a: (u64, u64), b: (u64, u64)) -> (u64, u64) { - // CHECK-LABEL: define{{.*}} @test_pair - // CHECK: select i1 %p, {{.*}}, !unpredictable - p.select_unpredictable(a, b) -} - -struct Large { - e: [u64; 100], -} - -#[no_mangle] -pub fn test_struct(p: bool, a: Large, b: Large) -> Large { - // CHECK-LABEL: define{{.*}} @test_struct - // CHECK: select i1 %p, {{.*}}, !unpredictable - p.select_unpredictable(a, b) -} - -#[no_mangle] -pub fn test_zst(p: bool, a: (), b: ()) -> () { - // CHECK-LABEL: define{{.*}} @test_zst - p.select_unpredictable(a, b) -} diff --git a/tests/codegen/intrinsics/select_unpredictable.rs b/tests/codegen/intrinsics/select_unpredictable.rs index 2054838dd79..b03c9708b8e 100644 --- a/tests/codegen/intrinsics/select_unpredictable.rs +++ b/tests/codegen/intrinsics/select_unpredictable.rs @@ -1,8 +1,11 @@ -//@ compile-flags: -O +//@ compile-flags: -O -Zmerge-functions=disabled #![feature(core_intrinsics)] +#![feature(select_unpredictable)] #![crate_type = "lib"] +/* Test the intrinsic */ + #[no_mangle] pub fn test_int(p: bool, a: u64, b: u64) -> u64 { // CHECK-LABEL: define{{.*}} @test_int @@ -33,3 +36,32 @@ pub fn test_zst(p: bool, a: (), b: ()) -> () { // CHECK-LABEL: define{{.*}} @test_zst core::intrinsics::select_unpredictable(p, a, b) } + +/* Test the user-facing version */ + +#[no_mangle] +pub fn test_int2(p: bool, a: u64, b: u64) -> u64 { + // CHECK-LABEL: define{{.*}} @test_int2 + // CHECK: select i1 %p, i64 %a, i64 %b, !unpredictable + p.select_unpredictable(a, b) +} + +#[no_mangle] +pub fn test_pair2(p: bool, a: (u64, u64), b: (u64, u64)) -> (u64, u64) { + // CHECK-LABEL: define{{.*}} @test_pair2 + // CHECK: select i1 %p, {{.*}}, !unpredictable + p.select_unpredictable(a, b) +} + +#[no_mangle] +pub fn test_struct2(p: bool, a: Large, b: Large) -> Large { + // CHECK-LABEL: define{{.*}} @test_struct2 + // CHECK: select i1 %p, {{.*}}, !unpredictable + p.select_unpredictable(a, b) +} + +#[no_mangle] +pub fn test_zst2(p: bool, a: (), b: ()) -> () { + // CHECK-LABEL: define{{.*}} @test_zst2 + p.select_unpredictable(a, b) +} -- cgit 1.4.1-3-g733a5 From 74d2d4bfa475a131df0c9ee0754b022a458cd152 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Sun, 5 Jan 2025 08:44:01 +0000 Subject: Expand the `select_unpredictable` test for ZSTs For ZSTs there is no selection that needs to take place, so assert that no `select` statement is emitted. --- tests/codegen/intrinsics/select_unpredictable.rs | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'tests/codegen') diff --git a/tests/codegen/intrinsics/select_unpredictable.rs b/tests/codegen/intrinsics/select_unpredictable.rs index b03c9708b8e..ea6127a48bf 100644 --- a/tests/codegen/intrinsics/select_unpredictable.rs +++ b/tests/codegen/intrinsics/select_unpredictable.rs @@ -31,9 +31,12 @@ pub fn test_struct(p: bool, a: Large, b: Large) -> Large { core::intrinsics::select_unpredictable(p, a, b) } +// ZSTs should not need a `select` expression. #[no_mangle] pub fn test_zst(p: bool, a: (), b: ()) -> () { // CHECK-LABEL: define{{.*}} @test_zst + // CHECK-NEXT: start: + // CHECK-NEXT: ret void core::intrinsics::select_unpredictable(p, a, b) } @@ -63,5 +66,7 @@ pub fn test_struct2(p: bool, a: Large, b: Large) -> Large { #[no_mangle] pub fn test_zst2(p: bool, a: (), b: ()) -> () { // CHECK-LABEL: define{{.*}} @test_zst2 + // CHECK-NEXT: start: + // CHECK-NEXT: ret void p.select_unpredictable(a, b) } -- cgit 1.4.1-3-g733a5 From 49c74234a79107afa7f86ca947708c3abef07674 Mon Sep 17 00:00:00 2001 From: Hood Chatham Date: Thu, 17 Oct 2024 13:00:35 +0200 Subject: Add support for wasm exception handling to Emscripten target Gated behind an unstable `-Z emscripten-wasm-eh` flag --- compiler/rustc_codegen_llvm/src/llvm_util.rs | 5 +- compiler/rustc_codegen_ssa/src/back/link.rs | 8 ++- compiler/rustc_codegen_ssa/src/base.rs | 3 +- compiler/rustc_feature/src/builtin_attrs.rs | 1 + compiler/rustc_feature/src/unstable.rs | 2 + compiler/rustc_interface/src/tests.rs | 1 + compiler/rustc_passes/src/weak_lang_items.rs | 5 +- compiler/rustc_session/src/config/cfg.rs | 5 ++ compiler/rustc_session/src/options.rs | 2 + compiler/rustc_span/src/symbol.rs | 2 + library/panic_unwind/Cargo.toml | 2 +- library/panic_unwind/src/lib.rs | 3 +- library/unwind/Cargo.toml | 2 +- library/unwind/src/lib.rs | 3 +- .../src/compiler-flags/emscripten-wasm-eh.md | 6 ++ tests/codegen/emcripten-catch-unwind.rs | 66 ---------------------- tests/codegen/emscripten-catch-unwind-js-eh.rs | 66 ++++++++++++++++++++++ tests/codegen/emscripten-catch-unwind-wasm-eh.rs | 65 +++++++++++++++++++++ .../disallowed-cli-cfgs.emscripten_wasm_eh_.stderr | 8 +++ tests/ui/cfg/disallowed-cli-cfgs.rs | 2 + .../feature-gate-cfg-emscripten-wasm-eh.rs | 4 ++ .../feature-gate-cfg-emscripten-wasm-eh.stderr | 12 ++++ 22 files changed, 197 insertions(+), 76 deletions(-) create mode 100644 src/doc/unstable-book/src/compiler-flags/emscripten-wasm-eh.md delete mode 100644 tests/codegen/emcripten-catch-unwind.rs create mode 100644 tests/codegen/emscripten-catch-unwind-js-eh.rs create mode 100644 tests/codegen/emscripten-catch-unwind-wasm-eh.rs create mode 100644 tests/ui/cfg/disallowed-cli-cfgs.emscripten_wasm_eh_.stderr create mode 100644 tests/ui/feature-gates/feature-gate-cfg-emscripten-wasm-eh.rs create mode 100644 tests/ui/feature-gates/feature-gate-cfg-emscripten-wasm-eh.stderr (limited to 'tests/codegen') diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 628c0b1c29c..b3e1210632f 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -109,7 +109,10 @@ unsafe fn configure_llvm(sess: &Session) { add("-wasm-enable-eh", false); } - if sess.target.os == "emscripten" && sess.panic_strategy() == PanicStrategy::Unwind { + if sess.target.os == "emscripten" + && !sess.opts.unstable_opts.emscripten_wasm_eh + && sess.panic_strategy() == PanicStrategy::Unwind + { add("-enable-emscripten-cxx-exceptions", false); } diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 4bc064528f3..0a941a89609 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -2466,10 +2466,12 @@ fn add_order_independent_options( } if sess.target.os == "emscripten" { - cmd.cc_arg("-s").cc_arg(if sess.panic_strategy() == PanicStrategy::Abort { - "DISABLE_EXCEPTION_CATCHING=1" + cmd.cc_arg(if sess.panic_strategy() == PanicStrategy::Abort { + "-sDISABLE_EXCEPTION_CATCHING=1" + } else if sess.opts.unstable_opts.emscripten_wasm_eh { + "-fwasm-exceptions" } else { - "DISABLE_EXCEPTION_CATCHING=0" + "-sDISABLE_EXCEPTION_CATCHING=0" }); } diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 77e1fed720d..544578b29f1 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -388,7 +388,8 @@ pub(crate) fn build_shift_expr_rhs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // exceptions. This means that the VM does the unwinding for // us pub fn wants_wasm_eh(sess: &Session) -> bool { - sess.target.is_like_wasm && sess.target.os != "emscripten" + sess.target.is_like_wasm + && (sess.target.os != "emscripten" || sess.opts.unstable_opts.emscripten_wasm_eh) } /// Returns `true` if this session's target will use SEH-based unwinding. diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 4112ae80980..09c8a8a06ec 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -37,6 +37,7 @@ const GATED_CFGS: &[GatedCfg] = &[ (sym::sanitizer_cfi_normalize_integers, sym::cfg_sanitizer_cfi, Features::cfg_sanitizer_cfi), // this is consistent with naming of the compiler flag it's for (sym::fmt_debug, sym::fmt_debug, Features::fmt_debug), + (sym::emscripten_wasm_eh, sym::cfg_emscripten_wasm_eh, Features::cfg_emscripten_wasm_eh), ]; /// Find a gated cfg determined by the `pred`icate which is given the cfg's name. diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index d40823d2ed6..8cc4c18c02a 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -202,6 +202,8 @@ declare_features! ( (internal, allow_internal_unstable, "1.0.0", None), /// Allows using anonymous lifetimes in argument-position impl-trait. (unstable, anonymous_lifetime_in_impl_trait, "1.63.0", None), + /// Allows access to the emscripten_wasm_eh config, used by panic_unwind and unwind + (internal, cfg_emscripten_wasm_eh, "CURRENT_RUSTC_VERSION", None), /// Allows identifying the `compiler_builtins` crate. (internal, compiler_builtins, "1.13.0", None), /// Allows writing custom MIR diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 9ad69039914..b50f3b38f2e 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -782,6 +782,7 @@ fn test_unstable_options_tracking_hash() { tracked!(dwarf_version, Some(5)); tracked!(embed_source, true); tracked!(emit_thin_lto, false); + tracked!(emscripten_wasm_eh, true); tracked!(export_executable_symbols, true); tracked!(fewer_names, Some(true)); tracked!(fixed_x18, true); diff --git a/compiler/rustc_passes/src/weak_lang_items.rs b/compiler/rustc_passes/src/weak_lang_items.rs index 020128f29c5..701f500e4f6 100644 --- a/compiler/rustc_passes/src/weak_lang_items.rs +++ b/compiler/rustc_passes/src/weak_lang_items.rs @@ -26,7 +26,10 @@ pub(crate) fn check_crate( if items.eh_personality().is_none() { items.missing.push(LangItem::EhPersonality); } - if tcx.sess.target.os == "emscripten" && items.eh_catch_typeinfo().is_none() { + if tcx.sess.target.os == "emscripten" + && items.eh_catch_typeinfo().is_none() + && !tcx.sess.opts.unstable_opts.emscripten_wasm_eh + { items.missing.push(LangItem::EhCatchTypeinfo); } diff --git a/compiler/rustc_session/src/config/cfg.rs b/compiler/rustc_session/src/config/cfg.rs index 3426858495b..40016cb76d6 100644 --- a/compiler/rustc_session/src/config/cfg.rs +++ b/compiler/rustc_session/src/config/cfg.rs @@ -143,6 +143,7 @@ pub(crate) fn disallow_cfgs(sess: &Session, user_cfgs: &Cfg) { | (sym::target_has_atomic_load_store, Some(_)) | (sym::target_thread_local, None) => disallow(cfg, "--target"), (sym::fmt_debug, None | Some(_)) => disallow(cfg, "-Z fmt-debug"), + (sym::emscripten_wasm_eh, None | Some(_)) => disallow(cfg, "-Z emscripten_wasm_eh"), _ => {} } } @@ -295,6 +296,10 @@ pub(crate) fn default_configuration(sess: &Session) -> Cfg { ins_none!(sym::ub_checks); } + // Nightly-only implementation detail for the `panic_unwind` and `unwind` crates. + if sess.is_nightly_build() && sess.opts.unstable_opts.emscripten_wasm_eh { + ins_none!(sym::emscripten_wasm_eh); + } ret } diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 3772a4a08af..a344ec94a26 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1771,6 +1771,8 @@ options! { "emit a section containing stack size metadata (default: no)"), emit_thin_lto: bool = (true, parse_bool, [TRACKED], "emit the bc module with thin LTO info (default: yes)"), + emscripten_wasm_eh: bool = (false, parse_bool, [TRACKED], + "Use WebAssembly error handling for wasm32-unknown-emscripten"), enforce_type_length_limit: bool = (false, parse_bool, [TRACKED], "enforce the type length limit when monomorphizing instances in codegen"), export_executable_symbols: bool = (false, parse_bool, [TRACKED], diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 4ecc4201f89..e62107c450e 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -570,6 +570,7 @@ symbols! { cfg_autodiff_fallback, cfg_boolean_literals, cfg_doctest, + cfg_emscripten_wasm_eh, cfg_eval, cfg_fmt_debug, cfg_hide, @@ -823,6 +824,7 @@ symbols! { emit_enum_variant_arg, emit_struct, emit_struct_field, + emscripten_wasm_eh, enable, encode, end, diff --git a/library/panic_unwind/Cargo.toml b/library/panic_unwind/Cargo.toml index 252f118fecf..c2abb79192e 100644 --- a/library/panic_unwind/Cargo.toml +++ b/library/panic_unwind/Cargo.toml @@ -23,4 +23,4 @@ libc = { version = "0.2", default-features = false } [lints.rust.unexpected_cfgs] level = "warn" -check-cfg = [] +check-cfg = ['cfg(emscripten_wasm_eh)'] diff --git a/library/panic_unwind/src/lib.rs b/library/panic_unwind/src/lib.rs index 1981675f409..085c07591d2 100644 --- a/library/panic_unwind/src/lib.rs +++ b/library/panic_unwind/src/lib.rs @@ -25,13 +25,14 @@ // `real_imp` is unused with Miri, so silence warnings. #![cfg_attr(miri, allow(dead_code))] #![allow(internal_features)] +#![cfg_attr(not(bootstrap), feature(cfg_emscripten_wasm_eh))] use alloc::boxed::Box; use core::any::Any; use core::panic::PanicPayload; cfg_if::cfg_if! { - if #[cfg(target_os = "emscripten")] { + if #[cfg(all(target_os = "emscripten", not(emscripten_wasm_eh)))] { #[path = "emcc.rs"] mod imp; } else if #[cfg(target_os = "hermit")] { diff --git a/library/unwind/Cargo.toml b/library/unwind/Cargo.toml index e13c9a06c05..66e8d1a3ffe 100644 --- a/library/unwind/Cargo.toml +++ b/library/unwind/Cargo.toml @@ -37,4 +37,4 @@ system-llvm-libunwind = [] [lints.rust.unexpected_cfgs] level = "warn" -check-cfg = [] +check-cfg = ['cfg(emscripten_wasm_eh)'] diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs index 40d409310ff..9b93f0b3da0 100644 --- a/library/unwind/src/lib.rs +++ b/library/unwind/src/lib.rs @@ -4,10 +4,11 @@ #![feature(staged_api)] #![cfg_attr(not(target_env = "msvc"), feature(libc))] #![cfg_attr( - all(target_family = "wasm", not(target_os = "emscripten")), + all(target_family = "wasm", any(not(target_os = "emscripten"), emscripten_wasm_eh)), feature(simd_wasm64, wasm_exception_handling_intrinsics) )] #![allow(internal_features)] +#![cfg_attr(not(bootstrap), feature(cfg_emscripten_wasm_eh))] // Force libc to be included even if unused. This is required by many platforms. #[cfg(not(all(windows, target_env = "msvc")))] diff --git a/src/doc/unstable-book/src/compiler-flags/emscripten-wasm-eh.md b/src/doc/unstable-book/src/compiler-flags/emscripten-wasm-eh.md new file mode 100644 index 00000000000..eab29a1744b --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/emscripten-wasm-eh.md @@ -0,0 +1,6 @@ +# `emscripten-wasm-eh` + +Use the WebAssembly exception handling ABI to unwind for the +`wasm32-unknown-emscripten`. If compiling with this setting, the `emcc` linker +should be invoked with `-fwasm-exceptions`. If linking with C/C++ files, the +C/C++ files should also be compiled with `-fwasm-exceptions`. diff --git a/tests/codegen/emcripten-catch-unwind.rs b/tests/codegen/emcripten-catch-unwind.rs deleted file mode 100644 index b15fb40b68f..00000000000 --- a/tests/codegen/emcripten-catch-unwind.rs +++ /dev/null @@ -1,66 +0,0 @@ -//@ compile-flags: -O --target wasm32-unknown-emscripten -//@ needs-llvm-components: webassembly - -// Emscripten has its own unique implementation of catch_unwind (in `codegen_emcc_try`), -// make sure it generates something reasonable. - -#![feature(no_core, lang_items, intrinsics, rustc_attrs)] -#![crate_type = "lib"] -#![no_std] -#![no_core] - -#[lang = "sized"] -trait Sized {} -#[lang = "freeze"] -trait Freeze {} -#[lang = "copy"] -trait Copy {} - -impl Copy for *mut T {} - -#[rustc_intrinsic] -fn size_of() -> usize { - loop {} -} - -extern "rust-intrinsic" { - fn catch_unwind( - try_fn: fn(_: *mut u8), - data: *mut u8, - catch_fn: fn(_: *mut u8, _: *mut u8), - ) -> i32; -} - -// CHECK-LABEL: @ptr_size -#[no_mangle] -pub fn ptr_size() -> usize { - // CHECK: ret [[PTR_SIZE:.*]] - size_of::<*mut u8>() -} - -// CHECK-LABEL: @test_catch_unwind -#[no_mangle] -pub unsafe fn test_catch_unwind( - try_fn: fn(_: *mut u8), - data: *mut u8, - catch_fn: fn(_: *mut u8, _: *mut u8), -) -> i32 { - // CHECK: start: - // CHECK: [[ALLOCA:%.*]] = alloca - - // CHECK: catch.i: - // CHECK: [[LANDINGPAD:%.*]] = landingpad - // CHECK: [[EXCEPTION:%.*]] = extractvalue {{.*}} [[LANDINGPAD]], 0 - // CHECK: [[SELECTOR:%.*]] = extractvalue {{.*}} [[LANDINGPAD]], 1 - - // CHECK: [[IS_RUST_EXN:%.*]] = icmp eq {{.*}}[[SELECTOR]] - // CHECK: [[IS_RUST_EXN_I8:%.*]] = zext i1 [[IS_RUST_EXN]] to i8 - - // CHECK: store ptr [[EXCEPTION]], ptr [[ALLOCA]] - // CHECK: [[IS_RUST_SLOT:%.*]] = getelementptr inbounds{{( nuw)?}} i8, ptr [[ALLOCA]], [[PTR_SIZE]] - // CHECK: store i8 [[IS_RUST_EXN_I8]], ptr [[IS_RUST_SLOT]] - - // CHECK: call void %catch_fn(ptr %data, ptr nonnull [[ALLOCA]]) - - catch_unwind(try_fn, data, catch_fn) -} diff --git a/tests/codegen/emscripten-catch-unwind-js-eh.rs b/tests/codegen/emscripten-catch-unwind-js-eh.rs new file mode 100644 index 00000000000..b15fb40b68f --- /dev/null +++ b/tests/codegen/emscripten-catch-unwind-js-eh.rs @@ -0,0 +1,66 @@ +//@ compile-flags: -O --target wasm32-unknown-emscripten +//@ needs-llvm-components: webassembly + +// Emscripten has its own unique implementation of catch_unwind (in `codegen_emcc_try`), +// make sure it generates something reasonable. + +#![feature(no_core, lang_items, intrinsics, rustc_attrs)] +#![crate_type = "lib"] +#![no_std] +#![no_core] + +#[lang = "sized"] +trait Sized {} +#[lang = "freeze"] +trait Freeze {} +#[lang = "copy"] +trait Copy {} + +impl Copy for *mut T {} + +#[rustc_intrinsic] +fn size_of() -> usize { + loop {} +} + +extern "rust-intrinsic" { + fn catch_unwind( + try_fn: fn(_: *mut u8), + data: *mut u8, + catch_fn: fn(_: *mut u8, _: *mut u8), + ) -> i32; +} + +// CHECK-LABEL: @ptr_size +#[no_mangle] +pub fn ptr_size() -> usize { + // CHECK: ret [[PTR_SIZE:.*]] + size_of::<*mut u8>() +} + +// CHECK-LABEL: @test_catch_unwind +#[no_mangle] +pub unsafe fn test_catch_unwind( + try_fn: fn(_: *mut u8), + data: *mut u8, + catch_fn: fn(_: *mut u8, _: *mut u8), +) -> i32 { + // CHECK: start: + // CHECK: [[ALLOCA:%.*]] = alloca + + // CHECK: catch.i: + // CHECK: [[LANDINGPAD:%.*]] = landingpad + // CHECK: [[EXCEPTION:%.*]] = extractvalue {{.*}} [[LANDINGPAD]], 0 + // CHECK: [[SELECTOR:%.*]] = extractvalue {{.*}} [[LANDINGPAD]], 1 + + // CHECK: [[IS_RUST_EXN:%.*]] = icmp eq {{.*}}[[SELECTOR]] + // CHECK: [[IS_RUST_EXN_I8:%.*]] = zext i1 [[IS_RUST_EXN]] to i8 + + // CHECK: store ptr [[EXCEPTION]], ptr [[ALLOCA]] + // CHECK: [[IS_RUST_SLOT:%.*]] = getelementptr inbounds{{( nuw)?}} i8, ptr [[ALLOCA]], [[PTR_SIZE]] + // CHECK: store i8 [[IS_RUST_EXN_I8]], ptr [[IS_RUST_SLOT]] + + // CHECK: call void %catch_fn(ptr %data, ptr nonnull [[ALLOCA]]) + + catch_unwind(try_fn, data, catch_fn) +} diff --git a/tests/codegen/emscripten-catch-unwind-wasm-eh.rs b/tests/codegen/emscripten-catch-unwind-wasm-eh.rs new file mode 100644 index 00000000000..72395f432d5 --- /dev/null +++ b/tests/codegen/emscripten-catch-unwind-wasm-eh.rs @@ -0,0 +1,65 @@ +//@ compile-flags: -O --target wasm32-unknown-emscripten -Z emscripten-wasm-eh +//@ needs-llvm-components: webassembly + +// Emscripten catch_unwind using wasm exceptions + +#![feature(no_core, lang_items, intrinsics, rustc_attrs)] +#![crate_type = "lib"] +#![no_std] +#![no_core] + +#[lang = "sized"] +trait Sized {} +#[lang = "freeze"] +trait Freeze {} +#[lang = "copy"] +trait Copy {} + +impl Copy for *mut T {} + +#[rustc_intrinsic] +fn size_of() -> usize { + loop {} +} + +extern "rust-intrinsic" { + fn catch_unwind( + try_fn: fn(_: *mut u8), + data: *mut u8, + catch_fn: fn(_: *mut u8, _: *mut u8), + ) -> i32; +} + +// CHECK-LABEL: @ptr_size +#[no_mangle] +pub fn ptr_size() -> usize { + // CHECK: ret [[PTR_SIZE:.*]] + size_of::<*mut u8>() +} + +// CHECK-LABEL: @test_catch_unwind +#[no_mangle] +pub unsafe fn test_catch_unwind( + try_fn: fn(_: *mut u8), + data: *mut u8, + catch_fn: fn(_: *mut u8, _: *mut u8), +) -> i32 { + // CHECK: start: + // CHECK: invoke void %try_fn(ptr %data) + // CHECK: to label %__rust_try.exit unwind label %catchswitch.i + // CHECK: catchswitch.i: ; preds = %start + // CHECK: %catchswitch1.i = catchswitch within none [label %catchpad.i] unwind to caller + + // CHECK: catchpad.i: ; preds = %catchswitch.i + // CHECK: %catchpad2.i = catchpad within %catchswitch1.i [ptr null] + // CHECK: %0 = tail call ptr @llvm.wasm.get.exception(token %catchpad2.i) + // CHECK: %1 = tail call i32 @llvm.wasm.get.ehselector(token %catchpad2.i) + // CHECK: call void %catch_fn(ptr %data, ptr %0) [ "funclet"(token %catchpad2.i) ] + // CHECK: catchret from %catchpad2.i to label %__rust_try.exit + + // CHECK: __rust_try.exit: ; preds = %start, %catchpad.i + // CHECK: %common.ret.op.i = phi i32 [ 0, %start ], [ 1, %catchpad.i ] + // CHECK: ret i32 %common.ret.op.i + + catch_unwind(try_fn, data, catch_fn) +} diff --git a/tests/ui/cfg/disallowed-cli-cfgs.emscripten_wasm_eh_.stderr b/tests/ui/cfg/disallowed-cli-cfgs.emscripten_wasm_eh_.stderr new file mode 100644 index 00000000000..8b2ee0e5c0c --- /dev/null +++ b/tests/ui/cfg/disallowed-cli-cfgs.emscripten_wasm_eh_.stderr @@ -0,0 +1,8 @@ +error: unexpected `--cfg emscripten_wasm_eh` flag + | + = note: config `emscripten_wasm_eh` is only supposed to be controlled by `-Z emscripten_wasm_eh` + = note: manually setting a built-in cfg can and does create incoherent behaviors + = note: `#[deny(explicit_builtin_cfgs_in_flags)]` on by default + +error: aborting due to 1 previous error + diff --git a/tests/ui/cfg/disallowed-cli-cfgs.rs b/tests/ui/cfg/disallowed-cli-cfgs.rs index 3c9ee87f28a..cae9c65cb45 100644 --- a/tests/ui/cfg/disallowed-cli-cfgs.rs +++ b/tests/ui/cfg/disallowed-cli-cfgs.rs @@ -7,6 +7,7 @@ //@ revisions: target_has_atomic_equal_alignment_ target_has_atomic_load_store_ //@ revisions: target_thread_local_ relocation_model_ //@ revisions: fmt_debug_ +//@ revisions: emscripten_wasm_eh_ //@ [overflow_checks_]compile-flags: --cfg overflow_checks //@ [debug_assertions_]compile-flags: --cfg debug_assertions @@ -33,5 +34,6 @@ //@ [target_thread_local_]compile-flags: --cfg target_thread_local //@ [relocation_model_]compile-flags: --cfg relocation_model="a" //@ [fmt_debug_]compile-flags: --cfg fmt_debug="shallow" +//@ [emscripten_wasm_eh_]compile-flags: --cfg emscripten_wasm_eh fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-cfg-emscripten-wasm-eh.rs b/tests/ui/feature-gates/feature-gate-cfg-emscripten-wasm-eh.rs new file mode 100644 index 00000000000..cff98b43fe7 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-cfg-emscripten-wasm-eh.rs @@ -0,0 +1,4 @@ +//@ compile-flags: --check-cfg=cfg(emscripten_wasm_eh) +#[cfg(not(emscripten_wasm_eh))] +//~^ `cfg(emscripten_wasm_eh)` is experimental +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-cfg-emscripten-wasm-eh.stderr b/tests/ui/feature-gates/feature-gate-cfg-emscripten-wasm-eh.stderr new file mode 100644 index 00000000000..67769e3c758 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-cfg-emscripten-wasm-eh.stderr @@ -0,0 +1,12 @@ +error[E0658]: `cfg(emscripten_wasm_eh)` is experimental and subject to change + --> $DIR/feature-gate-cfg-emscripten-wasm-eh.rs:2:11 + | +LL | #[cfg(not(emscripten_wasm_eh))] + | ^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(cfg_emscripten_wasm_eh)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0658`. -- cgit 1.4.1-3-g733a5