cranelift_codegen/ir/
jumptable.rs1use crate::ir::instructions::ValueListPool;
7use crate::ir::BlockCall;
8use alloc::vec::Vec;
9use core::fmt::{self, Display, Formatter};
10use core::slice::{Iter, IterMut};
11
12#[cfg(feature = "enable-serde")]
13use serde_derive::{Deserialize, Serialize};
14
15#[derive(Debug, Clone, PartialEq, Hash)]
24#[cfg_attr(feature = "enable-serde", derive(Serialize, Deserialize))]
25pub struct JumpTableData {
26 table: Vec<BlockCall>,
28}
29
30impl JumpTableData {
31 pub fn new(def: BlockCall, table: &[BlockCall]) -> Self {
33 Self {
34 table: std::iter::once(def).chain(table.iter().copied()).collect(),
35 }
36 }
37
38 pub fn default_block(&self) -> BlockCall {
40 *self.table.first().unwrap()
41 }
42
43 pub fn default_block_mut(&mut self) -> &mut BlockCall {
45 self.table.first_mut().unwrap()
46 }
47
48 pub fn all_branches(&self) -> &[BlockCall] {
50 self.table.as_slice()
51 }
52
53 pub fn all_branches_mut(&mut self) -> &mut [BlockCall] {
56 self.table.as_mut_slice()
57 }
58
59 pub fn as_slice(&self) -> &[BlockCall] {
61 &self.table.as_slice()[1..]
62 }
63
64 pub fn as_mut_slice(&mut self) -> &mut [BlockCall] {
66 &mut self.table.as_mut_slice()[1..]
67 }
68
69 #[deprecated(since = "7.0.0", note = "please use `.as_slice()` instead")]
71 pub fn iter(&self) -> Iter<BlockCall> {
72 self.as_slice().iter()
73 }
74
75 #[deprecated(since = "7.0.0", note = "please use `.as_mut_slice()` instead")]
77 pub fn iter_mut(&mut self) -> IterMut<BlockCall> {
78 self.as_mut_slice().iter_mut()
79 }
80
81 pub fn clear(&mut self) {
83 self.table.drain(1..);
84 }
85
86 pub fn display<'a>(&'a self, pool: &'a ValueListPool) -> DisplayJumpTable<'a> {
88 DisplayJumpTable { jt: self, pool }
89 }
90}
91
92pub struct DisplayJumpTable<'a> {
94 jt: &'a JumpTableData,
95 pool: &'a ValueListPool,
96}
97
98impl<'a> Display for DisplayJumpTable<'a> {
99 fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
100 write!(fmt, "{}, [", self.jt.default_block().display(self.pool))?;
101 if let Some((first, rest)) = self.jt.as_slice().split_first() {
102 write!(fmt, "{}", first.display(self.pool))?;
103 for block in rest {
104 write!(fmt, ", {}", block.display(self.pool))?;
105 }
106 }
107 write!(fmt, "]")
108 }
109}
110
111#[cfg(test)]
112mod tests {
113 use super::JumpTableData;
114 use crate::entity::EntityRef;
115 use crate::ir::instructions::ValueListPool;
116 use crate::ir::{Block, BlockArg, BlockCall, Value};
117 use alloc::vec::Vec;
118 use std::string::ToString;
119
120 #[test]
121 fn empty() {
122 let mut pool = ValueListPool::default();
123 let def = BlockCall::new(Block::new(0), core::iter::empty(), &mut pool);
124
125 let jt = JumpTableData::new(def, &[]);
126
127 assert_eq!(jt.all_branches().get(0), Some(&def));
128
129 assert_eq!(jt.as_slice().get(0), None);
130 assert_eq!(jt.as_slice().get(10), None);
131
132 assert_eq!(jt.display(&pool).to_string(), "block0, []");
133
134 assert_eq!(jt.all_branches(), [def]);
135 assert_eq!(jt.as_slice(), []);
136 }
137
138 #[test]
139 fn insert() {
140 let mut pool = ValueListPool::default();
141
142 let v0 = Value::new(0);
143 let v1 = Value::new(1);
144
145 let e0 = Block::new(0);
146 let e1 = Block::new(1);
147 let e2 = Block::new(2);
148
149 let def = BlockCall::new(e0, core::iter::empty(), &mut pool);
150 let b1 = BlockCall::new(e1, core::iter::once(v0.into()), &mut pool);
151 let b2 = BlockCall::new(e2, core::iter::empty(), &mut pool);
152 let b3 = BlockCall::new(e1, core::iter::once(v1.into()), &mut pool);
153
154 let jt = JumpTableData::new(def, &[b1, b2, b3]);
155
156 assert_eq!(jt.default_block(), def);
157 assert_eq!(
158 jt.display(&pool).to_string(),
159 "block0, [block1(v0), block2, block1(v1)]"
160 );
161
162 assert_eq!(jt.all_branches(), [def, b1, b2, b3]);
163 assert_eq!(jt.as_slice(), [b1, b2, b3]);
164
165 assert_eq!(
166 jt.as_slice()[0].args(&pool).collect::<Vec<_>>(),
167 [BlockArg::Value(v0)]
168 );
169 assert_eq!(jt.as_slice()[1].args(&pool).collect::<Vec<_>>(), []);
170 assert_eq!(
171 jt.as_slice()[2].args(&pool).collect::<Vec<_>>(),
172 [BlockArg::Value(v1)]
173 );
174 }
175}