4
4
5
5
use std:: assert_matches:: assert_matches;
6
6
7
- use rustc_abi:: Size ;
7
+ use rustc_abi:: { FieldIdx , Size } ;
8
8
use rustc_apfloat:: ieee:: { Double , Half , Quad , Single } ;
9
9
use rustc_middle:: mir:: { self , BinOp , ConstValue , NonDivergingIntrinsic } ;
10
10
use rustc_middle:: ty:: layout:: TyAndLayout ;
@@ -28,8 +28,35 @@ pub(crate) fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> ConstAll
28
28
let alloc = Allocation :: from_bytes_byte_aligned_immutable ( path. into_bytes ( ) , ( ) ) ;
29
29
tcx. mk_const_alloc ( alloc)
30
30
}
31
-
32
31
impl < ' 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
+
33
60
/// Returns `true` if emulation happened.
34
61
/// Here we implement the intrinsics that are common to all Miri instances; individual machines can add their own
35
62
/// intrinsic handling.
@@ -63,9 +90,48 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
63
90
sym:: type_id => {
64
91
let tp_ty = instance. args . type_at ( 0 ) ;
65
92
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) ?;
69
135
}
70
136
sym:: variant_count => {
71
137
let tp_ty = instance. args . type_at ( 0 ) ;
0 commit comments