@@ -15,6 +15,7 @@ use rustc_middle::mir::Place;
1515use rustc_middle:: mir:: * ;
1616use rustc_middle:: thir:: * ;
1717use rustc_middle:: ty:: cast:: { mir_cast_kind, CastTy } ;
18+ use rustc_middle:: ty:: layout:: IntegerExt ;
1819use rustc_middle:: ty:: { self , Ty , UpvarSubsts } ;
1920use rustc_span:: Span ;
2021
@@ -225,49 +226,63 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
225226 ) ;
226227 let ( op, ty) = ( Operand :: Move ( discr) , discr_ty) ;
227228
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+ ) ;
271286 }
272287
273288 ( op, ty)
0 commit comments