@@ -10,14 +10,15 @@ use log::trace;
10
10
11
11
use rustc_hir:: def:: { DefKind , Namespace } ;
12
12
use rustc_hir:: def_id:: { DefId , CRATE_DEF_INDEX } ;
13
+ use rustc_index:: IndexVec ;
13
14
use rustc_middle:: mir;
14
15
use rustc_middle:: ty:: {
15
16
self ,
16
17
layout:: { LayoutOf , TyAndLayout } ,
17
18
List , TyCtxt ,
18
19
} ;
19
20
use rustc_span:: { def_id:: CrateNum , sym, Span , Symbol } ;
20
- use rustc_target:: abi:: { Align , FieldsShape , Size , Variants } ;
21
+ use rustc_target:: abi:: { Align , FieldIdx , FieldsShape , Size , Variants } ;
21
22
use rustc_target:: spec:: abi:: Abi ;
22
23
23
24
use rand:: RngCore ;
@@ -229,20 +230,20 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
229
230
this. layout_of ( ty) . unwrap ( )
230
231
}
231
232
232
- /// Project to the given *named* field of the mplace (which must be a struct or union type).
233
- fn mplace_field_named (
233
+ /// Project to the given *named* field (which must be a struct or union type).
234
+ fn project_field_named < P : Projectable < ' mir , ' tcx , Provenance > > (
234
235
& self ,
235
- mplace : & MPlaceTy < ' tcx , Provenance > ,
236
+ base : & P ,
236
237
name : & str ,
237
- ) -> InterpResult < ' tcx , MPlaceTy < ' tcx , Provenance > > {
238
+ ) -> InterpResult < ' tcx , P > {
238
239
let this = self . eval_context_ref ( ) ;
239
- let adt = mplace . layout . ty . ty_adt_def ( ) . unwrap ( ) ;
240
+ let adt = base . layout ( ) . ty . ty_adt_def ( ) . unwrap ( ) ;
240
241
for ( idx, field) in adt. non_enum_variant ( ) . fields . iter ( ) . enumerate ( ) {
241
242
if field. name . as_str ( ) == name {
242
- return this. mplace_field ( mplace , idx) ;
243
+ return this. project_field ( base , idx) ;
243
244
}
244
245
}
245
- bug ! ( "No field named {} in type {}" , name, mplace . layout. ty) ;
246
+ bug ! ( "No field named {} in type {}" , name, base . layout( ) . ty) ;
246
247
}
247
248
248
249
/// Write an int of the appropriate size to `dest`. The target type may be signed or unsigned,
@@ -270,7 +271,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
270
271
) -> InterpResult < ' tcx > {
271
272
let this = self . eval_context_mut ( ) ;
272
273
for ( idx, & val) in values. iter ( ) . enumerate ( ) {
273
- let field = this. mplace_field ( dest, idx) ?;
274
+ let field = this. project_field ( dest, idx) ?;
274
275
this. write_int ( val, & field. into ( ) ) ?;
275
276
}
276
277
Ok ( ( ) )
@@ -284,7 +285,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
284
285
) -> InterpResult < ' tcx > {
285
286
let this = self . eval_context_mut ( ) ;
286
287
for & ( name, val) in values. iter ( ) {
287
- let field = this. mplace_field_named ( dest, name) ?;
288
+ let field = this. project_field_named ( dest, name) ?;
288
289
this. write_int ( val, & field. into ( ) ) ?;
289
290
}
290
291
Ok ( ( ) )
@@ -301,8 +302,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
301
302
}
302
303
303
304
/// Get the `Place` for a local
304
- fn local_place ( & mut self , local : mir:: Local ) -> InterpResult < ' tcx , PlaceTy < ' tcx , Provenance > > {
305
- let this = self . eval_context_mut ( ) ;
305
+ fn local_place ( & self , local : mir:: Local ) -> InterpResult < ' tcx , PlaceTy < ' tcx , Provenance > > {
306
+ let this = self . eval_context_ref ( ) ;
306
307
let place = mir:: Place { local, projection : List :: empty ( ) } ;
307
308
this. eval_place ( place)
308
309
}
@@ -479,6 +480,16 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
479
480
self . ecx
480
481
}
481
482
483
+ fn aggregate_field_order ( memory_index : & IndexVec < FieldIdx , u32 > , idx : usize ) -> usize {
484
+ // We need to do an *inverse* lookup: find the field that has position `idx` in memory order.
485
+ for ( src_field, & mem_pos) in memory_index. iter_enumerated ( ) {
486
+ if mem_pos as usize == idx {
487
+ return src_field. as_usize ( ) ;
488
+ }
489
+ }
490
+ panic ! ( "invalid `memory_index`, could not find {}-th field in memory order" , idx) ;
491
+ }
492
+
482
493
// Hook to detect `UnsafeCell`.
483
494
fn visit_value ( & mut self , v : & MPlaceTy < ' tcx , Provenance > ) -> InterpResult < ' tcx > {
484
495
trace ! ( "UnsafeCellVisitor: {:?} {:?}" , * v, v. layout. ty) ;
@@ -524,33 +535,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
524
535
}
525
536
}
526
537
527
- // Make sure we visit aggregates in increasing offset order.
528
- fn visit_aggregate (
529
- & mut self ,
530
- place : & MPlaceTy < ' tcx , Provenance > ,
531
- fields : impl Iterator < Item = InterpResult < ' tcx , MPlaceTy < ' tcx , Provenance > > > ,
532
- ) -> InterpResult < ' tcx > {
533
- match place. layout . fields {
534
- FieldsShape :: Array { .. } => {
535
- // For the array layout, we know the iterator will yield sorted elements so
536
- // we can avoid the allocation.
537
- self . walk_aggregate ( place, fields)
538
- }
539
- FieldsShape :: Arbitrary { .. } => {
540
- // Gather the subplaces and sort them before visiting.
541
- let mut places = fields
542
- . collect :: < InterpResult < ' tcx , Vec < MPlaceTy < ' tcx , Provenance > > > > ( ) ?;
543
- // we just compare offsets, the abs. value never matters
544
- places. sort_by_key ( |place| place. ptr . addr ( ) ) ;
545
- self . walk_aggregate ( place, places. into_iter ( ) . map ( Ok ) )
546
- }
547
- FieldsShape :: Union { .. } | FieldsShape :: Primitive => {
548
- // Uh, what?
549
- bug ! ( "unions/primitives are not aggregates we should ever visit" )
550
- }
551
- }
552
- }
553
-
554
538
fn visit_union (
555
539
& mut self ,
556
540
_v : & MPlaceTy < ' tcx , Provenance > ,
@@ -746,7 +730,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
746
730
Ok ( mplace)
747
731
}
748
732
749
- fn deref_pointer_as (
733
+ /// Deref' a pointer *without* checking that the place is dereferenceable.
734
+ fn deref_pointer_unchecked (
750
735
& self ,
751
736
val : & ImmTy < ' tcx , Provenance > ,
752
737
layout : TyAndLayout < ' tcx > ,
@@ -811,10 +796,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
811
796
tp : & MPlaceTy < ' tcx , Provenance > ,
812
797
) -> InterpResult < ' tcx , Option < Duration > > {
813
798
let this = self . eval_context_mut ( ) ;
814
- let seconds_place = this. mplace_field ( tp, 0 ) ?;
799
+ let seconds_place = this. project_field ( tp, 0 ) ?;
815
800
let seconds_scalar = this. read_scalar ( & seconds_place. into ( ) ) ?;
816
801
let seconds = seconds_scalar. to_target_isize ( this) ?;
817
- let nanoseconds_place = this. mplace_field ( tp, 1 ) ?;
802
+ let nanoseconds_place = this. project_field ( tp, 1 ) ?;
818
803
let nanoseconds_scalar = this. read_scalar ( & nanoseconds_place. into ( ) ) ?;
819
804
let nanoseconds = nanoseconds_scalar. to_target_isize ( this) ?;
820
805
0 commit comments