@samitouri / QOS-React-2 / commits / d660f37bf2

Validator pass that terminal successors all exist

Joe Savona committed Apr 4, 2023 at 13:29 UTC d660f37bf22dec1ffcad309bf3c8aa9e2b0d8eef
6 files changed +62 -1
compiler/forget/src/CompilerPipeline.ts
+3 -1
@@ -11,9 +11,10 @@ import {
11 lower,
12 mergeConsecutiveBlocks,
13 ReactiveFunction,
14 + validateConsistentIdentifiers,
15 + validateTerminalSuccessors,
16 } from "./HIR";
17 import { Environment, EnvironmentConfig } from "./HIR/Environment";
16 -import { validateConsistentIdentifiers } from "./HIR/ValidateConsistentIdentifiers";
18 import {
19 analyseFunctions,
20 dropMemoCalls,
@@ -61,6 +62,7 @@ export function* run(
62 yield log({ kind: "hir", name: "MergeConsecutiveBlocks", value: hir });
63
64 validateConsistentIdentifiers(hir);
65 + validateTerminalSuccessors(hir);
66
67 enterSSA(hir);
68 yield log({ kind: "hir", name: "SSA", value: hir });
compiler/forget/src/HIR/ValidateTerminalSuccessors.ts new
+27
@@ -0,0 +1,27 @@
1 +/**
2 + * Copyright (c) Facebook, Inc. and its 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 { mapTerminalSuccessors } from "./visitors";
12 +
13 +export function validateTerminalSuccessors(fn: HIRFunction): void {
14 + for (const [, block] of fn.body.blocks) {
15 + mapTerminalSuccessors(block.terminal, (successor) => {
16 + if (!fn.body.blocks.has(successor)) {
17 + CompilerError.invariant(
18 + `Block bb${successor} does not exist for terminal '${printTerminal(
19 + block.terminal
20 + )}'`,
21 + (block.terminal as any).loc ?? GeneratedSource
22 + );
23 + }
24 + return successor;
25 + });
26 + }
27 +}
compiler/forget/src/HIR/index.ts
+2
@@ -17,3 +17,5 @@ export {
17 } from "./HIRBuilder";
18 export { mergeConsecutiveBlocks } from "./MergeConsecutiveBlocks";
19 export { printFunction, printHIR } from "./PrintHIR";
20 +export { validateConsistentIdentifiers } from "./ValidateConsistentIdentifiers";
21 +export { validateTerminalSuccessors } from "./ValidateTerminalSuccessors";
compiler/forget/src/Optimization/ConstantPropagation.ts
+5
@@ -21,6 +21,8 @@ import {
21 removeUnreachableFallthroughs,
22 reversePostorderBlocks,
23 shrink,
24 + validateConsistentIdentifiers,
25 + validateTerminalSuccessors,
26 } from "../HIR";
27 import { removeDeadDoWhileStatements } from "../HIR/HIRBuilder";
28 import { eliminateRedundantPhi } from "../SSA";
@@ -70,6 +72,9 @@ export function constantPropagation(fn: HIRFunction): void {
72 // Finally, merge together any blocks that are now guaranteed to execute
73 // consecutively
74 mergeConsecutiveBlocks(fn);
75 +
76 + validateConsistentIdentifiers(fn);
77 + validateTerminalSuccessors(fn);
78 }
79 }
80
compiler/forget/src/__tests__/fixtures/compiler/error.for-return.expect.md new
+20
@@ -0,0 +1,20 @@
1 +
2 +## Input
3 +
4 +```javascript
5 +function Component(props) {
6 + for (let i = 0; i < props.count; i++) {
7 + return;
8 + }
9 +}
10 +
11 +```
12 +
13 +
14 +## Error
15 +
16 +```
17 +[ReactForget] Invariant: Block bb4 does not exist for terminal '[1] For init=bb3 test=bb1 loop=bb5 update=bb4 fallthrough=bb2' (2:4)
18 +```
19 +
20 +
\ No newline at end of file
compiler/forget/src/__tests__/fixtures/compiler/error.for-return.js new
+5
@@ -0,0 +1,5 @@
1 +function Component(props) {
2 + for (let i = 0; i < props.count; i++) {
3 + return;
4 + }
5 +}