| """Transform IR to lower-level ops. |
| |
| Higher-level ops are used in earlier compiler passes, as they make |
| various analyses, optimizations and transforms easier to implement. |
| Later passes use lower-level ops, as they are easier to generate code |
| from, and they help with lower-level optimizations. |
| |
| Lowering of various primitive ops is implemented in the mypyc.lower |
| package. |
| """ |
| |
| from __future__ import annotations |
| |
| from mypyc.ir.func_ir import FuncIR |
| from mypyc.ir.ops import PrimitiveOp, Value |
| from mypyc.irbuild.ll_builder import LowLevelIRBuilder |
| from mypyc.lower.registry import lowering_registry |
| from mypyc.options import CompilerOptions |
| from mypyc.transform.ir_transform import IRTransform |
| |
| |
| def lower_ir(ir: FuncIR, options: CompilerOptions) -> None: |
| builder = LowLevelIRBuilder(None, options) |
| visitor = LoweringVisitor(builder) |
| visitor.transform_blocks(ir.blocks) |
| ir.blocks = builder.blocks |
| |
| |
| class LoweringVisitor(IRTransform): |
| def visit_primitive_op(self, op: PrimitiveOp) -> Value | None: |
| # The lowering implementation functions of various primitive ops are stored |
| # in a registry, which is populated using function decorators. The name |
| # of op (such as "int_eq") is used as the key. |
| lower_fn = lowering_registry[op.desc.name] |
| return lower_fn(self.builder, op.args, op.line) |