rustc_mir_dataflow/
points.rs1use rustc_index::{Idx, IndexVec};
2use rustc_middle::mir::{BasicBlock, Body, Location};
3
4pub struct DenseLocationMap {
6 statements_before_block: IndexVec<BasicBlock, usize>,
8
9 basic_blocks: IndexVec<PointIndex, BasicBlock>,
12
13 num_points: usize,
14}
15
16impl DenseLocationMap {
17 #[inline]
18 pub fn new(body: &Body<'_>) -> Self {
19 let mut num_points = 0;
20 let statements_before_block: IndexVec<BasicBlock, usize> = body
21 .basic_blocks
22 .iter()
23 .map(|block_data| {
24 let v = num_points;
25 num_points += block_data.statements.len() + 1;
26 v
27 })
28 .collect();
29
30 let mut basic_blocks = IndexVec::with_capacity(num_points);
31 for (bb, bb_data) in body.basic_blocks.iter_enumerated() {
32 basic_blocks.extend((0..=bb_data.statements.len()).map(|_| bb));
33 }
34 if true {
if !(*statements_before_block.iter().max().unwrap() < num_points) {
::core::panicking::panic("assertion failed: *statements_before_block.iter().max().unwrap() < num_points")
};
};debug_assert!(*statements_before_block.iter().max().unwrap() < num_points);
36 Self { statements_before_block, basic_blocks, num_points }
37 }
38
39 #[inline]
41 pub fn num_points(&self) -> usize {
42 self.num_points
43 }
44
45 #[inline]
48 pub fn point_from_location(&self, location: Location) -> PointIndex {
49 let Location { block, statement_index } = location;
50 let start_index = self.statements_before_block[block];
51 if true {
if !(start_index < self.num_points) {
::core::panicking::panic("assertion failed: start_index < self.num_points")
};
};debug_assert!(start_index < self.num_points);
54 PointIndex::new(start_index + statement_index)
55 }
56
57 #[inline]
59 pub fn entry_point(&self, block: BasicBlock) -> PointIndex {
60 let start_index = self.statements_before_block[block];
61 PointIndex::new(start_index)
62 }
63
64 #[inline]
66 pub fn to_block_start(&self, index: PointIndex) -> PointIndex {
67 PointIndex::new(self.statements_before_block[self.basic_blocks[index]])
68 }
69
70 #[inline]
72 pub fn to_location(&self, index: PointIndex) -> Location {
73 if !(index.index() < self.num_points) {
::core::panicking::panic("assertion failed: index.index() < self.num_points")
};assert!(index.index() < self.num_points);
74 let block = self.basic_blocks[index];
75 let start_index = self.statements_before_block[block];
76 let statement_index = index.index() - start_index;
77 Location { block, statement_index }
78 }
79
80 #[inline]
85 pub fn point_in_range(&self, index: PointIndex) -> bool {
86 index.index() < self.num_points
87 }
88}
89
90#[automatically_derived]
impl ::core::marker::Copy for PointIndex { }
impl PointIndex {
#[doc = r" Maximum value the index can take, as a `u32`."]
pub const MAX_AS_U32: u32 = 0xFFFF_FF00;
#[doc = r" Maximum value the index can take."]
pub const MAX: Self = Self::from_u32(0xFFFF_FF00);
#[doc = r" Zero value of the index."]
pub const ZERO: Self = Self::from_u32(0);
#[doc = r" Creates a new index from a given `usize`."]
#[doc = r""]
#[doc = r" # Panics"]
#[doc = r""]
#[doc = r" Will panic if `value` exceeds `MAX`."]
#[inline]
pub const fn from_usize(value: usize) -> Self {
if !(value <= (0xFFFF_FF00 as usize)) {
::core::panicking::panic("assertion failed: value <= (0xFFFF_FF00 as usize)")
};
unsafe { Self::from_u32_unchecked(value as u32) }
}
#[doc = r" Creates a new index from a given `u32`."]
#[doc = r""]
#[doc = r" # Panics"]
#[doc = r""]
#[doc = r" Will panic if `value` exceeds `MAX`."]
#[inline]
pub const fn from_u32(value: u32) -> Self {
if !(value <= 0xFFFF_FF00) {
::core::panicking::panic("assertion failed: value <= 0xFFFF_FF00")
};
unsafe { Self::from_u32_unchecked(value) }
}
#[doc = r" Creates a new index from a given `u16`."]
#[doc = r""]
#[doc = r" # Panics"]
#[doc = r""]
#[doc = r" Will panic if `value` exceeds `MAX`."]
#[inline]
pub const fn from_u16(value: u16) -> Self {
let value = value as u32;
if !(value <= 0xFFFF_FF00) {
::core::panicking::panic("assertion failed: value <= 0xFFFF_FF00")
};
unsafe { Self::from_u32_unchecked(value) }
}
#[doc = r" Creates a new index from a given `u32`."]
#[doc = r""]
#[doc = r" # Safety"]
#[doc = r""]
#[doc =
r" The provided value must be less than or equal to the maximum value for the newtype."]
#[doc =
r" Providing a value outside this range is undefined due to layout restrictions."]
#[doc = r""]
#[doc = r" Prefer using `from_u32`."]
#[inline]
pub const unsafe fn from_u32_unchecked(value: u32) -> Self {
Self {
private_use_as_methods_instead: unsafe {
std::mem::transmute(value)
},
}
}
#[doc = r" Extracts the value of this index as a `usize`."]
#[inline]
pub const fn index(self) -> usize { self.as_usize() }
#[doc = r" Extracts the value of this index as a `u32`."]
#[inline]
pub const fn as_u32(self) -> u32 {
unsafe { std::mem::transmute(self.private_use_as_methods_instead) }
}
#[doc = r" Extracts the value of this index as a `usize`."]
#[inline]
pub const fn as_usize(self) -> usize { self.as_u32() as usize }
}
impl std::ops::Add<usize> for PointIndex {
type Output = Self;
#[inline]
fn add(self, other: usize) -> Self {
Self::from_usize(self.index() + other)
}
}
impl std::ops::AddAssign<usize> for PointIndex {
#[inline]
fn add_assign(&mut self, other: usize) { *self = *self + other; }
}
impl rustc_index::Idx for PointIndex {
#[inline]
fn new(value: usize) -> Self { Self::from_usize(value) }
#[inline]
fn index(self) -> usize { self.as_usize() }
}
impl ::std::iter::Step for PointIndex {
#[inline]
fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {
<usize as
::std::iter::Step>::steps_between(&Self::index(*start),
&Self::index(*end))
}
#[inline]
fn forward_checked(start: Self, u: usize) -> Option<Self> {
Self::index(start).checked_add(u).map(Self::from_usize)
}
#[inline]
fn backward_checked(start: Self, u: usize) -> Option<Self> {
Self::index(start).checked_sub(u).map(Self::from_usize)
}
#[inline]
fn forward_overflowing(start: Self, u: usize) -> (Self, bool) {
let (s, o) = Self::index(start).overflowing_add(u);
(Self::from_usize(s), o)
}
#[inline]
fn backward_overflowing(start: Self, u: usize) -> (Self, bool) {
let (s, o) = Self::index(start).overflowing_sub(u);
(Self::from_usize(s), o)
}
}
impl ::std::cmp::Ord for PointIndex {
#[inline]
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.as_u32().cmp(&other.as_u32())
}
}
impl ::std::cmp::PartialOrd for PointIndex {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl From<PointIndex> for u32 {
#[inline]
fn from(v: PointIndex) -> u32 { v.as_u32() }
}
impl From<PointIndex> for usize {
#[inline]
fn from(v: PointIndex) -> usize { v.as_usize() }
}
impl From<usize> for PointIndex {
#[inline]
fn from(value: usize) -> Self { Self::from_usize(value) }
}
impl From<u32> for PointIndex {
#[inline]
fn from(value: u32) -> Self { Self::from_u32(value) }
}
impl ::std::cmp::Eq for PointIndex {}
impl ::std::cmp::PartialEq for PointIndex {
fn eq(&self, other: &Self) -> bool { self.as_u32().eq(&other.as_u32()) }
}
impl ::std::marker::StructuralPartialEq for PointIndex {}
impl ::std::hash::Hash for PointIndex {
fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
self.as_u32().hash(state)
}
}
impl ::std::fmt::Debug for PointIndex {
fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
fmt.write_fmt(format_args!("PointIndex({0})", self.as_u32()))
}
}rustc_index::newtype_index! {
91 #[orderable]
94 #[debug_format = "PointIndex({})"]
95 pub struct PointIndex {}
96}