@@ -28,27 +28,9 @@ impl<'a, 'tcx> VirtualIndex {
28
28
29
29
let llty = bx. fn_ptr_backend_type ( fn_abi) ;
30
30
let ptr_size = bx. data_layout ( ) . pointer_size ;
31
- let ptr_align = bx. data_layout ( ) . pointer_align . abi ;
32
31
let vtable_byte_offset = self . 0 * ptr_size. bytes ( ) ;
33
32
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)
52
34
}
53
35
54
36
pub ( crate ) fn get_optional_fn < Bx : BuilderMethods < ' a , ' tcx > > (
@@ -75,31 +57,27 @@ impl<'a, 'tcx> VirtualIndex {
75
57
self ,
76
58
bx : & mut Bx ,
77
59
llvtable : Bx :: Value ,
60
+ ty : Ty < ' tcx > ,
78
61
) -> Bx :: Value {
79
62
// Load the data pointer from the object.
80
63
debug ! ( "get_int({:?}, {:?})" , llvtable, self ) ;
81
64
82
65
let llty = bx. type_isize ( ) ;
83
66
let ptr_size = bx. data_layout ( ) . pointer_size ;
84
- let ptr_align = bx. data_layout ( ) . pointer_align . abi ;
85
67
let vtable_byte_offset = self . 0 * ptr_size. bytes ( ) ;
86
68
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 )
92
70
}
93
71
}
94
72
95
73
/// 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 < ' _ > > {
98
76
for arg in ty. peel_refs ( ) . walk ( ) {
99
77
if let GenericArgKind :: Type ( ty) = arg. unpack ( )
100
78
&& let ty:: Dynamic ( data, _, _) = ty. kind ( )
101
79
{
102
- return data. principal ( ) . expect ( "expected principal trait object" ) ;
80
+ return data. principal ( ) ;
103
81
}
104
82
}
105
83
@@ -138,3 +116,36 @@ pub(crate) fn get_vtable<'tcx, Cx: CodegenMethods<'tcx>>(
138
116
cx. vtables ( ) . borrow_mut ( ) . insert ( ( ty, trait_ref) , vtable) ;
139
117
vtable
140
118
}
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