Rollup merge of #75226 - pnadon:miri-undef-uninit, r=RalfJung
Miri: Renamed "undef" to "uninit" Renamed remaining references to "undef" to "uninit" when referring to Miri. Impacted directories are: - `src/librustc_codegen_llvm/consts.rs` - `src/librustc_middle/mir/interpret/` - `src/librustc_middle/ty/print/pretty.rs` - `src/librustc_mir/` - `src/tools/clippy/clippy_lints/src/consts.rs` Upon building Miri based on the new changes it was verified that no changes needed to be made with the Miri project. Related issue #71193
This commit is contained in:
commit
c27779f59b
11 changed files with 37 additions and 37 deletions
|
@ -41,7 +41,7 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll
|
|||
// some arbitrary byte value.
|
||||
//
|
||||
// FIXME: relay undef bytes to codegen as undef const bytes
|
||||
let bytes = alloc.inspect_with_undef_and_ptr_outside_interpreter(next_offset..offset);
|
||||
let bytes = alloc.inspect_with_uninit_and_ptr_outside_interpreter(next_offset..offset);
|
||||
llvals.push(cx.const_bytes(bytes));
|
||||
}
|
||||
let ptr_offset = read_target_uint(
|
||||
|
@ -49,7 +49,7 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll
|
|||
// This `inspect` is okay since it is within the bounds of the allocation, it doesn't
|
||||
// affect interpreter execution (we inspect the result after interpreter execution),
|
||||
// and we properly interpret the relocation as a relocation pointer offset.
|
||||
alloc.inspect_with_undef_and_ptr_outside_interpreter(offset..(offset + pointer_size)),
|
||||
alloc.inspect_with_uninit_and_ptr_outside_interpreter(offset..(offset + pointer_size)),
|
||||
)
|
||||
.expect("const_alloc_to_llvm: could not read relocation pointer")
|
||||
as u64;
|
||||
|
@ -74,7 +74,7 @@ pub fn const_alloc_to_llvm(cx: &CodegenCx<'ll, '_>, alloc: &Allocation) -> &'ll
|
|||
// arbitrary byte value.
|
||||
//
|
||||
// FIXME: relay undef bytes to codegen as undef const bytes
|
||||
let bytes = alloc.inspect_with_undef_and_ptr_outside_interpreter(range);
|
||||
let bytes = alloc.inspect_with_uninit_and_ptr_outside_interpreter(range);
|
||||
llvals.push(cx.const_bytes(bytes));
|
||||
}
|
||||
|
||||
|
@ -452,7 +452,7 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> {
|
|||
// BSS.
|
||||
let all_bytes_are_zero = alloc.relocations().is_empty()
|
||||
&& alloc
|
||||
.inspect_with_undef_and_ptr_outside_interpreter(0..alloc.len())
|
||||
.inspect_with_uninit_and_ptr_outside_interpreter(0..alloc.len())
|
||||
.iter()
|
||||
.all(|&byte| byte == 0);
|
||||
|
||||
|
@ -480,7 +480,7 @@ impl StaticMethods for CodegenCx<'ll, 'tcx> {
|
|||
// because we are doing this access to inspect the final interpreter state (not
|
||||
// as part of the interpreter execution).
|
||||
let bytes =
|
||||
alloc.inspect_with_undef_and_ptr_outside_interpreter(0..alloc.len());
|
||||
alloc.inspect_with_uninit_and_ptr_outside_interpreter(0..alloc.len());
|
||||
let alloc = llvm::LLVMMDStringInContext(
|
||||
self.llcx,
|
||||
bytes.as_ptr().cast(),
|
||||
|
|
|
@ -154,10 +154,10 @@ impl<Tag, Extra> Allocation<Tag, Extra> {
|
|||
}
|
||||
|
||||
/// Looks at a slice which may describe uninitialized bytes or describe a relocation. This differs
|
||||
/// from `get_bytes_with_undef_and_ptr` in that it does no relocation checks (even on the
|
||||
/// from `get_bytes_with_uninit_and_ptr` in that it does no relocation checks (even on the
|
||||
/// edges) at all. It further ignores `AllocationExtra` callbacks.
|
||||
/// This must not be used for reads affecting the interpreter execution.
|
||||
pub fn inspect_with_undef_and_ptr_outside_interpreter(&self, range: Range<usize>) -> &[u8] {
|
||||
pub fn inspect_with_uninit_and_ptr_outside_interpreter(&self, range: Range<usize>) -> &[u8] {
|
||||
&self.bytes[range]
|
||||
}
|
||||
|
||||
|
@ -194,7 +194,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
|
|||
|
||||
/// The last argument controls whether we error out when there are uninitialized
|
||||
/// or pointer bytes. You should never call this, call `get_bytes` or
|
||||
/// `get_bytes_with_undef_and_ptr` instead,
|
||||
/// `get_bytes_with_uninit_and_ptr` instead,
|
||||
///
|
||||
/// This function also guarantees that the resulting pointer will remain stable
|
||||
/// even when new allocations are pushed to the `HashMap`. `copy_repeatedly` relies
|
||||
|
@ -244,7 +244,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
|
|||
///
|
||||
/// It is the caller's responsibility to check bounds and alignment beforehand.
|
||||
#[inline]
|
||||
pub fn get_bytes_with_undef_and_ptr(
|
||||
pub fn get_bytes_with_uninit_and_ptr(
|
||||
&self,
|
||||
cx: &impl HasDataLayout,
|
||||
ptr: Pointer<Tag>,
|
||||
|
@ -302,19 +302,19 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
|
|||
}
|
||||
|
||||
/// Validates that `ptr.offset` and `ptr.offset + size` do not point to the middle of a
|
||||
/// relocation. If `allow_ptr_and_undef` is `false`, also enforces that the memory in the
|
||||
/// relocation. If `allow_uninit_and_ptr` is `false`, also enforces that the memory in the
|
||||
/// given range contains neither relocations nor uninitialized bytes.
|
||||
pub fn check_bytes(
|
||||
&self,
|
||||
cx: &impl HasDataLayout,
|
||||
ptr: Pointer<Tag>,
|
||||
size: Size,
|
||||
allow_ptr_and_undef: bool,
|
||||
allow_uninit_and_ptr: bool,
|
||||
) -> InterpResult<'tcx> {
|
||||
// Check bounds and relocations on the edges.
|
||||
self.get_bytes_with_undef_and_ptr(cx, ptr, size)?;
|
||||
self.get_bytes_with_uninit_and_ptr(cx, ptr, size)?;
|
||||
// Check uninit and ptr.
|
||||
if !allow_ptr_and_undef {
|
||||
if !allow_uninit_and_ptr {
|
||||
self.check_init(ptr, size)?;
|
||||
self.check_relocations(cx, ptr, size)?;
|
||||
}
|
||||
|
@ -361,7 +361,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
|
|||
size: Size,
|
||||
) -> InterpResult<'tcx, ScalarMaybeUninit<Tag>> {
|
||||
// `get_bytes_unchecked` tests relocation edges.
|
||||
let bytes = self.get_bytes_with_undef_and_ptr(cx, ptr, size)?;
|
||||
let bytes = self.get_bytes_with_uninit_and_ptr(cx, ptr, size)?;
|
||||
// Uninit check happens *after* we established that the alignment is correct.
|
||||
// We must not return `Ok()` for unaligned pointers!
|
||||
if self.is_init(ptr, size).is_err() {
|
||||
|
@ -594,7 +594,7 @@ impl InitMaskCompressed {
|
|||
/// Transferring the initialization mask to other allocations.
|
||||
impl<Tag, Extra> Allocation<Tag, Extra> {
|
||||
/// Creates a run-length encoding of the initialization mask.
|
||||
pub fn compress_undef_range(&self, src: Pointer<Tag>, size: Size) -> InitMaskCompressed {
|
||||
pub fn compress_uninit_range(&self, src: Pointer<Tag>, size: Size) -> InitMaskCompressed {
|
||||
// Since we are copying `size` bytes from `src` to `dest + i * size` (`for i in 0..repeat`),
|
||||
// a naive initialization mask copying algorithm would repeatedly have to read the initialization mask from
|
||||
// the source and write it to the destination. Even if we optimized the memory accesses,
|
||||
|
@ -636,8 +636,8 @@ impl<Tag, Extra> Allocation<Tag, Extra> {
|
|||
size: Size,
|
||||
repeat: u64,
|
||||
) {
|
||||
// An optimization where we can just overwrite an entire range of definedness bits if
|
||||
// they are going to be uniformly `1` or `0`.
|
||||
// An optimization where we can just overwrite an entire range of initialization
|
||||
// bits if they are going to be uniformly `1` or `0`.
|
||||
if defined.ranges.len() <= 1 {
|
||||
self.init_mask.set_range_inbounds(
|
||||
dest.offset,
|
||||
|
|
|
@ -58,7 +58,7 @@ impl<'tcx> ConstValue<'tcx> {
|
|||
|
||||
pub fn try_to_str_slice(&self) -> Option<&'tcx str> {
|
||||
if let ConstValue::Slice { data, start, end } = *self {
|
||||
::std::str::from_utf8(data.inspect_with_undef_and_ptr_outside_interpreter(start..end))
|
||||
::std::str::from_utf8(data.inspect_with_uninit_and_ptr_outside_interpreter(start..end))
|
||||
.ok()
|
||||
} else {
|
||||
None
|
||||
|
|
|
@ -1107,7 +1107,7 @@ pub trait PrettyPrinter<'tcx>:
|
|||
// The `inspect` here is okay since we checked the bounds, and there are
|
||||
// no relocations (we have an active slice reference here). We don't use
|
||||
// this result to affect interpreter execution.
|
||||
let byte_str = data.inspect_with_undef_and_ptr_outside_interpreter(start..end);
|
||||
let byte_str = data.inspect_with_uninit_and_ptr_outside_interpreter(start..end);
|
||||
self.pretty_print_byte_str(byte_str)
|
||||
}
|
||||
(
|
||||
|
@ -1117,7 +1117,7 @@ pub trait PrettyPrinter<'tcx>:
|
|||
// The `inspect` here is okay since we checked the bounds, and there are no
|
||||
// relocations (we have an active `str` reference here). We don't use this
|
||||
// result to affect interpreter execution.
|
||||
let slice = data.inspect_with_undef_and_ptr_outside_interpreter(start..end);
|
||||
let slice = data.inspect_with_uninit_and_ptr_outside_interpreter(start..end);
|
||||
let s = ::std::str::from_utf8(slice).expect("non utf8 str from miri");
|
||||
p!(write("{:?}", s));
|
||||
Ok(self)
|
||||
|
|
|
@ -926,7 +926,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
|
|||
// first copy the relocations to a temporary buffer, because
|
||||
// `get_bytes_mut` will clear the relocations, which is correct,
|
||||
// since we don't want to keep any relocations at the target.
|
||||
// (`get_bytes_with_undef_and_ptr` below checks that there are no
|
||||
// (`get_bytes_with_uninit_and_ptr` below checks that there are no
|
||||
// relocations overlapping the edges; those would not be handled correctly).
|
||||
let relocations =
|
||||
self.get_raw(src.alloc_id)?.prepare_relocation_copy(self, src, size, dest, length);
|
||||
|
@ -935,7 +935,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
|
|||
|
||||
// This checks relocation edges on the src.
|
||||
let src_bytes =
|
||||
self.get_raw(src.alloc_id)?.get_bytes_with_undef_and_ptr(&tcx, src, size)?.as_ptr();
|
||||
self.get_raw(src.alloc_id)?.get_bytes_with_uninit_and_ptr(&tcx, src, size)?.as_ptr();
|
||||
let dest_bytes =
|
||||
self.get_raw_mut(dest.alloc_id)?.get_bytes_mut(&tcx, dest, size * length)?; // `Size` multiplication
|
||||
|
||||
|
@ -948,7 +948,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> {
|
|||
let dest_bytes = dest_bytes.as_mut_ptr();
|
||||
|
||||
// Prepare a copy of the initialization mask.
|
||||
let compressed = self.get_raw(src.alloc_id)?.compress_undef_range(src, size);
|
||||
let compressed = self.get_raw(src.alloc_id)?.compress_uninit_range(src, size);
|
||||
|
||||
if compressed.no_bytes_init() {
|
||||
// Fast path: If all bytes are `uninit` then there is nothing to copy. The target range
|
||||
|
|
|
@ -106,7 +106,7 @@ impl<Tag: Copy> std::fmt::Display for ImmTy<'tcx, Tag> {
|
|||
}
|
||||
ScalarMaybeUninit::Uninit => cx.typed_value(
|
||||
|mut this| {
|
||||
this.write_str("{undef ")?;
|
||||
this.write_str("{uninit ")?;
|
||||
Ok(this)
|
||||
},
|
||||
|this| this.print_type(ty),
|
||||
|
|
|
@ -61,7 +61,7 @@ impl<Tag> MemPlaceMeta<Tag> {
|
|||
pub struct MemPlace<Tag = ()> {
|
||||
/// A place may have an integral pointer for ZSTs, and since it might
|
||||
/// be turned back into a reference before ever being dereferenced.
|
||||
/// However, it may never be undef.
|
||||
/// However, it may never be uninit.
|
||||
pub ptr: Scalar<Tag>,
|
||||
pub align: Align,
|
||||
/// Metadata for unsized places. Interpretation is up to the type.
|
||||
|
@ -729,7 +729,7 @@ where
|
|||
"Size mismatch when writing bits"
|
||||
)
|
||||
}
|
||||
Immediate::Scalar(ScalarMaybeUninit::Uninit) => {} // undef can have any size
|
||||
Immediate::Scalar(ScalarMaybeUninit::Uninit) => {} // uninit can have any size
|
||||
Immediate::ScalarPair(_, _) => {
|
||||
// FIXME: Can we check anything here?
|
||||
}
|
||||
|
|
|
@ -508,12 +508,12 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
|
|||
}
|
||||
} else {
|
||||
// At run-time, for now, we accept *anything* for these types, including
|
||||
// undef. We should fix that, but let's start low.
|
||||
// uninit. We should fix that, but let's start low.
|
||||
}
|
||||
Ok(true)
|
||||
}
|
||||
ty::RawPtr(..) => {
|
||||
// We are conservative with undef for integers, but try to
|
||||
// We are conservative with uninit for integers, but try to
|
||||
// actually enforce the strict rules for raw pointers (mostly because
|
||||
// that lets us re-use `ref_to_mplace`).
|
||||
let place = try_validation!(
|
||||
|
@ -807,12 +807,12 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
|
|||
// reject it. However, that's good: We don't inherently want
|
||||
// to reject those pointers, we just do not have the machinery to
|
||||
// talk about parts of a pointer.
|
||||
// We also accept undef, for consistency with the slow path.
|
||||
// We also accept uninit, for consistency with the slow path.
|
||||
match self.ecx.memory.get_raw(ptr.alloc_id)?.check_bytes(
|
||||
self.ecx,
|
||||
ptr,
|
||||
size,
|
||||
/*allow_ptr_and_undef*/ self.ref_tracking_for_consts.is_none(),
|
||||
/*allow_uninit_and_ptr*/ self.ref_tracking_for_consts.is_none(),
|
||||
) {
|
||||
// In the happy case, we needn't check anything else.
|
||||
Ok(()) => {}
|
||||
|
|
|
@ -1076,7 +1076,7 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
|
|||
// ```rust
|
||||
// let mut x = 42;
|
||||
// x = SOME_MUTABLE_STATIC;
|
||||
// // x must now be undefined
|
||||
// // x must now be uninit
|
||||
// ```
|
||||
// FIXME: we overzealously erase the entire local, because that's easier to
|
||||
// implement.
|
||||
|
|
|
@ -743,8 +743,8 @@ fn write_allocation_bytes<Tag: Copy + Debug, Extra>(
|
|||
if let Some(&(tag, target_id)) = alloc.relocations().get(&i) {
|
||||
// Memory with a relocation must be defined
|
||||
let j = i.bytes_usize();
|
||||
let offset =
|
||||
alloc.inspect_with_undef_and_ptr_outside_interpreter(j..j + ptr_size.bytes_usize());
|
||||
let offset = alloc
|
||||
.inspect_with_uninit_and_ptr_outside_interpreter(j..j + ptr_size.bytes_usize());
|
||||
let offset = read_target_uint(tcx.data_layout.endian, offset).unwrap();
|
||||
let offset = Size::from_bytes(offset);
|
||||
let relocation_width = |bytes| bytes * 3;
|
||||
|
@ -803,7 +803,7 @@ fn write_allocation_bytes<Tag: Copy + Debug, Extra>(
|
|||
|
||||
// Checked definedness (and thus range) and relocations. This access also doesn't
|
||||
// influence interpreter execution but is only for debugging.
|
||||
let c = alloc.inspect_with_undef_and_ptr_outside_interpreter(j..j + 1)[0];
|
||||
let c = alloc.inspect_with_uninit_and_ptr_outside_interpreter(j..j + 1)[0];
|
||||
write!(w, "{:02x}", c)?;
|
||||
if c.is_ascii_control() || c >= 0x80 {
|
||||
ascii.push('.');
|
||||
|
|
|
@ -517,7 +517,7 @@ pub fn miri_to_const(result: &ty::Const<'_>) -> Option<Constant> {
|
|||
ty::ConstKind::Value(ConstValue::Slice { data, start, end }) => match result.ty.kind {
|
||||
ty::Ref(_, tam, _) => match tam.kind {
|
||||
ty::Str => String::from_utf8(
|
||||
data.inspect_with_undef_and_ptr_outside_interpreter(start..end)
|
||||
data.inspect_with_uninit_and_ptr_outside_interpreter(start..end)
|
||||
.to_owned(),
|
||||
)
|
||||
.ok()
|
||||
|
@ -530,7 +530,7 @@ pub fn miri_to_const(result: &ty::Const<'_>) -> Option<Constant> {
|
|||
ty::Array(sub_type, len) => match sub_type.kind {
|
||||
ty::Float(FloatTy::F32) => match miri_to_const(len) {
|
||||
Some(Constant::Int(len)) => alloc
|
||||
.inspect_with_undef_and_ptr_outside_interpreter(0..(4 * len as usize))
|
||||
.inspect_with_uninit_and_ptr_outside_interpreter(0..(4 * len as usize))
|
||||
.to_owned()
|
||||
.chunks(4)
|
||||
.map(|chunk| {
|
||||
|
@ -544,7 +544,7 @@ pub fn miri_to_const(result: &ty::Const<'_>) -> Option<Constant> {
|
|||
},
|
||||
ty::Float(FloatTy::F64) => match miri_to_const(len) {
|
||||
Some(Constant::Int(len)) => alloc
|
||||
.inspect_with_undef_and_ptr_outside_interpreter(0..(8 * len as usize))
|
||||
.inspect_with_uninit_and_ptr_outside_interpreter(0..(8 * len as usize))
|
||||
.to_owned()
|
||||
.chunks(8)
|
||||
.map(|chunk| {
|
||||
|
|
Loading…
Add table
Reference in a new issue