| 140 | |
| 141 | |
| 142 | class OptimizerEmitter(Emitter): |
| 143 | |
| 144 | def __init__(self, out: CWriter, labels: dict[str, Label], original_uop: Uop, stack: Stack): |
| 145 | super().__init__(out, labels) |
| 146 | self._replacers["REPLACE_OPCODE_IF_EVALUATES_PURE"] = self.replace_opcode_if_evaluates_pure |
| 147 | self.original_uop = original_uop |
| 148 | self.stack = stack |
| 149 | |
| 150 | def emit_save(self, storage: Storage) -> None: |
| 151 | storage.flush(self.out) |
| 152 | |
| 153 | def emit_reload(self, storage: Storage) -> None: |
| 154 | pass |
| 155 | |
| 156 | def goto_label(self, goto: Token, label: Token, storage: Storage) -> None: |
| 157 | self.out.emit(goto) |
| 158 | self.out.emit(label) |
| 159 | |
| 160 | def replace_opcode_if_evaluates_pure( |
| 161 | self, |
| 162 | tkn: Token, |
| 163 | tkn_iter: TokenIterator, |
| 164 | uop: CodeSection, |
| 165 | storage: Storage, |
| 166 | inst: Instruction | None, |
| 167 | ) -> bool: |
| 168 | assert isinstance(uop, Uop) |
| 169 | input_identifiers = [] |
| 170 | for token in tkn_iter: |
| 171 | if token.kind == "IDENTIFIER": |
| 172 | input_identifiers.append(token) |
| 173 | if token.kind == "SEMI": |
| 174 | break |
| 175 | |
| 176 | output_identifier = input_identifiers.pop() |
| 177 | |
| 178 | if len(input_identifiers) == 0: |
| 179 | raise analysis_error( |
| 180 | "To evaluate an operation as pure, it must have at least 1 input", |
| 181 | tkn |
| 182 | ) |
| 183 | # Check that the input identifiers belong to the uop's |
| 184 | # input stack effect |
| 185 | uop_stack_effect_input_identifers = {inp.name for inp in uop.stack.inputs} |
| 186 | for input_tkn in input_identifiers: |
| 187 | if input_tkn.text not in uop_stack_effect_input_identifers: |
| 188 | raise analysis_error(f"{input_tkn.text} referenced in " |
| 189 | f"REPLACE_OPCODE_IF_EVALUATES_PURE but does not " |
| 190 | f"exist in the base uop's input stack effects", |
| 191 | input_tkn) |
| 192 | input_identifiers_as_str = {tkn.text for tkn in input_identifiers} |
| 193 | used_stack_inputs = [inp for inp in uop.stack.inputs if inp.name in input_identifiers_as_str] |
| 194 | assert len(used_stack_inputs) > 0 |
| 195 | self.out.start_line() |
| 196 | emitter = OptimizerConstantEmitter(self.out, {}, self.original_uop, self.stack.copy()) |
| 197 | emitter.emit("if (\n") |
| 198 | for inp in used_stack_inputs[:-1]: |
| 199 | emitter.emit(f"sym_is_safe_const(ctx, {inp.name}) &&\n") |
no outgoing calls
no test coverage detected
searching dependent graphs…