@@ -28,27 +28,9 @@ impl<'a, 'tcx> VirtualIndex {
2828
2929 let llty = bx. fn_ptr_backend_type ( fn_abi) ;
3030 let ptr_size = bx. data_layout ( ) . pointer_size ;
31- let ptr_align = bx. data_layout ( ) . pointer_align . abi ;
3231 let vtable_byte_offset = self . 0 * ptr_size. bytes ( ) ;
3332
34- if bx. cx ( ) . sess ( ) . opts . unstable_opts . virtual_function_elimination
35- && bx. cx ( ) . sess ( ) . lto ( ) == Lto :: Fat
36- {
37- let typeid = bx
38- . typeid_metadata ( typeid_for_trait_ref ( bx. tcx ( ) , expect_dyn_trait_in_self ( ty) ) )
39- . unwrap ( ) ;
40- let func = bx. type_checked_load ( llvtable, vtable_byte_offset, typeid) ;
41- func
42- } else {
43- let gep = bx. inbounds_ptradd ( llvtable, bx. const_usize ( vtable_byte_offset) ) ;
44- let ptr = bx. load ( llty, gep, ptr_align) ;
45- // VTable loads are invariant.
46- bx. set_invariant_load ( ptr) ;
47- if nonnull {
48- bx. nonnull_metadata ( ptr) ;
49- }
50- ptr
51- }
33+ load_vtable ( bx, llvtable, llty, vtable_byte_offset, ty, nonnull)
5234 }
5335
5436 pub ( crate ) fn get_optional_fn < Bx : BuilderMethods < ' a , ' tcx > > (
@@ -75,31 +57,27 @@ impl<'a, 'tcx> VirtualIndex {
7557 self ,
7658 bx : & mut Bx ,
7759 llvtable : Bx :: Value ,
60+ ty : Ty < ' tcx > ,
7861 ) -> Bx :: Value {
7962 // Load the data pointer from the object.
8063 debug ! ( "get_int({:?}, {:?})" , llvtable, self ) ;
8164
8265 let llty = bx. type_isize ( ) ;
8366 let ptr_size = bx. data_layout ( ) . pointer_size ;
84- let ptr_align = bx. data_layout ( ) . pointer_align . abi ;
8567 let vtable_byte_offset = self . 0 * ptr_size. bytes ( ) ;
8668
87- let gep = bx. inbounds_ptradd ( llvtable, bx. const_usize ( vtable_byte_offset) ) ;
88- let ptr = bx. load ( llty, gep, ptr_align) ;
89- // VTable loads are invariant.
90- bx. set_invariant_load ( ptr) ;
91- ptr
69+ load_vtable ( bx, llvtable, llty, vtable_byte_offset, ty, false )
9270 }
9371}
9472
9573/// This takes a valid `self` receiver type and extracts the principal trait
96- /// ref of the type.
97- fn expect_dyn_trait_in_self ( ty : Ty < ' _ > ) -> ty:: PolyExistentialTraitRef < ' _ > {
74+ /// ref of the type. Return `None` if there is no principal trait.
75+ fn dyn_trait_in_self ( ty : Ty < ' _ > ) -> Option < ty:: PolyExistentialTraitRef < ' _ > > {
9876 for arg in ty. peel_refs ( ) . walk ( ) {
9977 if let GenericArgKind :: Type ( ty) = arg. unpack ( )
10078 && let ty:: Dynamic ( data, _, _) = ty. kind ( )
10179 {
102- return data. principal ( ) . expect ( "expected principal trait object" ) ;
80+ return data. principal ( ) ;
10381 }
10482 }
10583
@@ -138,3 +116,36 @@ pub(crate) fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>(
138116 cx. vtables ( ) . borrow_mut ( ) . insert ( ( ty, trait_ref) , vtable) ;
139117 vtable
140118}
119+
120+ /// Call this function whenever you need to load a vtable.
121+ pub ( crate ) fn load_vtable < ' a , ' tcx , Bx : BuilderMethods < ' a , ' tcx > > (
122+ bx : & mut Bx ,
123+ llvtable : Bx :: Value ,
124+ llty : Bx :: Type ,
125+ vtable_byte_offset : u64 ,
126+ ty : Ty < ' tcx > ,
127+ nonnull : bool ,
128+ ) -> Bx :: Value {
129+ let ptr_align = bx. data_layout ( ) . pointer_align . abi ;
130+
131+ if bx. cx ( ) . sess ( ) . opts . unstable_opts . virtual_function_elimination
132+ && bx. cx ( ) . sess ( ) . lto ( ) == Lto :: Fat
133+ {
134+ if let Some ( trait_ref) = dyn_trait_in_self ( ty) {
135+ let typeid = bx. typeid_metadata ( typeid_for_trait_ref ( bx. tcx ( ) , trait_ref) ) . unwrap ( ) ;
136+ let func = bx. type_checked_load ( llvtable, vtable_byte_offset, typeid) ;
137+ return func;
138+ } else if nonnull {
139+ bug ! ( "load nonnull value from a vtable without a principal trait" )
140+ }
141+ }
142+
143+ let gep = bx. inbounds_ptradd ( llvtable, bx. const_usize ( vtable_byte_offset) ) ;
144+ let ptr = bx. load ( llty, gep, ptr_align) ;
145+ // VTable loads are invariant.
146+ bx. set_invariant_load ( ptr) ;
147+ if nonnull {
148+ bx. nonnull_metadata ( ptr) ;
149+ }
150+ ptr
151+ }
0 commit comments