|
6 | 6 | //! in [codegen_place] below.
|
7 | 7 |
|
8 | 8 | use crate::gotoc::cbmc::goto_program::{Expr, Type};
|
| 9 | +use crate::gotoc::mir_to_goto::utils::slice_fat_ptr; |
9 | 10 | use crate::gotoc::mir_to_goto::GotocCtx;
|
| 11 | +use rustc_hir::Mutability; |
10 | 12 | use rustc_middle::{
|
11 | 13 | mir::{Field, Local, Place, ProjectionElem},
|
12 |
| - ty::{self, Ty, TyS, VariantDef}, |
| 14 | + ty::{self, Ty, TyS, TypeAndMut, VariantDef}, |
13 | 15 | };
|
14 | 16 | use rustc_target::abi::{LayoutOf, TagEncoding, Variants};
|
15 | 17 | use tracing::{debug, warn};
|
@@ -357,7 +359,46 @@ impl<'tcx> GotocCtx<'tcx> {
|
357 | 359 | ProjectionElem::ConstantIndex { offset, min_length, from_end } => {
|
358 | 360 | self.codegen_constant_index(before, offset, min_length, from_end)
|
359 | 361 | }
|
360 |
| - ProjectionElem::Subslice { .. } => unimplemented!(), |
| 362 | + // Best effort to codegen subslice projection. |
| 363 | + // This is known to fail with a CBMC invariant violation |
| 364 | + // in some cases. Full support to be added in |
| 365 | + // https://github.com/model-checking/rmc/issues/357 |
| 366 | + ProjectionElem::Subslice { from, to, from_end } => { |
| 367 | + // https://rust-lang.github.io/rfcs/2359-subslice-pattern-syntax.html |
| 368 | + match before.mir_typ().kind() { |
| 369 | + ty::Array(..) => unimplemented!(), |
| 370 | + ty::Slice(elemt) => { |
| 371 | + let len = if from_end { |
| 372 | + let olen = before |
| 373 | + .fat_ptr_goto_expr |
| 374 | + .clone() |
| 375 | + .unwrap() |
| 376 | + .member("len", &self.symbol_table); |
| 377 | + let sum = Expr::int_constant(to + from, Type::size_t()); |
| 378 | + olen.sub(sum) // olen - (to + from) = olen - to - from |
| 379 | + } else { |
| 380 | + Expr::int_constant(to - from, Type::size_t()) |
| 381 | + }; |
| 382 | + let typ = self.tcx.mk_slice(elemt); |
| 383 | + let typ_and_mut = TypeAndMut { ty: typ, mutbl: Mutability::Mut }; |
| 384 | + let ptr_typ = self.tcx.mk_ptr(typ_and_mut); |
| 385 | + let goto_type = self.codegen_ty(ptr_typ); |
| 386 | + |
| 387 | + let index = Expr::int_constant(from, Type::ssize_t()); |
| 388 | + let from_elem = before.goto_expr.index(index); |
| 389 | + let data = from_elem.address_of(); |
| 390 | + let fat_ptr = slice_fat_ptr(goto_type, data, len, &self.symbol_table); |
| 391 | + ProjectedPlace::new( |
| 392 | + fat_ptr.clone(), |
| 393 | + TypeOrVariant::Type(ptr_typ), |
| 394 | + Some(fat_ptr), |
| 395 | + Some(ptr_typ), |
| 396 | + self, |
| 397 | + ) |
| 398 | + } |
| 399 | + _ => unreachable!("must be array or slice"), |
| 400 | + } |
| 401 | + } |
361 | 402 | ProjectionElem::Downcast(_, idx) => {
|
362 | 403 | // downcast converts a variable of an enum type to one of its discriminated cases
|
363 | 404 | let t = before.mir_typ();
|
|
0 commit comments