@@ -5,6 +5,7 @@ use rustc_target::abi::Align;
55use  rustc_target:: spec:: SanitizerSet ; 
66
77use  crate :: mir:: mono:: Linkage ; 
8+ use  crate :: ty:: { self ,  Instance ,  ParamEnv ,  Ty ,  TyCtxt } ; 
89
910#[ derive( Clone ,  TyEncodable ,  TyDecodable ,  HashStable ,  Debug ) ]  
1011pub  struct  CodegenFnAttrs  { 
@@ -28,7 +29,7 @@ pub struct CodegenFnAttrs {
2829pub  link_ordinal :  Option < u16 > , 
2930    /// All the target features that are enabled for this function. Some features might be enabled 
3031/// implicitly. 
31- pub  target_features :  Vec < TargetFeature > , 
32+ pub  def_target_features :  Vec < TargetFeature > , 
3233    /// The `#[linkage = "..."]` attribute on Rust-defined items and the value we found. 
3334pub  linkage :  Option < Linkage > , 
3435    /// The `#[linkage = "..."]` attribute on foreign items and the value we found. 
@@ -139,6 +140,30 @@ bitflags::bitflags! {
139140} 
140141rustc_data_structures:: external_bitflags_debug! {  CodegenFnAttrFlags  } 
141142
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+ 
142167impl  CodegenFnAttrs  { 
143168    pub  const  EMPTY :  & ' static  Self  = & Self :: new ( ) ; 
144169
@@ -150,7 +175,7 @@ impl CodegenFnAttrs {
150175            export_name :  None , 
151176            link_name :  None , 
152177            link_ordinal :  None , 
153-             target_features :  vec ! [ ] , 
178+             def_target_features :  vec ! [ ] , 
154179            linkage :  None , 
155180            import_linkage :  None , 
156181            link_section :  None , 
@@ -177,4 +202,59 @@ impl CodegenFnAttrs {
177202                Some ( _)  => true , 
178203            } 
179204    } 
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+     } 
180260} 
0 commit comments