@@ -113,28 +113,47 @@ impl<Prov: Provenance> Immediate<Prov> {
113
113
}
114
114
115
115
/// Assert that this immediate is a valid value for the given ABI.
116
- pub fn assert_matches_abi ( self , abi : Abi , cx : & impl HasDataLayout ) {
116
+ pub fn assert_matches_abi ( self , abi : Abi , msg : & str , cx : & impl HasDataLayout ) {
117
117
match ( self , abi) {
118
118
( Immediate :: Scalar ( scalar) , Abi :: Scalar ( s) ) => {
119
- assert_eq ! ( scalar. size( ) , s. size( cx) ) ;
119
+ assert_eq ! ( scalar. size( ) , s. size( cx) , "{msg}: scalar value has wrong size" ) ;
120
120
if !matches ! ( s. primitive( ) , abi:: Pointer ( ..) ) {
121
121
// This is not a pointer, it should not carry provenance.
122
- assert ! ( matches!( scalar, Scalar :: Int ( ..) ) ) ;
122
+ assert ! (
123
+ matches!( scalar, Scalar :: Int ( ..) ) ,
124
+ "{msg}: scalar value should be an integer, but has provenance"
125
+ ) ;
123
126
}
124
127
}
125
128
( Immediate :: ScalarPair ( a_val, b_val) , Abi :: ScalarPair ( a, b) ) => {
126
- assert_eq ! ( a_val. size( ) , a. size( cx) ) ;
129
+ assert_eq ! (
130
+ a_val. size( ) ,
131
+ a. size( cx) ,
132
+ "{msg}: first component of scalar pair has wrong size"
133
+ ) ;
127
134
if !matches ! ( a. primitive( ) , abi:: Pointer ( ..) ) {
128
- assert ! ( matches!( a_val, Scalar :: Int ( ..) ) ) ;
135
+ assert ! (
136
+ matches!( a_val, Scalar :: Int ( ..) ) ,
137
+ "{msg}: first component of scalar pair should be an integer, but has provenance"
138
+ ) ;
129
139
}
130
- assert_eq ! ( b_val. size( ) , b. size( cx) ) ;
140
+ assert_eq ! (
141
+ b_val. size( ) ,
142
+ b. size( cx) ,
143
+ "{msg}: second component of scalar pair has wrong size"
144
+ ) ;
131
145
if !matches ! ( b. primitive( ) , abi:: Pointer ( ..) ) {
132
- assert ! ( matches!( b_val, Scalar :: Int ( ..) ) ) ;
146
+ assert ! (
147
+ matches!( b_val, Scalar :: Int ( ..) ) ,
148
+ "{msg}: second component of scalar pair should be an integer, but has provenance"
149
+ ) ;
133
150
}
134
151
}
135
- ( Immediate :: Uninit , _) => { }
152
+ ( Immediate :: Uninit , _) => {
153
+ assert ! ( abi. is_sized( ) , "{msg}: unsized immediates are not a thing" ) ;
154
+ }
136
155
_ => {
137
- bug ! ( "value {self:?} does not match ABI {abi:?})" , )
156
+ bug ! ( "{msg}: value {self:?} does not match ABI {abi:?})" , )
138
157
}
139
158
}
140
159
}
@@ -241,6 +260,7 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> {
241
260
242
261
#[ inline( always) ]
243
262
pub fn from_immediate ( imm : Immediate < Prov > , layout : TyAndLayout < ' tcx > ) -> Self {
263
+ // Without a `cx` we cannot call `assert_matches_abi`.
244
264
debug_assert ! (
245
265
match ( imm, layout. abi) {
246
266
( Immediate :: Scalar ( ..) , Abi :: Scalar ( ..) ) => true ,
@@ -261,7 +281,6 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> {
261
281
262
282
#[ inline]
263
283
pub fn from_scalar_int ( s : ScalarInt , layout : TyAndLayout < ' tcx > ) -> Self {
264
- assert_eq ! ( s. size( ) , layout. size) ;
265
284
Self :: from_scalar ( Scalar :: from ( s) , layout)
266
285
}
267
286
@@ -334,7 +353,10 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> {
334
353
/// given layout.
335
354
// Not called `offset` to avoid confusion with the trait method.
336
355
fn offset_ ( & self , offset : Size , layout : TyAndLayout < ' tcx > , cx : & impl HasDataLayout ) -> Self {
337
- debug_assert ! ( layout. is_sized( ) , "unsized immediates are not a thing" ) ;
356
+ // Verify that the input matches its type.
357
+ if cfg ! ( debug_assertions) {
358
+ self . assert_matches_abi ( self . layout . abi , "invalid input to Immediate::offset" , cx) ;
359
+ }
338
360
// `ImmTy` have already been checked to be in-bounds, so we can just check directly if this
339
361
// remains in-bounds. This cannot actually be violated since projections are type-checked
340
362
// and bounds-checked.
@@ -368,32 +390,14 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> {
368
390
// the field covers the entire type
369
391
_ if layout. size == self . layout . size => {
370
392
assert_eq ! ( offset. bytes( ) , 0 ) ;
371
- assert ! (
372
- match ( self . layout. abi, layout. abi) {
373
- ( Abi :: Scalar ( l) , Abi :: Scalar ( r) ) => l. size( cx) == r. size( cx) ,
374
- ( Abi :: ScalarPair ( l1, l2) , Abi :: ScalarPair ( r1, r2) ) =>
375
- l1. size( cx) == r1. size( cx) && l2. size( cx) == r2. size( cx) ,
376
- _ => false ,
377
- } ,
378
- "cannot project into {} immediate with equally-sized field {}\n outer ABI: {:#?}\n field ABI: {:#?}" ,
379
- self . layout. ty,
380
- layout. ty,
381
- self . layout. abi,
382
- layout. abi,
383
- ) ;
384
393
* * self
385
394
}
386
395
// extract fields from types with `ScalarPair` ABI
387
396
( Immediate :: ScalarPair ( a_val, b_val) , Abi :: ScalarPair ( a, b) ) => {
388
- assert_matches ! ( layout. abi, Abi :: Scalar ( ..) ) ;
389
397
Immediate :: from ( if offset. bytes ( ) == 0 {
390
- // It is "okay" to transmute from `usize` to a pointer (GVN relies on that).
391
- // So only compare the size.
392
- assert_eq ! ( layout. size, a. size( cx) ) ;
393
398
a_val
394
399
} else {
395
400
assert_eq ! ( offset, a. size( cx) . align_to( b. align( cx) . abi) ) ;
396
- assert_eq ! ( layout. size, b. size( cx) ) ;
397
401
b_val
398
402
} )
399
403
}
@@ -405,6 +409,8 @@ impl<'tcx, Prov: Provenance> ImmTy<'tcx, Prov> {
405
409
self . layout
406
410
) ,
407
411
} ;
412
+ // Ensure the new layout matches the new value.
413
+ inner_val. assert_matches_abi ( layout. abi , "invalid field type in Immediate::offset" , cx) ;
408
414
409
415
ImmTy :: from_immediate ( inner_val, layout)
410
416
}
0 commit comments