use crate::{
- index::{BlockIdx, DisplayOptionIdx, InstIdx, SSAValIdx},
+ index::{BlockIdx, BlockParamIdx, DisplayOptionIdx, IndexTy, InstIdx, OperandIdx, SSAValIdx},
loc::{BaseTy, Ty},
};
+use std::fmt;
use thiserror::Error;
+#[derive(Debug, Error)]
+#[error("SSA value index {idx} out of range")]
+pub struct SSAValIdxOutOfRange {
+ pub idx: SSAValIdx,
+}
+
+impl SSAValIdxOutOfRange {
+ pub fn with_inst_and_operand(
+ self,
+ inst: InstIdx,
+ operand: OperandIdx,
+ ) -> WithContext<
+ Option<BlockIdx>,
+ InstIdx,
+ AlwaysNone,
+ OperandIdx,
+ AlwaysNone,
+ SSAValIdxOutOfRange,
+ > {
+ WithContext {
+ block: None,
+ inst,
+ succ: AlwaysNone,
+ operand,
+ param: AlwaysNone,
+ out_of_range_error: self,
+ }
+ }
+ pub fn with_block_inst_and_operand(
+ self,
+ block: BlockIdx,
+ inst: InstIdx,
+ operand: OperandIdx,
+ ) -> WithContext<
+ Option<BlockIdx>,
+ InstIdx,
+ AlwaysNone,
+ OperandIdx,
+ AlwaysNone,
+ SSAValIdxOutOfRange,
+ > {
+ WithContext {
+ block: Some(block),
+ inst,
+ succ: AlwaysNone,
+ operand,
+ param: AlwaysNone,
+ out_of_range_error: self,
+ }
+ }
+ pub fn with_inst_succ_and_param(
+ self,
+ inst: InstIdx,
+ succ: BlockIdx,
+ param: BlockParamIdx,
+ ) -> WithContext<
+ Option<BlockIdx>,
+ InstIdx,
+ BlockIdx,
+ AlwaysNone,
+ BlockParamIdx,
+ SSAValIdxOutOfRange,
+ > {
+ WithContext {
+ block: None,
+ inst,
+ succ,
+ operand: AlwaysNone,
+ param,
+ out_of_range_error: self,
+ }
+ }
+ pub fn with_block_inst_succ_and_param(
+ self,
+ block: BlockIdx,
+ inst: InstIdx,
+ succ: BlockIdx,
+ param: BlockParamIdx,
+ ) -> WithContext<
+ Option<BlockIdx>,
+ InstIdx,
+ BlockIdx,
+ AlwaysNone,
+ BlockParamIdx,
+ SSAValIdxOutOfRange,
+ > {
+ WithContext {
+ block: Some(block),
+ inst,
+ succ,
+ operand: AlwaysNone,
+ param,
+ out_of_range_error: self,
+ }
+ }
+ pub fn with_block_and_param(
+ self,
+ block: BlockIdx,
+ param: BlockParamIdx,
+ ) -> WithContext<BlockIdx, AlwaysNone, AlwaysNone, AlwaysNone, BlockParamIdx, SSAValIdxOutOfRange>
+ {
+ WithContext {
+ block,
+ inst: AlwaysNone,
+ succ: AlwaysNone,
+ operand: AlwaysNone,
+ param,
+ out_of_range_error: self,
+ }
+ }
+}
+
+#[derive(Debug, Error)]
+#[error("instruction index {idx} out of range")]
+pub struct InstIdxOutOfRange {
+ pub idx: InstIdx,
+}
+
+impl InstIdxOutOfRange {
+ pub fn with_block(
+ self,
+ block: BlockIdx,
+ ) -> WithContext<BlockIdx, AlwaysNone, AlwaysNone, AlwaysNone, AlwaysNone, InstIdxOutOfRange>
+ {
+ WithContext {
+ block,
+ inst: AlwaysNone,
+ succ: AlwaysNone,
+ operand: AlwaysNone,
+ param: AlwaysNone,
+ out_of_range_error: self,
+ }
+ }
+}
+
+#[derive(Debug, Error)]
+#[error("block index {idx} out of range")]
+pub struct BlockIdxOutOfRange {
+ pub idx: BlockIdx,
+}
+
+#[derive(Debug, Error)]
+#[error("block parameter index {idx} is out of range")]
+pub struct BlockParamIdxOutOfRange {
+ pub idx: BlockParamIdx,
+}
+
+impl BlockParamIdxOutOfRange {
+ pub fn with_block(
+ self,
+ block: BlockIdx,
+ ) -> WithContext<
+ BlockIdx,
+ AlwaysNone,
+ AlwaysNone,
+ AlwaysNone,
+ AlwaysNone,
+ BlockParamIdxOutOfRange,
+ > {
+ WithContext {
+ block,
+ inst: AlwaysNone,
+ succ: AlwaysNone,
+ operand: AlwaysNone,
+ param: AlwaysNone,
+ out_of_range_error: self,
+ }
+ }
+ pub fn with_block_inst_and_succ(
+ self,
+ block: BlockIdx,
+ inst: InstIdx,
+ succ: BlockIdx,
+ ) -> WithContext<
+ Option<BlockIdx>,
+ InstIdx,
+ BlockIdx,
+ AlwaysNone,
+ AlwaysNone,
+ BlockParamIdxOutOfRange,
+ > {
+ WithContext {
+ block: Some(block),
+ inst,
+ succ,
+ operand: AlwaysNone,
+ param: AlwaysNone,
+ out_of_range_error: self,
+ }
+ }
+ pub fn with_inst_and_succ(
+ self,
+ inst: InstIdx,
+ succ: BlockIdx,
+ ) -> WithContext<
+ Option<BlockIdx>,
+ InstIdx,
+ BlockIdx,
+ AlwaysNone,
+ AlwaysNone,
+ BlockParamIdxOutOfRange,
+ > {
+ WithContext {
+ block: None,
+ inst,
+ succ,
+ operand: AlwaysNone,
+ param: AlwaysNone,
+ out_of_range_error: self,
+ }
+ }
+}
+
+#[derive(Debug, Error)]
+#[error("operand index {idx} is out of range")]
+pub struct OperandIdxOutOfRange {
+ pub idx: OperandIdx,
+}
+
+impl OperandIdxOutOfRange {
+ pub fn with_block_and_inst(
+ self,
+ block: BlockIdx,
+ inst: InstIdx,
+ ) -> WithContext<
+ Option<BlockIdx>,
+ InstIdx,
+ AlwaysNone,
+ AlwaysNone,
+ AlwaysNone,
+ OperandIdxOutOfRange,
+ > {
+ WithContext {
+ block: Some(block),
+ inst,
+ succ: AlwaysNone,
+ operand: AlwaysNone,
+ param: AlwaysNone,
+ out_of_range_error: self,
+ }
+ }
+ pub fn with_inst(
+ self,
+ inst: InstIdx,
+ ) -> WithContext<
+ Option<BlockIdx>,
+ InstIdx,
+ AlwaysNone,
+ AlwaysNone,
+ AlwaysNone,
+ OperandIdxOutOfRange,
+ > {
+ WithContext {
+ block: None,
+ inst,
+ succ: AlwaysNone,
+ operand: AlwaysNone,
+ param: AlwaysNone,
+ out_of_range_error: self,
+ }
+ }
+}
+
+#[derive(Default, Clone, Copy, Debug)]
+pub struct AlwaysNone;
+
+pub trait ToContextValue<T: IndexTy>: fmt::Debug + Copy {
+ fn to_context_value(self) -> Option<T>;
+}
+
+impl<T: IndexTy> ToContextValue<T> for AlwaysNone {
+ fn to_context_value(self) -> Option<T> {
+ None
+ }
+}
+
+impl<T: IndexTy> ToContextValue<T> for T {
+ fn to_context_value(self) -> Option<T> {
+ Some(self)
+ }
+}
+
+impl<T: IndexTy> ToContextValue<T> for Option<T> {
+ fn to_context_value(self) -> Option<T> {
+ self
+ }
+}
+
+#[derive(Debug, Error)]
+pub struct WithContext<Block, Inst, Succ, Operand, BlockParam, E>
+where
+ Block: ToContextValue<BlockIdx>,
+ Inst: ToContextValue<InstIdx>,
+ Succ: ToContextValue<BlockIdx>,
+ Operand: ToContextValue<OperandIdx>,
+ BlockParam: ToContextValue<BlockParamIdx>,
+{
+ pub block: Block,
+ pub inst: Inst,
+ pub succ: Succ,
+ pub operand: Operand,
+ pub param: BlockParam,
+ #[source]
+ pub out_of_range_error: E,
+}
+
+impl<Block, Inst, Succ, Operand, BlockParam, E> fmt::Display
+ for WithContext<Block, Inst, Succ, Operand, BlockParam, E>
+where
+ Block: ToContextValue<BlockIdx>,
+ Inst: ToContextValue<InstIdx>,
+ Succ: ToContextValue<BlockIdx>,
+ Operand: ToContextValue<OperandIdx>,
+ BlockParam: ToContextValue<BlockParamIdx>,
+{
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let Self {
+ block,
+ inst,
+ succ,
+ operand,
+ param,
+ out_of_range_error: _,
+ } = self;
+ let block = block.to_context_value();
+ let inst = inst.to_context_value();
+ let succ = succ.to_context_value();
+ let operand = operand.to_context_value();
+ let param = param.to_context_value();
+ macro_rules! write_if {
+ ($field:ident, $f:ident, $($rest:tt)+) => {
+ if let Some($field) = $field {
+ write!($f, $($rest)+)?;
+ }
+ };
+ }
+ if block.is_some() || inst.is_some() {
+ write!(f, " in ")?;
+ }
+ write_if!(block, f, "{block}");
+ if block.is_some() && inst.is_some() {
+ write!(f, ":")?;
+ }
+ write_if!(inst, f, "{inst}");
+ write_if!(succ, f, " in successor {succ}");
+ write_if!(operand, f, " in {operand}");
+ write_if!(param, f, " in block parameter {param}");
+ Ok(())
+ }
+}
+
#[derive(Debug, Error)]
pub enum Error {
+ #[error(transparent)]
+ SSAValIdxOutOfRangeWithBlockInstAndOperand(
+ #[from]
+ WithContext<
+ Option<BlockIdx>,
+ InstIdx,
+ AlwaysNone,
+ OperandIdx,
+ AlwaysNone,
+ SSAValIdxOutOfRange,
+ >,
+ ),
+ #[error(transparent)]
+ SSAValIdxOutOfRangeWithBlockInstSuccAndParam(
+ #[from]
+ WithContext<
+ Option<BlockIdx>,
+ InstIdx,
+ BlockIdx,
+ AlwaysNone,
+ BlockParamIdx,
+ SSAValIdxOutOfRange,
+ >,
+ ),
+ #[error(transparent)]
+ SSAValIdxOutOfRangeWithBlockAndParam(
+ #[from]
+ WithContext<
+ BlockIdx,
+ AlwaysNone,
+ AlwaysNone,
+ AlwaysNone,
+ BlockParamIdx,
+ SSAValIdxOutOfRange,
+ >,
+ ),
+ #[error(transparent)]
+ InstIdxOutOfRangeWithBlock(
+ #[from]
+ WithContext<BlockIdx, AlwaysNone, AlwaysNone, AlwaysNone, AlwaysNone, InstIdxOutOfRange>,
+ ),
+ #[error(transparent)]
+ InstIdxOutOfRange(#[from] InstIdxOutOfRange),
+ #[error(transparent)]
+ BlockIdxOutOfRange(#[from] BlockIdxOutOfRange),
+ #[error(transparent)]
+ BlockParamIdxOutOfRangeWithBlock(
+ #[from]
+ WithContext<
+ BlockIdx,
+ AlwaysNone,
+ AlwaysNone,
+ AlwaysNone,
+ AlwaysNone,
+ BlockParamIdxOutOfRange,
+ >,
+ ),
+ #[error(transparent)]
+ BlockParamIdxOutOfRangeWithBlockInstAndSucc(
+ #[from]
+ WithContext<
+ Option<BlockIdx>,
+ InstIdx,
+ BlockIdx,
+ AlwaysNone,
+ AlwaysNone,
+ BlockParamIdxOutOfRange,
+ >,
+ ),
+ #[error(transparent)]
+ OperandIdxOutOfRangeWithBlockAndInst(
+ #[from]
+ WithContext<
+ Option<BlockIdx>,
+ InstIdx,
+ AlwaysNone,
+ AlwaysNone,
+ AlwaysNone,
+ OperandIdxOutOfRange,
+ >,
+ ),
#[error("can't create a vector of an only-scalar type: {base_ty:?}")]
TriedToCreateVectorOfOnlyScalarType { base_ty: BaseTy },
#[error("reg_len out of range")]
TermInstOnlyAllowedAtBlockEnd { inst_idx: InstIdx },
#[error("instruction not in a block: {inst}")]
InstHasNoBlock { inst: InstIdx },
- #[error("operand index {operand_idx} out of range for {inst}")]
- OperandIndexOutOfRange { inst: InstIdx, operand_idx: usize },
#[error("duplicate copy destination operand: operand index {operand_idx} for {inst}")]
- DupCopyDestOperand { inst: InstIdx, operand_idx: usize },
- #[error("SSA value index {idx} out of range")]
- SSAValIdxOutOfRange { idx: SSAValIdx },
- #[error("instruction index {idx} out of range")]
- InstIdxOutOfRange { idx: InstIdx },
- #[error("block index {idx} out of range")]
- BlockIdxOutOfRange { idx: BlockIdx },
+ DupCopyDestOperand {
+ inst: InstIdx,
+ operand_idx: OperandIdx,
+ },
#[error("copy instruction's source type doesn't match source operands")]
CopySrcTyMismatch { inst: InstIdx },
#[error("copy instruction's destination type doesn't match destination operands")]
MissingOperandUse {
ssa_val_idx: SSAValIdx,
inst: InstIdx,
- operand_idx: usize,
+ operand_idx: OperandIdx,
},
#[error(
"operand index {operand_idx} for {inst} has kind `Def` but isn't \
OperandDefIsNotSSAValDef {
ssa_val_idx: SSAValIdx,
inst: InstIdx,
- operand_idx: usize,
+ operand_idx: OperandIdx,
},
#[error(
"SSA value {ssa_val_idx}'s definition isn't the corresponding \
SSAValDefIsNotOperandsSSAVal {
ssa_val_idx: SSAValIdx,
inst: InstIdx,
- operand_idx: usize,
+ operand_idx: OperandIdx,
},
#[error(
"SSA value {ssa_val_idx}'s type can't be used with the constraint on \
ConstraintTyMismatch {
ssa_val_idx: SSAValIdx,
inst: InstIdx,
- operand_idx: usize,
+ operand_idx: OperandIdx,
},
#[error(
"fixed location constraint on operand index {operand_idx} for \
{inst} conflicts with clobbers"
)]
- FixedLocConflictsWithClobbers { inst: InstIdx, operand_idx: usize },
+ FixedLocConflictsWithClobbers {
+ inst: InstIdx,
+ operand_idx: OperandIdx,
+ },
#[error("operand kind must be def")]
OperandKindMustBeDef,
#[error(
)]
ReuseTargetOperandMustBeUse {
inst: InstIdx,
- reuse_target_operand_idx: usize,
+ reuse_target_operand_idx: OperandIdx,
},
#[error(
"source block {src_block} missing from branch {branch_inst}'s \
ssa_val_idx: SSAValIdx,
inst: InstIdx,
succ: BlockIdx,
- param_idx: usize,
+ param_idx: BlockParamIdx,
},
#[error(
"the number of parameters ({branch_param_count}) for branch {inst}'s \
BranchSuccParamTyMismatch {
inst: InstIdx,
succ: BlockIdx,
- param_idx: usize,
+ param_idx: BlockParamIdx,
block_param_ty: Ty,
branch_param_ty: Ty,
},
MismatchedBlockParamDef {
ssa_val_idx: SSAValIdx,
block: BlockIdx,
- param_idx: usize,
+ param_idx: BlockParamIdx,
},
#[error(
"predecessor {src_block} of target block {tgt_block} is missing from \
branch_inst: InstIdx,
tgt_block: BlockIdx,
},
- #[error("block parameter index {param_idx} is out of range for block {block}")]
- BlockParamIdxOutOfRange { block: BlockIdx, param_idx: usize },
#[error(
"SSA value {ssa_val_idx}'s use isn't the corresponding \
operand's SSA Value: operand index {operand_idx} for {inst}"
SSAValUseIsNotOperandsSSAVal {
ssa_val_idx: SSAValIdx,
inst: InstIdx,
- operand_idx: usize,
+ operand_idx: OperandIdx,
},
#[error(
"SSA value {ssa_val_idx} is use as a branch instruction {inst}'s \
branch_inst: InstIdx,
tgt_block: BlockIdx,
},
- #[error(
- "branch instruction {branch_inst}'s block parameter index {param_idx} \
- is out of range for target block {tgt_block}"
- )]
- BranchTargetParamIdxOutOfRange {
- branch_inst: InstIdx,
- tgt_block: BlockIdx,
- param_idx: usize,
- },
#[error(
"SSA value {ssa_val_idx}'s use isn't the corresponding \
branch {branch_inst}'s target block parameter's SSA Value for \
ssa_val_idx: SSAValIdx,
branch_inst: InstIdx,
tgt_block: BlockIdx,
- param_idx: usize,
+ param_idx: BlockParamIdx,
},
#[error(
"block {block_idx} has incorrect immediate dominator: expected \
)]
ReuseOperandTyMismatch {
inst: InstIdx,
- tgt_operand_idx: usize,
- src_operand_idx: usize,
+ tgt_operand_idx: OperandIdx,
+ src_operand_idx: OperandIdx,
src_ty: Ty,
tgt_ty: Ty,
},