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