1
Fork 0

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
This commit is contained in:
bors 2024-08-28 22:54:55 +00:00
commit acb4e8b625
25 changed files with 512 additions and 28 deletions

View file

@ -747,12 +747,35 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
Target::Field | Target::Arm | Target::MacroDef => {
self.inline_attr_str_error_with_macro_def(hir_id, attr, "target_feature");
}
Target::Struct if self.tcx.features().struct_target_features => {
let ty = self.tcx.hir_node(hir_id).expect_item();
match ty.kind {
ItemKind::Struct(data, _) => {
if data.fields().len() != 0 {
self.dcx().emit_err(errors::AttrShouldBeAppliedToFnOrUnitStruct {
attr_span: attr.span,
defn_span: span,
});
}
}
_ => {
panic!("Target::Struct for a non-struct");
}
}
}
_ => {
self.dcx().emit_err(errors::AttrShouldBeAppliedToFn {
attr_span: attr.span,
defn_span: span,
on_crate: hir_id == CRATE_HIR_ID,
});
if self.tcx.features().struct_target_features {
self.dcx().emit_err(errors::AttrShouldBeAppliedToFnOrUnitStruct {
attr_span: attr.span,
defn_span: span,
});
} else {
self.dcx().emit_err(errors::AttrShouldBeAppliedToFn {
attr_span: attr.span,
defn_span: span,
on_crate: hir_id == CRATE_HIR_ID,
});
}
}
}
}

View file

@ -82,6 +82,15 @@ pub struct AttrShouldBeAppliedToFn {
pub on_crate: bool,
}
#[derive(Diagnostic)]
#[diag(passes_should_be_applied_to_fn_or_unit_struct)]
pub struct AttrShouldBeAppliedToFnOrUnitStruct {
#[primary_span]
pub attr_span: Span,
#[label]
pub defn_span: Span,
}
#[derive(Diagnostic)]
#[diag(passes_should_be_applied_to_fn, code = E0739)]
pub struct TrackedCallerWrongLocation {