@@ -12,6 +12,7 @@ use rustc_middle::mir::Operand;
12
12
use rustc_middle:: ty:: cast:: { CastTy , IntTy } ;
13
13
use rustc_middle:: ty:: layout:: { HasTyCtxt , LayoutOf , TyAndLayout } ;
14
14
use rustc_middle:: ty:: { self , adjustment:: PointerCast , Instance , Ty , TyCtxt } ;
15
+ use rustc_session:: config:: OptLevel ;
15
16
use rustc_span:: source_map:: { Span , DUMMY_SP } ;
16
17
use rustc_target:: abi:: { self , FIRST_VARIANT } ;
17
18
@@ -231,10 +232,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
231
232
( ScalarOrZst :: Scalar ( in_scalar) , ScalarOrZst :: Scalar ( out_scalar) )
232
233
if in_scalar. size ( self . cx ) == out_scalar. size ( self . cx ) =>
233
234
{
235
+ let operand_bty = bx. backend_type ( operand. layout ) ;
234
236
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
+ ) ) )
238
245
}
239
246
_ => None ,
240
247
}
@@ -250,11 +257,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
250
257
&& in_a. size ( self . cx ) == out_a. size ( self . cx )
251
258
&& in_b. size ( self . cx ) == out_b. size ( self . cx )
252
259
{
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 ) ;
253
262
let out_a_ibty = bx. scalar_pair_element_backend_type ( cast, 0 , false ) ;
254
263
let out_b_ibty = bx. scalar_pair_element_backend_type ( cast, 1 , false ) ;
255
264
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) ,
258
267
) )
259
268
} else {
260
269
None
@@ -273,13 +282,21 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
273
282
bx : & mut Bx ,
274
283
mut imm : Bx :: Value ,
275
284
from_scalar : abi:: Scalar ,
285
+ from_backend_ty : Bx :: Type ,
276
286
to_scalar : abi:: Scalar ,
277
287
to_backend_ty : Bx :: Type ,
278
288
) -> Bx :: Value {
279
289
debug_assert_eq ! ( from_scalar. size( self . cx) , to_scalar. size( self . cx) ) ;
280
290
281
291
use abi:: Primitive :: * ;
282
292
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
+
283
300
imm = match ( from_scalar. primitive ( ) , to_scalar. primitive ( ) ) {
284
301
( Int ( ..) | F32 | F64 , Int ( ..) | F32 | F64 ) => bx. bitcast ( imm, to_backend_ty) ,
285
302
( Pointer ( ..) , Pointer ( ..) ) => bx. pointercast ( imm, to_backend_ty) ,
@@ -294,10 +311,55 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
294
311
bx. bitcast ( int_imm, to_backend_ty)
295
312
}
296
313
} ;
314
+ self . assume_scalar_range ( bx, imm, to_scalar, to_backend_ty) ;
297
315
imm = bx. to_immediate_scalar ( imm, to_scalar) ;
298
316
imm
299
317
}
300
318
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
+
301
363
pub fn codegen_rvalue_unsized (
302
364
& mut self ,
303
365
bx : & mut Bx ,
0 commit comments