@@ -309,6 +309,42 @@ pub(crate) fn codegen_checked_int_binop<'tcx>(
309
309
CValue :: by_val_pair ( res, has_overflow, out_layout)
310
310
}
311
311
312
+ pub ( crate ) fn codegen_saturating_int_binop < ' tcx > (
313
+ fx : & mut FunctionCx < ' _ , ' _ , ' tcx > ,
314
+ bin_op : BinOp ,
315
+ lhs : CValue < ' tcx > ,
316
+ rhs : CValue < ' tcx > ,
317
+ ) -> CValue < ' tcx > {
318
+ assert_eq ! ( lhs. layout( ) . ty, rhs. layout( ) . ty) ;
319
+
320
+ let signed = type_sign ( lhs. layout ( ) . ty ) ;
321
+ let clif_ty = fx. clif_type ( lhs. layout ( ) . ty ) . unwrap ( ) ;
322
+ let ( min, max) = type_min_max_value ( & mut fx. bcx , clif_ty, signed) ;
323
+
324
+ let checked_res = crate :: num:: codegen_checked_int_binop ( fx, bin_op, lhs, rhs) ;
325
+ let ( val, has_overflow) = checked_res. load_scalar_pair ( fx) ;
326
+
327
+ let val = match ( bin_op, signed) {
328
+ ( BinOp :: Add , false ) => fx. bcx . ins ( ) . select ( has_overflow, max, val) ,
329
+ ( BinOp :: Sub , false ) => fx. bcx . ins ( ) . select ( has_overflow, min, val) ,
330
+ ( BinOp :: Add , true ) => {
331
+ let rhs = rhs. load_scalar ( fx) ;
332
+ let rhs_ge_zero = fx. bcx . ins ( ) . icmp_imm ( IntCC :: SignedGreaterThanOrEqual , rhs, 0 ) ;
333
+ let sat_val = fx. bcx . ins ( ) . select ( rhs_ge_zero, max, min) ;
334
+ fx. bcx . ins ( ) . select ( has_overflow, sat_val, val)
335
+ }
336
+ ( BinOp :: Sub , true ) => {
337
+ let rhs = rhs. load_scalar ( fx) ;
338
+ let rhs_ge_zero = fx. bcx . ins ( ) . icmp_imm ( IntCC :: SignedGreaterThanOrEqual , rhs, 0 ) ;
339
+ let sat_val = fx. bcx . ins ( ) . select ( rhs_ge_zero, min, max) ;
340
+ fx. bcx . ins ( ) . select ( has_overflow, sat_val, val)
341
+ }
342
+ _ => unreachable ! ( ) ,
343
+ } ;
344
+
345
+ CValue :: by_val ( val, lhs. layout ( ) )
346
+ }
347
+
312
348
pub ( crate ) fn codegen_float_binop < ' tcx > (
313
349
fx : & mut FunctionCx < ' _ , ' _ , ' tcx > ,
314
350
bin_op : BinOp ,
0 commit comments