1
1
use std:: convert:: TryFrom ;
2
2
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
+ } ;
4
7
use rustc_middle:: ty:: {
5
8
self , Instance , Ty , VtblEntry , COMMON_VTABLE_ENTRIES , COMMON_VTABLE_ENTRIES_ALIGN ,
6
9
COMMON_VTABLE_ENTRIES_DROPINPLACE , COMMON_VTABLE_ENTRIES_SIZE ,
7
10
} ;
8
11
use rustc_target:: abi:: { Align , LayoutOf , Size } ;
9
12
13
+ use super :: alloc_range;
10
14
use 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
+ }
12
27
13
28
impl < ' mir , ' tcx : ' mir , M : Machine < ' mir , ' tcx > > InterpCx < ' mir , ' tcx , M > {
14
29
/// 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> {
60
75
// `get_vtable` in `rust_codegen_llvm/meth.rs`.
61
76
// /////////////////////////////////////////////////////////////////////////////////////////
62
77
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) ;
67
79
68
80
// No need to do any alignment checks on the memory accesses below, because we know the
69
81
// 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> {
72
84
. iter ( )
73
85
. map ( |entry| -> InterpResult < ' tcx , _ > {
74
86
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
+ }
76
93
VtblEntry :: MetadataSize => Ok ( Some ( Scalar :: from_uint ( size, ptr_size) . into ( ) ) ) ,
77
94
VtblEntry :: MetadataAlign => Ok ( Some ( Scalar :: from_uint ( align, ptr_size) . into ( ) ) ) ,
78
95
VtblEntry :: Vacant => Ok ( None ) ,
79
96
VtblEntry :: Method ( def_id, substs) => {
80
97
// Prepare the fn ptr we write into the vtable.
81
98
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)
83
100
. 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) ;
85
103
Ok ( Some ( fn_ptr. into ( ) ) )
86
104
}
87
105
}
88
106
} )
89
107
. collect :: < Result < Vec < _ > , _ > > ( ) ?;
90
- let mut vtable_alloc =
91
- self . memory . get_mut ( vtable. into ( ) , vtable_size, ptr_align) ?. expect ( "not a ZST" ) ;
92
108
for ( idx, scalar) in scalars. into_iter ( ) . enumerate ( ) {
93
109
if let Some ( scalar) = scalar {
94
110
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) ?;
96
114
}
97
115
}
98
116
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) ) ?;
100
119
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( ) ) ;
103
121
104
- Ok ( vtable )
122
+ Ok ( vtable_ptr )
105
123
}
106
124
107
125
/// Resolves the function at the specified slot in the provided
0 commit comments