main
ts 81 lines 2.62 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 {CompilerError} from '../CompilerError';
9 import {
10 GeneratedSource,
11 HIRFunction,
12 Identifier,
13 IdentifierId,
14 SourceLocation,
15 } from './HIR';
16 import {printPlace} from './PrintHIR';
17 import {
18 eachInstructionLValue,
19 eachInstructionValueOperand,
20 eachTerminalOperand,
21 } from './visitors';
22
23 /*
24 * Validation pass to check that there is a 1:1 mapping between Identifier objects and IdentifierIds,
25 * ie there can only be one Identifier instance per IdentifierId.
26 */
27 export function assertConsistentIdentifiers(fn: HIRFunction): void {
28 const identifiers: Identifiers = new Map();
29 const assignments: Set<IdentifierId> = new Set();
30 for (const [, block] of fn.body.blocks) {
31 for (const phi of block.phis) {
32 validate(identifiers, phi.place.identifier);
33 for (const [, operand] of phi.operands) {
34 validate(identifiers, operand.identifier);
35 }
36 }
37 for (const instr of block.instructions) {
38 CompilerError.invariant(instr.lvalue.identifier.name === null, {
39 reason: `Expected all lvalues to be temporaries`,
40 description: `Found named lvalue \`${instr.lvalue.identifier.name}\``,
41 loc: instr.lvalue.loc,
42 });
43 CompilerError.invariant(!assignments.has(instr.lvalue.identifier.id), {
44 reason: `Expected lvalues to be assigned exactly once`,
45 description: `Found duplicate assignment of '${printPlace(
46 instr.lvalue,
47 )}'`,
48 loc: instr.lvalue.loc,
49 });
50 assignments.add(instr.lvalue.identifier.id);
51 for (const operand of eachInstructionLValue(instr)) {
52 validate(identifiers, operand.identifier, operand.loc);
53 }
54 for (const operand of eachInstructionValueOperand(instr.value)) {
55 validate(identifiers, operand.identifier, operand.loc);
56 }
57 }
58 for (const operand of eachTerminalOperand(block.terminal)) {
59 validate(identifiers, operand.identifier, operand.loc);
60 }
61 }
62 }
63
64 type Identifiers = Map<IdentifierId, Identifier>;
65
66 function validate(
67 identifiers: Identifiers,
68 identifier: Identifier,
69 loc: SourceLocation | null = null,
70 ): void {
71 const previous = identifiers.get(identifier.id);
72 if (previous === undefined) {
73 identifiers.set(identifier.id, identifier);
74 } else {
75 CompilerError.invariant(identifier === previous, {
76 reason: `Duplicate identifier object`,
77 description: `Found duplicate identifier object for id ${identifier.id}`,
78 loc: loc ?? GeneratedSource,
79 });
80 }
81 }