Auto merge of #129881 - veluca93:struct_tf, r= · rust-lang/rust@446b363 (original) (raw)

`@@ -8,7 +8,8 @@ use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};

`

8

8

`use rustc_hir::weak_lang_items::WEAK_LANG_ITEMS;

`

9

9

`use rustc_hir::{LangItem, lang_items};

`

10

10

`use rustc_middle::middle::codegen_fn_attrs::{

`

11

``

`-

CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry,

`

``

11

`+

CodegenFnAttrFlags, CodegenFnAttrs, PatchableFunctionEntry, TargetFeature,

`

``

12

`+

extend_with_struct_target_features,

`

12

13

`};

`

13

14

`use rustc_middle::mir::mono::Linkage;

`

14

15

`use rustc_middle::query::Providers;

`

`@@ -78,23 +79,26 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {

`

78

79

`let mut link_ordinal_span = None;

`

79

80

`let mut no_sanitize_span = None;

`

80

81

``

``

82

`+

let fn_sig_outer = || {

`

``

83

`+

use DefKind::*;

`

``

84

+

``

85

`+

let def_kind = tcx.def_kind(did);

`

``

86

`+

if let Fn | AssocFn | Variant | Ctor(..) = def_kind { Some(tcx.fn_sig(did)) } else { None }

`

``

87

`+

};

`

``

88

+

81

89

`for attr in attrs.iter() {

`

82

90

`` // In some cases, attribute are only valid on functions, but it's the check_attr

``

83

91

`// pass that check that they aren't used anywhere else, rather this module.

`

84

92

`// In these cases, we bail from performing further checks that are only meaningful for

`

85

93

`` // functions (such as calling fn_sig, which ICEs if given a non-function). We also

``

86

94

`` // report a delayed bug, just in case check_attr isn't doing its job.

``

87

95

`let fn_sig = || {

`

88

``

`-

use DefKind::*;

`

89

``

-

90

``

`-

let def_kind = tcx.def_kind(did);

`

91

``

`-

if let Fn | AssocFn | Variant | Ctor(..) = def_kind {

`

92

``

`-

Some(tcx.fn_sig(did))

`

93

``

`-

} else {

`

``

96

`+

let sig = fn_sig_outer();

`

``

97

`+

if sig.is_none() {

`

94

98

` tcx.dcx()

`

95

99

`.span_delayed_bug(attr.span, "this attribute can only be applied to functions");

`

96

``

`-

None

`

97

100

`}

`

``

101

`+

sig

`

98

102

`};

`

99

103

``

100

104

`let Some(Ident { name, .. }) = attr.ident() else {

`

`@@ -246,7 +250,12 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {

`

246

250

` && let Some(fn_sig) = fn_sig()

`

247

251

` && fn_sig.skip_binder().safety() == hir::Safety::Safe

`

248

252

`{

`

249

``

`-

if tcx.sess.target.is_like_wasm || tcx.sess.opts.actually_rustdoc {

`

``

253

`+

if attr.meta_item_list().is_some_and(|list| {

`

``

254

`+

list.len() == 1 && list[0].ident().is_some_and(|x| x.name == sym::from_args)

`

``

255

`+

}) {

`

``

256

`+

// #[target_feature(from_args)] can be applied to safe functions and safe

`

``

257

`+

// trait methods.

`

``

258

`+

} else if tcx.sess.target.is_like_wasm || tcx.sess.opts.actually_rustdoc {

`

250

259

`` // The #[target_feature] attribute is allowed on

``

251

260

`// WebAssembly targets on all functions, including safe

`

252

261

`` // ones. Other targets require that #[target_feature] is

``

`@@ -284,7 +293,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {

`

284

293

` tcx,

`

285

294

` attr,

`

286

295

` supported_target_features,

`

287

``

`-

&mut codegen_fn_attrs.target_features,

`

``

296

`+

&mut codegen_fn_attrs.def_target_features,

`

``

297

