Skip to content

Renamed "undef" -> "uninit" #71418

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 39 additions & 39 deletions src/librustc_middle/mir/interpret/allocation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use rustc_data_structures::sorted_map::SortedMap;
use rustc_target::abi::{Align, HasDataLayout, Size};

use super::{
read_target_uint, write_target_uint, AllocId, InterpResult, Pointer, Scalar, ScalarMaybeUndef,
read_target_uint, write_target_uint, AllocId, InterpResult, Pointer, Scalar, ScalarMaybeUninit,
};

#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
Expand All @@ -25,7 +25,7 @@ pub struct Allocation<Tag = (), Extra = ()> {
/// at the given offset.
relocations: Relocations<Tag>,
/// Denotes which part of this allocation is initialized.
undef_mask: UndefMask,
init_mask: InitMask,
/// The size of the allocation. Currently, must always equal `bytes.len()`.
pub size: Size,
/// The alignment of the allocation to detect unaligned reads.
Expand Down Expand Up @@ -92,7 +92,7 @@ impl<Tag> Allocation<Tag> {
Self {
bytes,
relocations: Relocations::new(),
undef_mask: UndefMask::new(size, true),
init_mask: InitMask::new(size, true),
size,
align,
mutability: Mutability::Not,
Expand All @@ -108,7 +108,7 @@ impl<Tag> Allocation<Tag> {
Allocation {
bytes: vec![0; size.bytes_usize()],
relocations: Relocations::new(),
undef_mask: UndefMask::new(size, false),
init_mask: InitMask::new(size, false),
size,
align,
mutability: Mutability::Mut,
Expand Down Expand Up @@ -138,7 +138,7 @@ impl Allocation<(), ()> {
})
.collect(),
),
undef_mask: self.undef_mask,
init_mask: self.init_mask,
align: self.align,
mutability: self.mutability,
extra,
Expand All @@ -160,9 +160,9 @@ impl<Tag, Extra> Allocation<Tag, Extra> {
&self.bytes[range]
}

/// Returns the undef mask.
pub fn undef_mask(&self) -> &UndefMask {
&self.undef_mask
/// Returns the mask indicating which bytes are initialized.
pub fn init_mask(&self) -> &InitMask {
&self.init_mask
}

/// Returns the relocation list.
Expand Down Expand Up @@ -358,15 +358,15 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
cx: &impl HasDataLayout,
ptr: Pointer<Tag>,
size: Size,
) -> InterpResult<'tcx, ScalarMaybeUndef<Tag>> {
) -> InterpResult<'tcx, ScalarMaybeUninit<Tag>> {
// `get_bytes_unchecked` tests relocation edges.
let bytes = self.get_bytes_with_undef_and_ptr(cx, ptr, size)?;
// Undef check happens *after* we established that the alignment is correct.
// Uninit check happens *after* we established that the alignment is correct.
// We must not return `Ok()` for unaligned pointers!
if self.is_defined(ptr, size).is_err() {
// This inflates undefined bytes to the entire scalar, even if only a few
// bytes are undefined.
return Ok(ScalarMaybeUndef::Undef);
// This inflates uninitialized bytes to the entire scalar, even if only a few
// bytes are uninitialized.
return Ok(ScalarMaybeUninit::Uninit);
}
// Now we do the actual reading.
let bits = read_target_uint(cx.data_layout().endian, bytes).unwrap();
Expand All @@ -377,11 +377,11 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
} else {
if let Some(&(tag, alloc_id)) = self.relocations.get(&ptr.offset) {
let ptr = Pointer::new_with_tag(alloc_id, Size::from_bytes(bits), tag);
return Ok(ScalarMaybeUndef::Scalar(ptr.into()));
return Ok(ScalarMaybeUninit::Scalar(ptr.into()));
}
}
// We don't. Just return the bits.
Ok(ScalarMaybeUndef::Scalar(Scalar::from_uint(bits, size)))
Ok(ScalarMaybeUninit::Scalar(Scalar::from_uint(bits, size)))
}

/// Reads a pointer-sized scalar.
Expand All @@ -392,7 +392,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
&self,
cx: &impl HasDataLayout,
ptr: Pointer<Tag>,
) -> InterpResult<'tcx, ScalarMaybeUndef<Tag>> {
) -> InterpResult<'tcx, ScalarMaybeUninit<Tag>> {
self.read_scalar(cx, ptr, cx.data_layout().pointer_size)
}

