Skip to content

Commit 8b1d18c

Browse files
authored
Cleanup the way we test niche values (rust-lang#1544)
1 parent cf76024 commit 8b1d18c

File tree

3 files changed

+24
-19
lines changed

3 files changed

+24
-19
lines changed

cprover_bindings/src/goto_program/expr.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1328,7 +1328,7 @@ impl Expr {
13281328

13291329
/// `self == 0`
13301330
pub fn is_zero(self) -> Self {
1331-
assert!(self.typ.is_numeric());
1331+
assert!(self.typ.is_numeric() || self.typ.is_pointer());
13321332
let typ = self.typ.clone();
13331333
self.eq(typ.zero())
13341334
}

kani-compiler/src/codegen_cprover_gotoc/codegen/operand.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -608,12 +608,16 @@ impl<'tcx> GotocCtx<'tcx> {
608608

609609
/// fetch the niche value (as both left and right value)
610610
pub fn codegen_get_niche(&self, v: Expr, offset: Size, niche_ty: Type) -> Expr {
611-
v // t: T
612-
.address_of() // &t: T*
613-
.cast_to(Type::unsigned_int(8).to_pointer()) // (u8 *)&t: u8 *
614-
.plus(Expr::int_constant(offset.bytes_usize(), Type::size_t())) // ((u8 *)&t) + offset: u8 *
615-
.cast_to(niche_ty.to_pointer()) // (N *)(((u8 *)&t) + offset): N *
616-
.dereference() // *(N *)(((u8 *)&t) + offset): N
611+
if offset == Size::ZERO {
612+
v.reinterpret_cast(niche_ty)
613+
} else {
614+
v // t: T
615+
.address_of() // &t: T*
616+
.cast_to(Type::unsigned_int(8).to_pointer()) // (u8 *)&t: u8 *
617+
.plus(Expr::int_constant(offset.bytes(), Type::size_t())) // ((u8 *)&t) + offset: u8 *
618+
.cast_to(niche_ty.to_pointer()) // (N *)(((u8 *)&t) + offset): N *
619+
.dereference() // *(N *)(((u8 *)&t) + offset): N
620+
}
617621
}
618622

619623
/// Ensure that the given instance is in the symbol table, returning the symbol.

kani-compiler/src/codegen_cprover_gotoc/codegen/rvalue.rs

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use rustc_middle::mir::{AggregateKind, BinOp, CastKind, NullOp, Operand, Place,
1414
use rustc_middle::ty::adjustment::PointerCast;
1515
use rustc_middle::ty::layout::LayoutOf;
1616
use rustc_middle::ty::{self, Instance, IntTy, Ty, TyCtxt, UintTy, VtblEntry};
17-
use rustc_target::abi::{FieldsShape, Primitive, TagEncoding, Variants};
17+
use rustc_target::abi::{FieldsShape, TagEncoding, Variants};
1818
use tracing::{debug, warn};
1919

2020
impl<'tcx> GotocCtx<'tcx> {
@@ -503,12 +503,14 @@ impl<'tcx> GotocCtx<'tcx> {
503503
.map_or(index.as_u32() as u128, |discr| discr.val);
504504
Expr::int_constant(discr_val, self.codegen_ty(res_ty))
505505
}
506-
Variants::Multiple { tag, tag_encoding, .. } => match tag_encoding {
506+
Variants::Multiple { tag_encoding, .. } => match tag_encoding {
507507
TagEncoding::Direct => {
508508
self.codegen_discriminant_field(e, ty).cast_to(self.codegen_ty(res_ty))
509509
}
510510
TagEncoding::Niche { dataful_variant, niche_variants, niche_start } => {
511-
// This code follows the logic in the cranelift codegen backend:
511+
// This code follows the logic in the ssa codegen backend:
512+
// https://github.com/rust-lang/rust/blob/fee75fbe11b1fad5d93c723234178b2a329a3c03/compiler/rustc_codegen_ssa/src/mir/place.rs#L247
513+
// See also the cranelift backend:
512514
// https://github.com/rust-lang/rust/blob/05d22212e89588e7c443cc6b9bc0e4e02fdfbc8d/compiler/rustc_codegen_cranelift/src/discriminant.rs#L116
513515
let offset = match &layout.fields {
514516
FieldsShape::Arbitrary { offsets, .. } => offsets[0],
@@ -523,36 +525,35 @@ impl<'tcx> GotocCtx<'tcx> {
523525
// https://github.com/rust-lang/rust/blob/fee75fbe11b1fad5d93c723234178b2a329a3c03/compiler/rustc_codegen_ssa/src/mir/place.rs#L247
524526
//
525527
// Note: niche_variants can only represent values that fit in a u32.
528+
let result_type = self.codegen_ty(res_ty);
526529
let discr_mir_ty = self.codegen_enum_discr_typ(ty);
527530
let discr_type = self.codegen_ty(discr_mir_ty);
528-
let niche_val = self.codegen_get_niche(e, offset, discr_type.clone());
531+
let niche_val = self.codegen_get_niche(e, offset, discr_type);
529532
let relative_discr =
530533
wrapping_sub(&niche_val, u64::try_from(*niche_start).unwrap());
531534
let relative_max =
532535
niche_variants.end().as_u32() - niche_variants.start().as_u32();
533-
let is_niche = if tag.primitive() == Primitive::Pointer {
534-
tracing::trace!(?tag, "Primitive::Pointer");
535-
discr_type.null().eq(relative_discr.clone())
536+
let is_niche = if relative_max == 0 {
537+
relative_discr.clone().is_zero()
536538
} else {
537-
tracing::trace!(?tag, "Not Primitive::Pointer");
538539
relative_discr
539540
.clone()
540541
.le(Expr::int_constant(relative_max, relative_discr.typ().clone()))
541542
};
542543
let niche_discr = {
543544
let relative_discr = if relative_max == 0 {
544-
self.codegen_ty(res_ty).zero()
545+
result_type.zero()
545546
} else {
546-
relative_discr.cast_to(self.codegen_ty(res_ty))
547+
relative_discr.cast_to(result_type.clone())
547548
};
548549
relative_discr.plus(Expr::int_constant(
549550
niche_variants.start().as_u32(),
550-
self.codegen_ty(res_ty),
551+
result_type.clone(),
551552
))
552553
};
553554
is_niche.ternary(
554555
niche_discr,
555-
Expr::int_constant(dataful_variant.as_u32(), self.codegen_ty(res_ty)),
556+
Expr::int_constant(dataful_variant.as_u32(), result_type),
556557
)
557558
}
558559
},

0 commit comments

Comments
 (0)