Skip to content

Commit d4f7dd6

Browse files
committed
CTFE/Miri engine Pointer type overhaul: make Scalar-to-Pointer conversion infallible
This resolves all the problems we had around "normalizing" the representation of a Scalar in case it carries a Pointer value: we can just use Pointer if we want to have a value taht we are sure is already normalized.
1 parent 5aff6dd commit d4f7dd6

34 files changed

+837
-722
lines changed

compiler/rustc_codegen_llvm/src/common.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -244,15 +244,16 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
244244
}
245245
}
246246
Scalar::Ptr(ptr) => {
247-
let (base_addr, base_addr_space) = match self.tcx.global_alloc(ptr.alloc_id) {
247+
let (alloc_id, offset) = ptr.into_parts();
248+
let (base_addr, base_addr_space) = match self.tcx.global_alloc(alloc_id) {
248249
GlobalAlloc::Memory(alloc) => {
249250
let init = const_alloc_to_llvm(self, alloc);
250251
let value = match alloc.mutability {
251252
Mutability::Mut => self.static_addr_of_mut(init, alloc.align, None),
252253
_ => self.static_addr_of(init, alloc.align, None),
253254
};
254255
if !self.sess().fewer_names() {
255-
llvm::set_value_name(value, format!("{:?}", ptr.alloc_id).as_bytes());
256+
llvm::set_value_name(value, format!("{:?}", alloc_id).as_bytes());
256257
}
257258
(value, AddressSpace::DATA)
258259
}
@@ -269,7 +270,7 @@ impl ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
269270
let llval = unsafe {
270271
llvm::LLVMConstInBoundsGEP(
271272
self.const_bitcast(base_addr, self.type_i8p_ext(base_addr_space)),
272-
&self.const_usize(ptr.offset.bytes()),
273+
&self.const_usize(offset.bytes()),
273274
1,
274275
)
275276
};

compiler/rustc_codegen_llvm/src/consts.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll
2525
let pointer_size = dl.pointer_size.bytes() as usize;
2626

2727
let mut next_offset = 0;
28-
for &(offset, ((), alloc_id)) in alloc.relocations().iter() {
28+
for &(offset, alloc_id) in alloc.relocations().iter() {
2929
let offset = offset.bytes();
3030
assert_eq!(offset as usize as u64, offset);
3131
let offset = offset as usize;

compiler/rustc_middle/src/mir/interpret/allocation.rs

+25-34
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use crate::ty;
2525
/// module provides higher-level access.
2626
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
2727
#[derive(HashStable)]
28-
pub struct Allocation<Tag = (), Extra = ()> {
28+
pub struct Allocation<Tag = AllocId, Extra = ()> {
2929
/// The actual bytes of the allocation.
3030
/// Note that the bytes of a pointer represent the offset of the pointer.
3131
bytes: Vec<u8>,
@@ -154,25 +154,17 @@ impl<Tag> Allocation<Tag> {
154154
}
155155
}
156156

157-
impl Allocation<()> {
158-
/// Add Tag and Extra fields
159-
pub fn with_tags_and_extra<T, E>(
157+
impl Allocation {
158+
/// Convert Tag and add Extra fields
159+
pub fn with_prov_and_extra<Tag, Extra>(
160160
self,
161-
mut tagger: impl FnMut(AllocId) -> T,
162-
extra: E,
163-
) -> Allocation<T, E> {
161+
mut tagger: impl FnMut(AllocId) -> Tag,
162+
extra: Extra,
163+
) -> Allocation<Tag, Extra> {
164164
Allocation {
165165
bytes: self.bytes,
166166
relocations: Relocations::from_presorted(
167-
self.relocations
168-
.iter()
169-
// The allocations in the relocations (pointers stored *inside* this allocation)
170-
// all get the base pointer tag.
171-
.map(|&(offset, ((), alloc))| {
172-
let tag = tagger(alloc);
173-
(offset, (tag, alloc))
174-
})
175-
.collect(),
167+
self.relocations.iter().map(|&(offset, tag)| (offset, tagger(tag))).collect(),
176168
),
177169
init_mask: self.init_mask,
178170
align: self.align,
@@ -339,8 +331,8 @@ impl<Tag: Copy, Extra> Allocation<Tag, Extra> {
339331
self.check_relocations(cx, range)?;
340332
} else {
341333
// Maybe a pointer.
342-
if let Some(&(tag, alloc_id)) = self.relocations.get(&range.start) {
343-
let ptr = Pointer::new_with_tag(alloc_id, Size::from_bytes(bits), tag);
334+
if let Some(&prov) = self.relocations.get(&range.start) {
335+
let ptr = Pointer::new(prov, Size::from_bytes(bits));
344336
return Ok(ScalarMaybeUninit::Scalar(ptr.into()));
345337
}
346338
}
@@ -371,18 +363,21 @@ impl<Tag: Copy, Extra> Allocation<Tag, Extra> {
371363
}
372364
};
373365

374-
let bytes = match val.to_bits_or_ptr(range.size, cx) {
375-
Err(val) => u128::from(val.offset.bytes()),
376-
Ok(data) => data,
366+
let (bytes, provenance) = match val.to_bits_or_ptr(range.size, cx) {
367+
Err(val) => {
368+
let (provenance, offset) = val.into_parts();
369+
(u128::from(offset.bytes()), Some(provenance))
370+
}
371+
Ok(data) => (data, None),
377372
};
378373

379374
let endian = cx.data_layout().endian;
380375
let dst = self.get_bytes_mut(cx, range);
381376
write_target_uint(endian, dst, bytes).unwrap();
382377

383378
// See if we have to also write a relocation.
384-
if let Scalar::Ptr(val) = val {
385-
self.relocations.insert(range.start, (val.tag, val.alloc_id));
379+
if let Some(provenance) = provenance {
380+
self.relocations.insert(range.start, provenance);
386381
}
387382

388383
Ok(())
@@ -392,11 +387,7 @@ impl<Tag: Copy, Extra> Allocation<Tag, Extra> {
392387
/// Relocations.
393388
impl<Tag: Copy, Extra> Allocation<Tag, Extra> {
394389
/// Returns all relocations overlapping with the given pointer-offset pair.
395-
pub fn get_relocations(
396-
&self,
397-
cx: &impl HasDataLayout,
398-
range: AllocRange,
399-
) -> &[(Size, (Tag, AllocId))] {
390+
pub fn get_relocations(&self, cx: &impl HasDataLayout, range: AllocRange) -> &[(Size, Tag)] {
400391
// We have to go back `pointer_size - 1` bytes, as that one would still overlap with
401392
// the beginning of this range.
402393
let start = range.start.bytes().saturating_sub(cx.data_layout().pointer_size.bytes() - 1);
@@ -582,24 +573,24 @@ impl<Tag, Extra> Allocation<Tag, Extra> {
582573
}
583574
}
584575

585-
/// Relocations.
576+
/// "Relocations" stores the provenance information of pointers stored in memory.
586577
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
587-
pub struct Relocations<Tag = (), Id = AllocId>(SortedMap<Size, (Tag, Id)>);
578+
pub struct Relocations<Tag = AllocId>(SortedMap<Size, Tag>);
588579

589-
impl<Tag, Id> Relocations<Tag, Id> {
580+
impl<Tag> Relocations<Tag> {
590581
pub fn new() -> Self {
591582
Relocations(SortedMap::new())
592583
}
593584

594585
// The caller must guarantee that the given relocations are already sorted
595586
// by address and contain no duplicates.
596-
pub fn from_presorted(r: Vec<(Size, (Tag, Id))>) -> Self {
587+
pub fn from_presorted(r: Vec<(Size, Tag)>) -> Self {
597588
Relocations(SortedMap::from_presorted_elements(r))
598589
}
599590
}
600591

601592
impl<Tag> Deref for Relocations<Tag> {
602-
type Target = SortedMap<Size, (Tag, AllocId)>;
593+
type Target = SortedMap<Size, Tag>;
603594

604595
fn deref(&self) -> &Self::Target {
605596
&self.0
@@ -614,7 +605,7 @@ impl<Tag> DerefMut for Relocations<Tag> {
614605

615606
/// A partial, owned list of relocations to transfer into another allocation.
616607
pub struct AllocationRelocations<Tag> {
617-
relative_relocations: Vec<(Size, (Tag, AllocId))>,
608+
relative_relocations: Vec<(Size, Tag)>,
618609
}
619610

620611
impl<Tag: Copy, Extra> Allocation<Tag, Extra> {

compiler/rustc_middle/src/mir/interpret/error.rs

+12-10
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,9 @@ pub enum UndefinedBehaviorInfo<'tcx> {
238238
PointerUseAfterFree(AllocId),
239239
/// Used a pointer outside the bounds it is valid for.
240240
PointerOutOfBounds {
241-
ptr: Pointer,
241+
alloc_id: AllocId,
242+
offset: Size,
243+
size: Size,
242244
msg: CheckInAllocMsg,
243245
allocation_size: Size,
244246
},
@@ -307,19 +309,19 @@ impl fmt::Display for UndefinedBehaviorInfo<'_> {
307309
InvalidVtableAlignment(msg) => write!(f, "invalid vtable: alignment {}", msg),
308310
UnterminatedCString(p) => write!(
309311
f,
310-
"reading a null-terminated string starting at {} with no null found before end of allocation",
312+
"reading a null-terminated string starting at {:?} with no null found before end of allocation",
311313
p,
312314
),
313315
PointerUseAfterFree(a) => {
314316
write!(f, "pointer to {} was dereferenced after this allocation got freed", a)
315317
}
316-
PointerOutOfBounds { ptr, msg, allocation_size } => write!(
318+
PointerOutOfBounds { alloc_id, offset, size, msg, allocation_size } => write!(
317319
f,
318-
"{}pointer must be in-bounds at offset {}, \
319-
but is outside bounds of {} which has size {}",
320+
"{}pointer must be in-bounds for {} bytes at offset {}, but {} has size {}",
320321
msg,
321-
ptr.offset.bytes(),
322-
ptr.alloc_id,
322+
size.bytes(),
323+
offset.bytes(),
324+
alloc_id,
323325
allocation_size.bytes()
324326
),
325327
DanglingIntPointer(0, CheckInAllocMsg::InboundsTest) => {
@@ -348,13 +350,13 @@ impl fmt::Display for UndefinedBehaviorInfo<'_> {
348350
}
349351
InvalidTag(val) => write!(f, "enum value has invalid tag: {}", val),
350352
InvalidFunctionPointer(p) => {
351-
write!(f, "using {} as function pointer but it does not point to a function", p)
353+
write!(f, "using {:?} as function pointer but it does not point to a function", p)
352354
}
353355
InvalidStr(err) => write!(f, "this string is not valid UTF-8: {}", err),
354356
InvalidUninitBytes(Some((alloc, access))) => write!(
355357
f,
356-
"reading {} byte{} of memory starting at {}, \
357-
but {} byte{} {} uninitialized starting at {}, \
358+
"reading {} byte{} of memory starting at {:?}, \
359+
but {} byte{} {} uninitialized starting at {:?}, \
358360
and this operation requires initialized memory",
359361
access.access_size.bytes(),
360362
pluralize!(access.access_size.bytes()),

compiler/rustc_middle/src/mir/interpret/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ pub use self::value::{get_slice_bytes, ConstAlloc, ConstValue, Scalar, ScalarMay
127127

128128
pub use self::allocation::{alloc_range, AllocRange, Allocation, InitMask, Relocations};
129129

130-
pub use self::pointer::{Pointer, PointerArithmetic};
130+
pub use self::pointer::{Pointer, PointerArithmetic, Provenance};
131131

132132
/// Uniquely identifies one of the following:
133133
/// - A constant

0 commit comments

Comments
 (0)