about summary refs log tree commit diff
path: root/tests/ui/target-feature/struct-target-features.rs
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-08-28 22:54:55 +0000
committerbors <bors@rust-lang.org>2024-08-28 22:54:55 +0000
commitacb4e8b6251f1d8da36f08e7a70fa23fc581839e (patch)
treed34182dd7a2cb603a9aafa52839d64101c2dcc3f /tests/ui/target-feature/struct-target-features.rs
parent100fde5246bf56f22fb5cc85374dd841296fce0e (diff)
parent7eb4cfeaced28d49952e4ef54f8fe02258125854 (diff)
downloadrust-acb4e8b6251f1d8da36f08e7a70fa23fc581839e.tar.gz
rust-acb4e8b6251f1d8da36f08e7a70fa23fc581839e.zip
Auto merge of #127537 - veluca93:struct_tf, r=BoxyUwU
Implement a first version of RFC 3525: struct target features

This PR is an attempt at implementing https://github.com/rust-lang/rfcs/pull/3525, behind a feature gate `struct_target_features`.

There's obviously a few tasks that ought to be done before this is merged; in no particular order:
- add proper error messages
- add tests
- create a tracking issue for the RFC
- properly serialize/deserialize the new target_features field in `rmeta` (assuming I even understood that correctly :-))

That said, as I am definitely not a `rustc` expert, I'd like to get some early feedback on the overall approach before fixing those things (and perhaps some pointers for `rmeta`...), hence this early PR :-)

Here's an example piece of code that I have been using for testing - with the new code, the calls to intrinsics get correctly inlined:
```rust
#![feature(struct_target_features)]

use std::arch::x86_64::*;

/*
// fails to compile
#[target_feature(enable = "avx")]
struct Invalid(u32);
*/

#[target_feature(enable = "avx")]
struct Avx {}

#[target_feature(enable = "sse")]
struct Sse();

/*
// fails to compile
extern "C" fn bad_fun(_: Avx) {}
*/

/*
// fails to compile
#[inline(always)]
fn inline_fun(_: Avx) {}
*/

trait Simd {
    fn do_something(&self);
}

impl Simd for Avx {
    fn do_something(&self) {
        unsafe {
            println!("{:?}", _mm256_setzero_ps());
        }
    }
}

impl Simd for Sse {
    fn do_something(&self) {
        unsafe {
            println!("{:?}", _mm_setzero_ps());
        }
    }
}

struct WithAvx {
    #[allow(dead_code)]
    avx: Avx,
}

impl Simd for WithAvx {
    fn do_something(&self) {
        unsafe {
            println!("{:?}", _mm256_setzero_ps());
        }
    }
}

#[inline(never)]
fn dosomething<S: Simd>(simd: &S) {
    simd.do_something();
}

fn main() {
    /*
    // fails to compile
    Avx {};
    */

    if is_x86_feature_detected!("avx") {
        let avx = unsafe { Avx {} };
        dosomething(&avx);
        dosomething(&WithAvx { avx });
    }
    if is_x86_feature_detected!("sse") {
        dosomething(&unsafe { Sse {} })
    }
}
```

Tracking:

- https://github.com/rust-lang/rust/issues/129107
Diffstat (limited to 'tests/ui/target-feature/struct-target-features.rs')
-rw-r--r--tests/ui/target-feature/struct-target-features.rs98
1 files changed, 98 insertions, 0 deletions
diff --git a/tests/ui/target-feature/struct-target-features.rs b/tests/ui/target-feature/struct-target-features.rs
new file mode 100644
index 00000000000..feb479b6dc8
--- /dev/null
+++ b/tests/ui/target-feature/struct-target-features.rs
@@ -0,0 +1,98 @@
+//@ only-x86_64
+#![feature(struct_target_features)]
+//~^ WARNING the feature `struct_target_features` is incomplete and may not be safe to use and/or cause compiler crashes
+#![feature(target_feature_11)]
+
+use std::arch::x86_64::*;
+
+#[target_feature(enable = "avx")]
+//~^ ERROR attribute should be applied to a function definition or unit struct
+struct Invalid(u32);
+
+#[target_feature(enable = "avx")]
+struct Avx {}
+
+#[target_feature(enable = "sse")]
+struct Sse();
+
+#[target_feature(enable = "avx")]
+fn avx() {}
+
+trait TFAssociatedType {
+    type Assoc;
+}
+
+impl TFAssociatedType for () {
+    type Assoc = Avx;
+}
+
+fn avx_self(_: <() as TFAssociatedType>::Assoc) {
+    avx();
+}
+
+fn avx_avx(_: Avx) {
+    avx();
+}
+
+extern "C" fn bad_fun(_: Avx) {}
+//~^ ERROR cannot use a struct with target features in a function with non-Rust ABI
+
+#[inline(always)]
+//~^ ERROR cannot use `#[inline(always)]` with `#[target_feature]`
+fn inline_fun(_: Avx) {}
+//~^ ERROR cannot use a struct with target features in a #[inline(always)] function
+
+trait Simd {
+    fn do_something(&self);
+}
+
+impl Simd for Avx {
+    fn do_something(&self) {
+        unsafe {
+            println!("{:?}", _mm256_setzero_ps());
+        }
+    }
+}
+
+impl Simd for Sse {
+    fn do_something(&self) {
+        unsafe {
+            println!("{:?}", _mm_setzero_ps());
+        }
+    }
+}
+
+struct WithAvx {
+    #[allow(dead_code)]
+    avx: Avx,
+}
+
+impl Simd for WithAvx {
+    fn do_something(&self) {
+        unsafe {
+            println!("{:?}", _mm256_setzero_ps());
+        }
+    }
+}
+
+#[inline(never)]
+fn dosomething<S: Simd>(simd: &S) {
+    simd.do_something();
+}
+
+fn avxfn(_: &Avx) {}
+
+fn main() {
+    Avx {};
+    //~^ ERROR initializing type with `target_feature` attr is unsafe and requires unsafe function or block [E0133]
+
+    if is_x86_feature_detected!("avx") {
+        let avx = unsafe { Avx {} };
+        avxfn(&avx);
+        dosomething(&avx);
+        dosomething(&WithAvx { avx });
+    }
+    if is_x86_feature_detected!("sse") {
+        dosomething(&unsafe { Sse {} })
+    }
+}