Skip to main content

laddu_kernel/ir/
instruction.rs

1use super::*;
2
3impl KernelInstruction {
4    /// Returns the stable instruction name used in diagnostics and support reporting.
5    pub fn diagnostic_name(&self) -> &'static str {
6        match self {
7            Self::Cached(_) => "Cached",
8            Self::RealConstant(_) => "RealConstant",
9            Self::ComplexConstant(_) => "ComplexConstant",
10            Self::Parameter(_) => "Parameter",
11            Self::Unary { .. } => "Unary",
12            Self::Binary { .. } => "Binary",
13            Self::Add(_) => "Add",
14            Self::Mul(_) => "Mul",
15            Self::Complex { .. } => "Complex",
16            Self::Vector(_) => "Vector",
17            Self::Matrix { .. } => "Matrix",
18            Self::Component { .. } => "Component",
19            Self::MatrixElement { .. } => "MatrixElement",
20            Self::MatMul { .. } => "MatMul",
21            Self::MatVec { .. } => "MatVec",
22            Self::Dot { .. } => "Dot",
23            Self::Solve { .. } => "Solve",
24            Self::SolveRow { .. } => "SolveRow",
25            Self::SolveRowAdjointElement { .. } => "SolveRowAdjointElement",
26        }
27    }
28
29    /// Returns the backend-independent event-dependence rule for this instruction.
30    pub fn event_dependence(&self) -> KernelEventDependence {
31        match self {
32            Self::Cached(_) | Self::SolveRow { .. } | Self::SolveRowAdjointElement { .. } => {
33                KernelEventDependence::Event
34            }
35            Self::RealConstant(_) | Self::ComplexConstant(_) | Self::Parameter(_) => {
36                KernelEventDependence::Invariant
37            }
38            _ => KernelEventDependence::Operands,
39        }
40    }
41
42    /// Returns the direct input value identifiers.
43    pub fn operands(&self) -> Vec<KernelValueId> {
44        let mut operands = Vec::new();
45        self.visit_operands(|operand| operands.push(operand));
46        operands
47    }
48
49    pub(super) fn visit_operands(&self, mut visit: impl FnMut(KernelValueId)) {
50        match self {
51            Self::Cached(_)
52            | Self::RealConstant(_)
53            | Self::ComplexConstant(_)
54            | Self::Parameter(_) => {}
55            Self::Unary { input, .. }
56            | Self::Component { input, .. }
57            | Self::MatrixElement { input, .. }
58            | Self::SolveRowAdjointElement { adjoint: input, .. } => visit(*input),
59            Self::Binary { lhs, rhs, .. } | Self::MatMul { lhs, rhs } | Self::Dot { lhs, rhs } => {
60                visit(*lhs);
61                visit(*rhs);
62            }
63            Self::MatVec { matrix, vector }
64            | Self::Solve {
65                matrix,
66                rhs: vector,
67            } => {
68                visit(*matrix);
69                visit(*vector);
70            }
71            Self::Add(values)
72            | Self::Mul(values)
73            | Self::Vector(values)
74            | Self::SolveRow { rhs: values, .. } => values.iter().copied().for_each(visit),
75            Self::Complex { re, im } => {
76                visit(*re);
77                visit(*im);
78            }
79            Self::Matrix { elements, .. } => elements.iter().copied().for_each(visit),
80        }
81    }
82
83    pub(super) fn validate_operand_order(&self, value: usize) -> Result<(), KernelIrError> {
84        let mut invalid_operand = None;
85        self.visit_operands(|operand| {
86            if invalid_operand.is_none() && operand.index() >= value {
87                invalid_operand = Some(operand.index());
88            }
89        });
90        invalid_operand.map_or(Ok(()), |operand| {
91            Err(KernelIrError::InvalidOperand { value, operand })
92        })
93    }
94}