@@ -15,6 +15,7 @@ use rustc_middle::mir::Place;
15
15
use rustc_middle:: mir:: * ;
16
16
use rustc_middle:: thir:: * ;
17
17
use rustc_middle:: ty:: cast:: { mir_cast_kind, CastTy } ;
18
+ use rustc_middle:: ty:: layout:: IntegerExt ;
18
19
use rustc_middle:: ty:: { self , Ty , UpvarSubsts } ;
19
20
use rustc_span:: Span ;
20
21
@@ -225,49 +226,63 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
225
226
) ;
226
227
let ( op, ty) = ( Operand :: Move ( discr) , discr_ty) ;
227
228
228
- if let Abi :: Scalar ( scalar) = layout. unwrap ( ) . abi {
229
- if let Primitive :: Int ( _, signed) = scalar. primitive ( ) {
230
- let range = scalar. valid_range ( & this. tcx ) ;
231
- // FIXME: Handle wraparound cases too.
232
- if range. end >= range. start {
233
- let mut assumer = |range : u128 , bin_op : BinOp | {
234
- // We will be overwriting this val if our scalar is signed value
235
- // because sign extension on unsigned types might cause unintended things
236
- let mut range_val =
237
- ConstantKind :: from_bits ( this. tcx , range, ty:: ParamEnv :: empty ( ) . and ( discr_ty) ) ;
238
- let bool_ty = this. tcx . types . bool ;
239
- if signed {
240
- let scalar_size_extend = scalar. size ( & this. tcx ) . sign_extend ( range) ;
241
- let discr_layout = this. tcx . layout_of ( this. param_env . and ( discr_ty) ) ;
242
- let truncated_val = discr_layout. unwrap ( ) . size . truncate ( scalar_size_extend) ;
243
- range_val = ConstantKind :: from_bits (
244
- this. tcx ,
245
- truncated_val,
246
- ty:: ParamEnv :: empty ( ) . and ( discr_ty) ,
247
- ) ;
248
- }
249
- let lit_op = this. literal_operand ( expr. span , range_val) ;
250
- let is_bin_op = this. temp ( bool_ty, expr_span) ;
251
- this. cfg . push_assign (
252
- block,
253
- source_info,
254
- is_bin_op,
255
- Rvalue :: BinaryOp ( bin_op, Box :: new ( ( ( lit_op) , ( Operand :: Copy ( discr) ) ) ) ) ,
256
- ) ;
257
- this. cfg . push (
258
- block,
259
- Statement {
260
- source_info,
261
- kind : StatementKind :: Intrinsic ( Box :: new ( NonDivergingIntrinsic :: Assume (
262
- Operand :: Copy ( is_bin_op) ,
263
- ) ) ) ,
264
- } ,
265
- )
266
- } ;
267
- assumer ( range. end , BinOp :: Ge ) ;
268
- assumer ( range. start , BinOp :: Le ) ;
269
- }
270
- }
229
+ if let Abi :: Scalar ( scalar) = layout. unwrap ( ) . abi
230
+ && !scalar. is_always_valid ( & this. tcx )
231
+ && let Primitive :: Int ( int_width, _signed) = scalar. primitive ( )
232
+ {
233
+ let unsigned_ty = int_width. to_ty ( this. tcx , false ) ;
234
+ let unsigned_place = this. temp ( unsigned_ty, expr_span) ;
235
+ this. cfg . push_assign (
236
+ block,
237
+ source_info,
238
+ unsigned_place,
239
+ Rvalue :: Cast ( CastKind :: IntToInt , Operand :: Copy ( discr) , unsigned_ty) ) ;
240
+
241
+ let bool_ty = this. tcx . types . bool ;
242
+ let range = scalar. valid_range ( & this. tcx ) ;
243
+ let merge_op =
244
+ if range. start <= range. end {
245
+ BinOp :: BitAnd
246
+ } else {
247
+ BinOp :: BitOr
248
+ } ;
249
+
250
+ let mut comparer = |range : u128 , bin_op : BinOp | -> Place < ' tcx > {
251
+ let range_val =
252
+ ConstantKind :: from_bits ( this. tcx , range, ty:: ParamEnv :: empty ( ) . and ( unsigned_ty) ) ;
253
+ let lit_op = this. literal_operand ( expr. span , range_val) ;
254
+ let is_bin_op = this. temp ( bool_ty, expr_span) ;
255
+ this. cfg . push_assign (
256
+ block,
257
+ source_info,
258
+ is_bin_op,
259
+ Rvalue :: BinaryOp ( bin_op, Box :: new ( ( Operand :: Copy ( unsigned_place) , lit_op) ) ) ,
260
+ ) ;
261
+ is_bin_op
262
+ } ;
263
+ let assert_place = if range. start == 0 {
264
+ comparer ( range. end , BinOp :: Le )
265
+ } else {
266
+ let start_place = comparer ( range. start , BinOp :: Ge ) ;
267
+ let end_place = comparer ( range. end , BinOp :: Le ) ;
268
+ let merge_place = this. temp ( bool_ty, expr_span) ;
269
+ this. cfg . push_assign (
270
+ block,
271
+ source_info,
272
+ merge_place,
273
+ Rvalue :: BinaryOp ( merge_op, Box :: new ( ( Operand :: Move ( start_place) , Operand :: Move ( end_place) ) ) ) ,
274
+ ) ;
275
+ merge_place
276
+ } ;
277
+ this. cfg . push (
278
+ block,
279
+ Statement {
280
+ source_info,
281
+ kind : StatementKind :: Intrinsic ( Box :: new ( NonDivergingIntrinsic :: Assume (
282
+ Operand :: Move ( assert_place) ,
283
+ ) ) ) ,
284
+ } ,
285
+ ) ;
271
286
}
272
287
273
288
( op, ty)
0 commit comments