(self, op: Branch)
| 240 | return f"{self.reg(value)} {compare} {self.c_error_value(typ)}" |
| 241 | |
| 242 | def visit_branch(self, op: Branch) -> None: |
| 243 | true, false = op.true, op.false |
| 244 | negated = op.negated |
| 245 | negated_rare = False |
| 246 | if true is self.next_block and op.traceback_entry is None: |
| 247 | # Switch true/false since it avoids an else block. |
| 248 | true, false = false, true |
| 249 | negated = not negated |
| 250 | negated_rare = True |
| 251 | |
| 252 | neg = "!" if negated else "" |
| 253 | cond = "" |
| 254 | if op.op == Branch.BOOL: |
| 255 | expr_result = self.reg(op.value) |
| 256 | cond = f"{neg}{expr_result}" |
| 257 | elif op.op == Branch.IS_ERROR: |
| 258 | compare = "!=" if negated else "==" |
| 259 | cond = self.error_value_check(op.value, compare) |
| 260 | else: |
| 261 | assert False, "Invalid branch" |
| 262 | |
| 263 | # For error checks, tell the compiler the branch is unlikely |
| 264 | if op.traceback_entry is not None or op.rare: |
| 265 | if not negated_rare: |
| 266 | cond = f"unlikely({cond})" |
| 267 | else: |
| 268 | cond = f"likely({cond})" |
| 269 | |
| 270 | if false is self.next_block: |
| 271 | if op.traceback_entry is None: |
| 272 | if true is not self.next_block: |
| 273 | self.emit_line(f"if ({cond}) goto {self.label(true)};") |
| 274 | else: |
| 275 | self.emit_line(f"if ({cond}) {{") |
| 276 | self.emit_traceback(op) |
| 277 | self.emit_lines("goto %s;" % self.label(true), "}") |
| 278 | else: |
| 279 | self.emit_line(f"if ({cond}) {{") |
| 280 | self.emit_traceback(op) |
| 281 | |
| 282 | if true is not self.next_block: |
| 283 | self.emit_line("goto %s;" % self.label(true)) |
| 284 | |
| 285 | self.emit_lines("} else", " goto %s;" % self.label(false)) |
| 286 | |
| 287 | def visit_return(self, op: Return) -> None: |
| 288 | value_str = self.reg(op.value) |
nothing calls this directly
no test coverage detected