11use std:: convert:: TryFrom ;
22
3- use rustc_middle:: mir:: interpret:: { InterpResult , Pointer , PointerArithmetic , Scalar } ;
3+ use rustc_middle:: mir:: interpret:: {
4+ AllocError , InterpError , InterpResult , Pointer , PointerArithmetic , Scalar ,
5+ UndefinedBehaviorInfo , UnsupportedOpInfo ,
6+ } ;
47use rustc_middle:: ty:: {
58 self , Instance , Ty , VtblEntry , COMMON_VTABLE_ENTRIES , COMMON_VTABLE_ENTRIES_ALIGN ,
69 COMMON_VTABLE_ENTRIES_DROPINPLACE , COMMON_VTABLE_ENTRIES_SIZE ,
710} ;
811use rustc_target:: abi:: { Align , LayoutOf , Size } ;
912
13+ use super :: alloc_range;
1014use super :: util:: ensure_monomorphic_enough;
11- use super :: { FnVal , InterpCx , Machine , MemoryKind } ;
15+ use super :: { Allocation , FnVal , InterpCx , Machine } ;
16+
17+ fn vtable_alloc_error_to_interp_error < ' tcx > ( error : AllocError ) -> InterpError < ' tcx > {
18+ match error {
19+ AllocError :: ReadPointerAsBytes => {
20+ InterpError :: Unsupported ( UnsupportedOpInfo :: ReadPointerAsBytes )
21+ }
22+ AllocError :: InvalidUninitBytes ( _info) => {
23+ InterpError :: UndefinedBehavior ( UndefinedBehaviorInfo :: InvalidUninitBytes ( None ) )
24+ }
25+ }
26+ }
1227
1328impl < ' mir , ' tcx : ' mir , M : Machine < ' mir , ' tcx > > InterpCx < ' mir , ' tcx , M > {
1429 /// Creates a dynamic vtable for the given type and vtable origin. This is used only for
@@ -60,10 +75,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
6075 // `get_vtable` in `rust_codegen_llvm/meth.rs`.
6176 // /////////////////////////////////////////////////////////////////////////////////////////
6277 let vtable_size = ptr_size * u64:: try_from ( vtable_entries. len ( ) ) . unwrap ( ) ;
63- let vtable = self . memory . allocate ( vtable_size, ptr_align, MemoryKind :: Vtable ) ;
64-
65- let drop = Instance :: resolve_drop_in_place ( tcx, ty) ;
66- let drop = self . memory . create_fn_alloc ( FnVal :: Instance ( drop) ) ;
78+ let mut vtable = Allocation :: uninit ( vtable_size, ptr_align) ;
6779
6880 // No need to do any alignment checks on the memory accesses below, because we know the
6981 // allocation is correctly aligned as we created it above. Also we're only offsetting by
@@ -72,36 +84,42 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
7284 . iter ( )
7385 . map ( |entry| -> InterpResult < ' tcx , _ > {
7486 match entry {
75- VtblEntry :: MetadataDropInPlace => Ok ( Some ( drop. into ( ) ) ) ,
87+ VtblEntry :: MetadataDropInPlace => {
88+ let instance = Instance :: resolve_drop_in_place ( tcx, ty) ;
89+ let fn_alloc_id = tcx. create_fn_alloc ( instance) ;
90+ let fn_ptr = Pointer :: from ( fn_alloc_id) ;
91+ Ok ( Some ( fn_ptr. into ( ) ) )
92+ }
7693 VtblEntry :: MetadataSize => Ok ( Some ( Scalar :: from_uint ( size, ptr_size) . into ( ) ) ) ,
7794 VtblEntry :: MetadataAlign => Ok ( Some ( Scalar :: from_uint ( align, ptr_size) . into ( ) ) ) ,
7895 VtblEntry :: Vacant => Ok ( None ) ,
7996 VtblEntry :: Method ( def_id, substs) => {
8097 // Prepare the fn ptr we write into the vtable.
8198 let instance =
82- ty :: Instance :: resolve_for_vtable ( tcx, self . param_env , * def_id, substs)
99+ Instance :: resolve_for_vtable ( tcx, self . param_env , * def_id, substs)
83100 . ok_or_else ( || err_inval ! ( TooGeneric ) ) ?;
84- let fn_ptr = self . memory . create_fn_alloc ( FnVal :: Instance ( instance) ) ;
101+ let fn_alloc_id = tcx. create_fn_alloc ( instance) ;
102+ let fn_ptr = Pointer :: from ( fn_alloc_id) ;
85103 Ok ( Some ( fn_ptr. into ( ) ) )
86104 }
87105 }
88106 } )
89107 . collect :: < Result < Vec < _ > , _ > > ( ) ?;
90- let mut vtable_alloc =
91- self . memory . get_mut ( vtable. into ( ) , vtable_size, ptr_align) ?. expect ( "not a ZST" ) ;
92108 for ( idx, scalar) in scalars. into_iter ( ) . enumerate ( ) {
93109 if let Some ( scalar) = scalar {
94110 let idx: u64 = u64:: try_from ( idx) . unwrap ( ) ;
95- vtable_alloc. write_ptr_sized ( ptr_size * idx, scalar) ?;
111+ vtable
112+ . write_scalar ( self , alloc_range ( ptr_size * idx, ptr_size) , scalar)
113+ . map_err ( vtable_alloc_error_to_interp_error) ?;
96114 }
97115 }
98116
99- M :: after_static_mem_initialized ( self , vtable, vtable_size) ?;
117+ let vtable_id = tcx. create_memory_alloc ( tcx. intern_const_alloc ( vtable) ) ;
118+ let vtable_ptr = self . memory . global_base_pointer ( Pointer :: from ( vtable_id) ) ?;
100119
101- self . memory . mark_immutable ( vtable. alloc_id ) ?;
102- assert ! ( self . vtables. insert( ( ty, poly_trait_ref) , vtable) . is_none( ) ) ;
120+ assert ! ( self . vtables. insert( ( ty, poly_trait_ref) , vtable_ptr) . is_none( ) ) ;
103121
104- Ok ( vtable )
122+ Ok ( vtable_ptr )
105123 }
106124
107125 /// Resolves the function at the specified slot in the provided
0 commit comments