Skip to content

Commit 77be06b

Browse files
committed
no longer assume that there is a default tag: give the machine the chance to tag all allocations
1 parent 2726a91 commit 77be06b

File tree

12 files changed

+196
-227
lines changed

12 files changed

+196
-227
lines changed

src/librustc/mir/interpret/allocation.rs

+8-7
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,10 @@ pub trait AllocationExtra<Tag>: ::std::fmt::Debug + Clone {
111111
// For Tag=() and no extra state, we have is a trivial implementation.
112112
impl AllocationExtra<()> for () { }
113113

114-
impl<Tag, Extra> Allocation<Tag, Extra> {
114+
// The constructors are all without extra; the extra gets added by a machine hook later.
115+
impl<Tag> Allocation<Tag> {
115116
/// Creates a read-only allocation initialized by the given bytes
116-
pub fn from_bytes<'a>(slice: impl Into<Cow<'a, [u8]>>, align: Align, extra: Extra) -> Self {
117+
pub fn from_bytes<'a>(slice: impl Into<Cow<'a, [u8]>>, align: Align) -> Self {
117118
let bytes = slice.into().into_owned();
118119
let undef_mask = UndefMask::new(Size::from_bytes(bytes.len() as u64), true);
119120
Self {
@@ -122,23 +123,23 @@ impl<Tag, Extra> Allocation<Tag, Extra> {
122123
undef_mask,
123124
align,
124125
mutability: Mutability::Immutable,
125-
extra,
126+
extra: (),
126127
}
127128
}
128129

129-
pub fn from_byte_aligned_bytes<'a>(slice: impl Into<Cow<'a, [u8]>>, extra: Extra) -> Self {
130-
Allocation::from_bytes(slice, Align::from_bytes(1).unwrap(), extra)
130+
pub fn from_byte_aligned_bytes<'a>(slice: impl Into<Cow<'a, [u8]>>) -> Self {
131+
Allocation::from_bytes(slice, Align::from_bytes(1).unwrap())
131132
}
132133

133-
pub fn undef(size: Size, align: Align, extra: Extra) -> Self {
134+
pub fn undef(size: Size, align: Align) -> Self {
134135
assert_eq!(size.bytes() as usize as u64, size.bytes());
135136
Allocation {
136137
bytes: vec![0; size.bytes() as usize],
137138
relocations: Relocations::new(),
138139
undef_mask: UndefMask::new(size, false),
139140
align,
140141
mutability: Mutability::Mutable,
141-
extra,
142+
extra: (),
142143
}
143144
}
144145
}

src/librustc/mir/interpret/pointer.rs

-7
Original file line numberDiff line numberDiff line change
@@ -116,13 +116,6 @@ impl<'tcx> Pointer<()> {
116116
{
117117
Pointer::new_with_tag(self.alloc_id, self.offset, tag)
118118
}
119-
120-
#[inline(always)]
121-
pub fn with_default_tag<Tag>(self) -> Pointer<Tag>
122-
where Tag: Default
123-
{
124-
self.with_tag(Tag::default())
125-
}
126119
}
127120

128121
impl<'tcx, Tag> Pointer<Tag> {

src/librustc/mir/interpret/value.rs

+3-24
Original file line numberDiff line numberDiff line change
@@ -140,23 +140,18 @@ impl<'tcx> Scalar<()> {
140140

141141
#[inline]
142142
pub fn with_tag<Tag>(self, new_tag: Tag) -> Scalar<Tag> {
143+
// Used by `MemPlace::replace_tag`
143144
match self {
144145
Scalar::Ptr(ptr) => Scalar::Ptr(ptr.with_tag(new_tag)),
145146
Scalar::Raw { data, size } => Scalar::Raw { data, size },
146147
}
147148
}
148-
149-
#[inline(always)]
150-
pub fn with_default_tag<Tag>(self) -> Scalar<Tag>
151-
where Tag: Default
152-
{
153-
self.with_tag(Tag::default())
154-
}
155149
}
156150

