@@ -122,55 +122,41 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
122122 self . binop_with_overflow ( bin_op, lhs, rhs, dest) ?;
123123 }
124124 }
125- "saturating_add" => {
125+ "saturating_add" | "saturating_sub" => {
126126 let l = self . read_immediate ( args[ 0 ] ) ?;
127127 let r = self . read_immediate ( args[ 1 ] ) ?;
128- let ( val, overflowed) = self . binary_op_imm ( BinOp :: Add , l, r) ?;
129- if overflowed {
130- let first_term: u128 = l. to_scalar ( ) ?. to_bits ( l. layout . size ) ?;
131- let num_bits = l. layout . size . bits ( ) ;
132- let val = if l. layout . abi . is_signed ( ) {
133- // For signed addition the saturated value depends on the
134- // sign of either term
135- if first_term & ( 1 << ( num_bits-1 ) ) == 0 { // signed term is positive
136- Scalar :: from_uint ( ( 1u128 << ( num_bits - 1 ) ) - 1 ,
137- Size :: from_bits ( num_bits) )
138- } else { // signed term is negative
139- Scalar :: from_uint ( 1u128 << ( num_bits - 1 ) , Size :: from_bits ( num_bits) )
140- }
141- } else {
142- Scalar :: from_uint ( u128:: max_value ( ) >> ( 128 - num_bits) ,
143- Size :: from_bits ( num_bits) )
144- } ;
145- self . write_scalar ( val, dest) ?;
128+ let is_add = intrinsic_name == "saturating_add" ;
129+ let ( val, overflowed) = self . binary_op_imm ( if is_add {
130+ BinOp :: Add
146131 } else {
147- self . write_scalar ( val, dest) ?;
148- }
149- }
150- "saturating_sub" => {
151- let l = self . read_immediate ( args[ 0 ] ) ?;
152- let r = self . read_immediate ( args[ 1 ] ) ?;
153- let ( val, overflowed) = self . binary_op_imm ( BinOp :: Sub , l, r) ?;
154- if overflowed {
132+ BinOp :: Sub
133+ } , l, r) ?;
134+ let val = if overflowed {
135+ // For signed ints the saturated value depends on the
136+ // sign of the first term
155137 let first_term: u128 = l. to_scalar ( ) ?. to_bits ( l. layout . size ) ?;
156138 let num_bits = l. layout . size . bits ( ) ;
157- let val = if l. layout . abi . is_signed ( ) {
139+ if l. layout . abi . is_signed ( ) {
158140 if first_term & ( 1 << ( num_bits-1 ) ) == 0 { // first term is positive
159- // so overflow is positive
160- Scalar :: from_uint ( ( 1u128 << ( num_bits - 1 ) ) - 1 ,
141+ Scalar :: from_uint ( ( 1u128 << ( num_bits - 1 ) ) - 1 , // max positive
161142 Size :: from_bits ( num_bits) )
162- } else {
163- // if first term negative, overflow must be negative
143+ } else { // first term is negative
144+ // max negative
164145 Scalar :: from_uint ( 1u128 << ( num_bits - 1 ) , Size :: from_bits ( num_bits) )
165146 }
166- } else {
167- // unsigned underflow saturates to 0
168- Scalar :: from_uint ( 0u128 , Size :: from_bits ( num_bits) )
169- } ;
170- self . write_scalar ( val, dest) ?;
147+ } else { // unsigned
148+ if is_add {
149+ // max unsigned
150+ Scalar :: from_uint ( u128:: max_value ( ) >> ( 128 - num_bits) ,
151+ Size :: from_bits ( num_bits) )
152+ } else { // underflow to 0
153+ Scalar :: from_uint ( 0u128 , Size :: from_bits ( num_bits) )
154+ }
155+ }
171156 } else {
172- self . write_scalar ( val, dest) ?;
173- }
157+ val
158+ } ;
159+ self . write_scalar ( val, dest) ?;
174160 }
175161 "unchecked_shl" | "unchecked_shr" => {
176162 let l = self . read_immediate ( args[ 0 ] ) ?;
0 commit comments