Format a list of IR basic blocks into a human-readable form.
(
blocks: list[BasicBlock],
names: dict[Value, str],
source_to_error: dict[ErrorSource, list[str]],
)
| 392 | |
| 393 | |
| 394 | def format_blocks( |
| 395 | blocks: list[BasicBlock], |
| 396 | names: dict[Value, str], |
| 397 | source_to_error: dict[ErrorSource, list[str]], |
| 398 | ) -> list[str]: |
| 399 | """Format a list of IR basic blocks into a human-readable form.""" |
| 400 | # First label all of the blocks |
| 401 | for i, block in enumerate(blocks): |
| 402 | block.label = i |
| 403 | |
| 404 | handler_map: dict[BasicBlock, list[BasicBlock]] = {} |
| 405 | for b in blocks: |
| 406 | if b.error_handler: |
| 407 | handler_map.setdefault(b.error_handler, []).append(b) |
| 408 | |
| 409 | visitor = IRPrettyPrintVisitor(names) |
| 410 | |
| 411 | lines = [] |
| 412 | for i, block in enumerate(blocks): |
| 413 | handler_msg = "" |
| 414 | if block in handler_map: |
| 415 | labels = sorted("L%d" % b.label for b in handler_map[block]) |
| 416 | handler_msg = " (handler for {})".format(", ".join(labels)) |
| 417 | |
| 418 | lines.append("L%d:%s" % (block.label, handler_msg)) |
| 419 | if block in source_to_error: |
| 420 | for error in source_to_error[block]: |
| 421 | lines.append(f" ERROR: {error}") |
| 422 | ops = block.ops |
| 423 | if ( |
| 424 | isinstance(ops[-1], Goto) |
| 425 | and i + 1 < len(blocks) |
| 426 | and ops[-1].label == blocks[i + 1] |
| 427 | and not source_to_error.get(ops[-1], []) |
| 428 | ): |
| 429 | # Hide the last goto if it just goes to the next basic block, |
| 430 | # and there are no assocatiated errors with the op. |
| 431 | ops = ops[:-1] |
| 432 | for op in ops: |
| 433 | line = " " + op.accept(visitor) |
| 434 | lines.append(line) |
| 435 | if op in source_to_error: |
| 436 | first = len(lines) - 1 |
| 437 | # Use emojis to highlight the error |
| 438 | for error in source_to_error[op]: |
| 439 | lines.append(f" \U0001f446 ERROR: {error}") |
| 440 | lines[first] = " \U0000274c " + lines[first][4:] |
| 441 | |
| 442 | if not isinstance(block.ops[-1], (Goto, Branch, Return, Unreachable)): |
| 443 | # Each basic block needs to exit somewhere. |
| 444 | lines.append(" [MISSING BLOCK EXIT OPCODE]") |
| 445 | return lines |
| 446 | |
| 447 | |
| 448 | def format_func(fn: FuncIR, errors: Sequence[tuple[ErrorSource, str]] = ()) -> list[str]: |
searching dependent graphs…