From 585141b219e18f7c4c5817347241f597b59035a5 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 23 May 2021 12:03:39 +0200 Subject: [PATCH] support creating mutable allocations from byte slices --- .../rustc_middle/src/mir/interpret/allocation.rs | 12 ++++++++---- compiler/rustc_middle/src/ty/context.rs | 2 +- compiler/rustc_mir/src/const_eval/eval_queries.rs | 5 +++-- .../src/interpret/intrinsics/caller_location.rs | 4 +++- .../rustc_mir/src/interpret/intrinsics/type_name.rs | 2 +- compiler/rustc_mir/src/interpret/memory.rs | 4 +++- compiler/rustc_mir/src/interpret/place.rs | 12 +++++++++--- compiler/rustc_mir_build/src/thir/constant.rs | 4 ++-- 8 files changed, 30 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs index 622eaf57578..cf832ee0f7a 100644 --- a/compiler/rustc_middle/src/mir/interpret/allocation.rs +++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs @@ -100,7 +100,11 @@ impl AllocRange { // The constructors are all without extra; the extra gets added by a machine hook later. impl Allocation { /// Creates a read-only allocation initialized by the given bytes - pub fn from_bytes<'a>(slice: impl Into>, align: Align) -> Self { + pub fn from_bytes<'a>( + slice: impl Into>, + align: Align, + mutability: Mutability, + ) -> Self { let bytes = slice.into().into_owned(); let size = Size::from_bytes(bytes.len()); Self { @@ -108,13 +112,13 @@ impl Allocation { relocations: Relocations::new(), init_mask: InitMask::new(size, true), align, - mutability: Mutability::Not, + mutability, extra: (), } } - pub fn from_byte_aligned_bytes<'a>(slice: impl Into>) -> Self { - Allocation::from_bytes(slice, Align::ONE) + pub fn from_bytes_byte_aligned_immutable<'a>(slice: impl Into>) -> Self { + Allocation::from_bytes(slice, Align::ONE, Mutability::Not) } pub fn uninit(size: Size, align: Align) -> Self { diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index dde5cbadbd9..790463d6fc6 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1072,7 +1072,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Allocates a read-only byte or string literal for `mir::interpret`. pub fn allocate_bytes(self, bytes: &[u8]) -> interpret::AllocId { // Create an allocation that just contains these bytes. - let alloc = interpret::Allocation::from_byte_aligned_bytes(bytes); + let alloc = interpret::Allocation::from_bytes_byte_aligned_immutable(bytes); let alloc = self.intern_const_alloc(alloc); self.create_memory_alloc(alloc) } diff --git a/compiler/rustc_mir/src/const_eval/eval_queries.rs b/compiler/rustc_mir/src/const_eval/eval_queries.rs index d51adc8864d..a12185393de 100644 --- a/compiler/rustc_mir/src/const_eval/eval_queries.rs +++ b/compiler/rustc_mir/src/const_eval/eval_queries.rs @@ -169,8 +169,9 @@ pub(super) fn op_to_const<'tcx>( (ecx.tcx.global_alloc(ptr.alloc_id).unwrap_memory(), ptr.offset.bytes()) } Scalar::Int { .. } => ( - ecx.tcx - .intern_const_alloc(Allocation::from_byte_aligned_bytes(b"" as &[u8])), + ecx.tcx.intern_const_alloc(Allocation::from_bytes_byte_aligned_immutable( + b"" as &[u8], + )), 0, ), }; diff --git a/compiler/rustc_mir/src/interpret/intrinsics/caller_location.rs b/compiler/rustc_mir/src/interpret/intrinsics/caller_location.rs index 2b996cf62a3..792a4749108 100644 --- a/compiler/rustc_mir/src/interpret/intrinsics/caller_location.rs +++ b/compiler/rustc_mir/src/interpret/intrinsics/caller_location.rs @@ -1,5 +1,6 @@ use std::convert::TryFrom; +use rustc_ast::Mutability; use rustc_hir::lang_items::LangItem; use rustc_middle::mir::TerminatorKind; use rustc_middle::ty::subst::Subst; @@ -79,7 +80,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { line: u32, col: u32, ) -> MPlaceTy<'tcx, M::PointerTag> { - let file = self.allocate_str(&filename.as_str(), MemoryKind::CallerLocation); + let file = + self.allocate_str(&filename.as_str(), MemoryKind::CallerLocation, Mutability::Not); let line = Scalar::from_u32(line); let col = Scalar::from_u32(col); diff --git a/compiler/rustc_mir/src/interpret/intrinsics/type_name.rs b/compiler/rustc_mir/src/interpret/intrinsics/type_name.rs index ae5e78ee33f..4978cc3606d 100644 --- a/compiler/rustc_mir/src/interpret/intrinsics/type_name.rs +++ b/compiler/rustc_mir/src/interpret/intrinsics/type_name.rs @@ -197,6 +197,6 @@ impl Write for AbsolutePathPrinter<'_> { /// Directly returns an `Allocation` containing an absolute path representation of the given type. crate fn alloc_type_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> &'tcx Allocation { let path = AbsolutePathPrinter { tcx, path: String::new() }.print_type(ty).unwrap().path; - let alloc = Allocation::from_byte_aligned_bytes(path.into_bytes()); + let alloc = Allocation::from_bytes_byte_aligned_immutable(path.into_bytes()); tcx.intern_const_alloc(alloc) } diff --git a/compiler/rustc_mir/src/interpret/memory.rs b/compiler/rustc_mir/src/interpret/memory.rs index c26fcf83288..77de19ac674 100644 --- a/compiler/rustc_mir/src/interpret/memory.rs +++ b/compiler/rustc_mir/src/interpret/memory.rs @@ -219,9 +219,11 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { pub fn allocate_bytes( &mut self, bytes: &[u8], + align: Align, kind: MemoryKind, + mutability: Mutability, ) -> Pointer { - let alloc = Allocation::from_byte_aligned_bytes(bytes); + let alloc = Allocation::from_bytes(bytes, align, mutability); self.allocate_with(alloc, kind) } diff --git a/compiler/rustc_mir/src/interpret/place.rs b/compiler/rustc_mir/src/interpret/place.rs index ef603b51554..79aaff1c5eb 100644 --- a/compiler/rustc_mir/src/interpret/place.rs +++ b/compiler/rustc_mir/src/interpret/place.rs @@ -6,6 +6,7 @@ use std::convert::TryFrom; use std::fmt::Debug; use std::hash::Hash; +use rustc_ast::Mutability; use rustc_macros::HashStable; use rustc_middle::mir; use rustc_middle::ty::layout::{PrimitiveExt, TyAndLayout}; @@ -1024,18 +1025,23 @@ where MPlaceTy::from_aligned_ptr(ptr, layout) } - /// Returns a wide MPlace. + /// Returns a wide MPlace of type `&'static [mut] str` to a new 1-aligned allocation. pub fn allocate_str( &mut self, str: &str, kind: MemoryKind, + mutbl: Mutability, ) -> MPlaceTy<'tcx, M::PointerTag> { - let ptr = self.memory.allocate_bytes(str.as_bytes(), kind); + let ptr = self.memory.allocate_bytes(str.as_bytes(), Align::ONE, kind, mutbl); let meta = Scalar::from_machine_usize(u64::try_from(str.len()).unwrap(), self); let mplace = MemPlace { ptr: ptr.into(), align: Align::ONE, meta: MemPlaceMeta::Meta(meta) }; - let layout = self.layout_of(self.tcx.mk_static_str()).unwrap(); + let ty = self.tcx.mk_ref( + self.tcx.lifetimes.re_static, + ty::TypeAndMut { ty: self.tcx.types.str_, mutbl }, + ); + let layout = self.layout_of(ty).unwrap(); MPlaceTy { mplace, layout } } diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs index ac93d042970..d62fd161e2f 100644 --- a/compiler/rustc_mir_build/src/thir/constant.rs +++ b/compiler/rustc_mir_build/src/thir/constant.rs @@ -25,14 +25,14 @@ crate fn lit_to_const<'tcx>( let lit = match (lit, &ty.kind()) { (ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => { let s = s.as_str(); - let allocation = Allocation::from_byte_aligned_bytes(s.as_bytes()); + let allocation = Allocation::from_bytes_byte_aligned_immutable(s.as_bytes()); let allocation = tcx.intern_const_alloc(allocation); ConstValue::Slice { data: allocation, start: 0, end: s.len() } } (ast::LitKind::ByteStr(data), ty::Ref(_, inner_ty, _)) if matches!(inner_ty.kind(), ty::Slice(_)) => { - let allocation = Allocation::from_byte_aligned_bytes(data as &[u8]); + let allocation = Allocation::from_bytes_byte_aligned_immutable(data as &[u8]); let allocation = tcx.intern_const_alloc(allocation); ConstValue::Slice { data: allocation, start: 0, end: data.len() } }