@@ -21,7 +21,12 @@ use rustc_target::callconv::{
2121use tracing:: debug;
2222
2323pub ( crate ) fn provide ( providers : & mut Providers ) {
24- * providers = Providers { fn_abi_of_fn_ptr, fn_abi_of_instance, ..* providers } ;
24+ * providers = Providers {
25+ fn_abi_of_fn_ptr,
26+ fn_abi_of_instance_no_deduced_attrs,
27+ fn_abi_of_instance,
28+ ..* providers
29+ } ;
2530}
2631
2732// NOTE(eddyb) this is private to avoid using it from outside of
@@ -250,25 +255,71 @@ fn fn_abi_of_fn_ptr<'tcx>(
250255 let ty:: PseudoCanonicalInput { typing_env, value : ( sig, extra_args) } = query;
251256 fn_abi_new_uncached (
252257 & LayoutCx :: new ( tcx, typing_env) ,
253- tcx. instantiate_bound_regions_with_erased ( sig) ,
254- extra_args ,
258+ tcx. normalize_erasing_regions ( typing_env , tcx . instantiate_bound_regions_with_erased ( sig) ) ,
259+ None ,
255260 None ,
261+ false ,
262+ extra_args,
256263 )
257264}
258265
259- fn fn_abi_of_instance < ' tcx > (
266+ fn instance_params < ' tcx > (
260267 tcx : TyCtxt < ' tcx > ,
261268 query : ty:: PseudoCanonicalInput < ' tcx , ( ty:: Instance < ' tcx > , & ' tcx ty:: List < Ty < ' tcx > > ) > ,
262- ) -> Result < & ' tcx FnAbi < ' tcx , Ty < ' tcx > > , & ' tcx FnAbiError < ' tcx > > {
269+ ) -> ( LayoutCx < ' tcx > , ty :: FnSig < ' tcx > , Option < DefId > , Option < Ty < ' tcx > > , bool , & ' tcx [ Ty < ' tcx > ] ) {
263270 let ty:: PseudoCanonicalInput { typing_env, value : ( instance, extra_args) } = query;
271+ let cx = LayoutCx :: new ( tcx, typing_env) ;
272+ let sig =
273+ tcx. normalize_erasing_regions ( typing_env, fn_sig_for_fn_abi ( tcx, instance, typing_env) ) ;
274+ let is_virtual_call = matches ! ( instance. def, ty:: InstanceKind :: Virtual ( ..) ) ;
275+ let is_tls_shim_call = matches ! ( instance. def, ty:: InstanceKind :: ThreadLocalShim ( _) ) ;
276+ (
277+ cx,
278+ sig,
279+ ( !is_virtual_call && !is_tls_shim_call) . then ( || instance. def_id ( ) ) ,
280+ instance. def . requires_caller_location ( tcx) . then ( || tcx. caller_location_ty ( ) ) ,
281+ is_virtual_call,
282+ extra_args,
283+ )
284+ }
285+
286+ fn fn_abi_of_instance_no_deduced_attrs < ' tcx > (
287+ tcx : TyCtxt < ' tcx > ,
288+ query : ty:: PseudoCanonicalInput < ' tcx , ( ty:: Instance < ' tcx > , & ' tcx ty:: List < Ty < ' tcx > > ) > ,
289+ ) -> Result < & ' tcx FnAbi < ' tcx , Ty < ' tcx > > , & ' tcx FnAbiError < ' tcx > > {
290+ let ( cx, sig, determined_fn_def_id, caller_location, is_virtual_call, extra_args) =
291+ instance_params ( tcx, query) ;
264292 fn_abi_new_uncached (
265- & LayoutCx :: new ( tcx, typing_env) ,
266- fn_sig_for_fn_abi ( tcx, instance, typing_env) ,
293+ & cx,
294+ sig,
295+ caller_location,
296+ determined_fn_def_id,
297+ is_virtual_call,
267298 extra_args,
268- Some ( instance) ,
269299 )
270300}
271301
302+ fn fn_abi_of_instance < ' tcx > (
303+ tcx : TyCtxt < ' tcx > ,
304+ query : ty:: PseudoCanonicalInput < ' tcx , ( ty:: Instance < ' tcx > , & ' tcx ty:: List < Ty < ' tcx > > ) > ,
305+ ) -> Result < & ' tcx FnAbi < ' tcx , Ty < ' tcx > > , & ' tcx FnAbiError < ' tcx > > {
306+ tcx. fn_abi_of_instance_no_deduced_attrs ( query) . map ( |fn_abi| {
307+ let ( cx, sig, determined_fn_def_id, ..) = instance_params ( tcx, query) ;
308+ determined_fn_def_id. map_or ( fn_abi, |determined_fn_def_id| {
309+ fn_abi_adjust_for_deduced_attrs (
310+ & cx,
311+ fn_abi,
312+ sig. abi ,
313+ // If this is a virtual call, we cannot pass the `fn_def_id`, as it might call other
314+ // functions from vtable. And for a tls shim, passing the `fn_def_id` would refer to
315+ // the underlying static. Internally, `deduced_param_attrs` attempts to infer attributes
316+ // by visit the function body.
317+ determined_fn_def_id,
318+ )
319+ } )
320+ } )
321+ }
322+
272323// Handle safe Rust thin and wide pointers.
273324fn arg_attrs_for_rust_scalar < ' tcx > (
274325 cx : LayoutCx < ' tcx > ,
@@ -479,27 +530,19 @@ fn fn_abi_sanity_check<'tcx>(
479530 fn_arg_sanity_check ( cx, fn_abi, spec_abi, & fn_abi. ret ) ;
480531}
481532
482- #[ tracing:: instrument( level = "debug" , skip( cx, instance) ) ]
533+ #[ tracing:: instrument(
534+ level = "debug" ,
535+ skip( cx, caller_location, determined_fn_def_id, is_virtual_call)
536+ ) ]
483537fn fn_abi_new_uncached < ' tcx > (
484538 cx : & LayoutCx < ' tcx > ,
485539 sig : ty:: FnSig < ' tcx > ,
540+ caller_location : Option < Ty < ' tcx > > ,
541+ determined_fn_def_id : Option < DefId > ,
542+ is_virtual_call : bool ,
486543 extra_args : & [ Ty < ' tcx > ] ,
487- instance : Option < ty:: Instance < ' tcx > > ,
488544) -> Result < & ' tcx FnAbi < ' tcx , Ty < ' tcx > > , & ' tcx FnAbiError < ' tcx > > {
489545 let tcx = cx. tcx ( ) ;
490- let ( caller_location, determined_fn_def_id, is_virtual_call) = if let Some ( instance) = instance
491- {
492- let is_virtual_call = matches ! ( instance. def, ty:: InstanceKind :: Virtual ( ..) ) ;
493- let is_tls_shim_call = matches ! ( instance. def, ty:: InstanceKind :: ThreadLocalShim ( _) ) ;
494- (
495- instance. def . requires_caller_location ( tcx) . then ( || tcx. caller_location_ty ( ) ) ,
496- if is_virtual_call || is_tls_shim_call { None } else { Some ( instance. def_id ( ) ) } ,
497- is_virtual_call,
498- )
499- } else {
500- ( None , None , false )
501- } ;
502- let sig = tcx. normalize_erasing_regions ( cx. typing_env , sig) ;
503546
504547 let abi_map = AbiMap :: from_target ( & tcx. sess . target ) ;
505548 let conv = abi_map. canonize_abi ( sig. abi , sig. c_variadic ) . unwrap ( ) ;
@@ -575,16 +618,7 @@ fn fn_abi_new_uncached<'tcx>(
575618 sig. abi ,
576619 ) ,
577620 } ;
578- fn_abi_adjust_for_abi (
579- cx,
580- & mut fn_abi,
581- sig. abi ,
582- // If this is a virtual call, we cannot pass the `fn_def_id`, as it might call other
583- // functions from vtable. And for a tls shim, passing the `fn_def_id` would refer to
584- // the underlying static. Internally, `deduced_param_attrs` attempts to infer attributes
585- // by visit the function body.
586- determined_fn_def_id,
587- ) ;
621+ fn_abi_adjust_for_abi ( cx, & mut fn_abi, sig. abi ) ;
588622 debug ! ( "fn_abi_new_uncached = {:?}" , fn_abi) ;
589623 fn_abi_sanity_check ( cx, & fn_abi, sig. abi ) ;
590624 Ok ( tcx. arena . alloc ( fn_abi) )
@@ -595,7 +629,6 @@ fn fn_abi_adjust_for_abi<'tcx>(
595629 cx : & LayoutCx < ' tcx > ,
596630 fn_abi : & mut FnAbi < ' tcx , Ty < ' tcx > > ,
597631 abi : ExternAbi ,
598- fn_def_id : Option < DefId > ,
599632) {
600633 if abi == ExternAbi :: Unadjusted {
601634 // The "unadjusted" ABI passes aggregates in "direct" mode. That's fragile but needed for
@@ -616,30 +649,43 @@ fn fn_abi_adjust_for_abi<'tcx>(
616649 for arg in fn_abi. args . iter_mut ( ) {
617650 unadjust ( arg) ;
618651 }
619- return ;
652+ } else if abi. is_rustic_abi ( ) {
653+ fn_abi. adjust_for_rust_abi ( cx) ;
654+ } else {
655+ fn_abi. adjust_for_foreign_abi ( cx, abi) ;
620656 }
657+ }
621658
659+ #[ tracing:: instrument( level = "trace" , skip( cx) ) ]
660+ fn fn_abi_adjust_for_deduced_attrs < ' tcx > (
661+ cx : & LayoutCx < ' tcx > ,
662+ fn_abi : & ' tcx FnAbi < ' tcx , Ty < ' tcx > > ,
663+ abi : ExternAbi ,
664+ fn_def_id : DefId ,
665+ ) -> & ' tcx FnAbi < ' tcx , Ty < ' tcx > > {
622666 let tcx = cx. tcx ( ) ;
623-
624- if abi. is_rustic_abi ( ) {
625- fn_abi. adjust_for_rust_abi ( cx) ;
626- // Look up the deduced parameter attributes for this function, if we have its def ID and
627- // we're optimizing in non-incremental mode. We'll tag its parameters with those attributes
628- // as appropriate.
629- let deduced =
630- if tcx. sess . opts . optimize != OptLevel :: No && tcx. sess . opts . incremental . is_none ( ) {
631- fn_def_id. map ( |fn_def_id| tcx. deduced_param_attrs ( fn_def_id) ) . unwrap_or_default ( )
632- } else {
633- & [ ]
634- } ;
635- if !deduced. is_empty ( ) {
636- apply_deduced_attributes ( cx, deduced, 0 , & mut fn_abi. ret ) ;
637- for ( arg_idx, arg) in fn_abi. args . iter_mut ( ) . enumerate ( ) {
638- apply_deduced_attributes ( cx, deduced, arg_idx + 1 , arg) ;
639- }
640- }
667+ // Look up the deduced parameter attributes for this function, if we have its def ID and
668+ // we're optimizing in non-incremental mode. We'll tag its parameters with those attributes
669+ // as appropriate.
670+ let deduced = if abi. is_rustic_abi ( )
671+ && tcx. sess . opts . optimize != OptLevel :: No
672+ && tcx. sess . opts . incremental . is_none ( )
673+ {
674+ tcx. deduced_param_attrs ( fn_def_id)
641675 } else {
642- fn_abi. adjust_for_foreign_abi ( cx, abi) ;
676+ & [ ]
677+ } ;
678+ if deduced. is_empty ( ) {
679+ fn_abi
680+ } else {
681+ let mut fn_abi = fn_abi. clone ( ) ;
682+ apply_deduced_attributes ( cx, deduced, 0 , & mut fn_abi. ret ) ;
683+ for ( arg_idx, arg) in fn_abi. args . iter_mut ( ) . enumerate ( ) {
684+ apply_deduced_attributes ( cx, deduced, arg_idx + 1 , arg) ;
685+ }
686+ debug ! ( "fn_abi_adjust_for_deduced_attrs = {:?}" , fn_abi) ;
687+ fn_abi_sanity_check ( cx, & fn_abi, abi) ;
688+ tcx. arena . alloc ( fn_abi)
643689 }
644690}
645691
0 commit comments