@@ -34,7 +34,7 @@ use rustc::mir::interpret::{
34
34
use syntax:: source_map:: { self , Span } ;
35
35
36
36
use super :: {
37
- Value , Operand , MemPlace , MPlaceTy , Place , PlaceExtra ,
37
+ Value , Operand , MemPlace , MPlaceTy , Place ,
38
38
Memory , Machine
39
39
} ;
40
40
@@ -462,90 +462,94 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M
462
462
}
463
463
464
464
/// Return the actual dynamic size and alignment of the place at the given type.
465
- /// Note that the value does not matter if the type is sized. For unsized types,
466
- /// the value has to be a fat pointer, and we only care about the "extra" data in it.
467
- pub fn size_and_align_of_mplace (
465
+ /// Only the "extra" (metadata) part of the place matters.
466
+ pub ( super ) fn size_and_align_of (
468
467
& self ,
469
- mplace : MPlaceTy < ' tcx > ,
468
+ metadata : Option < Scalar > ,
469
+ layout : TyLayout < ' tcx > ,
470
470
) -> EvalResult < ' tcx , ( Size , Align ) > {
471
- if let PlaceExtra :: None = mplace. extra {
472
- assert ! ( !mplace. layout. is_unsized( ) ) ;
473
- Ok ( mplace. layout . size_and_align ( ) )
474
- } else {
475
- let layout = mplace. layout ;
476
- assert ! ( layout. is_unsized( ) ) ;
477
- match layout. ty . sty {
478
- ty:: Adt ( ..) | ty:: Tuple ( ..) => {
479
- // First get the size of all statically known fields.
480
- // Don't use type_of::sizing_type_of because that expects t to be sized,
481
- // and it also rounds up to alignment, which we want to avoid,
482
- // as the unsized field's alignment could be smaller.
483
- assert ! ( !layout. ty. is_simd( ) ) ;
484
- debug ! ( "DST layout: {:?}" , layout) ;
485
-
486
- let sized_size = layout. fields . offset ( layout. fields . count ( ) - 1 ) ;
487
- let sized_align = layout. align ;
488
- debug ! (
489
- "DST {} statically sized prefix size: {:?} align: {:?}" ,
490
- layout. ty,
491
- sized_size,
492
- sized_align
493
- ) ;
494
-
495
- // Recurse to get the size of the dynamically sized field (must be
496
- // the last field).
497
- let field = self . mplace_field ( mplace, layout. fields . count ( ) as u64 - 1 ) ?;
498
- let ( unsized_size, unsized_align) = self . size_and_align_of_mplace ( field) ?;
499
-
500
- // FIXME (#26403, #27023): We should be adding padding
501
- // to `sized_size` (to accommodate the `unsized_align`
502
- // required of the unsized field that follows) before
503
- // summing it with `sized_size`. (Note that since #26403
504
- // is unfixed, we do not yet add the necessary padding
505
- // here. But this is where the add would go.)
506
-
507
- // Return the sum of sizes and max of aligns.
508
- let size = sized_size + unsized_size;
509
-
510
- // Choose max of two known alignments (combined value must
511
- // be aligned according to more restrictive of the two).
512
- let align = sized_align. max ( unsized_align) ;
513
-
514
- // Issue #27023: must add any necessary padding to `size`
515
- // (to make it a multiple of `align`) before returning it.
516
- //
517
- // Namely, the returned size should be, in C notation:
518
- //
519
- // `size + ((size & (align-1)) ? align : 0)`
520
- //
521
- // emulated via the semi-standard fast bit trick:
522
- //
523
- // `(size + (align-1)) & -align`
524
-
525
- Ok ( ( size. abi_align ( align) , align) )
526
- }
527
- ty:: Dynamic ( ..) => {
528
- let vtable = match mplace. extra {
529
- PlaceExtra :: Vtable ( vtable) => vtable,
530
- _ => bug ! ( "Expected vtable" ) ,
531
- } ;
532
- // the second entry in the vtable is the dynamic size of the object.
533
- self . read_size_and_align_from_vtable ( vtable)
534
- }
535
-
536
- ty:: Slice ( _) | ty:: Str => {
537
- let len = match mplace. extra {
538
- PlaceExtra :: Length ( len) => len,
539
- _ => bug ! ( "Expected length" ) ,
540
- } ;
541
- let ( elem_size, align) = layout. field ( self , 0 ) ?. size_and_align ( ) ;
542
- Ok ( ( elem_size * len, align) )
543
- }
471
+ let metadata = match metadata {
472
+ None => {
473
+ assert ! ( !layout. is_unsized( ) ) ;
474
+ return Ok ( layout. size_and_align ( ) )
475
+ }
476
+ Some ( metadata) => {
477
+ assert ! ( layout. is_unsized( ) ) ;
478
+ metadata
479
+ }
480
+ } ;
481
+ match layout. ty . sty {
482
+ ty:: Adt ( ..) | ty:: Tuple ( ..) => {
483
+ // First get the size of all statically known fields.
484
+ // Don't use type_of::sizing_type_of because that expects t to be sized,
485
+ // and it also rounds up to alignment, which we want to avoid,
486
+ // as the unsized field's alignment could be smaller.
487
+ assert ! ( !layout. ty. is_simd( ) ) ;
488
+ debug ! ( "DST layout: {:?}" , layout) ;
489
+
490
+ let sized_size = layout. fields . offset ( layout. fields . count ( ) - 1 ) ;
491
+ let sized_align = layout. align ;
492
+ debug ! (
493
+ "DST {} statically sized prefix size: {:?} align: {:?}" ,
494
+ layout. ty,
495
+ sized_size,
496
+ sized_align
497
+ ) ;
498
+
499
+ // Recurse to get the size of the dynamically sized field (must be
500
+ // the last field).
501
+ let field = layout. field ( self , layout. fields . count ( ) - 1 ) ?;
502
+ let ( unsized_size, unsized_align) = self . size_and_align_of ( Some ( metadata) , field) ?;
503
+
504
+ // FIXME (#26403, #27023): We should be adding padding
505
+ // to `sized_size` (to accommodate the `unsized_align`
506
+ // required of the unsized field that follows) before
507
+ // summing it with `sized_size`. (Note that since #26403
508
+ // is unfixed, we do not yet add the necessary padding
509
+ // here. But this is where the add would go.)
510
+
511
+ // Return the sum of sizes and max of aligns.
512
+ let size = sized_size + unsized_size;
513
+
514
+ // Choose max of two known alignments (combined value must
515
+ // be aligned according to more restrictive of the two).
516
+ let align = sized_align. max ( unsized_align) ;
517
+
518
+ // Issue #27023: must add any necessary padding to `size`
519
+ // (to make it a multiple of `align`) before returning it.
520
+ //
521
+ // Namely, the returned size should be, in C notation:
522
+ //
523
+ // `size + ((size & (align-1)) ? align : 0)`
524
+ //
525
+ // emulated via the semi-standard fast bit trick:
526
+ //
527
+ // `(size + (align-1)) & -align`
528
+
529
+ Ok ( ( size. abi_align ( align) , align) )
530
+ }
531
+ ty:: Dynamic ( ..) => {
532
+ let vtable = metadata. to_ptr ( ) ?;
533
+ // the second entry in the vtable is the dynamic size of the object.
534
+ self . read_size_and_align_from_vtable ( vtable)
535
+ }
544
536
545
- _ => bug ! ( "size_of_val::<{:?}> not supported" , layout. ty) ,
537
+ ty:: Slice ( _) | ty:: Str => {
538
+ let len = metadata. to_usize ( self ) ?;
539
+ let ( elem_size, align) = layout. field ( self , 0 ) ?. size_and_align ( ) ;
540
+ Ok ( ( elem_size * len, align) )
546
541
}
542
+
543
+ _ => bug ! ( "size_and_align_of::<{:?}> not supported" , layout. ty) ,
547
544
}
548
545
}
546
+ #[ inline]
547
+ pub fn size_and_align_of_mplace (
548
+ & self ,
549
+ mplace : MPlaceTy < ' tcx >
550
+ ) -> EvalResult < ' tcx , ( Size , Align ) > {
551
+ self . size_and_align_of ( mplace. extra , mplace. layout )
552
+ }
549
553
550
554
pub fn push_stack_frame (
551
555
& mut self ,
0 commit comments