@@ -5,7 +5,7 @@ use rustc::mir::repr as mir;
5
5
use rustc:: traits:: Reveal ;
6
6
use rustc:: ty:: layout:: { self , Layout , Size } ;
7
7
use rustc:: ty:: subst:: { self , Subst , Substs } ;
8
- use rustc:: ty:: { self , Ty , TyCtxt } ;
8
+ use rustc:: ty:: { self , Ty , TyCtxt , TypeFoldable } ;
9
9
use rustc:: util:: nodemap:: DefIdMap ;
10
10
use rustc_data_structures:: indexed_vec:: Idx ;
11
11
use std:: cell:: RefCell ;
@@ -22,6 +22,7 @@ use std::collections::HashMap;
22
22
23
23
mod step;
24
24
mod terminator;
25
+ mod cast;
25
26
26
27
pub struct EvalContext < ' a , ' tcx : ' a > {
27
28
/// The results of the type checker, from rustc.
@@ -211,9 +212,10 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
211
212
let psize = self . memory . pointer_size ( ) ;
212
213
let static_ptr = self . memory . allocate ( s. len ( ) , 1 ) ?;
213
214
let ptr = self . memory . allocate ( psize * 2 , psize) ?;
215
+ let ( ptr, extra) = self . get_fat_ptr ( ptr) ;
214
216
self . memory . write_bytes ( static_ptr, s. as_bytes ( ) ) ?;
215
217
self . memory . write_ptr ( ptr, static_ptr) ?;
216
- self . memory . write_usize ( ptr . offset ( psize as isize ) , s. len ( ) as u64 ) ?;
218
+ self . memory . write_usize ( extra , s. len ( ) as u64 ) ?;
217
219
Ok ( ptr)
218
220
}
219
221
ByteStr ( ref bs) => {
@@ -244,6 +246,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
244
246
}
245
247
246
248
fn type_is_sized ( & self , ty : Ty < ' tcx > ) -> bool {
249
+ // generics are weird, don't run this function on a generic
250
+ assert ! ( !ty. needs_subst( ) ) ;
247
251
ty. is_sized ( self . tcx , & self . tcx . empty_parameter_environment ( ) , DUMMY_SP )
248
252
}
249
253
@@ -558,12 +562,12 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
558
562
559
563
Ref ( _, _, ref lvalue) => {
560
564
let lv = self . eval_lvalue ( lvalue) ?;
561
- self . memory . write_ptr ( dest, lv. ptr ) ?;
565
+ let ( ptr, extra) = self . get_fat_ptr ( dest) ;
566
+ self . memory . write_ptr ( ptr, lv. ptr ) ?;
562
567
match lv. extra {
563
568
LvalueExtra :: None => { } ,
564
569
LvalueExtra :: Length ( len) => {
565
- let len_ptr = dest. offset ( self . memory . pointer_size ( ) as isize ) ;
566
- self . memory . write_usize ( len_ptr, len) ?;
570
+ self . memory . write_usize ( extra, len) ?;
567
571
}
568
572
LvalueExtra :: DowncastVariant ( ..) =>
569
573
bug ! ( "attempted to take a reference to an enum downcast lvalue" ) ,
@@ -583,14 +587,14 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
583
587
Unsize => {
584
588
let src = self . eval_operand ( operand) ?;
585
589
let src_ty = self . operand_ty ( operand) ;
586
- self . move_ ( src, dest, src_ty) ?;
590
+ let ( ptr, extra) = self . get_fat_ptr ( dest) ;
591
+ self . move_ ( src, ptr, src_ty) ?;
587
592
let src_pointee_ty = pointee_type ( src_ty) . unwrap ( ) ;
588
593
let dest_pointee_ty = pointee_type ( dest_ty) . unwrap ( ) ;
589
594
590
595
match ( & src_pointee_ty. sty , & dest_pointee_ty. sty ) {
591
596
( & ty:: TyArray ( _, length) , & ty:: TySlice ( _) ) => {
592
- let len_ptr = dest. offset ( self . memory . pointer_size ( ) as isize ) ;
593
- self . memory . write_usize ( len_ptr, length as u64 ) ?;
597
+ self . memory . write_usize ( extra, length as u64 ) ?;
594
598
}
595
599
596
600
_ => return Err ( EvalError :: Unimplemented ( format ! ( "can't handle cast: {:?}" , rvalue) ) ) ,
@@ -600,20 +604,25 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
600
604
Misc => {
601
605
let src = self . eval_operand ( operand) ?;
602
606
let src_ty = self . operand_ty ( operand) ;
603
- // FIXME(solson): Wrong for almost everything.
604
- warn ! ( "misc cast from {:?} to {:?}" , src_ty, dest_ty) ;
605
- let dest_size = self . type_size ( dest_ty) ;
606
- let src_size = self . type_size ( src_ty) ;
607
- let dest_align = self . type_align ( dest_ty) ;
608
-
609
- // Hack to support fat pointer -> thin pointer casts to keep tests for
610
- // other things passing for now.
611
- let is_fat_ptr_cast = pointee_type ( src_ty) . map_or ( false , |ty| !self . type_is_sized ( ty) ) ;
612
-
613
- if dest_size == src_size || is_fat_ptr_cast {
614
- self . memory . copy ( src, dest, dest_size, dest_align) ?;
607
+ if self . type_is_fat_ptr ( src_ty) {
608
+ let ( data_ptr, _meta_ptr) = self . get_fat_ptr ( src) ;
609
+ let ptr_size = self . memory . pointer_size ( ) ;
610
+ let dest_ty = self . monomorphize ( dest_ty, self . substs ( ) ) ;
611
+ if self . type_is_fat_ptr ( dest_ty) {
612
+ // FIXME: add assertion that the extra part of the src_ty and
613
+ // dest_ty is of the same type
614
+ self . memory . copy ( data_ptr, dest, ptr_size * 2 , ptr_size) ?;
615
+ } else { // cast to thin-ptr
616
+ // Cast of fat-ptr to thin-ptr is an extraction of data-ptr and
617
+ // pointer-cast of that pointer to desired pointer type.
618
+ self . memory . copy ( data_ptr, dest, ptr_size, ptr_size) ?;
619
+ }
615
620
} else {
616
- return Err ( EvalError :: Unimplemented ( format ! ( "can't handle cast: {:?}" , rvalue) ) ) ;
621
+ // FIXME: dest_ty should already be monomorphized
622
+ let dest_ty = self . monomorphize ( dest_ty, self . substs ( ) ) ;
623
+ let src_val = self . read_primval ( src, src_ty) ?;
624
+ let dest_val = self . cast_primval ( src_val, dest_ty) ?;
625
+ self . memory . write_primval ( dest, dest_val) ?;
617
626
}
618
627
}
619
628
@@ -644,6 +653,15 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
644
653
Ok ( ( ) )
645
654
}
646
655
656
+ fn type_is_fat_ptr ( & self , ty : Ty < ' tcx > ) -> bool {
657
+ match ty. sty {
658
+ ty:: TyRawPtr ( ty:: TypeAndMut { ty, ..} ) |
659
+ ty:: TyRef ( _, ty:: TypeAndMut { ty, ..} ) |
660
+ ty:: TyBox ( ty) => !self . type_is_sized ( ty) ,
661
+ _ => false ,
662
+ }
663
+ }
664
+
647
665
fn nonnull_offset ( & self , ty : Ty < ' tcx > , nndiscr : u64 , discrfield : & [ u32 ] ) -> EvalResult < ' tcx , Size > {
648
666
// Skip the constant 0 at the start meant for LLVM GEP.
649
667
let mut path = discrfield. iter ( ) . skip ( 1 ) . map ( |& i| i as usize ) ;
@@ -809,11 +827,12 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
809
827
810
828
Deref => {
811
829
let pointee_ty = pointee_type ( base_ty) . expect ( "Deref of non-pointer" ) ;
830
+ self . memory . dump ( base. ptr . alloc_id ) ;
812
831
let ptr = self . memory . read_ptr ( base. ptr ) ?;
813
832
let extra = match pointee_ty. sty {
814
833
ty:: TySlice ( _) | ty:: TyStr => {
815
- let len_ptr = base . ptr . offset ( self . memory . pointer_size ( ) as isize ) ;
816
- let len = self . memory . read_usize ( len_ptr ) ?;
834
+ let ( _ , extra ) = self . get_fat_ptr ( base . ptr ) ;
835
+ let len = self . memory . read_usize ( extra ) ?;
817
836
LvalueExtra :: Length ( len)
818
837
}
819
838
ty:: TyTrait ( _) => unimplemented ! ( ) ,
@@ -842,6 +861,12 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
842
861
Ok ( Lvalue { ptr : ptr, extra : LvalueExtra :: None } )
843
862
}
844
863
864
+ fn get_fat_ptr ( & self , ptr : Pointer ) -> ( Pointer , Pointer ) {
865
+ assert_eq ! ( layout:: FAT_PTR_ADDR , 0 ) ;
866
+ assert_eq ! ( layout:: FAT_PTR_EXTRA , 1 ) ;
867
+ ( ptr, ptr. offset ( self . memory . pointer_size ( ) as isize ) )
868
+ }
869
+
845
870
fn lvalue_ty ( & self , lvalue : & mir:: Lvalue < ' tcx > ) -> Ty < ' tcx > {
846
871
self . monomorphize ( lvalue. ty ( & self . mir ( ) , self . tcx ) . to_ty ( self . tcx ) , self . substs ( ) )
847
872
}
@@ -865,7 +890,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
865
890
let c = self . memory . read_uint ( ptr, 4 ) ? as u32 ;
866
891
match :: std:: char:: from_u32 ( c) {
867
892
Some ( ch) => PrimVal :: Char ( ch) ,
868
- None => return Err ( EvalError :: InvalidChar ( c) ) ,
893
+ None => return Err ( EvalError :: InvalidChar ( c as u64 ) ) ,
869
894
}
870
895
}
871
896
( _, & ty:: TyInt ( IntTy :: I8 ) ) => PrimVal :: I8 ( self . memory . read_int ( ptr, 1 ) ? as i8 ) ,
@@ -905,6 +930,25 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
905
930
}
906
931
}
907
932
933
+ ( _, & ty:: TyEnum ( ..) ) => {
934
+ use rustc:: ty:: layout:: Layout :: * ;
935
+ if let CEnum { discr, signed, .. } = * self . type_layout ( ty) {
936
+ match ( discr. size ( ) . bytes ( ) , signed) {
937
+ ( 1 , true ) => PrimVal :: I8 ( self . memory . read_int ( ptr, 1 ) ? as i8 ) ,
938
+ ( 2 , true ) => PrimVal :: I16 ( self . memory . read_int ( ptr, 2 ) ? as i16 ) ,
939
+ ( 4 , true ) => PrimVal :: I32 ( self . memory . read_int ( ptr, 4 ) ? as i32 ) ,
940
+ ( 8 , true ) => PrimVal :: I64 ( self . memory . read_int ( ptr, 8 ) ? as i64 ) ,
941
+ ( 1 , false ) => PrimVal :: U8 ( self . memory . read_uint ( ptr, 1 ) ? as u8 ) ,
942
+ ( 2 , false ) => PrimVal :: U16 ( self . memory . read_uint ( ptr, 2 ) ? as u16 ) ,
943
+ ( 4 , false ) => PrimVal :: U32 ( self . memory . read_uint ( ptr, 4 ) ? as u32 ) ,
944
+ ( 8 , false ) => PrimVal :: U64 ( self . memory . read_uint ( ptr, 8 ) ? as u64 ) ,
945
+ ( size, _) => bug ! ( "CEnum discr size {}" , size) ,
946
+ }
947
+ } else {
948
+ bug ! ( "primitive read of non-clike enum: {:?}" , ty) ;
949
+ }
950
+ } ,
951
+
908
952
_ => bug ! ( "primitive read of non-primitive type: {:?}" , ty) ,
909
953
} ;
910
954
Ok ( val)
0 commit comments