Skip to content

Commit 62333e9

Browse files
authored
Add a newtypes for LiveRange, LiveBundle, SpillSet, and VReg storage (#142)
* Add a newtypes for LiveRange, LiveBundle, SpillSet, and VReg storage * Use a macro to define storage newtypes * Generate a push method in the define_index macro * Derive IntoIterator impls for derived storage types
1 parent e530854 commit 62333e9

File tree

10 files changed

+403
-368
lines changed

10 files changed

+403
-368
lines changed

src/index.rs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,81 @@
11
#[macro_export]
22
macro_rules! define_index {
3+
($ix:ident, $storage:ident, $elem:ident) => {
4+
define_index!($ix);
5+
6+
#[derive(Clone, Debug)]
7+
pub struct $storage {
8+
storage: Vec<$elem>,
9+
}
10+
11+
impl $storage {
12+
#[inline(always)]
13+
pub fn with_capacity(n: usize) -> Self {
14+
Self {
15+
storage: Vec::with_capacity(n),
16+
}
17+
}
18+
19+
#[inline(always)]
20+
pub fn len(&self) -> usize {
21+
self.storage.len()
22+
}
23+
24+
#[inline(always)]
25+
pub fn iter(&self) -> impl Iterator<Item = &$elem> {
26+
self.storage.iter()
27+
}
28+
29+
#[inline(always)]
30+
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut $elem> {
31+
self.storage.iter_mut()
32+
}
33+
34+
#[inline(always)]
35+
pub fn push(&mut self, value: $elem) -> $ix {
36+
let idx = $ix(self.storage.len() as u32);
37+
self.storage.push(value);
38+
idx
39+
}
40+
}
41+
42+
impl core::ops::Index<$ix> for $storage {
43+
type Output = $elem;
44+
45+
#[inline(always)]
46+
fn index(&self, i: $ix) -> &Self::Output {
47+
&self.storage[i.index()]
48+
}
49+
}
50+
51+
impl core::ops::IndexMut<$ix> for $storage {
52+
#[inline(always)]
53+
fn index_mut(&mut self, i: $ix) -> &mut Self::Output {
54+
&mut self.storage[i.index()]
55+
}
56+
}
57+
58+
impl<'a> IntoIterator for &'a $storage {
59+
type Item = &'a $elem;
60+
type IntoIter = core::slice::Iter<'a, $elem>;
61+
62+
#[inline(always)]
63+
fn into_iter(self) -> Self::IntoIter {
64+
self.storage.iter()
65+
}
66+
}
67+
68+
impl<'a> IntoIterator for &'a mut $storage {
69+
type Item = &'a mut $elem;
70+
type IntoIter = core::slice::IterMut<'a, $elem>;
71+
72+
#[inline(always)]
73+
fn into_iter(self) -> Self::IntoIter {
74+
self.storage.iter_mut()
75+
}
76+
}
77+
};
78+
379
($ix:ident) => {
480
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
581
#[cfg_attr(

src/ion/data_structures.rs

Lines changed: 61 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use alloc::vec::Vec;
2626
use core::cmp::Ordering;
2727
use core::fmt::Debug;
2828
use hashbrown::{HashMap, HashSet};
29-
use smallvec::SmallVec;
29+
use smallvec::{smallvec, SmallVec};
3030

3131
/// A range from `from` (inclusive) to `to` (exclusive).
3232
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
@@ -94,11 +94,11 @@ impl core::cmp::Ord for CodeRange {
9494
}
9595
}
9696

97-
define_index!(LiveBundleIndex);
98-
define_index!(LiveRangeIndex);
99-
define_index!(SpillSetIndex);
97+
define_index!(LiveBundleIndex, LiveBundles, LiveBundle);
98+
define_index!(LiveRangeIndex, LiveRanges, LiveRange);
99+
define_index!(SpillSetIndex, SpillSets, SpillSet);
100100
define_index!(UseIndex);
101-
define_index!(VRegIndex);
101+
define_index!(VRegIndex, VRegs, VRegData);
102102
define_index!(PRegIndex);
103103
define_index!(SpillSlotIndex);
104104

@@ -396,6 +396,55 @@ impl BlockparamIn {
396396
}
397397
}
398398

399+
impl LiveRanges {
400+
pub fn add(&mut self, range: CodeRange) -> LiveRangeIndex {
401+
self.push(LiveRange {
402+
range,
403+
vreg: VRegIndex::invalid(),
404+
bundle: LiveBundleIndex::invalid(),
405+
uses_spill_weight_and_flags: 0,
406+
407+
uses: smallvec![],
408+
})
409+
}
410+
}
411+
412+
impl LiveBundles {
413+
pub fn add(&mut self) -> LiveBundleIndex {
414+
self.push(LiveBundle {
415+
allocation: Allocation::none(),
416+
ranges: smallvec![],
417+
spillset: SpillSetIndex::invalid(),
418+
prio: 0,
419+
spill_weight_and_props: 0,
420+
})
421+
}
422+
}
423+
424+
impl VRegs {
425+
pub fn add(&mut self, reg: VReg, data: VRegData) -> VRegIndex {
426+
let idx = self.push(data);
427+
debug_assert_eq!(reg.vreg(), idx.index());
428+
idx
429+
}
430+
}
431+
432+
impl core::ops::Index<VReg> for VRegs {
433+
type Output = VRegData;
434+
435+
#[inline(always)]
436+
fn index(&self, idx: VReg) -> &Self::Output {
437+
&self.storage[idx.vreg()]
438+
}
439+
}
440+
441+
impl core::ops::IndexMut<VReg> for VRegs {
442+
#[inline(always)]
443+
fn index_mut(&mut self, idx: VReg) -> &mut Self::Output {
444+
&mut self.storage[idx.vreg()]
445+
}
446+
}
447+
399448
#[derive(Clone, Debug)]
400449
pub struct Env<'a, F: Function> {
401450
pub func: &'a F,
@@ -406,10 +455,10 @@ pub struct Env<'a, F: Function> {
406455
pub blockparam_outs: Vec<BlockparamOut>,
407456
pub blockparam_ins: Vec<BlockparamIn>,
408457

409-
pub ranges: Vec<LiveRange>,
410-
pub bundles: Vec<LiveBundle>,
411-
pub spillsets: Vec<SpillSet>,
412-
pub vregs: Vec<VRegData>,
458+
pub ranges: LiveRanges,
459+
pub bundles: LiveBundles,
460+
pub spillsets: SpillSets,
461+
pub vregs: VRegs,
413462
pub pregs: Vec<PRegData>,
414463
pub allocation_queue: PrioQueue,
415464
pub safepoints: Vec<Inst>, // Sorted list of safepoint insts.
@@ -457,7 +506,7 @@ impl<'a, F: Function> Env<'a, F> {
457506
/// Get the VReg (with bundled RegClass) from a vreg index.
458507
#[inline]
459508
pub fn vreg(&self, index: VRegIndex) -> VReg {
460-
let class = self.vregs[index.index()]
509+
let class = self.vregs[index]
461510
.class
462511
.expect("trying to get a VReg before observing its class");
463512
VReg::new(index.index(), class)
@@ -466,15 +515,15 @@ impl<'a, F: Function> Env<'a, F> {
466515
/// Record the class of a VReg. We learn this only when we observe
467516
/// the VRegs in use.
468517
pub fn observe_vreg_class(&mut self, vreg: VReg) {
469-
let old_class = self.vregs[vreg.vreg()].class.replace(vreg.class());
518+
let old_class = self.vregs[vreg].class.replace(vreg.class());
470519
// We should never observe two different classes for two
471520
// mentions of a VReg in the source program.
472521
debug_assert!(old_class == None || old_class == Some(vreg.class()));
473522
}
474523

475524
/// Is this vreg actually used in the source program?
476525
pub fn is_vreg_used(&self, index: VRegIndex) -> bool {
477-
self.vregs[index.index()].class.is_some()
526+
self.vregs[index].class.is_some()
478527
}
479528
}
480529

0 commit comments

Comments
 (0)