main
ts 63 lines 1.9 KB
Raw
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 {HIRFunction, MutableRange, Place} from './HIR';
9 import {
10 eachInstructionLValue,
11 eachInstructionOperand,
12 eachTerminalOperand,
13 } from './visitors';
14 import {CompilerError} from '..';
15 import {printPlace} from './PrintHIR';
16
17 /*
18 * Checks that all mutable ranges in the function are well-formed, with
19 * start === end === 0 OR end > start.
20 */
21 export function assertValidMutableRanges(fn: HIRFunction): void {
22 for (const [, block] of fn.body.blocks) {
23 for (const phi of block.phis) {
24 visit(phi.place, `phi for block bb${block.id}`);
25 for (const [pred, operand] of phi.operands) {
26 visit(operand, `phi predecessor bb${pred} for block bb${block.id}`);
27 }
28 }
29 for (const instr of block.instructions) {
30 for (const operand of eachInstructionLValue(instr)) {
31 visit(operand, `instruction [${instr.id}]`);
32 }
33 for (const operand of eachInstructionOperand(instr)) {
34 visit(operand, `instruction [${instr.id}]`);
35 }
36 }
37 for (const operand of eachTerminalOperand(block.terminal)) {
38 visit(operand, `terminal [${block.terminal.id}]`);
39 }
40 }
41 }
42
43 function visit(place: Place, description: string): void {
44 validateMutableRange(place, place.identifier.mutableRange, description);
45 if (place.identifier.scope !== null) {
46 validateMutableRange(place, place.identifier.scope.range, description);
47 }
48 }
49
50 function validateMutableRange(
51 place: Place,
52 range: MutableRange,
53 description: string,
54 ): void {
55 CompilerError.invariant(
56 (range.start === 0 && range.end === 0) || range.end > range.start,
57 {
58 reason: `Invalid mutable range: [${range.start}:${range.end}]`,
59 description: `${printPlace(place)} in ${description}`,
60 loc: place.loc,
61 },
62 );
63 }