@@ -182,7 +182,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
182
182
ty : Ty < ' tcx > ,
183
183
substs : & ' tcx Substs < ' tcx >
184
184
) -> EvalResult < ' tcx , Pointer > {
185
- let size = self . type_size_with_substs ( ty, substs) ;
185
+ let size = self . type_size_with_substs ( ty, substs) . expect ( "cannot alloc memory for unsized type" ) ;
186
186
let align = self . type_align_with_substs ( ty, substs) ;
187
187
self . memory . allocate ( size, align)
188
188
}
@@ -203,10 +203,6 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
203
203
PrimVal :: from_uint_with_size ( n, self . memory . pointer_size ( ) )
204
204
}
205
205
206
- fn isize_primval ( & self , n : i64 ) -> PrimVal {
207
- PrimVal :: from_int_with_size ( n, self . memory . pointer_size ( ) )
208
- }
209
-
210
206
fn str_to_value ( & mut self , s : & str ) -> EvalResult < ' tcx , Value > {
211
207
// FIXME: cache these allocs
212
208
let ptr = self . memory . allocate ( s. len ( ) , 1 ) ?;
@@ -290,16 +286,21 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
290
286
self . tcx . normalize_associated_type ( & substituted)
291
287
}
292
288
293
- fn type_size ( & self , ty : Ty < ' tcx > ) -> usize {
289
+ fn type_size ( & self , ty : Ty < ' tcx > ) -> Option < usize > {
294
290
self . type_size_with_substs ( ty, self . substs ( ) )
295
291
}
296
292
297
293
fn type_align ( & self , ty : Ty < ' tcx > ) -> usize {
298
294
self . type_align_with_substs ( ty, self . substs ( ) )
299
295
}
300
296
301
- fn type_size_with_substs ( & self , ty : Ty < ' tcx > , substs : & ' tcx Substs < ' tcx > ) -> usize {
302
- self . type_layout_with_substs ( ty, substs) . size ( & self . tcx . data_layout ) . bytes ( ) as usize
297
+ fn type_size_with_substs ( & self , ty : Ty < ' tcx > , substs : & ' tcx Substs < ' tcx > ) -> Option < usize > {
298
+ let layout = self . type_layout_with_substs ( ty, substs) ;
299
+ if layout. is_unsized ( ) {
300
+ None
301
+ } else {
302
+ Some ( layout. size ( & self . tcx . data_layout ) . bytes ( ) as usize )
303
+ }
303
304
}
304
305
305
306
fn type_align_with_substs ( & self , ty : Ty < ' tcx > , substs : & ' tcx Substs < ' tcx > ) -> usize {
@@ -480,7 +481,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
480
481
481
482
Array { .. } => {
482
483
let elem_size = match dest_ty. sty {
483
- ty:: TyArray ( elem_ty, _) => self . type_size ( elem_ty) as u64 ,
484
+ ty:: TyArray ( elem_ty, _) => self . type_size ( elem_ty) . expect ( "array elements are sized" ) as u64 ,
484
485
_ => bug ! ( "tried to assign {:?} to non-array type {:?}" , kind, dest_ty) ,
485
486
} ;
486
487
let offsets = ( 0 ..) . map ( |i| i * elem_size) ;
@@ -517,8 +518,13 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
517
518
let value_ty = self . operand_ty ( operand) ;
518
519
self . write_value ( value, dest, value_ty) ?;
519
520
} else {
520
- assert_eq ! ( operands. len( ) , 0 ) ;
521
- let zero = self . isize_primval ( 0 ) ;
521
+ if let Some ( operand) = operands. get ( 0 ) {
522
+ assert_eq ! ( operands. len( ) , 1 ) ;
523
+ let operand_ty = self . operand_ty ( operand) ;
524
+ assert_eq ! ( self . type_size( operand_ty) , Some ( 0 ) ) ;
525
+ }
526
+ let value_size = self . type_size ( dest_ty) . expect ( "pointer types are sized" ) ;
527
+ let zero = PrimVal :: from_int_with_size ( 0 , value_size) ;
522
528
self . write_primval ( dest, zero) ?;
523
529
}
524
530
} else {
@@ -534,15 +540,16 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
534
540
} else {
535
541
for operand in operands {
536
542
let operand_ty = self . operand_ty ( operand) ;
537
- assert_eq ! ( self . type_size( operand_ty) , 0 ) ;
543
+ assert_eq ! ( self . type_size( operand_ty) , Some ( 0 ) ) ;
538
544
}
539
- let offset = self . nonnull_offset ( dest_ty, nndiscr, discrfield) ?;
545
+ let ( offset, ty ) = self . nonnull_offset_and_ty ( dest_ty, nndiscr, discrfield) ?;
540
546
541
547
// FIXME(solson)
542
548
let dest = self . force_allocation ( dest) ?. to_ptr ( ) ;
543
549
544
550
let dest = dest. offset ( offset. bytes ( ) as isize ) ;
545
- try!( self . memory . write_isize ( dest, 0 ) ) ;
551
+ let dest_size = self . type_size ( ty) . expect ( "bad StructWrappedNullablePointer discrfield" ) ;
552
+ try!( self . memory . write_int ( dest, 0 , dest_size) ) ;
546
553
}
547
554
} else {
548
555
bug ! ( "tried to assign {:?} to Layout::RawNullablePointer" , kind) ;
@@ -567,6 +574,13 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
567
574
}
568
575
}
569
576
577
+ Vector { element, count } => {
578
+ let elem_size = element. size ( & self . tcx . data_layout ) . bytes ( ) ;
579
+ debug_assert_eq ! ( count, operands. len( ) as u64 ) ;
580
+ let offsets = ( 0 ..) . map ( |i| i * elem_size) ;
581
+ self . assign_fields ( dest, offsets, operands) ?;
582
+ }
583
+
570
584
_ => return Err ( EvalError :: Unimplemented ( format ! ( "can't handle destination layout {:?} when assigning {:?}" , dest_layout, kind) ) ) ,
571
585
}
572
586
}
@@ -576,7 +590,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
576
590
ty:: TyArray ( elem_ty, n) => ( elem_ty, n) ,
577
591
_ => bug ! ( "tried to assign array-repeat to non-array type {:?}" , dest_ty) ,
578
592
} ;
579
- let elem_size = self . type_size ( elem_ty) ;
593
+ let elem_size = self . type_size ( elem_ty) . expect ( "repeat element type must be sized" ) ;
580
594
let value = self . eval_operand ( operand) ?;
581
595
582
596
// FIXME(solson)
@@ -651,7 +665,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
651
665
652
666
ReifyFnPointer => match self . operand_ty ( operand) . sty {
653
667
ty:: TyFnDef ( def_id, substs, fn_ty) => {
654
- let fn_ptr = self . memory . create_fn_ptr ( def_id, substs, fn_ty) ;
668
+ let fn_ty = self . tcx . erase_regions ( & fn_ty) ;
669
+ let fn_ptr = self . memory . create_fn_ptr ( self . tcx , def_id, substs, fn_ty) ;
655
670
self . write_value ( Value :: ByVal ( PrimVal :: from_fn_ptr ( fn_ptr) ) , dest, dest_ty) ?;
656
671
} ,
657
672
ref other => bug ! ( "reify fn pointer on {:?}" , other) ,
@@ -661,8 +676,9 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
661
676
ty:: TyFnPtr ( unsafe_fn_ty) => {
662
677
let src = self . eval_operand ( operand) ?;
663
678
let ptr = src. read_ptr ( & self . memory ) ?;
664
- let ( def_id, substs, _) = self . memory . get_fn ( ptr. alloc_id ) ?;
665
- let fn_ptr = self . memory . create_fn_ptr ( def_id, substs, unsafe_fn_ty) ;
679
+ let ( def_id, substs, _, _) = self . memory . get_fn ( ptr. alloc_id ) ?;
680
+ let unsafe_fn_ty = self . tcx . erase_regions ( & unsafe_fn_ty) ;
681
+ let fn_ptr = self . memory . create_fn_ptr ( self . tcx , def_id, substs, unsafe_fn_ty) ;
666
682
self . write_value ( Value :: ByVal ( PrimVal :: from_fn_ptr ( fn_ptr) ) , dest, dest_ty) ?;
667
683
} ,
668
684
ref other => bug ! ( "fn to unsafe fn cast on {:?}" , other) ,
@@ -689,7 +705,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
689
705
}
690
706
}
691
707
692
- fn nonnull_offset ( & self , ty : Ty < ' tcx > , nndiscr : u64 , discrfield : & [ u32 ] ) -> EvalResult < ' tcx , Size > {
708
+ fn nonnull_offset_and_ty ( & self , ty : Ty < ' tcx > , nndiscr : u64 , discrfield : & [ u32 ] ) -> EvalResult < ' tcx , ( Size , Ty < ' tcx > ) > {
693
709
// Skip the constant 0 at the start meant for LLVM GEP.
694
710
let mut path = discrfield. iter ( ) . skip ( 1 ) . map ( |& i| i as usize ) ;
695
711
@@ -704,10 +720,10 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
704
720
_ => bug ! ( "non-enum for StructWrappedNullablePointer: {}" , ty) ,
705
721
} ;
706
722
707
- self . field_path_offset ( inner_ty, path)
723
+ self . field_path_offset_and_ty ( inner_ty, path)
708
724
}
709
725
710
- fn field_path_offset < I : Iterator < Item = usize > > ( & self , mut ty : Ty < ' tcx > , path : I ) -> EvalResult < ' tcx , Size > {
726
+ fn field_path_offset_and_ty < I : Iterator < Item = usize > > ( & self , mut ty : Ty < ' tcx > , path : I ) -> EvalResult < ' tcx , ( Size , Ty < ' tcx > ) > {
711
727
let mut offset = Size :: from_bytes ( 0 ) ;
712
728
713
729
// Skip the initial 0 intended for LLVM GEP.
@@ -717,7 +733,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
717
733
offset = offset. checked_add ( field_offset, & self . tcx . data_layout ) . unwrap ( ) ;
718
734
}
719
735
720
- Ok ( offset)
736
+ Ok ( ( offset, ty ) )
721
737
}
722
738
723
739
fn get_field_ty ( & self , ty : Ty < ' tcx > , field_index : usize ) -> EvalResult < ' tcx , Ty < ' tcx > > {
@@ -731,8 +747,13 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
731
747
ty:: TyRef ( _, ty:: TypeAndMut { ty, .. } ) |
732
748
ty:: TyRawPtr ( ty:: TypeAndMut { ty, .. } ) |
733
749
ty:: TyBox ( ty) => {
734
- assert_eq ! ( field_index, 0 ) ;
735
- Ok ( ty)
750
+ match ( field_index, & self . tcx . struct_tail ( ty) . sty ) {
751
+ ( 1 , & ty:: TyStr ) |
752
+ ( 1 , & ty:: TySlice ( _) ) => Ok ( self . tcx . types . usize ) ,
753
+ ( 1 , & ty:: TyTrait ( _) ) |
754
+ ( 0 , _) => Ok ( self . tcx . mk_imm_ptr ( self . tcx . types . u8 ) ) ,
755
+ _ => bug ! ( "invalid fat pointee type: {}" , ty) ,
756
+ }
736
757
}
737
758
_ => Err ( EvalError :: Unimplemented ( format ! ( "can't handle type: {:?}, {:?}" , ty, ty. sty) ) ) ,
738
759
}
@@ -955,33 +976,27 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
955
976
}
956
977
957
978
Deref => {
958
- use interpreter :: value :: Value :: * ;
979
+ let val = self . eval_and_read_lvalue ( & proj . base ) ? ;
959
980
960
- let val = match self . eval_and_read_lvalue ( & proj. base ) ? {
961
- ByRef ( ptr) => self . read_value ( ptr, base_ty) ?,
962
- v => v,
981
+ let pointee_type = match base_ty. sty {
982
+ ty:: TyRawPtr ( ty:: TypeAndMut { ty, ..} ) |
983
+ ty:: TyRef ( _, ty:: TypeAndMut { ty, ..} ) |
984
+ ty:: TyBox ( ty) => ty,
985
+ _ => bug ! ( "can only deref pointer types" ) ,
963
986
} ;
964
987
965
- match val {
966
- ByValPair ( ptr, vtable)
967
- if ptr. try_as_ptr ( ) . is_some ( ) && vtable. try_as_ptr ( ) . is_some ( )
968
- => {
969
- let ptr = ptr. try_as_ptr ( ) . unwrap ( ) ;
970
- let vtable = vtable. try_as_ptr ( ) . unwrap ( ) ;
971
- ( ptr, LvalueExtra :: Vtable ( vtable) )
972
- }
973
-
974
- ByValPair ( ptr, n) if ptr. try_as_ptr ( ) . is_some ( ) => {
975
- let ptr = ptr. try_as_ptr ( ) . unwrap ( ) ;
976
- ( ptr, LvalueExtra :: Length ( n. expect_uint ( "slice length" ) ) )
977
- }
988
+ trace ! ( "deref to {} on {:?}" , pointee_type, val) ;
978
989
979
- ByVal ( ptr) if ptr. try_as_ptr ( ) . is_some ( ) => {
980
- let ptr = ptr. try_as_ptr ( ) . unwrap ( ) ;
981
- ( ptr, LvalueExtra :: None )
982
- }
983
-
984
- _ => bug ! ( "can't deref non pointer types" ) ,
990
+ match self . tcx . struct_tail ( pointee_type) . sty {
991
+ ty:: TyTrait ( _) => {
992
+ let ( ptr, vtable) = val. expect_ptr_vtable_pair ( & self . memory ) ?;
993
+ ( ptr, LvalueExtra :: Vtable ( vtable) )
994
+ } ,
995
+ ty:: TyStr | ty:: TySlice ( _) => {
996
+ let ( ptr, len) = val. expect_slice ( & self . memory ) ?;
997
+ ( ptr, LvalueExtra :: Length ( len) )
998
+ } ,
999
+ _ => ( val. read_ptr ( & self . memory ) ?, LvalueExtra :: None ) ,
985
1000
}
986
1001
}
987
1002
@@ -991,7 +1006,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
991
1006
let ( base_ptr, _) = base. to_ptr_and_extra ( ) ;
992
1007
993
1008
let ( elem_ty, len) = base. elem_ty_and_len ( base_ty) ;
994
- let elem_size = self . type_size ( elem_ty) ;
1009
+ let elem_size = self . type_size ( elem_ty) . expect ( "slice element must be sized" ) ;
995
1010
let n_ptr = self . eval_operand ( operand) ?;
996
1011
let usize = self . tcx . types . usize ;
997
1012
let n = self . value_to_primval ( n_ptr, usize) ?
@@ -1007,7 +1022,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
1007
1022
let ( base_ptr, _) = base. to_ptr_and_extra ( ) ;
1008
1023
1009
1024
let ( elem_ty, n) = base. elem_ty_and_len ( base_ty) ;
1010
- let elem_size = self . type_size ( elem_ty) ;
1025
+ let elem_size = self . type_size ( elem_ty) . expect ( "sequence element must be sized" ) ;
1011
1026
assert ! ( n >= min_length as u64 ) ;
1012
1027
1013
1028
let index = if from_end {
@@ -1026,7 +1041,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
1026
1041
let ( base_ptr, _) = base. to_ptr_and_extra ( ) ;
1027
1042
1028
1043
let ( elem_ty, n) = base. elem_ty_and_len ( base_ty) ;
1029
- let elem_size = self . type_size ( elem_ty) ;
1044
+ let elem_size = self . type_size ( elem_ty) . expect ( "slice element must be sized" ) ;
1030
1045
assert ! ( ( from as u64 ) <= n - ( to as u64 ) ) ;
1031
1046
let ptr = base_ptr. offset ( from as isize * elem_size as isize ) ;
1032
1047
let extra = LvalueExtra :: Length ( n - to as u64 - from as u64 ) ;
@@ -1046,7 +1061,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
1046
1061
}
1047
1062
1048
1063
fn copy ( & mut self , src : Pointer , dest : Pointer , ty : Ty < ' tcx > ) -> EvalResult < ' tcx , ( ) > {
1049
- let size = self . type_size ( ty) ;
1064
+ let size = self . type_size ( ty) . expect ( "cannot copy from an unsized type" ) ;
1050
1065
let align = self . type_align ( ty) ;
1051
1066
self . memory . copy ( src, dest, size, align) ?;
1052
1067
Ok ( ( ) )
@@ -1388,7 +1403,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
1388
1403
ty:: TyFloat ( FloatTy :: F64 ) => PrimVal :: from_f64 ( self . memory . read_f64 ( ptr) ?) ,
1389
1404
1390
1405
ty:: TyFnDef ( def_id, substs, fn_ty) => {
1391
- PrimVal :: from_fn_ptr ( self . memory . create_fn_ptr ( def_id, substs, fn_ty) )
1406
+ PrimVal :: from_fn_ptr ( self . memory . create_fn_ptr ( self . tcx , def_id, substs, fn_ty) )
1392
1407
} ,
1393
1408
ty:: TyFnPtr ( _) => self . memory . read_ptr ( ptr) . map ( PrimVal :: from_fn_ptr) ?,
1394
1409
ty:: TyBox ( ty) |
@@ -1398,7 +1413,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
1398
1413
if self . type_is_sized ( ty) {
1399
1414
PrimVal :: from_ptr ( p)
1400
1415
} else {
1401
- // FIXME: extract the offset to the tail field for `Box<(i64, i32, [u8])>`
1416
+ trace ! ( "reading fat pointer extra of type {}" , ty ) ;
1402
1417
let extra = ptr. offset ( self . memory . pointer_size ( ) as isize ) ;
1403
1418
let extra = match self . tcx . struct_tail ( ty) . sty {
1404
1419
ty:: TyTrait ( ..) => PrimVal :: from_ptr ( self . memory . read_ptr ( extra) ?) ,
@@ -1505,14 +1520,14 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
1505
1520
//let dst = adt::MaybeSizedValue::sized(dst);
1506
1521
let src_ptr = match src {
1507
1522
Value :: ByRef ( ptr) => ptr,
1508
- _ => panic ! ( "expected pointer, got {:?}" , src) ,
1523
+ _ => bug ! ( "expected pointer, got {:?}" , src) ,
1509
1524
} ;
1510
1525
1511
1526
let iter = src_fields. zip ( dst_fields) . enumerate ( ) ;
1512
1527
for ( i, ( src_f, dst_f) ) in iter {
1513
1528
let src_fty = monomorphize_field_ty ( self . tcx , src_f, substs_a) ;
1514
1529
let dst_fty = monomorphize_field_ty ( self . tcx , dst_f, substs_b) ;
1515
- if self . type_size ( dst_fty) == 0 {
1530
+ if self . type_size ( dst_fty) == Some ( 0 ) {
1516
1531
continue ;
1517
1532
}
1518
1533
let src_field_offset = self . get_field_offset ( src_ty, i) ?. bytes ( ) as isize ;
0 commit comments