11use crate :: traits:: * ;
22
3- use rustc_middle:: ty:: { self , Ty } ;
3+ use rustc_middle:: ty:: { self , subst:: GenericArgKind , ExistentialPredicate , Ty , TyCtxt } ;
4+ use rustc_session:: config:: Lto ;
5+ use rustc_symbol_mangling:: typeid_for_trait_ref;
46use rustc_target:: abi:: call:: FnAbi ;
57
68#[ derive( Copy , Clone , Debug ) ]
@@ -15,20 +17,32 @@ impl<'a, 'tcx> VirtualIndex {
1517 self ,
1618 bx : & mut Bx ,
1719 llvtable : Bx :: Value ,
20+ ty : Ty < ' tcx > ,
1821 fn_abi : & FnAbi < ' tcx , Ty < ' tcx > > ,
1922 ) -> Bx :: Value {
2023 // Load the data pointer from the object.
21- debug ! ( "get_fn({:?}, {:?})" , llvtable, self ) ;
22-
24+ debug ! ( "get_fn({llvtable:?}, {ty:?}, {self:?})" ) ;
2325 let llty = bx. fn_ptr_backend_type ( fn_abi) ;
2426 let llvtable = bx. pointercast ( llvtable, bx. type_ptr_to ( llty) ) ;
25- let ptr_align = bx. tcx ( ) . data_layout . pointer_align . abi ;
26- let gep = bx. inbounds_gep ( llty, llvtable, & [ bx. const_usize ( self . 0 ) ] ) ;
27- let ptr = bx. load ( llty, gep, ptr_align) ;
28- bx. nonnull_metadata ( ptr) ;
29- // Vtable loads are invariant.
30- bx. set_invariant_load ( ptr) ;
31- ptr
27+
28+ if bx. cx ( ) . sess ( ) . opts . debugging_opts . virtual_function_elimination
29+ && bx. cx ( ) . sess ( ) . lto ( ) == Lto :: Fat
30+ {
31+ let typeid =
32+ bx. typeid_metadata ( typeid_for_trait_ref ( bx. tcx ( ) , get_trait_ref ( bx. tcx ( ) , ty) ) ) ;
33+ let vtable_byte_offset = self . 0 * bx. data_layout ( ) . pointer_size . bytes ( ) ;
34+ let type_checked_load = bx. type_checked_load ( llvtable, vtable_byte_offset, typeid) ;
35+ let func = bx. extract_value ( type_checked_load, 0 ) ;
36+ bx. pointercast ( func, llty)
37+ } else {
38+ let ptr_align = bx. tcx ( ) . data_layout . pointer_align . abi ;
39+ let gep = bx. inbounds_gep ( llty, llvtable, & [ bx. const_usize ( self . 0 ) ] ) ;
40+ let ptr = bx. load ( llty, gep, ptr_align) ;
41+ bx. nonnull_metadata ( ptr) ;
42+ // Vtable loads are invariant.
43+ bx. set_invariant_load ( ptr) ;
44+ ptr
45+ }
3246 }
3347
3448 pub fn get_usize < Bx : BuilderMethods < ' a , ' tcx > > (
@@ -50,6 +64,24 @@ impl<'a, 'tcx> VirtualIndex {
5064 }
5165}
5266
67+ fn get_trait_ref < ' tcx > ( tcx : TyCtxt < ' tcx > , ty : Ty < ' tcx > ) -> ty:: PolyExistentialTraitRef < ' tcx > {
68+ for arg in ty. peel_refs ( ) . walk ( ) {
69+ if let GenericArgKind :: Type ( ty) = arg. unpack ( ) {
70+ if let ty:: Dynamic ( trait_refs, _) = ty. kind ( ) {
71+ return trait_refs[ 0 ] . map_bound ( |trait_ref| match trait_ref {
72+ ExistentialPredicate :: Trait ( tr) => tr,
73+ ExistentialPredicate :: Projection ( proj) => proj. trait_ref ( tcx) ,
74+ ExistentialPredicate :: AutoTrait ( _) => {
75+ bug ! ( "auto traits don't have functions" )
76+ }
77+ } ) ;
78+ }
79+ }
80+ }
81+
82+ bug ! ( "expected a `dyn Trait` ty, found {ty:?}" )
83+ }
84+
5385/// Creates a dynamic vtable for the given type and vtable origin.
5486/// This is used only for objects.
5587///
0 commit comments