2 error::{Error, Result},
3 index::{BlockIdx, InstIdx, InstRange, SSAValIdx},
9 use serde::{Deserialize, Serialize};
12 #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, Serialize, Deserialize)]
17 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash, Serialize, Deserialize)]
24 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
25 #[serde(try_from = "SerializedProgPoint", into = "SerializedProgPoint")]
26 pub struct ProgPoint(usize);
29 pub const fn new(inst: InstIdx, stage: InstStage) -> Self {
30 const_unwrap_res!(Self::try_new(inst, stage))
32 pub const fn try_new(inst: InstIdx, stage: InstStage) -> Result<Self> {
33 let Some(inst) = inst.get().checked_shl(1) else {
34 return Err(Error::InstIdxTooBig);
36 Ok(Self(inst | stage as usize))
38 pub const fn inst(self) -> InstIdx {
39 InstIdx::new(self.0 >> 1)
41 pub const fn stage(self) -> InstStage {
48 pub const fn next(self) -> Self {
51 pub const fn prev(self) -> Self {
56 impl fmt::Debug for ProgPoint {
57 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58 f.debug_struct("ProgPoint")
59 .field("inst", &self.inst())
60 .field("stage", &self.stage())
65 #[derive(Serialize, Deserialize)]
66 struct SerializedProgPoint {
71 impl From<ProgPoint> for SerializedProgPoint {
72 fn from(value: ProgPoint) -> Self {
80 impl TryFrom<SerializedProgPoint> for ProgPoint {
83 fn try_from(value: SerializedProgPoint) -> Result<Self, Self::Error> {
84 ProgPoint::try_new(value.inst, value.stage)
88 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash, Serialize, Deserialize)]
90 pub enum OperandKind {
95 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash, Serialize, Deserialize)]
97 /// any register or stack location
101 /// r2,r4,r6,r8,...r126
107 /// any stack location
113 #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash, Serialize, Deserialize)]
115 pub ssa_val: SSAValIdx,
116 pub constraint: Constraint,
117 pub kind: OperandKind,
118 pub stage: InstStage,
121 #[derive(Clone, PartialEq, Eq, Debug, Hash, Serialize, Deserialize)]
122 pub struct BranchSucc {
124 pub params: Vec<SSAValIdx>,
127 #[derive(Clone, PartialEq, Eq, Debug, Hash, Serialize, Deserialize)]
130 /// copy concatenates all `srcs` together and de-concatenates the result into all `dests`.
137 succs: Vec<BranchSucc>,
142 pub fn is_normal(&self) -> bool {
143 matches!(self, Self::Normal)
145 pub fn is_block_term(&self) -> bool {
146 matches!(self, Self::Return | Self::Branch { .. })
148 pub fn succs(&self) -> Option<&[BranchSucc]> {
150 InstKind::Normal | InstKind::Copy { .. } => None,
151 InstKind::Return => Some(&[]),
152 InstKind::Branch { succs } => Some(succs),
157 impl Default for InstKind {
158 fn default() -> Self {
163 #[derive(Clone, PartialEq, Eq, Debug, Hash, Serialize, Deserialize)]
165 #[serde(default, skip_serializing_if = "InstKind::is_normal")]
167 pub operands: Vec<Operand>,
168 pub clobbers: Interned<LocSet>,
171 #[derive(Clone, PartialEq, Eq, Debug, Hash, Serialize, Deserialize)]
173 pub params: Vec<SSAValIdx>,
174 pub insts: InstRange,
175 pub preds: Vec<BlockIdx>,
179 #[fields_ty = FnFields]
180 #[derive(Clone, PartialEq, Eq, Debug, Hash)]
181 pub struct Function {
182 pub ssa_vals: Vec<SSAVal>,
183 pub insts: Vec<Inst>,
184 pub blocks: Vec<Block>,
189 pub fn new(fields: FnFields) -> Result<Self> {
195 let entry_block = blocks
196 .get(BlockIdx::ENTRY_BLOCK.get())
197 .ok_or(Error::MissingEntryBlock)?;
198 if !entry_block.params.is_empty() {
199 return Err(Error::EntryBlockCantHaveParams);
201 if !entry_block.preds.is_empty() {
202 return Err(Error::EntryBlockCantHavePreds);
204 let mut expected_start = InstIdx::new(0);
205 for (block_idx, block) in fields.blocks.iter().enumerate() {
206 let block_idx = BlockIdx::new(block_idx);
212 if inst_range.start != expected_start {
213 return Err(Error::BlockHasInvalidStart {
214 start: inst_range.start,
218 let Some((term_idx, non_term_inst_range)) = inst_range.split_last() else {
219 return Err(Error::BlockIsEmpty { block: block_idx });
221 expected_start = inst_range.end;
222 let Some(Inst { kind: term_kind, .. }) = insts_vec.get(term_idx.get()) else {
223 return Err(Error::BlockEndOutOfRange { end: inst_range.end });
225 if !term_kind.is_block_term() {
226 return Err(Error::BlocksLastInstMustBeTerm { term_idx });
228 for inst_idx in non_term_inst_range {
229 if insts_vec[inst_idx].kind.is_block_term() {
230 return Err(Error::TermInstOnlyAllowedAtBlockEnd { inst_idx });
236 pub fn entry_block(&self) -> &Block {
239 pub fn block_succs(&self, block: BlockIdx) -> &[BranchSucc] {
240 self.insts[self.blocks[block].insts.last().unwrap()]
247 impl Index<SSAValIdx> for Vec<SSAVal> {
248 type Output = SSAVal;
250 fn index(&self, index: SSAValIdx) -> &Self::Output {
255 impl Index<InstIdx> for Vec<Inst> {
258 fn index(&self, index: InstIdx) -> &Self::Output {
263 impl Index<BlockIdx> for Vec<Block> {
266 fn index(&self, index: BlockIdx) -> &Self::Output {