@@ -5,7 +5,7 @@ use crate::back::write::{
55    compute_per_cgu_lto_type,  start_async_codegen,  submit_codegened_module_to_llvm, 
66    submit_post_lto_module_to_llvm,  submit_pre_lto_module_to_llvm,  ComputedLtoType ,  OngoingCodegen , 
77} ; 
8- use  crate :: common:: { IntPredicate ,  RealPredicate ,  TypeKind } ; 
8+ use  crate :: common:: { self ,   IntPredicate ,  RealPredicate ,  TypeKind } ; 
99use  crate :: errors; 
1010use  crate :: meth; 
1111use  crate :: mir; 
@@ -33,7 +33,7 @@ use rustc_middle::mir::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem};
3333use  rustc_middle:: query:: Providers ; 
3434use  rustc_middle:: ty:: layout:: { HasTyCtxt ,  LayoutOf ,  TyAndLayout } ; 
3535use  rustc_middle:: ty:: { self ,  Instance ,  Ty ,  TyCtxt } ; 
36- use  rustc_session:: config:: { self ,  CrateType ,  EntryFnType ,  OutputType } ; 
36+ use  rustc_session:: config:: { self ,  CrateType ,  EntryFnType ,  OptLevel ,   OutputType } ; 
3737use  rustc_session:: Session ; 
3838use  rustc_span:: symbol:: sym; 
3939use  rustc_span:: Symbol ; 
@@ -300,14 +300,32 @@ pub fn coerce_unsized_into<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
300300    } 
301301} 
302302
303- pub  fn  cast_shift_expr_rhs < ' a ,  ' tcx ,  Bx :  BuilderMethods < ' a ,  ' tcx > > ( 
303+ /// Shifts in MIR are all allowed to have mismatched LHS & RHS types. 
304+ /// 
305+ /// This does all the appropriate conversions needed to pass it to the builder's 
306+ /// shift methods, which are UB for out-of-range shifts. 
307+ /// 
308+ /// If `is_unchecked` is false, this masks the RHS to ensure it stays in-bounds. 
309+ /// For 32- and 64-bit types, this matches the semantics 
310+ /// of Java. (See related discussion on #1877 and #10183.) 
311+ /// 
312+ /// If `is_unchecked` is true, this does no masking, and adds sufficient `assume` 
313+ /// calls or operation flags to preserve as much freedom to optimize as possible. 
314+ pub  fn  build_shift_expr_rhs < ' a ,  ' tcx ,  Bx :  BuilderMethods < ' a ,  ' tcx > > ( 
304315    bx :  & mut  Bx , 
305316    lhs :  Bx :: Value , 
306-     rhs :  Bx :: Value , 
317+     mut  rhs :  Bx :: Value , 
318+     is_unchecked :  bool , 
307319)  -> Bx :: Value  { 
308320    // Shifts may have any size int on the rhs 
309321    let  mut  rhs_llty = bx. cx ( ) . val_ty ( rhs) ; 
310322    let  mut  lhs_llty = bx. cx ( ) . val_ty ( lhs) ; 
323+ 
324+     let  mask = common:: shift_mask_val ( bx,  lhs_llty,  rhs_llty,  false ) ; 
325+     if  !is_unchecked { 
326+         rhs = bx. and ( rhs,  mask) ; 
327+     } 
328+ 
311329    if  bx. cx ( ) . type_kind ( rhs_llty)  == TypeKind :: Vector  { 
312330        rhs_llty = bx. cx ( ) . element_type ( rhs_llty) 
313331    } 
@@ -317,6 +335,12 @@ pub fn cast_shift_expr_rhs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
317335    let  rhs_sz = bx. cx ( ) . int_width ( rhs_llty) ; 
318336    let  lhs_sz = bx. cx ( ) . int_width ( lhs_llty) ; 
319337    if  lhs_sz < rhs_sz { 
338+         if  is_unchecked && bx. sess ( ) . opts . optimize  != OptLevel :: No  { 
339+             // FIXME: Use `trunc nuw` once that's available 
340+             let  inrange = bx. icmp ( IntPredicate :: IntULE ,  rhs,  mask) ; 
341+             bx. assume ( inrange) ; 
342+         } 
343+ 
320344        bx. trunc ( rhs,  lhs_llty) 
321345    }  else  if  lhs_sz > rhs_sz { 
322346        // We zero-extend even if the RHS is signed. So e.g. `(x: i32) << -1i8` will zero-extend the 
0 commit comments