(fn: FuncIR)
| 140 | |
| 141 | |
| 142 | def check_op_sources_valid(fn: FuncIR) -> list[FnError]: |
| 143 | errors = [] |
| 144 | valid_ops: set[Op] = set() |
| 145 | valid_registers: set[Register] = set() |
| 146 | |
| 147 | for block in fn.blocks: |
| 148 | valid_ops.update(block.ops) |
| 149 | |
| 150 | for op in block.ops: |
| 151 | if isinstance(op, BaseAssign): |
| 152 | valid_registers.add(op.dest) |
| 153 | elif isinstance(op, LoadAddress) and isinstance(op.src, Register): |
| 154 | valid_registers.add(op.src) |
| 155 | |
| 156 | valid_registers.update(fn.arg_regs) |
| 157 | |
| 158 | for block in fn.blocks: |
| 159 | for op in block.ops: |
| 160 | for source in op.sources(): |
| 161 | if isinstance(source, (Integer, Float, Undef)): |
| 162 | pass |
| 163 | elif isinstance(source, Op): |
| 164 | if source not in valid_ops: |
| 165 | errors.append( |
| 166 | FnError( |
| 167 | source=op, |
| 168 | desc=f"Invalid op reference to op of type {type(source).__name__}", |
| 169 | ) |
| 170 | ) |
| 171 | elif isinstance(source, Register): |
| 172 | if source not in valid_registers: |
| 173 | errors.append( |
| 174 | FnError( |
| 175 | source=op, desc=f"Invalid op reference to register {source.name!r}" |
| 176 | ) |
| 177 | ) |
| 178 | |
| 179 | return errors |
| 180 | |
| 181 | |
| 182 | disjoint_types = { |
no test coverage detected
searching dependent graphs…