|
2 | 2 |
|
3 | 3 | use rustc_index::vec::Idx;
|
4 | 4 | use rustc_middle::ty::util::IntTypeExt;
|
| 5 | +use rustc_target::abi::{Abi, Primitive}; |
5 | 6 |
|
6 | 7 | use crate::build::expr::as_place::PlaceBase;
|
7 | 8 | use crate::build::expr::category::{Category, RvalueFunc};
|
@@ -198,15 +199,63 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
198 | 199 | let (source, ty) = if let ty::Adt(adt_def, ..) = source.ty.kind() && adt_def.is_enum() {
|
199 | 200 | let discr_ty = adt_def.repr().discr_type().to_ty(this.tcx);
|
200 | 201 | let temp = unpack!(block = this.as_temp(block, scope, source, Mutability::Not));
|
| 202 | + let layout = this.tcx.layout_of(this.param_env.and(source.ty)); |
201 | 203 | let discr = this.temp(discr_ty, source.span);
|
202 | 204 | this.cfg.push_assign(
|
203 | 205 | block,
|
204 | 206 | source_info,
|
205 | 207 | discr,
|
206 | 208 | Rvalue::Discriminant(temp.into()),
|
207 | 209 | );
|
| 210 | + let (op,ty) = (Operand::Move(discr), discr_ty); |
| 211 | + |
| 212 | + if let Abi::Scalar(scalar) = layout.unwrap().abi{ |
| 213 | + if let Primitive::Int(_, signed) = scalar.primitive() { |
| 214 | + let range = scalar.valid_range(&this.tcx); |
| 215 | + // FIXME: Handle wraparound cases too. |
| 216 | + if range.end >= range.start { |
| 217 | + let mut assumer = |range: u128, bin_op: BinOp| { |
| 218 | + // We will be overwriting this val if our scalar is signed value |
| 219 | + // because sign extension on unsigned types might cause unintended things |
| 220 | + let mut range_val = |
| 221 | + ConstantKind::from_bits(this.tcx, range, ty::ParamEnv::empty().and(discr_ty)); |
| 222 | + let bool_ty = this.tcx.types.bool; |
| 223 | + if signed { |
| 224 | + let scalar_size_extend = scalar.size(&this.tcx).sign_extend(range); |
| 225 | + let discr_layout = this.tcx.layout_of(this.param_env.and(discr_ty)); |
| 226 | + let truncated_val = discr_layout.unwrap().size.truncate(scalar_size_extend); |
| 227 | + range_val = ConstantKind::from_bits( |
| 228 | + this.tcx, |
| 229 | + truncated_val, |
| 230 | + ty::ParamEnv::empty().and(discr_ty), |
| 231 | + ); |
| 232 | + } |
| 233 | + let lit_op = this.literal_operand(expr.span, range_val); |
| 234 | + let is_bin_op = this.temp(bool_ty, expr_span); |
| 235 | + this.cfg.push_assign( |
| 236 | + block, |
| 237 | + source_info, |
| 238 | + is_bin_op, |
| 239 | + Rvalue::BinaryOp(bin_op, Box::new(((lit_op), (Operand::Copy(discr))))), |
| 240 | + ); |
| 241 | + this.cfg.push( |
| 242 | + block, |
| 243 | + Statement { |
| 244 | + source_info, |
| 245 | + kind: StatementKind::Intrinsic(Box::new(NonDivergingIntrinsic::Assume( |
| 246 | + Operand::Copy(is_bin_op), |
| 247 | + ))), |
| 248 | + }, |
| 249 | + ) |
| 250 | + }; |
| 251 | + assumer(range.end, BinOp::Ge); |
| 252 | + assumer(range.start, BinOp::Le); |
| 253 | + } |
| 254 | + } |
| 255 | + } |
| 256 | + |
| 257 | + (op,ty) |
208 | 258 |
|
209 |
| - (Operand::Move(discr), discr_ty) |
210 | 259 | } else {
|
211 | 260 | let ty = source.ty;
|
212 | 261 | let source = unpack!(
|
|
0 commit comments