@@ -5,6 +5,7 @@ use rustc_target::abi::Align;
5
5
use rustc_target:: spec:: SanitizerSet ;
6
6
7
7
use crate :: mir:: mono:: Linkage ;
8
+ use crate :: ty:: { self , Instance , ParamEnv , Ty , TyCtxt } ;
8
9
9
10
#[ derive( Clone , TyEncodable , TyDecodable , HashStable , Debug ) ]
10
11
pub struct CodegenFnAttrs {
@@ -28,7 +29,7 @@ pub struct CodegenFnAttrs {
28
29
pub link_ordinal : Option < u16 > ,
29
30
/// All the target features that are enabled for this function. Some features might be enabled
30
31
/// implicitly.
31
- pub target_features : Vec < TargetFeature > ,
32
+ pub def_target_features : Vec < TargetFeature > ,
32
33
/// The `#[linkage = "..."]` attribute on Rust-defined items and the value we found.
33
34
pub linkage : Option < Linkage > ,
34
35
/// The `#[linkage = "..."]` attribute on foreign items and the value we found.
@@ -139,6 +140,30 @@ bitflags::bitflags! {
139
140
}
140
141
rustc_data_structures:: external_bitflags_debug! { CodegenFnAttrFlags }
141
142
143
+ pub fn extend_with_struct_target_features < ' tcx > (
144
+ tcx : TyCtxt < ' tcx > ,
145
+ env : ty:: ParamEnvAnd < ' tcx , Ty < ' tcx > > ,
146
+ target_features : & mut Vec < TargetFeature > ,
147
+ ) {
148
+ // Collect target features from types reachable from `env.value` by dereferencing a certain
149
+ // number of references and resolving aliases.
150
+
151
+ let mut ty = env. value ;
152
+ if matches ! ( ty. kind( ) , ty:: Alias ( ..) ) {
153
+ ty = match tcx. try_normalize_erasing_regions ( env. param_env , ty) {
154
+ Ok ( ty) => ty,
155
+ Err ( _) => return ,
156
+ } ;
157
+ }
158
+ while let ty:: Ref ( _, inner, _) = ty. kind ( ) {
159
+ ty = * inner;
160
+ }
161
+
162
+ if let ty:: Adt ( adt_def, ..) = ty. kind ( ) {
163
+ target_features. extend_from_slice ( & tcx. struct_target_features ( adt_def. did ( ) ) ) ;
164
+ }
165
+ }
166
+
142
167
impl CodegenFnAttrs {
143
168
pub const EMPTY : & ' static Self = & Self :: new ( ) ;
144
169
@@ -150,7 +175,7 @@ impl CodegenFnAttrs {
150
175
export_name : None ,
151
176
link_name : None ,
152
177
link_ordinal : None ,
153
- target_features : vec ! [ ] ,
178
+ def_target_features : vec ! [ ] ,
154
179
linkage : None ,
155
180
import_linkage : None ,
156
181
link_section : None ,
@@ -177,4 +202,59 @@ impl CodegenFnAttrs {
177
202
Some ( _) => true ,
178
203
}
179
204
}
205
+
206
+ pub fn target_features_for_instance < ' tcx > (
207
+ & self ,
208
+ tcx : TyCtxt < ' tcx > ,
209
+ param_env : ParamEnv < ' tcx > ,
210
+ instance : Instance < ' tcx > ,
211
+ ) -> Vec < TargetFeature > {
212
+ if !self . target_features_from_args {
213
+ return self . def_target_features . clone ( ) ;
214
+ }
215
+ let inputs = match tcx. type_of ( instance. def_id ( ) ) . skip_binder ( ) . kind ( ) {
216
+ ty:: Closure ( ..) => {
217
+ let closure = instance. args . as_closure ( ) ;
218
+ let mut inputs =
219
+ tcx. instantiate_bound_regions_with_erased ( closure. sig ( ) ) . inputs ( ) . to_vec ( ) ;
220
+ inputs. extend ( closure. upvar_tys ( ) ) ;
221
+ inputs
222
+ }
223
+ ty:: CoroutineClosure ( ..) => {
224
+ let closure = instance. args . as_coroutine_closure ( ) ;
225
+ // FIXME: might be missing inputs to the closure
226
+ closure. upvar_tys ( ) . to_vec ( )
227
+ }
228
+ ty:: Coroutine ( ..) => {
229
+ let coro = instance. args . as_coroutine ( ) ;
230
+ coro. upvar_tys ( ) . to_vec ( )
231
+ }
232
+ _ => {
233
+ let ty = match tcx. try_instantiate_and_normalize_erasing_regions (
234
+ instance. args ,
235
+ param_env,
236
+ tcx. type_of ( instance. def_id ( ) ) ,
237
+ ) {
238
+ Ok ( ty) => ty,
239
+ Err ( _) => {
240
+ return self . def_target_features . clone ( ) ;
241
+ }
242
+ } ;
243
+ let sig = tcx. instantiate_bound_regions_with_erased ( ty. fn_sig ( tcx) ) ;
244
+ sig. inputs ( ) . to_vec ( )
245
+ }
246
+ } ;
247
+ let mut additional_features = vec ! [ ] ;
248
+ for input in inputs {
249
+ extend_with_struct_target_features ( tcx, param_env. and ( input) , & mut additional_features) ;
250
+ }
251
+ if additional_features. is_empty ( ) {
252
+ self . def_target_features . clone ( )
253
+ } else {
254
+ additional_features. extend_from_slice ( & self . def_target_features ) ;
255
+ additional_features. sort_by_key ( |a| ( a. name , a. implied ) ) ;
256
+ additional_features. dedup_by_key ( |a| a. name ) ;
257
+ additional_features
258
+ }
259
+ }
180
260
}
0 commit comments