157151
impl<'tcx, Tag> Scalar<Tag> {
158152
#[inline]
159153
pub fn erase_tag(self) -> Scalar {
154+
// Used by error reporting code to avoid having the error type depend on `Tag`
160155
match self {
161156
Scalar::Ptr(ptr) => Scalar::Ptr(ptr.erase_tag()),
162157
Scalar::Raw { data, size } => Scalar::Raw { data, size },
@@ -476,27 +471,11 @@ impl<Tag> fmt::Display for ScalarMaybeUndef<Tag> {
476471
}
477472
}
478473

479-
impl<'tcx> ScalarMaybeUndef<()> {
480-
#[inline]
481-
pub fn with_tag<Tag>(self, new_tag: Tag) -> ScalarMaybeUndef<Tag> {
482-
match self {
483-
ScalarMaybeUndef::Scalar(s) => ScalarMaybeUndef::Scalar(s.with_tag(new_tag)),
484-
ScalarMaybeUndef::Undef => ScalarMaybeUndef::Undef,
485-
}
486-
}
487-
488-
#[inline(always)]
489-
pub fn with_default_tag<Tag>(self) -> ScalarMaybeUndef<Tag>
490-
where Tag: Default
491-
{
492-
self.with_tag(Tag::default())
493-
}
494-
}
495-
496474
impl<'tcx, Tag> ScalarMaybeUndef<Tag> {
497475
#[inline]
498476
pub fn erase_tag(self) -> ScalarMaybeUndef
499477
{
478+
// Used by error reporting code to avoid having the error type depend on `Tag`
500479
match self {
501480
ScalarMaybeUndef::Scalar(s) => ScalarMaybeUndef::Scalar(s.erase_tag()),
502481
ScalarMaybeUndef::Undef => ScalarMaybeUndef::Undef,

src/librustc/ty/context.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1154,7 +1154,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
11541154
/// Allocates a byte or string literal for `mir::interpret`, read-only
11551155
pub fn allocate_bytes(self, bytes: &[u8]) -> interpret::AllocId {
11561156
// create an allocation that just contains these bytes
1157-
let alloc = interpret::Allocation::from_byte_aligned_bytes(bytes, ());
1157+
let alloc = interpret::Allocation::from_byte_aligned_bytes(bytes);
11581158
let alloc = self.intern_const_alloc(alloc);
11591159
self.alloc_map.lock().create_memory_alloc(alloc)
11601160
}

src/librustc_mir/const_eval.rs

+14-14
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use rustc::hir::def_id::DefId;
1212
use rustc::mir::interpret::{ConstEvalErr, ErrorHandled};
1313
use rustc::mir;
1414
use rustc::ty::{self, TyCtxt, query::TyCtxtAt};
15-
use rustc::ty::layout::{self, LayoutOf, VariantIdx, Size};
15+
use rustc::ty::layout::{self, LayoutOf, VariantIdx};
1616
use rustc::ty::subst::Subst;
1717
use rustc::traits::Reveal;
1818
use rustc::util::common::ErrorReported;
@@ -117,7 +117,7 @@ fn op_to_const<'tcx>(
117117
),
118118
Scalar::Raw { .. } => (
119119
ecx.tcx.intern_const_alloc(Allocation::from_byte_aligned_bytes(
120-
b"" as &[u8], (),
120+
b"" as &[u8],
121121
)),
122122
0,
123123
),
@@ -397,27 +397,27 @@ impl<'a, 'mir, 'tcx> interpret::Machine<'a, 'mir, 'tcx>
397397
fn find_foreign_static(
398398
_def_id: DefId,
399399
_tcx: TyCtxtAt<'a, 'tcx, 'tcx>,
400-
_memory_extra: &(),
401400
) -> EvalResult<'tcx, Cow<'tcx, Allocation<Self::PointerTag>>> {
402401
err!(ReadForeignStatic)
403402
}
404403

405404
#[inline(always)]
406-
fn adjust_static_allocation<'b>(
407-
alloc: &'b Allocation,
405+
fn tag_allocation<'b>(
406+
_id: AllocId,
407+
alloc: Cow<'b, Allocation>,
408+
_kind: Option<MemoryKind<!>>,
408409
_memory_extra: &(),
409-
) -> Cow<'b, Allocation<Self::PointerTag>> {
410-
// We do not use a tag so we can just cheaply forward the reference
411-
Cow::Borrowed(alloc)
410+
) -> (Cow<'b, Allocation<Self::PointerTag>>, Self::PointerTag) {
411+
// We do not use a tag so we can just cheaply forward the allocation
412+
(alloc, ())
412413
}
413414

