| 1 | /** |
| 2 | * Copyright (c) Meta Platforms, Inc. and affiliates. |
| 3 | * |
| 4 | * This source code is licensed under the MIT license found in the |
| 5 | * LICENSE file in the root directory of this source tree. |
| 6 | */ |
| 7 | |
| 8 | import {CompilerError} from '../CompilerError'; |
| 9 | import {GeneratedSource, HIRFunction} from './HIR'; |
| 10 | import {printTerminal} from './PrintHIR'; |
| 11 | import {eachTerminalSuccessor, mapTerminalSuccessors} from './visitors'; |
| 12 | |
| 13 | export function assertTerminalSuccessorsExist(fn: HIRFunction): void { |
| 14 | for (const [, block] of fn.body.blocks) { |
| 15 | mapTerminalSuccessors(block.terminal, successor => { |
| 16 | CompilerError.invariant(fn.body.blocks.has(successor), { |
| 17 | reason: `Terminal successor references unknown block`, |
| 18 | description: `Block bb${successor} does not exist for terminal '${printTerminal( |
| 19 | block.terminal, |
| 20 | )}'`, |
| 21 | loc: (block.terminal as any).loc ?? GeneratedSource, |
| 22 | }); |
| 23 | return successor; |
| 24 | }); |
| 25 | } |
| 26 | } |
| 27 | |
| 28 | export function assertTerminalPredsExist(fn: HIRFunction): void { |
| 29 | for (const [, block] of fn.body.blocks) { |
| 30 | for (const pred of block.preds) { |
| 31 | const predBlock = fn.body.blocks.get(pred); |
| 32 | CompilerError.invariant(predBlock != null, { |
| 33 | reason: 'Expected predecessor block to exist', |
| 34 | description: `Block ${block.id} references non-existent ${pred}`, |
| 35 | loc: GeneratedSource, |
| 36 | }); |
| 37 | CompilerError.invariant( |
| 38 | [...eachTerminalSuccessor(predBlock.terminal)].includes(block.id), |
| 39 | { |
| 40 | reason: 'Terminal successor does not reference correct predecessor', |
| 41 | description: `Block bb${block.id} has bb${predBlock.id} as a predecessor, but bb${predBlock.id}'s successors do not include bb${block.id}`, |
| 42 | loc: GeneratedSource, |
| 43 | }, |
| 44 | ); |
| 45 | } |
| 46 | } |
| 47 | } |