`+

Some(&mut codegen_fn_attrs.target_features_from_args),

`

288

298

`);

`

289

299

`}

`

290

300

` sym::linkage => {

`

`@@ -590,16 +600,39 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {

`

590

600

`let owner_id = tcx.parent(did.to_def_id());

`

591

601

`if tcx.def_kind(owner_id).has_codegen_attrs() {

`

592

602

` codegen_fn_attrs

`

593

``

`-

.target_features

`

594

``

`-

.extend(tcx.codegen_fn_attrs(owner_id).target_features.iter().copied());

`

``

603

`+

.def_target_features

`

``

604

`+

.extend(tcx.codegen_fn_attrs(owner_id).def_target_features.iter().copied());

`

595

605

`}

`

596

606

`}

`

597

607

``

598

``

`-

// If a function uses #[target_feature] it can't be inlined into general

`

``

608

`+

if let Some(sig) = fn_sig_outer()

`

``

609

`+

&& codegen_fn_attrs.target_features_from_args

`

``

610

`+

{

`

``

611

`+

let mut additional_tf = vec![];

`

``

612

`+

for ty in sig.skip_binder().inputs().skip_binder() {

`

``

613

`+

extend_with_struct_target_features(

`

``

614

`+

tcx,

`

``

615

`+

tcx.param_env(did.to_def_id()).and(*ty),

`

``

616

`+

&mut additional_tf,

`

``

617

`+

)

`

``

618

`+

}

`

``

619

`+

if !additional_tf.is_empty() && codegen_fn_attrs.inline == InlineAttr::Always {

`

``

620

`+

tcx.dcx().span_err(

`

``

621

`+

tcx.hir().span(tcx.local_def_id_to_hir_id(did)),

`

``

622

`+

"cannot use a struct with target features in a #[inline(always)] function",

`

``

623

`+

);

`

``

624

`+

}

`

``

625

`+

codegen_fn_attrs

`

``

626

`+

.def_target_features

`

``

627

`+

.extend(additional_tf.iter().map(|tf| TargetFeature { implied: true, ..*tf }));

`

``

628

`+

}

`

``

629

+

``

630

`+

// If a function uses non-default target_features it can't be inlined into general

`

599

631

`// purpose functions as they wouldn't have the right target features

`

600

632

`// enabled. For that reason we also forbid #[inline(always)] as it can't be

`

601

633

`// respected.

`

602

``

`-

if !codegen_fn_attrs.target_features.is_empty() && codegen_fn_attrs.inline == InlineAttr::Always

`

``

634

`+

if !codegen_fn_attrs.def_target_features.is_empty()

`

``

635

`+

&& codegen_fn_attrs.inline == InlineAttr::Always

`

603

636

`{

`

604

637

`if let Some(span) = inline_span {

`

605

638

` tcx.dcx().span_err(

`

`@@ -738,6 +771,20 @@ fn check_link_name_xor_ordinal(

`

738

771

`}

`

739

772

`}

`

740

773

``

``

774

`+

fn struct_target_features(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &[TargetFeature] {

`

``

775

`+

let mut features = vec![];

`

``

776

`+

let supported_features = tcx.supported_target_features(LOCAL_CRATE);

`

``

777

`+

for attr in tcx.get_attrs(def_id, sym::target_feature) {

`

``

778

`+

from_target_feature(tcx, attr, supported_features, &mut features, None);

`

``

779

`+

}

`

``

780

`+

tcx.arena.alloc_slice(&features)

`

``

781

`+

}

`

``

782

+

741

783

`pub(crate) fn provide(providers: &mut Providers) {

`

742

``

`-

*providers = Providers { codegen_fn_attrs, should_inherit_track_caller, ..*providers };

`

``

784

`+

*providers = Providers {

`

``

785

`+

codegen_fn_attrs,

`

``

786

`+

should_inherit_track_caller,

`

``

787

`+

struct_target_features,

`

``

788

`+

..*providers

`

``

789

`+

};

`

743

790

`}

`