Expand All @@ -409,12 +409,12 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
&mut self,
cx: &impl HasDataLayout,
ptr: Pointer<Tag>,
val: ScalarMaybeUndef<Tag>,
val: ScalarMaybeUninit<Tag>,
type_size: Size,
) -> InterpResult<'tcx> {
let val = match val {
ScalarMaybeUndef::Scalar(scalar) => scalar,
ScalarMaybeUndef::Undef => {
ScalarMaybeUninit::Scalar(scalar) => scalar,
ScalarMaybeUninit::Uninit => {
self.mark_definedness(ptr, type_size, false);
return Ok(());
}
Expand Down Expand Up @@ -445,7 +445,7 @@ impl<'tcx, Tag: Copy, Extra: AllocationExtra<Tag>> Allocation<Tag, Extra> {
&mut self,
cx: &impl HasDataLayout,
ptr: Pointer<Tag>,
val: ScalarMaybeUndef<Tag>,
val: ScalarMaybeUninit<Tag>,
) -> InterpResult<'tcx> {
let ptr_size = cx.data_layout().pointer_size;
self.write_scalar(cx, ptr, val, ptr_size)
Expand Down Expand Up @@ -514,10 +514,10 @@ impl<'tcx, Tag: Copy, Extra> Allocation<Tag, Extra> {
// Mark parts of the outermost relocations as undefined if they partially fall outside the
// given range.
if first < start {
self.undef_mask.set_range(first, start, false);
self.init_mask.set_range(first, start, false);
}
if last > end {
self.undef_mask.set_range(end, last, false);
self.init_mask.set_range(end, last, false);
}

// Forget all the relocations.
Expand Down Expand Up @@ -548,21 +548,21 @@ impl<'tcx, Tag: Copy, Extra> Allocation<Tag, Extra> {
/// Returns `Ok(())` if it's defined. Otherwise returns the index of the byte
/// at which the first undefined access begins.
fn is_defined(&self, ptr: Pointer<Tag>, size: Size) -> Result<(), Size> {
self.undef_mask.is_range_defined(ptr.offset, ptr.offset + size) // `Size` addition
self.init_mask.is_range_initialized(ptr.offset, ptr.offset + size) // `Size` addition
}

/// Checks that a range of bytes is defined. If not, returns the `ReadUndefBytes`
/// error which will report the first byte which is undefined.
fn check_defined(&self, ptr: Pointer<Tag>, size: Size) -> InterpResult<'tcx> {
self.is_defined(ptr, size)
.or_else(|idx| throw_ub!(InvalidUndefBytes(Some(Pointer::new(ptr.alloc_id, idx)))))
.or_else(|idx| throw_ub!(InvalidUninitBytes(Some(Pointer::new(ptr.alloc_id, idx)))))
}

pub fn mark_definedness(&mut self, ptr: Pointer<Tag>, size: Size, new_state: bool) {
if size.bytes() == 0 {
return;
}
self.undef_mask.set_range(ptr.offset, ptr.offset + size, new_state);
self.init_mask.set_range(ptr.offset, ptr.offset + size, new_state);
}
}

