@@ -12,6 +12,7 @@ use rustc_middle::mir::Operand;
1212use rustc_middle:: ty:: cast:: { CastTy , IntTy } ;
1313use rustc_middle:: ty:: layout:: { HasTyCtxt , LayoutOf , TyAndLayout } ;
1414use rustc_middle:: ty:: { self , adjustment:: PointerCast , Instance , Ty , TyCtxt } ;
15+ use rustc_session:: config:: OptLevel ;
1516use rustc_span:: source_map:: { Span , DUMMY_SP } ;
1617use rustc_target:: abi:: { self , FIRST_VARIANT } ;
1718
@@ -231,10 +232,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
231232 ( ScalarOrZst :: Scalar ( in_scalar) , ScalarOrZst :: Scalar ( out_scalar) )
232233 if in_scalar. size ( self . cx ) == out_scalar. size ( self . cx ) =>
233234 {
235+ let operand_bty = bx. backend_type ( operand. layout ) ;
234236 let cast_bty = bx. backend_type ( cast) ;
235- Some ( OperandValue :: Immediate (
236- self . transmute_immediate ( bx, imm, in_scalar, out_scalar, cast_bty) ,
237- ) )
237+ Some ( OperandValue :: Immediate ( self . transmute_immediate (
238+ bx,
239+ imm,
240+ in_scalar,
241+ operand_bty,
242+ out_scalar,
243+ cast_bty,
244+ ) ) )
238245 }
239246 _ => None ,
240247 }
@@ -250,11 +257,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
250257 && in_a. size ( self . cx ) == out_a. size ( self . cx )
251258 && in_b. size ( self . cx ) == out_b. size ( self . cx )
252259 {
260+ let in_a_ibty = bx. scalar_pair_element_backend_type ( operand. layout , 0 , false ) ;
261+ let in_b_ibty = bx. scalar_pair_element_backend_type ( operand. layout , 1 , false ) ;
253262 let out_a_ibty = bx. scalar_pair_element_backend_type ( cast, 0 , false ) ;
254263 let out_b_ibty = bx. scalar_pair_element_backend_type ( cast, 1 , false ) ;
255264 Some ( OperandValue :: Pair (
256- self . transmute_immediate ( bx, imm_a, in_a, out_a, out_a_ibty) ,
257- self . transmute_immediate ( bx, imm_b, in_b, out_b, out_b_ibty) ,
265+ self . transmute_immediate ( bx, imm_a, in_a, in_a_ibty , out_a, out_a_ibty) ,
266+ self . transmute_immediate ( bx, imm_b, in_b, in_b_ibty , out_b, out_b_ibty) ,
258267 ) )
259268 } else {
260269 None
@@ -273,13 +282,21 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
273282 bx : & mut Bx ,
274283 mut imm : Bx :: Value ,
275284 from_scalar : abi:: Scalar ,
285+ from_backend_ty : Bx :: Type ,
276286 to_scalar : abi:: Scalar ,
277287 to_backend_ty : Bx :: Type ,
278288 ) -> Bx :: Value {
279289 debug_assert_eq ! ( from_scalar. size( self . cx) , to_scalar. size( self . cx) ) ;
280290
281291 use abi:: Primitive :: * ;
282292 imm = bx. from_immediate ( imm) ;
293+
294+ // When scalars are passed by value, there's no metadata recording their
295+ // valid ranges. For example, `char`s are passed as just `i32`, with no
296+ // way for LLVM to know that they're 0x10FFFF at most. Thus we assume
297+ // the range of the input value too, not just the output range.
298+ self . assume_scalar_range ( bx, imm, from_scalar, from_backend_ty) ;
299+
283300 imm = match ( from_scalar. primitive ( ) , to_scalar. primitive ( ) ) {
284301 ( Int ( ..) | F32 | F64 , Int ( ..) | F32 | F64 ) => bx. bitcast ( imm, to_backend_ty) ,
285302 ( Pointer ( ..) , Pointer ( ..) ) => bx. pointercast ( imm, to_backend_ty) ,
@@ -294,10 +311,55 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
294311 bx. bitcast ( int_imm, to_backend_ty)
295312 }
296313 } ;
314+ self . assume_scalar_range ( bx, imm, to_scalar, to_backend_ty) ;
297315 imm = bx. to_immediate_scalar ( imm, to_scalar) ;
298316 imm
299317 }
300318
319+ fn assume_scalar_range (
320+ & self ,
321+ bx : & mut Bx ,
322+ imm : Bx :: Value ,
323+ scalar : abi:: Scalar ,
324+ backend_ty : Bx :: Type ,
325+ ) {
326+ if matches ! ( self . cx. sess( ) . opts. optimize, OptLevel :: No | OptLevel :: Less )
327+ // For now, the critical niches are all over `Int`eger values.
328+ // Should floating-point values or pointers ever get more complex
329+ // niches, then this code will probably want to handle them too.
330+ || !matches ! ( scalar. primitive( ) , abi:: Primitive :: Int ( ..) )
331+ || scalar. is_always_valid ( self . cx )
332+ {
333+ return ;
334+ }
335+
336+ let abi:: WrappingRange { start, end } = scalar. valid_range ( self . cx ) ;
337+
338+ if start <= end {
339+ if start > 0 {
340+ let low = bx. const_uint_big ( backend_ty, start) ;
341+ let cmp = bx. icmp ( IntPredicate :: IntUGE , imm, low) ;
342+ bx. assume ( cmp) ;
343+ }
344+
345+ let type_max = scalar. size ( self . cx ) . unsigned_int_max ( ) ;
346+ if end < type_max {
347+ let high = bx. const_uint_big ( backend_ty, end) ;
348+ let cmp = bx. icmp ( IntPredicate :: IntULE , imm, high) ;
349+ bx. assume ( cmp) ;
350+ }
351+ } else {
352+ let low = bx. const_uint_big ( backend_ty, start) ;
353+ let cmp_low = bx. icmp ( IntPredicate :: IntUGE , imm, low) ;
354+
355+ let high = bx. const_uint_big ( backend_ty, end) ;
356+ let cmp_high = bx. icmp ( IntPredicate :: IntULE , imm, high) ;
357+
358+ let or = bx. or ( cmp_low, cmp_high) ;
359+ bx. assume ( or) ;
360+ }
361+ }
362+
301363 pub fn codegen_rvalue_unsized (
302364 & mut self ,
303365 bx : & mut Bx ,
0 commit comments