414415
#[inline(always)]
415-
fn new_allocation(
416-
_size: Size,
417-
_extra: &Self::MemoryExtra,
418-
_kind: MemoryKind<!>,
419-
) -> (Self::AllocExtra, Self::PointerTag) {
420-
((), ())
416+
fn tag_static_base_pointer(
417+
_id: AllocId,
418+
_memory_extra: &(),
419+
) -> Self::PointerTag {
420+
()
421421
}
422422

423423
fn box_alloc(

src/librustc_mir/hair/constant.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,13 @@ crate fn lit_to_const<'a, 'gcx, 'tcx>(
3030
let lit = match *lit {
3131
LitKind::Str(ref s, _) => {
3232
let s = s.as_str();
33-
let allocation = Allocation::from_byte_aligned_bytes(s.as_bytes(), ());
33+
let allocation = Allocation::from_byte_aligned_bytes(s.as_bytes());
3434
let allocation = tcx.intern_const_alloc(allocation);
3535
ConstValue::Slice { data: allocation, start: 0, end: s.len() }
3636
},
3737
LitKind::Err(ref s) => {
3838
let s = s.as_str();
39-
let allocation = Allocation::from_byte_aligned_bytes(s.as_bytes(), ());
39+
let allocation = Allocation::from_byte_aligned_bytes(s.as_bytes());
4040
let allocation = tcx.intern_const_alloc(allocation);
4141
return Ok(tcx.mk_const(ty::Const {
4242
val: ConstValue::Slice{ data: allocation, start: 0, end: s.len() },

src/librustc_mir/interpret/eval_context.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,11 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tc
225225
&mut self.memory
226226
}
227227

228+
#[inline(always)]
229+
pub fn tag_static_base_pointer(&self, ptr: Pointer) -> Pointer<M::PointerTag> {
230+
self.memory.tag_static_base_pointer(ptr)
231+
}
232+
228233
#[inline(always)]
229234
pub fn stack(&self) -> &[Frame<'mir, 'tcx, M::PointerTag, M::FrameExtra>] {
230235
&self.stack
@@ -363,11 +368,6 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> InterpretCx<'a, 'mir, 'tc
363368
}
364369
}
365370

366-
pub fn str_to_immediate(&mut self, s: &str) -> EvalResult<'tcx, Immediate<M::PointerTag>> {
367-
let ptr = self.memory.allocate_static_bytes(s.as_bytes()).with_default_tag();
368-
Ok(Immediate::new_slice(Scalar::Ptr(ptr), s.len() as u64, self))
369-
}
370-
371371
/// Returns the actual dynamic size and alignment of the place at the given type.
372372
/// Only the "meta" (metadata) part of the place matters.
373373
/// This can fail to provide an answer for extern types.

src/librustc_mir/interpret/intrinsics/type_name.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ impl Write for AbsolutePathPrinter<'_, '_> {
215215
pub fn type_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> &'tcx ty::Const<'tcx> {
216216
let path = AbsolutePathPrinter { tcx, path: String::new() }.print_type(ty).unwrap().path;
217217
let len = path.len();
218-
let alloc = Allocation::from_byte_aligned_bytes(path.into_bytes(), ());
218+
let alloc = Allocation::from_byte_aligned_bytes(path.into_bytes());
219219
let alloc = tcx.intern_const_alloc(alloc);
220220
tcx.mk_const(ty::Const {
221221
val: ConstValue::Slice {

src/librustc_mir/interpret/machine.rs

+33-31
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@
55
use std::borrow::{Borrow, Cow};
66
use std::hash::Hash;
77

8-
use rustc::hir::{self, def_id::DefId};
8+
use rustc::hir::def_id::DefId;
99
use rustc::mir;
10-
use rustc::ty::{self, query::TyCtxtAt, layout::Size};
10+
use rustc::ty::{self, query::TyCtxtAt};
1111

1212
use super::{
1313
Allocation, AllocId, EvalResult, Scalar, AllocationExtra,
14-
InterpretCx, PlaceTy, MPlaceTy, OpTy, ImmTy, MemoryKind,
14+
InterpretCx, PlaceTy, OpTy, ImmTy, MemoryKind,
1515
};
1616

1717
/// Whether this kind of memory is allowed to leak
@@ -65,7 +65,7 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized {
6565
/// Tag tracked alongside every pointer. This is used to implement "Stacked Borrows"
6666
/// <https://www.ralfj.de/blog/2018/08/07/stacked-borrows.html>.
6767
/// The `default()` is used for pointers to consts, statics, vtables and functions.
68-
type PointerTag: ::std::fmt::Debug + Default + Copy + Eq + Hash + 'static;
68+
type PointerTag: ::std::fmt::Debug + Copy + Eq + Hash + 'static;
6969

7070
/// Extra data stored in every call frame.
7171
type FrameExtra;
@@ -90,7 +90,7 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized {
9090
/// The memory kind to use for copied statics -- or None if statics should not be mutated
9191
/// and thus any such attempt will cause a `ModifiedStatic` error to be raised.
9292
/// Statics are copied under two circumstances: When they are mutated, and when
93-
/// `static_with_default_tag` or `find_foreign_static` (see below) returns an owned allocation
93+
/// `tag_allocation` or `find_foreign_static` (see below) returns an owned allocation
9494
/// that is added to the memory so that the work is not done twice.
9595
const STATIC_KIND: Option<Self::MemoryKinds>;
9696

@@ -133,11 +133,12 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized {
133133
/// This will only be called once per static and machine; the result is cached in
134134
/// the machine memory. (This relies on `AllocMap::get_or` being able to add the
135135
/// owned allocation to the map even when the map is shared.)
136+
///
137+
/// This allocation will then be fed to `tag_allocation` to initialize the "extra" state.
136138
fn find_foreign_static(
137139
def_id: DefId,
138140
tcx: TyCtxtAt<'a, 'tcx, 'tcx>,
139-
memory_extra: &Self::MemoryExtra,
140-
) -> EvalResult<'tcx, Cow<'tcx, Allocation<Self::PointerTag, Self::AllocExtra>>>;
141+
) -> EvalResult<'tcx, Cow<'tcx, Allocation>>;
141142

142143
/// Called for all binary operations on integer(-like) types when one operand is a pointer
143144
/// value, and for the `Offset` operation that is inherently about pointers.
@@ -156,36 +157,37 @@ pub trait Machine<'a, 'mir, 'tcx>: Sized {
156157
dest: PlaceTy<'tcx, Self::PointerTag>,
157158
) -> EvalResult<'tcx>;
158159

159-
/// Called to turn an allocation obtained from the `tcx` into one that has
160-
/// the right type for this machine.
160+
/// Called to initialize the "extra" state of an allocation and make the pointers
161+
/// it contains (in relocations) tagged. The way we construct allocations is
162+
/// to always first construct it without extra and then add the extra.
163+
/// This keeps uniform code paths for handling both allocations created by CTFE
164+
/// for statics, and allocations ceated by Miri during evaluation.
165+
///
166+
/// `kind` is the kind of the allocation being tagged; it can be `None` when
167+
/// it's a static and `STATIC_KIND` is `None`.
161168
///
162169
/// This should avoid copying if no work has to be done! If this returns an owned
163170
/// allocation (because a copy had to be done to add tags or metadata), machine memory will
164171
/// cache the result. (This relies on `AllocMap::get_or` being able to add the
165172
/// owned allocation to the map even when the map is shared.)
166-
fn adjust_static_allocation<'b>(
167-
alloc: &'b Allocation,
173+
///
174+
/// The tag returned must be the same as the one returned by `tag_base_pointer`.
175+
fn tag_allocation<'b>(
176+
id: AllocId,
177+
alloc: Cow<'b, Allocation>,
178+
kind: Option<MemoryKind<Self::MemoryKinds>>,
168179
memory_extra: &Self::MemoryExtra,
169-
) -> Cow<'b, Allocation<Self::PointerTag, Self::AllocExtra>>;
170-
171-
/// Computes the extra state and the tag for a new allocation.
172-
fn new_allocation(
173-
size: Size,
174-
extra: &Self::MemoryExtra,
175-
kind: MemoryKind<Self::MemoryKinds>,
176-
) -> (Self::AllocExtra, Self::PointerTag);
177-
178-
/// Executed when evaluating the `*` operator: Following a reference.
179-
/// This has the chance to adjust the tag. It should not change anything else!
180-
/// `mutability` can be `None` in case a raw ptr is being dereferenced.
181-
#[inline]
182-
fn tag_dereference(
183-
_ecx: &InterpretCx<'a, 'mir, 'tcx, Self>,
184-
place: MPlaceTy<'tcx, Self::PointerTag>,
185-
_mutability: Option<hir::Mutability>,
186-
) -> EvalResult<'tcx, Scalar<Self::PointerTag>> {
187-
Ok(place.ptr)
188-
}
180+
) -> (Cow<'b, Allocation<Self::PointerTag, Self::AllocExtra>>, Self::PointerTag);
181+
182+
/// Return the "base" tag for the given static allocation: the one that is used for direct
183+
/// accesses to this static/const/fn allocation.
184+
///
185+
/// Be aware that requesting the `Allocation` for that `id` will lead to cycles
186+
/// for cyclic statics!
187+
fn tag_static_base_pointer(
188+
id: AllocId,
189+
memory_extra: &Self::MemoryExtra,
190+
) -> Self::PointerTag;
189191

190192
/// Executes a retagging operation
191193
#[inline]

0 commit comments

Comments
 (0)