44
55use std:: assert_matches:: assert_matches;
66
7- use rustc_abi:: Size ;
7+ use rustc_abi:: { FieldIdx , Size } ;
88use rustc_apfloat:: ieee:: { Double , Half , Quad , Single } ;
99use rustc_middle:: mir:: { self , BinOp , ConstValue , NonDivergingIntrinsic } ;
1010use rustc_middle:: ty:: layout:: TyAndLayout ;
@@ -28,8 +28,35 @@ pub(crate) fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ConstAll
2828 let alloc = Allocation :: from_bytes_byte_aligned_immutable ( path. into_bytes ( ) , ( ) ) ;
2929 tcx. mk_const_alloc ( alloc)
3030}
31-
3231impl < ' tcx , M : Machine < ' tcx > > InterpCx < ' tcx , M > {
32+ /// Generates a value of `TypeId` for `ty` in-place.
33+ pub ( crate ) fn write_type_id (
34+ & mut self ,
35+ ty : Ty < ' tcx > ,
36+ dest : & PlaceTy < ' tcx , M :: Provenance > ,
37+ ) -> InterpResult < ' tcx , ( ) > {
38+ let tcx = self . tcx ;
39+ let type_id_hash = tcx. type_id_hash ( ty) . as_u128 ( ) ;
40+ let op = self . const_val_to_op (
41+ ConstValue :: Scalar ( Scalar :: from_u128 ( type_id_hash) ) ,
42+ tcx. types . u128 ,
43+ None ,
44+ ) ?;
45+ self . copy_op_allow_transmute ( & op, dest) ?;
46+
47+ // Give the first pointer-size bytes provenance that knows about the type id.
48+ // Here we rely on `TypeId` being a newtype around an array of pointers, so we
49+ // first project to its only field and then the first array element.
50+ let alloc_id = tcx. reserve_and_set_type_id_alloc ( ty) ;
51+ let first = self . project_field ( dest, FieldIdx :: ZERO ) ?;
52+ let first = self . project_index ( & first, 0 ) ?;
53+ let offset = self . read_scalar ( & first) ?. to_target_usize ( & tcx) ?;
54+ let ptr = Pointer :: new ( alloc_id. into ( ) , Size :: from_bytes ( offset) ) ;
55+ let ptr = self . global_root_pointer ( ptr) ?;
56+ let val = Scalar :: from_pointer ( ptr, & tcx) ;
57+ self . write_scalar ( val, & first)
58+ }
59+
3360 /// Returns `true` if emulation happened.
3461 /// Here we implement the intrinsics that are common to all Miri instances; individual machines can add their own
3562 /// intrinsic handling.
@@ -63,9 +90,48 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
6390 sym:: type_id => {
6491 let tp_ty = instance. args . type_at ( 0 ) ;
6592 ensure_monomorphic_enough ( tcx, tp_ty) ?;
66- let val = ConstValue :: from_u128 ( tcx. type_id_hash ( tp_ty) . as_u128 ( ) ) ;
67- let val = self . const_val_to_op ( val, dest. layout . ty , Some ( dest. layout ) ) ?;
68- self . copy_op ( & val, dest) ?;
93+ self . write_type_id ( tp_ty, dest) ?;
94+ }
95+ sym:: type_id_eq => {
96+ // Both operands are `TypeId`, which is a newtype around an array of pointers.
97+ // Project until we have the array elements.
98+ let a_fields = self . project_field ( & args[ 0 ] , FieldIdx :: ZERO ) ?;
99+ let b_fields = self . project_field ( & args[ 1 ] , FieldIdx :: ZERO ) ?;
100+
101+ let mut a_fields = self . project_array_fields ( & a_fields) ?;
102+ let mut b_fields = self . project_array_fields ( & b_fields) ?;
103+
104+ let ( _idx, a) = a_fields
105+ . next ( self ) ?
106+ . expect ( "we know the layout of TypeId has at least 2 array elements" ) ;
107+ let a = self . deref_pointer ( & a) ?;
108+ let ( a, offset_a) = self . get_ptr_type_id ( a. ptr ( ) ) ?;
109+
110+ let ( _idx, b) = b_fields
111+ . next ( self ) ?
112+ . expect ( "we know the layout of TypeId has at least 2 array elements" ) ;
113+ let b = self . deref_pointer ( & b) ?;
114+ let ( b, offset_b) = self . get_ptr_type_id ( b. ptr ( ) ) ?;
115+
116+ let provenance_matches = a == b;
117+
118+ let mut eq_id = offset_a == offset_b;
119+
120+ while let Some ( ( _, a) ) = a_fields. next ( self ) ? {
121+ let ( _, b) = b_fields. next ( self ) ?. unwrap ( ) ;
122+
123+ let a = self . read_target_usize ( & a) ?;
124+ let b = self . read_target_usize ( & b) ?;
125+ eq_id &= a == b;
126+ }
127+
128+ if !eq_id && provenance_matches {
129+ throw_ub_format ! (
130+ "type_id_eq: one of the TypeId arguments is invalid, the hash does not match the type it represents"
131+ )
132+ }
133+
134+ self . write_scalar ( Scalar :: from_bool ( provenance_matches) , dest) ?;
69135 }
70136 sym:: variant_count => {
71137 let tp_ty = instance. args . type_at ( 0 ) ;
0 commit comments