mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
HIRVisitor - change labels to block ids
HIRTreeVisitor previously passed a string label (for certain blocks). This changes to pass the raw BlockId, and have codegen convert that to a string. I'm not sure if we'll need this but it would be helpful for eg visiting the IR and emitting a new IR, while mapping block ids forward. Even if we don't need that it makes sense for Codegen to decide how to convert a block id into a label (which has to obey the rules of an identifier, not the visitor's concern).
This commit is contained in:
@@ -9,6 +9,7 @@ import * as t from "@babel/types";
|
||||
import { assertExhaustive } from "../Common/utils";
|
||||
import { invariant } from "../CompilerError";
|
||||
import {
|
||||
BlockId,
|
||||
GeneratedSource,
|
||||
HIRFunction,
|
||||
Identifier,
|
||||
@@ -168,14 +169,16 @@ class CodegenVisitor
|
||||
switch (terminal.kind) {
|
||||
case "break": {
|
||||
if (terminal.label) {
|
||||
return t.breakStatement(t.identifier(terminal.label));
|
||||
return t.breakStatement(t.identifier(codegenLabel(terminal.label)));
|
||||
} else {
|
||||
return t.breakStatement();
|
||||
}
|
||||
}
|
||||
case "continue": {
|
||||
if (terminal.label) {
|
||||
return t.continueStatement(t.identifier(terminal.label));
|
||||
return t.continueStatement(
|
||||
t.identifier(codegenLabel(terminal.label))
|
||||
);
|
||||
} else {
|
||||
return t.continueStatement();
|
||||
}
|
||||
@@ -223,13 +226,19 @@ class CodegenVisitor
|
||||
appendBlock(
|
||||
block: t.Statement[],
|
||||
item: t.Statement,
|
||||
label?: string | undefined
|
||||
blockId?: BlockId | undefined
|
||||
): void {
|
||||
if (item.type === "EmptyStatement") {
|
||||
return;
|
||||
}
|
||||
if (label !== undefined) {
|
||||
block.push(createLabelledStatement(item.loc, t.identifier(label), item));
|
||||
if (blockId !== undefined) {
|
||||
block.push(
|
||||
createLabelledStatement(
|
||||
item.loc,
|
||||
t.identifier(codegenLabel(blockId)),
|
||||
item
|
||||
)
|
||||
);
|
||||
} else {
|
||||
block.push(item);
|
||||
}
|
||||
@@ -240,6 +249,10 @@ class CodegenVisitor
|
||||
}
|
||||
}
|
||||
|
||||
function codegenLabel(id: BlockId): string {
|
||||
return `bb${id}`;
|
||||
}
|
||||
|
||||
function codegenInstructionValue(
|
||||
temp: Temporaries,
|
||||
instrValue: InstructionValue
|
||||
|
||||
@@ -138,7 +138,7 @@ class Driver<TBlock, TValue, TItem, TCase> {
|
||||
consequent: consequent ?? this.emptyBlock(),
|
||||
alternate: alternate,
|
||||
}),
|
||||
`bb${fallthroughId}` //
|
||||
fallthroughId
|
||||
);
|
||||
this.visitBlock(this.cx.ir.blocks.get(fallthroughId)!, blockValue);
|
||||
} else {
|
||||
@@ -217,7 +217,7 @@ class Driver<TBlock, TValue, TItem, TCase> {
|
||||
test,
|
||||
cases,
|
||||
}),
|
||||
`bb${fallthroughId}`
|
||||
fallthroughId
|
||||
);
|
||||
this.visitBlock(this.cx.ir.blocks.get(fallthroughId)!, blockValue);
|
||||
} else {
|
||||
@@ -290,7 +290,7 @@ class Driver<TBlock, TValue, TItem, TCase> {
|
||||
test: testValue,
|
||||
loop: loopBody,
|
||||
}),
|
||||
`bb${fallthroughId}`
|
||||
fallthroughId
|
||||
);
|
||||
this.visitBlock(this.cx.ir.blocks.get(fallthroughId)!, blockValue);
|
||||
} else {
|
||||
@@ -359,7 +359,7 @@ class Driver<TBlock, TValue, TItem, TCase> {
|
||||
case "labeled": {
|
||||
return this.visitor.visitTerminal({
|
||||
kind: "break",
|
||||
label: `bb${target.block}`,
|
||||
label: target.block,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -375,7 +375,7 @@ class Driver<TBlock, TValue, TItem, TCase> {
|
||||
case "labeled": {
|
||||
return this.visitor.visitTerminal({
|
||||
kind: "continue",
|
||||
label: `bb${target.block}`,
|
||||
label: target.block,
|
||||
});
|
||||
}
|
||||
case "unlabeled": {
|
||||
@@ -687,7 +687,7 @@ export interface Visitor<TBlock, TValue, TItem, TCase> {
|
||||
* Appends an item onto the given block, with an optional label. The label
|
||||
* indicates that a break/continue will proceed to code *after* the given item.
|
||||
*/
|
||||
appendBlock(block: TBlock, item: TItem, label?: string): void;
|
||||
appendBlock(block: TBlock, item: TItem, label?: BlockId): void;
|
||||
|
||||
/**
|
||||
* Converts the visitor's block representation into the representation of a
|
||||
@@ -713,5 +713,5 @@ export type BlockTerminal<TBlock, TValue, TItem, TCase> =
|
||||
test: TValue;
|
||||
loop: TItem;
|
||||
}
|
||||
| { kind: "break"; label: string | null }
|
||||
| { kind: "continue"; label: string | null };
|
||||
| { kind: "break"; label: BlockId | null }
|
||||
| { kind: "continue"; label: BlockId | null };
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
import { assertExhaustive, retainWhere } from "../Common/utils";
|
||||
import {
|
||||
BlockId,
|
||||
HIRFunction,
|
||||
Identifier,
|
||||
Instruction,
|
||||
@@ -190,6 +191,6 @@ class ScopeDependenciesVisitor
|
||||
enterBlock(): void {}
|
||||
visitImplicitTerminal(): void | null {}
|
||||
visitCase(test: InstructionValue, block: void): void {}
|
||||
appendBlock(block: void, item: void, label?: string | undefined): void {}
|
||||
appendBlock(block: void, item: void, label?: BlockId | undefined): void {}
|
||||
leaveBlock(block: void): void {}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import invariant from "invariant";
|
||||
import { retainWhere } from "../Common/utils";
|
||||
import DisjointSet from "./DisjointSet";
|
||||
import {
|
||||
BlockId,
|
||||
HIRFunction,
|
||||
Instruction,
|
||||
InstructionId,
|
||||
@@ -282,7 +283,7 @@ class MergeOverlappingReactiveScopesVisitor
|
||||
visitImplicitTerminal(): void | null {}
|
||||
visitTerminal(terminal: BlockTerminal<void, void, void, void>): void {}
|
||||
visitCase(test: void | null, block: void): void {}
|
||||
appendBlock(block: void, item: void, label?: string | undefined): void {}
|
||||
appendBlock(block: void, item: void, label?: BlockId | undefined): void {}
|
||||
leaveBlock(block: void): void {
|
||||
this.scopes.pop();
|
||||
if (this.scopes.length === 0) {
|
||||
@@ -381,7 +382,7 @@ class AlignReactiveScopesToBlockScopeRangeVisitor
|
||||
// no-ops
|
||||
visitValue(value: InstructionValue): void {}
|
||||
visitCase(test: void | null, block: void): void {}
|
||||
appendBlock(block: void, item: void, label?: string | undefined): void {}
|
||||
appendBlock(block: void, item: void, label?: BlockId | undefined): void {}
|
||||
}
|
||||
|
||||
function getInstructionScope(instr: Instruction): ReactiveScope | null {
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
*/
|
||||
|
||||
import { assertExhaustive } from "../Common/utils";
|
||||
import { BlockId } from "../ControlFlowGraph";
|
||||
import {
|
||||
HIRFunction,
|
||||
Instruction,
|
||||
@@ -116,13 +117,17 @@ class PrintVisitor implements Visitor<Array<string>, string, string, string> {
|
||||
return `${prefix}case ${test}: ${block.trimStart()}`;
|
||||
}
|
||||
}
|
||||
appendBlock(block: string[], item: string, label?: string | undefined): void {
|
||||
appendBlock(
|
||||
block: string[],
|
||||
item: string,
|
||||
label?: BlockId | undefined
|
||||
): void {
|
||||
const prefix = " ".repeat(this.depth);
|
||||
if (item !== "") {
|
||||
block.push(`${prefix}${item.trimStart()}`);
|
||||
}
|
||||
if (label !== undefined) {
|
||||
block.push(`${prefix}${label}:`);
|
||||
block.push(`${prefix}bb${label}:`);
|
||||
}
|
||||
}
|
||||
leaveBlock(block: string[]): string {
|
||||
|
||||
Reference in New Issue
Block a user