@@ -122,55 +122,41 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
122
122
self . binop_with_overflow ( bin_op, lhs, rhs, dest) ?;
123
123
}
124
124
}
125
- "saturating_add" => {
125
+ "saturating_add" | "saturating_sub" => {
126
126
let l = self . read_immediate ( args[ 0 ] ) ?;
127
127
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
146
131
} 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
155
137
let first_term: u128 = l. to_scalar ( ) ?. to_bits ( l. layout . size ) ?;
156
138
let num_bits = l. layout . size . bits ( ) ;
157
- let val = if l. layout . abi . is_signed ( ) {
139
+ if l. layout . abi . is_signed ( ) {
158
140
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
161
142
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
164
145
Scalar :: from_uint ( 1u128 << ( num_bits - 1 ) , Size :: from_bits ( num_bits) )
165
146
}
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
+ }
171
156
} else {
172
- self . write_scalar ( val, dest) ?;
173
- }
157
+ val
158
+ } ;
159
+ self . write_scalar ( val, dest) ?;
174
160
}
175
161
"unchecked_shl" | "unchecked_shr" => {
176
162
let l = self . read_immediate ( args[ 0 ] ) ?;
0 commit comments