Expand Down Expand Up @@ -601,13 +601,13 @@ impl<Tag, Extra> Allocation<Tag, Extra> {
// where each element toggles the state.

let mut ranges = smallvec::SmallVec::<[u64; 1]>::new();
let initial = self.undef_mask.get(src.offset);
let initial = self.init_mask.get(src.offset);
let mut cur_len = 1;
let mut cur = initial;

for i in 1..size.bytes() {
// FIXME: optimize to bitshift the current undef block's bits and read the top bit.
if self.undef_mask.get(src.offset + Size::from_bytes(i)) == cur {
if self.init_mask.get(src.offset + Size::from_bytes(i)) == cur {
cur_len += 1;
} else {
ranges.push(cur_len);
Expand All @@ -632,7 +632,7 @@ impl<Tag, Extra> Allocation<Tag, Extra> {
// An optimization where we can just overwrite an entire range of definedness bits if
// they are going to be uniformly `1` or `0`.
if defined.ranges.len() <= 1 {
self.undef_mask.set_range_inbounds(
self.init_mask.set_range_inbounds(
dest.offset,
dest.offset + size * repeat, // `Size` operations
defined.initial,
Expand All @@ -647,7 +647,7 @@ impl<Tag, Extra> Allocation<Tag, Extra> {
for range in &defined.ranges {
let old_j = j;
j += range;
self.undef_mask.set_range_inbounds(
self.init_mask.set_range_inbounds(
Size::from_bytes(old_j),
Size::from_bytes(j),
cur,
Expand Down Expand Up @@ -739,29 +739,29 @@ impl<Tag: Copy, Extra> Allocation<Tag, Extra> {
type Block = u64;

/// A bitmask where each bit refers to the byte with the same index. If the bit is `true`, the byte
/// is defined. If it is `false` the byte is undefined.
/// is initialized. If it is `false` the byte is uninitialized.
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)]
#[derive(HashStable)]
pub struct UndefMask {
pub struct InitMask {
blocks: Vec<Block>,
len: Size,
}

impl UndefMask {
impl InitMask {
pub const BLOCK_SIZE: u64 = 64;

pub fn new(size: Size, state: bool) -> Self {
let mut m = UndefMask { blocks: vec![], len: Size::ZERO };
let mut m = InitMask { blocks: vec![], len: Size::ZERO };
m.grow(size, state);
m
}

/// Checks whether the range `start..end` (end-exclusive) is entirely defined.
/// Checks whether the range `start..end` (end-exclusive) is entirely initialized.
///
/// Returns `Ok(())` if it's defined. Otherwise returns the index of the byte
/// at which the first undefined access begins.
/// Returns `Ok(())` if it's initialized. Otherwise returns the index of the byte
/// at which the first uninitialized access begins.
#[inline]
pub fn is_range_defined(&self, start: Size, end: Size) -> Result<(), Size> {
pub fn is_range_initialized(&self, start: Size, end: Size) -> Result<(), Size> {
if end > self.len {
return Err(self.len);
}
Expand Down Expand Up @@ -870,7 +870,7 @@ impl UndefMask {
#[inline]
fn bit_index(bits: Size) -> (usize, usize) {
let bits = bits.bytes();
let a = bits / UndefMask::BLOCK_SIZE;
let b = bits % UndefMask::BLOCK_SIZE;
let a = bits / InitMask::BLOCK_SIZE;
let b = bits % InitMask::BLOCK_SIZE;
(usize::try_from(a).unwrap(), usize::try_from(b).unwrap())
}
10 changes: 5 additions & 5 deletions src/librustc_middle/mir/interpret/error.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::{AllocId, Pointer, RawConst, ScalarMaybeUndef};
use super::{AllocId, Pointer, RawConst, ScalarMaybeUninit};

use crate::mir::interpret::ConstValue;
use crate::ty::layout::LayoutError;
Expand Down Expand Up @@ -378,13 +378,13 @@ pub enum UndefinedBehaviorInfo<'tcx> {
/// Using a non-character `u32` as character.
InvalidChar(u32),
/// An enum discriminant was set to a value which was outside the range of valid values.
InvalidDiscriminant(ScalarMaybeUndef),
InvalidDiscriminant(ScalarMaybeUninit),
/// Using a pointer-not-to-a-function as function pointer.
InvalidFunctionPointer(Pointer),
/// Using a string that is not valid UTF-8,
InvalidStr(std::str::Utf8Error),
/// Using uninitialized data where it is not allowed.
InvalidUndefBytes(Option<Pointer>),
InvalidUninitBytes(Option<Pointer>),
/// Working with a local that is not currently live.
DeadLocal,
/// Data size is not equal to target size.
Expand Down Expand Up @@ -455,12 +455,12 @@ impl fmt::Display for UndefinedBehaviorInfo<'_> {
write!(f, "using {} as function pointer but it does not point to a function", p)
}
InvalidStr(err) => write!(f, "this string is not valid UTF-8: {}", err),
InvalidUndefBytes(Some(p)) => write!(
InvalidUninitBytes(Some(p)) => write!(
f,
"reading uninitialized memory at {}, but this operation requires initialized memory",
p
),
InvalidUndefBytes(None) => write!(
InvalidUninitBytes(None) => write!(
f,
"using uninitialized data, but this operation requires initialized memory"
),
Expand Down
4 changes: 2 additions & 2 deletions src/librustc_middle/mir/interpret/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,9 @@ pub use self::error::{
ResourceExhaustionInfo, UndefinedBehaviorInfo, UnsupportedOpInfo,
};

pub use self::value::{get_slice_bytes, ConstValue, RawConst, Scalar, ScalarMaybeUndef};
pub use self::value::{get_slice_bytes, ConstValue, RawConst, Scalar, ScalarMaybeUninit};

pub use self::allocation::{Allocation, AllocationExtra, Relocations, UndefMask};
pub use self::allocation::{Allocation, AllocationExtra, InitMask, Relocations};

pub use self::pointer::{Pointer, PointerArithmetic};

Expand Down
38 changes: 19 additions & 19 deletions src/librustc_middle/mir/interpret/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ pub struct RawConst<'tcx> {
pub enum ConstValue<'tcx> {
/// Used only for types with `layout::abi::Scalar` ABI and ZSTs.
///
/// Not using the enum `Value` to encode that this must not be `Undef`.
/// Not using the enum `Value` to encode that this must not be `Uninit`.
Scalar(Scalar),

/// Used only for `&[u8]` and `&str`
Expand Down Expand Up @@ -542,62 +542,62 @@ impl<Tag> From<Pointer<Tag>> for Scalar<Tag> {
}

#[derive(Clone, Copy, Eq, PartialEq, RustcEncodable, RustcDecodable, HashStable, Hash)]
pub enum ScalarMaybeUndef<Tag = ()> {
pub enum ScalarMaybeUninit<Tag = ()> {
Scalar(Scalar<Tag>),
Undef,
Uninit,
}

impl<Tag> From<Scalar<Tag>> for ScalarMaybeUndef<Tag> {
impl<Tag> From<Scalar<Tag>> for ScalarMaybeUninit<Tag> {
#[inline(always)]
fn from(s: Scalar<Tag>) -> Self {
ScalarMaybeUndef::Scalar(s)
ScalarMaybeUninit::Scalar(s)
}
}

impl<Tag> From<Pointer<Tag>> for ScalarMaybeUndef<Tag> {
impl<Tag> From<Pointer<Tag>> for ScalarMaybeUninit<Tag> {
#[inline(always)]
fn from(s: Pointer<Tag>) -> Self {
ScalarMaybeUndef::Scalar(s.into())
ScalarMaybeUninit::Scalar(s.into())
}
}

// We want the `Debug` output to be readable as it is used by `derive(Debug)` for
// all the Miri types.
impl<Tag: fmt::Debug> fmt::Debug for ScalarMaybeUndef<Tag> {
impl<Tag: fmt::Debug> fmt::Debug for ScalarMaybeUninit<Tag> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ScalarMaybeUndef::Undef => write!(f, "<uninitialized>"),
ScalarMaybeUndef::Scalar(s) => write!(f, "{:?}", s),
ScalarMaybeUninit::Uninit => write!(f, "<uninitialized>"),
ScalarMaybeUninit::Scalar(s) => write!(f, "{:?}", s),
}
}
}

impl<Tag: fmt::Debug> fmt::Display for ScalarMaybeUndef<Tag> {
impl<Tag: fmt::Debug> fmt::Display for ScalarMaybeUninit<Tag> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ScalarMaybeUndef::Undef => write!(f, "uninitialized bytes"),
ScalarMaybeUndef::Scalar(s) => write!(f, "{}", s),
ScalarMaybeUninit::Uninit => write!(f, "uninitialized bytes"),
ScalarMaybeUninit::Scalar(s) => write!(f, "{}", s),
}
}
}

impl<'tcx, Tag> ScalarMaybeUndef<Tag> {
impl<'tcx, Tag> ScalarMaybeUninit<Tag> {
/// Erase the tag from the scalar, if any.
///
/// Used by error reporting code to avoid having the error type depend on `Tag`.
#[inline]
pub fn erase_tag(self) -> ScalarMaybeUndef {
pub fn erase_tag(self) -> ScalarMaybeUninit {
match self {
ScalarMaybeUndef::Scalar(s) => ScalarMaybeUndef::Scalar(s.erase_tag()),
ScalarMaybeUndef::Undef => ScalarMaybeUndef::Undef,
ScalarMaybeUninit::Scalar(s) => ScalarMaybeUninit::Scalar(s.erase_tag()),
ScalarMaybeUninit::Uninit => ScalarMaybeUninit::Uninit,
}
}

#[inline]
pub fn not_undef(self) -> InterpResult<'static, Scalar<Tag>> {
match self {
ScalarMaybeUndef::Scalar(scalar) => Ok(scalar),
ScalarMaybeUndef::Undef => throw_ub!(InvalidUndefBytes(None)),
ScalarMaybeUninit::Scalar(scalar) => Ok(scalar),
ScalarMaybeUninit::Uninit => throw_ub!(InvalidUninitBytes(None)),
}
}

Expand Down
Loading