From 1b81e0ada9bd6de4aa65f0bb07669f7f97303ca8 Mon Sep 17 00:00:00 2001 From: David Holland Date: Thu, 1 Aug 2024 17:04:56 -0400 Subject: [PATCH 1/7] Rearrange the way slices are handled. String slices and ordinary array slices are still special cases, but they're now handled like references: they contain a def_id that points to an allocation, which for constants is a static allocation holding the body. Previously they were handled like values and contained an inline copy of the actual data. This makes them come out in Crucible as global references rather than (magic) constant references; the latter do not support operations that are needed in practice. See saw-script #2064. The special cases for bstr are removed; they're no longer needed. It's probable that at least the body-data special cases for slices are no longer needed either, but one thing at a time. --- src/analyz/ty_json.rs | 165 ++++++++++++++++++++++++++---------------- 1 file changed, 104 insertions(+), 61 deletions(-) diff --git a/src/analyz/ty_json.rs b/src/analyz/ty_json.rs index 8f11486..0f42c74 100644 --- a/src/analyz/ty_json.rs +++ b/src/analyz/ty_json.rs @@ -1153,6 +1153,78 @@ pub fn try_render_opty<'mir, 'tcx>( }) } +fn make_static_ref<'mir, 'tcx>( + mir: &mut MirState<'_, 'tcx>, + icx: &mut interpret::InterpCx<'mir, 'tcx, RenderConstMachine<'mir, 'tcx>>, + rty: ty::Ty<'tcx>, + d: MPlaceTy<'tcx>, + is_mut: bool, + ca: interpret::ConstAllocation<'tcx> +) -> serde_json::Value { + let tcx = mir.state.tcx; + + if !is_mut { + match *rty.kind() { + // Special case for &str + ty::TyKind::Str => { + let len = mplace_ty_len(&d, icx).unwrap(); + let mem = icx.read_bytes_ptr_strip_provenance(d.ptr, Size::from_bytes(len)).unwrap(); + // corresponding array type for contents + let elem_ty = tcx.mk_ty(ty::TyKind::Uint(ty::UintTy::U8)); + let aty = tcx.mk_array(elem_ty, len); + let rendered = json!({ + "kind": "strbody", + "elements": mem, + "len": len + }); + return json!({ + "kind": "constant", + "mutable": false, + "ty": aty.to_json(mir), + "rendered": rendered, + }); + }, + // Special case for slices + ty::TyKind::Slice(slice_ty) => { + let slice_len = mplace_ty_len(&d, icx).unwrap(); + let mut elt_values = Vec::with_capacity(slice_len as usize); + for idx in 0..slice_len { + let elt = icx.operand_index(&d.into(), idx).unwrap(); + elt_values.push(try_render_opty(mir, icx, &elt)); + } + // corresponding array type for contents + let aty = tcx.mk_array(slice_ty, slice_len); + let rendered = json!({ + "kind": "slicebody", + "elements": elt_values, + "len": slice_len + }); + return json!({ + "kind": "constant", + "mutable": false, + "ty": aty.to_json(mir), + "rendered": rendered, + }); + }, + _ => () + } + } + + // Default case + let ma = tcx.create_memory_alloc(ca); + let rlayout = tcx.layout_of(ty::ParamEnv::reveal_all().and(rty)).unwrap(); + let ptr = interpret::Pointer::new(Some(ma), Size::ZERO); + let mpty = interpret::MPlaceTy::from_aligned_ptr_with_meta(ptr, rlayout, d.meta); + let rendered = try_render_opty(mir, icx, &mpty.into()); + + return json!({ + "kind": "constant", + "mutable": false, + "ty": rty.to_json(mir), + "rendered": rendered, + }); +} + fn try_render_ref_opty<'mir, 'tcx>( mir: &mut MirState<'_, 'tcx>, icx: &mut interpret::InterpCx<'mir, 'tcx, RenderConstMachine<'mir, 'tcx>>, @@ -1178,86 +1250,57 @@ fn try_render_ref_opty<'mir, 'tcx>( let d = icx.deref_operand(op_ty).unwrap(); let is_mut = mutability == hir::Mutability::Mut; + let (prov, _offset) = d.ptr.into_parts(); + let alloc = tcx.try_get_global_alloc(prov?)?; + + let def_id = match alloc { + interpret::GlobalAlloc::Static(def_id) => + def_id.to_json(mir), + interpret::GlobalAlloc::Memory(ca) => { + let ty = op_ty.layout.ty; + let def_id = match mir.allocs.get(ca, ty) { + Some(alloc_id) => alloc_id.to_owned(), + None => { + // create the allocation + let static_ref = make_static_ref(mir, icx, rty, d, is_mut, ca); + mir.allocs.insert(tcx, ca, ty, static_ref) + } + }; + def_id.to_json(mir) + } + _ => + // Give up + return None + }; + if !is_mut { match *rty.kind() { // Special case for &str ty::TyKind::Str => { let len = mplace_ty_len(&d, icx).unwrap(); - let mem = icx.read_bytes_ptr_strip_provenance(d.ptr, Size::from_bytes(len)).unwrap(); return Some(json!({ "kind": "str", - "val": mem + "def_id": def_id, + "len": len })) }, - // Special case for &[u8; N] - ty::TyKind::Array(elem_ty, _) => { - if let ty::TyKind::Uint(ty::UintTy::U8) = *elem_ty.kind() { - let mem = icx.read_bytes_ptr_strip_provenance(d.ptr, d.layout.size).unwrap(); - return Some(json!({ - "kind": "bstr", - "val": mem, - })) - } else { - () - } - }, // Special case for &[T] - ty::TyKind::Slice(slice_ty) => { + ty::TyKind::Slice(_slice_ty) => { let slice_len = mplace_ty_len(&d, icx).unwrap(); - let mut elt_values = Vec::with_capacity(slice_len as usize); - for idx in 0..slice_len { - let elt = icx.operand_index(&d.into(), idx).unwrap(); - elt_values.push(try_render_opty(mir, icx, &elt)); - } - return Some(json!({ "kind": "slice", - "element_ty": slice_ty.to_json(mir), - "elements": elt_values + "def_id": def_id, + "len": slice_len })) }, _ => () } } - let (prov, _offset) = d.ptr.into_parts(); - let alloc = tcx.try_get_global_alloc(prov?)?; - match alloc { - interpret::GlobalAlloc::Static(def_id) => - return Some(json!({ - "kind": "static_ref", - "def_id": def_id.to_json(mir), - })), - interpret::GlobalAlloc::Memory(ca) => { - let ty = op_ty.layout.ty; - let aid = match mir.allocs.get(ca, ty) { - Some(alloc_id) => alloc_id.to_owned(), - None => { - let ma = tcx.create_memory_alloc(ca); - let rlayout = tcx.layout_of(ty::ParamEnv::reveal_all().and(rty)).unwrap(); - let ptr = interpret::Pointer::new(Some(ma), Size::ZERO); - - let mpty = interpret::MPlaceTy::from_aligned_ptr_with_meta(ptr, rlayout, d.meta); - let rendered = try_render_opty(mir, icx, &mpty.into()); - - let static_ref = json!({ - "kind": "constant", - "mutable": false, - "ty": rty.to_json(mir), - "rendered": rendered, - }); - - mir.allocs.insert(tcx, ca, ty, static_ref) - } - }; - - return Some(json!({ - "kind": "static_ref", - "def_id": aid, - })); - } - _ => return None - } + return Some(json!({ + "kind": "static_ref", + "def_id": def_id, + })); } // A copied version of MPlaceTy::len, which (sadly) isn't exported. See From 7e36e9d8af15bc4ae7af5a0303c0e39337ca0d31 Mon Sep 17 00:00:00 2001 From: David Holland Date: Thu, 22 Aug 2024 19:42:14 -0400 Subject: [PATCH 2/7] Silence voluminous warnings in ty_json.rs (while I'm passing through). Remove some entirely unused functions flagged by the compiler. --- src/analyz/ty_json.rs | 145 +++++++++++++++--------------------------- 1 file changed, 53 insertions(+), 92 deletions(-) diff --git a/src/analyz/ty_json.rs b/src/analyz/ty_json.rs index 0f42c74..24ae466 100644 --- a/src/analyz/ty_json.rs +++ b/src/analyz/ty_json.rs @@ -8,7 +8,7 @@ use rustc_const_eval::interpret::{self, InterpCx, InterpResult, MPlaceTy, Proven use rustc_const_eval::const_eval::CheckAlignment; use rustc_middle::bug; use rustc_middle::ty; -use rustc_middle::ty::{AdtKind, DynKind, TyCtxt, TypeFoldable, TypeVisitable}; +use rustc_middle::ty::{AdtKind, DynKind, TyCtxt, TypeVisitable}; use rustc_middle::ty::util::{IntTypeExt}; use rustc_query_system::ich::StableHashingContext; use rustc_target::spec::abi; @@ -184,20 +184,6 @@ pub fn get_fn_def_name<'tcx>( } } -pub fn get_promoted_name<'tcx>( - mir: &mut MirState<'_, 'tcx>, - defid: DefId, - substs: ty::subst::SubstsRef<'tcx>, - promoted: Option, -) -> String { - let parent = get_fn_def_name(mir, defid, substs); - let idx = match promoted { - Some(x) => x, - None => return parent, - }; - format!("{}::{{{{promoted}}}}[{}]", parent, idx.as_usize()) -} - pub fn get_drop_fn_name<'tcx>( mir: &mut MirState<'_, 'tcx>, ty: ty::Ty<'tcx>, @@ -305,7 +291,7 @@ impl<'tcx> ToJson<'tcx> for ty::Instance<'tcx> { let sub_tys = match *ty.kind() { ty::TyKind::Array(t, _) => vec![t], ty::TyKind::Tuple(ts) => ts[..].to_owned(), - ty::TyKind::Closure(closure_did, substs) => + ty::TyKind::Closure(_closure_did, substs) => substs.as_closure().upvar_tys().collect(), _ => { eprintln!("warning: don't know how to build clone shim for {:?}", ty); @@ -416,7 +402,7 @@ impl<'tcx> ToJson<'tcx> for ty::Ty<'tcx> { &ty::TyKind::Param(..) => unreachable!( "no TyKind::Param should remain after monomorphization" ), - &ty::TyKind::Closure(defid, ref substs) => { + &ty::TyKind::Closure(_defid, ref substs) => { json!({ "kind": "Closure", "upvar_tys": substs.as_closure().upvar_tys() @@ -666,21 +652,6 @@ impl<'tcx> ToJson<'tcx> for ty::subst::GenericArg<'tcx> { } } -fn eval_array_len<'tcx>( - tcx: TyCtxt<'tcx>, - c: ty::Const<'tcx>, -) -> usize { - match c.kind() { - // ty::ConstKind::Unevaluated(un) => { - // tcx.const_eval_resolve(ty::ParamEnv::reveal_all(), un.expand(), None).unwrap() - // }, - // NB: the type of "val" changed to valtree - try to get the size out of that - ty::ConstKind::Value(ty::ValTree::Leaf(val)) => - val.try_to_machine_usize(tcx).expect("expecting usize value from constant") as usize, - ref val => panic!("don't know how to translate ConstKind::{:?}", val), - } -} - use self::machine::RenderConstMachine; mod machine { use std::borrow::Cow; @@ -717,20 +688,20 @@ mod machine { const GLOBAL_KIND: Option = None; const PANIC_ON_ALLOC_FAIL: bool = false; - fn enforce_alignment(ecx: &InterpCx<'mir, 'tcx, Self>) -> CheckAlignment { + fn enforce_alignment(_ecx: &InterpCx<'mir, 'tcx, Self>) -> CheckAlignment { CheckAlignment::No } fn alignment_check_failed( - ecx: &InterpCx<'mir, 'tcx, Self>, - has: Align, - required: Align, - check: CheckAlignment, + _ecx: &InterpCx<'mir, 'tcx, Self>, + _has: Align, + _required: Align, + _check: CheckAlignment, ) -> InterpResult<'tcx, ()> { panic!("not implemented: alignment_check_failed"); } - fn use_addr_for_alignment_check(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool { + fn use_addr_for_alignment_check(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool { false } @@ -739,18 +710,18 @@ mod machine { true } - fn enforce_validity(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool { + fn enforce_validity(_ecx: &InterpCx<'mir, 'tcx, Self>) -> bool { false } fn find_mir_or_eval_fn( - ecx: &mut InterpCx<'mir, 'tcx, Self>, - instance: ty::Instance<'tcx>, - abi: Abi, - args: &[OpTy<'tcx, Self::Provenance>], - destination: &PlaceTy<'tcx, Self::Provenance>, - target: Option, - unwind: StackPopUnwind, + _ecx: &mut InterpCx<'mir, 'tcx, Self>, + _instance: ty::Instance<'tcx>, + _abi: Abi, + _args: &[OpTy<'tcx, Self::Provenance>], + _destination: &PlaceTy<'tcx, Self::Provenance>, + _target: Option, + _unwind: StackPopUnwind, ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> { Err(InterpError::Unsupported( UnsupportedOpInfo::Unsupported( @@ -760,13 +731,13 @@ mod machine { } fn call_extra_fn( - ecx: &mut InterpCx<'mir, 'tcx, Self>, - fn_val: Self::ExtraFnVal, - abi: Abi, - args: &[OpTy<'tcx, Self::Provenance>], - destination: &PlaceTy<'tcx, Self::Provenance>, - target: Option, - unwind: StackPopUnwind, + _ecx: &mut InterpCx<'mir, 'tcx, Self>, + _fn_val: Self::ExtraFnVal, + _abi: Abi, + _args: &[OpTy<'tcx, Self::Provenance>], + _destination: &PlaceTy<'tcx, Self::Provenance>, + _target: Option, + _unwind: StackPopUnwind, ) -> InterpResult<'tcx> { Err(InterpError::Unsupported( UnsupportedOpInfo::Unsupported( @@ -776,12 +747,12 @@ mod machine { } fn call_intrinsic( - ecx: &mut InterpCx<'mir, 'tcx, Self>, - instance: ty::Instance<'tcx>, - args: &[OpTy<'tcx, Self::Provenance>], - destination: &PlaceTy<'tcx, Self::Provenance>, - target: Option, - unwind: StackPopUnwind, + _ecx: &mut InterpCx<'mir, 'tcx, Self>, + _instance: ty::Instance<'tcx>, + _args: &[OpTy<'tcx, Self::Provenance>], + _destination: &PlaceTy<'tcx, Self::Provenance>, + _target: Option, + _unwind: StackPopUnwind, ) -> InterpResult<'tcx> { Err(InterpError::Unsupported( UnsupportedOpInfo::Unsupported( @@ -791,9 +762,9 @@ mod machine { } fn assert_panic( - ecx: &mut InterpCx<'mir, 'tcx, Self>, - msg: &mir::AssertMessage<'tcx>, - unwind: Option, + _ecx: &mut InterpCx<'mir, 'tcx, Self>, + _msg: &mir::AssertMessage<'tcx>, + _unwind: Option, ) -> InterpResult<'tcx> { Err(InterpError::Unsupported( UnsupportedOpInfo::Unsupported( @@ -803,10 +774,10 @@ mod machine { } fn binary_ptr_op( - ecx: &InterpCx<'mir, 'tcx, Self>, - bin_op: mir::BinOp, - left: &ImmTy<'tcx, Self::Provenance>, - right: &ImmTy<'tcx, Self::Provenance>, + _ecx: &InterpCx<'mir, 'tcx, Self>, + _bin_op: mir::BinOp, + _left: &ImmTy<'tcx, Self::Provenance>, + _right: &ImmTy<'tcx, Self::Provenance>, ) -> InterpResult<'tcx, (Scalar, bool, Ty<'tcx>)> { Err(InterpError::Unsupported( UnsupportedOpInfo::Unsupported( @@ -816,8 +787,8 @@ mod machine { } fn extern_static_base_pointer( - ecx: &InterpCx<'mir, 'tcx, Self>, - def_id: DefId, + _ecx: &InterpCx<'mir, 'tcx, Self>, + _def_id: DefId, ) -> InterpResult<'tcx, Pointer> { Err(InterpError::Unsupported( UnsupportedOpInfo::Unsupported( @@ -827,22 +798,22 @@ mod machine { } fn adjust_alloc_base_pointer( - ecx: &InterpCx<'mir, 'tcx, Self>, + _ecx: &InterpCx<'mir, 'tcx, Self>, ptr: Pointer, ) -> Pointer { ptr } fn ptr_from_addr_cast( - ecx: &InterpCx<'mir, 'tcx, Self>, - addr: u64, + _ecx: &InterpCx<'mir, 'tcx, Self>, + _addr: u64, ) -> InterpResult<'tcx, Pointer>> { unimplemented!("ptr_from_addr_cast") } fn expose_ptr( - ecx: &mut InterpCx<'mir, 'tcx, Self>, - ptr: Pointer, + _ecx: &mut InterpCx<'mir, 'tcx, Self>, + _ptr: Pointer, ) -> InterpResult<'tcx> { Err(InterpError::Unsupported( UnsupportedOpInfo::Unsupported( @@ -852,7 +823,7 @@ mod machine { } fn ptr_get_alloc( - ecx: &InterpCx<'mir, 'tcx, Self>, + _ecx: &InterpCx<'mir, 'tcx, Self>, ptr: Pointer, ) -> Option<(AllocId, Size, Self::ProvenanceExtra)> { let (prov, offset) = ptr.into_parts(); @@ -860,17 +831,17 @@ mod machine { } fn adjust_allocation<'b>( - ecx: &InterpCx<'mir, 'tcx, Self>, - id: AllocId, + _ecx: &InterpCx<'mir, 'tcx, Self>, + _id: AllocId, alloc: Cow<'b, Allocation>, - kind: Option>, + _kind: Option>, ) -> InterpResult<'tcx, Cow<'b, Allocation>> { Ok(alloc) } fn init_frame_extra( - ecx: &mut InterpCx<'mir, 'tcx, Self>, - frame: Frame<'mir, 'tcx, Self::Provenance>, + _ecx: &mut InterpCx<'mir, 'tcx, Self>, + _frame: Frame<'mir, 'tcx, Self::Provenance>, ) -> InterpResult<'tcx, Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>> { Err(InterpError::Unsupported( UnsupportedOpInfo::Unsupported( @@ -887,7 +858,7 @@ mod machine { } fn stack_mut<'a>( - ecx: &'a mut InterpCx<'mir, 'tcx, Self>, + _ecx: &'a mut InterpCx<'mir, 'tcx, Self>, ) -> &'a mut Vec> { unimplemented!("stack_mut") } @@ -999,7 +970,7 @@ pub fn try_render_opty<'mir, 'tcx>( "val": bits.to_string(), }) } - ty::TyKind::Int(i) => { + ty::TyKind::Int(_i) => { let s = icx.read_immediate(op_ty).unwrap().to_scalar(); let size = layout.size(); let bits = s.to_bits(size).unwrap(); @@ -1326,8 +1297,7 @@ pub fn mplace_ty_len<'tcx, Tag: Provenance>(mplace_ty: &MPlaceTy<'tcx, Tag>, cx: pub fn as_opty<'tcx>(tcx: TyCtxt<'tcx>, cv: interpret::ConstValue<'tcx>, ty: ty::Ty<'tcx>) -> interpret::OpTy<'tcx, interpret::AllocId> { - use rustc_const_eval::interpret::{Operand, Pointer, MemPlace, ConstValue, Immediate, Scalar, OpTy, ImmTy, MPlaceTy}; - use rustc_target::abi::Size; + use rustc_const_eval::interpret::{Operand, Pointer, MemPlace, ConstValue, Immediate, Scalar, ImmTy}; let op = match cv { ConstValue::ByRef { alloc, offset } => { let id = tcx.create_memory_alloc(alloc); @@ -1536,15 +1506,6 @@ pub fn handle_adt_ag<'tcx>( } } -pub fn eval_mir_constant2<'mir, 'tcx>( - icx: &InterpCx<'mir, 'tcx, RenderConstMachine<'mir, 'tcx>>, - tcx: ty::TyCtxt<'tcx>, - constant: &mir::Constant<'tcx>, -) -> interpret::OpTy<'tcx> { - let layout = tcx.layout_of(ty::ParamEnv::reveal_all().and(constant.ty())).unwrap(); - icx.eval_mir_constant(&constant.literal, Some(constant.span), Some(layout)).unwrap() -} - // Based on `rustc_codegen_ssa::mir::FunctionCx::eval_mir_constant` pub fn eval_mir_constant<'tcx>( tcx: TyCtxt<'tcx>, From 3ae9b16ce9827c684b0495d94b5ec88a8cfb0651 Mon Sep 17 00:00:00 2001 From: David Holland Date: Thu, 22 Aug 2024 21:29:09 -0400 Subject: [PATCH 3/7] Indeed, slice bodies are just arrays. Use the "array" output kind. The code to generate slice bodies is still different from the general array case, though. None of this is true of _string_ slice bodies, whose elements fields are just lists of character values. That should probably stay that way to avoid bloating out large string constants. --- src/analyz/ty_json.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/analyz/ty_json.rs b/src/analyz/ty_json.rs index 24ae466..06d1d07 100644 --- a/src/analyz/ty_json.rs +++ b/src/analyz/ty_json.rs @@ -1166,7 +1166,8 @@ fn make_static_ref<'mir, 'tcx>( // corresponding array type for contents let aty = tcx.mk_array(slice_ty, slice_len); let rendered = json!({ - "kind": "slicebody", + // this can now be the same as an ordinary array + "kind": "array", "elements": elt_values, "len": slice_len }); From 517add885ed16049168418545dc839648e35ad83 Mon Sep 17 00:00:00 2001 From: David Holland Date: Thu, 22 Aug 2024 21:36:14 -0400 Subject: [PATCH 4/7] String slices and ordinary slices should probably stay separate cases. (even though the logic is the same) Add a note to this effect. --- src/analyz/ty_json.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/analyz/ty_json.rs b/src/analyz/ty_json.rs index 06d1d07..fa81b88 100644 --- a/src/analyz/ty_json.rs +++ b/src/analyz/ty_json.rs @@ -1247,7 +1247,13 @@ fn try_render_ref_opty<'mir, 'tcx>( if !is_mut { match *rty.kind() { - // Special case for &str + // Special cases for &str and &[T] + // + // These cases are the same apart from the kind label, and + // it's possible they could be folded together. But it + // seems like a bad idea to conflate string slices and + // ordinary slices unless/until we're sure it won't create + // complications, now or in the future. ty::TyKind::Str => { let len = mplace_ty_len(&d, icx).unwrap(); return Some(json!({ @@ -1256,13 +1262,12 @@ fn try_render_ref_opty<'mir, 'tcx>( "len": len })) }, - // Special case for &[T] ty::TyKind::Slice(_slice_ty) => { - let slice_len = mplace_ty_len(&d, icx).unwrap(); + let len = mplace_ty_len(&d, icx).unwrap(); return Some(json!({ "kind": "slice", "def_id": def_id, - "len": slice_len + "len": len })) }, _ => () From 7f76e7194f82759dcb206fcc9952d2792b9f78f1 Mon Sep 17 00:00:00 2001 From: David Holland Date: Fri, 23 Aug 2024 16:55:23 -0400 Subject: [PATCH 5/7] Handle review comments: - expand some comments - get a better name for make_static_ref - adjust some other names for clarity - assert if we hit a nonzero reference output (instead of silently emitting bad code) --- src/analyz/ty_json.rs | 30 ++++++++++++++++++------------ 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/src/analyz/ty_json.rs b/src/analyz/ty_json.rs index fa81b88..bfcf360 100644 --- a/src/analyz/ty_json.rs +++ b/src/analyz/ty_json.rs @@ -1124,7 +1124,7 @@ pub fn try_render_opty<'mir, 'tcx>( }) } -fn make_static_ref<'mir, 'tcx>( +fn make_allocation_body<'mir, 'tcx>( mir: &mut MirState<'_, 'tcx>, icx: &mut interpret::InterpCx<'mir, 'tcx, RenderConstMachine<'mir, 'tcx>>, rty: ty::Ty<'tcx>, @@ -1136,7 +1136,10 @@ fn make_static_ref<'mir, 'tcx>( if !is_mut { match *rty.kind() { - // Special case for &str + // Special cases for &str and &[T] + // + // These and the ones in try_render_ref_opty below should be + // kept in sync. ty::TyKind::Str => { let len = mplace_ty_len(&d, icx).unwrap(); let mem = icx.read_bytes_ptr_strip_provenance(d.ptr, Size::from_bytes(len)).unwrap(); @@ -1155,7 +1158,6 @@ fn make_static_ref<'mir, 'tcx>( "rendered": rendered, }); }, - // Special case for slices ty::TyKind::Slice(slice_ty) => { let slice_len = mplace_ty_len(&d, icx).unwrap(); let mut elt_values = Vec::with_capacity(slice_len as usize); @@ -1222,23 +1224,24 @@ fn try_render_ref_opty<'mir, 'tcx>( let d = icx.deref_operand(op_ty).unwrap(); let is_mut = mutability == hir::Mutability::Mut; - let (prov, _offset) = d.ptr.into_parts(); + let (prov, d_offset) = d.ptr.into_parts(); + assert!(d_offset == Size::ZERO, "cannot handle nonzero reference offsets"); let alloc = tcx.try_get_global_alloc(prov?)?; - let def_id = match alloc { + let def_id_json = match alloc { interpret::GlobalAlloc::Static(def_id) => def_id.to_json(mir), interpret::GlobalAlloc::Memory(ca) => { let ty = op_ty.layout.ty; - let def_id = match mir.allocs.get(ca, ty) { + let def_id_str = match mir.allocs.get(ca, ty) { Some(alloc_id) => alloc_id.to_owned(), None => { // create the allocation - let static_ref = make_static_ref(mir, icx, rty, d, is_mut, ca); - mir.allocs.insert(tcx, ca, ty, static_ref) + let body = make_allocation_body(mir, icx, rty, d, is_mut, ca); + mir.allocs.insert(tcx, ca, ty, body) } }; - def_id.to_json(mir) + def_id_str.to_json(mir) } _ => // Give up @@ -1254,11 +1257,14 @@ fn try_render_ref_opty<'mir, 'tcx>( // seems like a bad idea to conflate string slices and // ordinary slices unless/until we're sure it won't create // complications, now or in the future. + // + // These and the ones in make_allocation_body above should be + // kept in sync. ty::TyKind::Str => { let len = mplace_ty_len(&d, icx).unwrap(); return Some(json!({ "kind": "str", - "def_id": def_id, + "def_id": def_id_json, "len": len })) }, @@ -1266,7 +1272,7 @@ fn try_render_ref_opty<'mir, 'tcx>( let len = mplace_ty_len(&d, icx).unwrap(); return Some(json!({ "kind": "slice", - "def_id": def_id, + "def_id": def_id_json, "len": len })) }, @@ -1276,7 +1282,7 @@ fn try_render_ref_opty<'mir, 'tcx>( return Some(json!({ "kind": "static_ref", - "def_id": def_id, + "def_id": def_id_json, })); } From b36d4a0a12f8b97c6a5280d17fa4a1a77851a13f Mon Sep 17 00:00:00 2001 From: David Holland Date: Fri, 23 Aug 2024 17:57:31 -0400 Subject: [PATCH 6/7] Apply simplification suggested by Stuart. --- src/analyz/ty_json.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/analyz/ty_json.rs b/src/analyz/ty_json.rs index bfcf360..63d0435 100644 --- a/src/analyz/ty_json.rs +++ b/src/analyz/ty_json.rs @@ -1130,7 +1130,6 @@ fn make_allocation_body<'mir, 'tcx>( rty: ty::Ty<'tcx>, d: MPlaceTy<'tcx>, is_mut: bool, - ca: interpret::ConstAllocation<'tcx> ) -> serde_json::Value { let tcx = mir.state.tcx; @@ -1185,10 +1184,8 @@ fn make_allocation_body<'mir, 'tcx>( } // Default case - let ma = tcx.create_memory_alloc(ca); let rlayout = tcx.layout_of(ty::ParamEnv::reveal_all().and(rty)).unwrap(); - let ptr = interpret::Pointer::new(Some(ma), Size::ZERO); - let mpty = interpret::MPlaceTy::from_aligned_ptr_with_meta(ptr, rlayout, d.meta); + let mpty = interpret::MPlaceTy::from_aligned_ptr_with_meta(d.ptr, rlayout, d.meta); let rendered = try_render_opty(mir, icx, &mpty.into()); return json!({ @@ -1237,7 +1234,7 @@ fn try_render_ref_opty<'mir, 'tcx>( Some(alloc_id) => alloc_id.to_owned(), None => { // create the allocation - let body = make_allocation_body(mir, icx, rty, d, is_mut, ca); + let body = make_allocation_body(mir, icx, rty, d, is_mut); mir.allocs.insert(tcx, ca, ty, body) } }; From ced2a9f4724f592fa60946066d0c1e6c136f1d5c Mon Sep 17 00:00:00 2001 From: David Holland Date: Fri, 23 Aug 2024 18:28:20 -0400 Subject: [PATCH 7/7] Fold the string slice and array slices together after all. (on the reference side, the bodies of strings are still special-cased) Advice from those much more familiar with things is that the representation of strings is not likely to diverge from [u8]. --- src/analyz/ty_json.rs | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/src/analyz/ty_json.rs b/src/analyz/ty_json.rs index 63d0435..b3e7632 100644 --- a/src/analyz/ty_json.rs +++ b/src/analyz/ty_json.rs @@ -1249,23 +1249,9 @@ fn try_render_ref_opty<'mir, 'tcx>( match *rty.kind() { // Special cases for &str and &[T] // - // These cases are the same apart from the kind label, and - // it's possible they could be folded together. But it - // seems like a bad idea to conflate string slices and - // ordinary slices unless/until we're sure it won't create - // complications, now or in the future. - // // These and the ones in make_allocation_body above should be // kept in sync. - ty::TyKind::Str => { - let len = mplace_ty_len(&d, icx).unwrap(); - return Some(json!({ - "kind": "str", - "def_id": def_id_json, - "len": len - })) - }, - ty::TyKind::Slice(_slice_ty) => { + ty::TyKind::Str | ty::TyKind::Slice(_) => { let len = mplace_ty_len(&d, icx).unwrap(); return Some(json!({ "kind": "slice",