|
1 |
| -use std::convert::TryFrom; |
| 1 | +use super::{FnVal, InterpCx, Machine, Memory, MemoryKind}; |
2 | 2 |
|
3 | 3 | use rustc_middle::mir::interpret::{InterpResult, Pointer, PointerArithmetic, Scalar};
|
4 | 4 | use rustc_middle::ty::{self, Instance, Ty, TypeFoldable};
|
5 | 5 | use rustc_target::abi::{Align, HasDataLayout, LayoutOf, Size};
|
6 | 6 |
|
7 |
| -use super::{FnVal, InterpCx, Machine, MemoryKind}; |
| 7 | +use std::convert::TryFrom; |
8 | 8 |
|
9 | 9 | impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
10 | 10 | /// Creates a dynamic vtable for the given type and vtable origin. This is used only for
|
@@ -62,34 +62,35 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
62 | 62 | );
|
63 | 63 | let tcx = &*self.tcx;
|
64 | 64 |
|
| 65 | + // Keep track of current position within vtable and write to there, offsetting position by |
| 66 | + // one pointer size each time. |
| 67 | + let mut cur_ptr = vtable; |
| 68 | + let mut write_ptr = |memory: &mut Memory<'mir, 'tcx, M>, val| -> InterpResult<'_> { |
| 69 | + let res = memory |
| 70 | + .get_raw_mut(cur_ptr.alloc_id)? |
| 71 | + .write_ptr_sized(tcx, cur_ptr, val)?; |
| 72 | + cur_ptr = cur_ptr.offset(ptr_size, tcx)?; |
| 73 | + Ok(res) |
| 74 | + }; |
| 75 | + |
65 | 76 | let drop = Instance::resolve_drop_in_place(*tcx, ty);
|
66 | 77 | let drop = self.memory.create_fn_alloc(FnVal::Instance(drop));
|
67 | 78 |
|
68 | 79 | // No need to do any alignment checks on the memory accesses below, because we know the
|
69 |
| - // allocation is correctly aligned as we created it above. Also we're only offsetting by |
70 |
| - // multiples of `ptr_align`, which means that it will stay aligned to `ptr_align`. |
71 |
| - let vtable_alloc = self.memory.get_raw_mut(vtable.alloc_id)?; |
72 |
| - vtable_alloc.write_ptr_sized(tcx, vtable, drop.into())?; |
73 |
| - |
74 |
| - let size_ptr = vtable.offset(ptr_size, tcx)?; |
75 |
| - vtable_alloc.write_ptr_sized(tcx, size_ptr, Scalar::from_uint(size, ptr_size).into())?; |
76 |
| - let align_ptr = vtable.offset(ptr_size * 2, tcx)?; |
77 |
| - vtable_alloc.write_ptr_sized(tcx, align_ptr, Scalar::from_uint(align, ptr_size).into())?; |
| 80 | + // allocation is correctly aligned, as we created it above. Also. we're only offsetting |
| 81 | + // by multiples of `ptr_align`, which means that it will stay aligned to `ptr_align`. |
| 82 | + write_ptr(&mut self.memory, Scalar::Ptr(drop).into())?; |
| 83 | + write_ptr(&mut self.memory, Scalar::from_uint(size, ptr_size).into())?; |
| 84 | + write_ptr(&mut self.memory, Scalar::from_uint(align, ptr_size).into())?; |
78 | 85 |
|
79 |
| - for (i, method) in methods.iter().enumerate() { |
| 86 | + for method in methods.iter() { |
80 | 87 | if let Some((def_id, substs)) = *method {
|
81 |
| - // resolve for vtable: insert shims where needed |
| 88 | + // Resolve for vtable; insert shims where needed. |
82 | 89 | let instance =
|
83 | 90 | ty::Instance::resolve_for_vtable(*tcx, self.param_env, def_id, substs)
|
84 | 91 | .ok_or_else(|| err_inval!(TooGeneric))?;
|
85 | 92 | let fn_ptr = self.memory.create_fn_alloc(FnVal::Instance(instance));
|
86 |
| - // We cannot use `vtable_allic` as we are creating fn ptrs in this loop. |
87 |
| - let method_ptr = vtable.offset(ptr_size * (3 + i as u64), tcx)?; |
88 |
| - self.memory.get_raw_mut(vtable.alloc_id)?.write_ptr_sized( |
89 |
| - tcx, |
90 |
| - method_ptr, |
91 |
| - fn_ptr.into(), |
92 |
| - )?; |
| 93 | + write_ptr(&mut self.memory, Scalar::Ptr(fn_ptr).into())?; |
93 | 94 | }
|
94 | 95 | }
|
95 | 96 |
|
@@ -179,7 +180,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
|
179 | 180 | if size >= self.tcx.data_layout().obj_size_bound() {
|
180 | 181 | throw_ub_format!(
|
181 | 182 | "invalid vtable: \
|
182 |
| - size is bigger than largest supported object" |
| 183 | + size is bigger than largest supported object" |
183 | 184 | );
|
184 | 185 | }
|
185 | 186 | Ok((Size::from_bytes(size), Align::from_bytes(align).unwrap()))
|
|
0 commit comments