mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
LabelTerminal scaffolding
Adds a new `LabelTerminal` which will be used to represent LabeledStatements that contain a statement other than a loop. What we do for these cases is basically break the containing block in two, with a goto after the inner statement to the fallthrough. This allows us to model the label, and any `break` to it, in the HIR. However this fails in codegen because we can't find the fallthrough branch — we need a high level terminal that knows about this structure. Hence LabelTerminal. Now, instead of just a continuation block and a goto, we have a structured terminal. The LabelTerminal expresses the block for the labeled statement and the continuation, and we can use this to put it back together when constructing a ReactiveFunction. Note that this PR is just the scaffolding for LabelTerminal, the next PR is the interesting bits.
This commit is contained in:
@@ -269,7 +269,8 @@ export type Terminal =
|
||||
| WhileTerminal
|
||||
| LogicalTerminal
|
||||
| TernaryTerminal
|
||||
| OptionalCallTerminal;
|
||||
| OptionalCallTerminal
|
||||
| LabelTerminal;
|
||||
|
||||
/**
|
||||
* Terminal nodes allowed for a value block
|
||||
@@ -379,6 +380,14 @@ export type TernaryTerminal = {
|
||||
loc: SourceLocation;
|
||||
};
|
||||
|
||||
export type LabelTerminal = {
|
||||
kind: "label";
|
||||
block: BlockId;
|
||||
fallthrough: BlockId | null;
|
||||
id: InstructionId;
|
||||
loc: SourceLocation;
|
||||
};
|
||||
|
||||
export type OptionalCallTerminal = {
|
||||
kind: "optional-call";
|
||||
// Whether the call itself is optional. If false, this means that the callee itself
|
||||
|
||||
@@ -667,6 +667,10 @@ export function reversePostorderBlocks(func: HIR): void {
|
||||
visit(terminal.init);
|
||||
break;
|
||||
}
|
||||
case "label": {
|
||||
visit(terminal.block);
|
||||
break;
|
||||
}
|
||||
case "unsupported": {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -79,6 +79,7 @@ export function printMixedHIR(
|
||||
return printInstruction(value);
|
||||
}
|
||||
switch (value.kind) {
|
||||
case "label":
|
||||
case "optional-call":
|
||||
case "branch":
|
||||
case "if":
|
||||
@@ -213,6 +214,12 @@ export function printTerminal(terminal: Terminal): Array<string> | string {
|
||||
value = `[${terminal.id}] ForOf init=bb${terminal.init} loop=bb${terminal.loop} fallthrough=bb${terminal.fallthrough}`;
|
||||
break;
|
||||
}
|
||||
case "label": {
|
||||
value = `[${terminal.id}] Label block=bb${terminal.block} fallthrough=${
|
||||
terminal.fallthrough ? `bb${terminal.fallthrough}` : ""
|
||||
}`;
|
||||
break;
|
||||
}
|
||||
case "unsupported": {
|
||||
value = `Unsupported`;
|
||||
break;
|
||||
|
||||
@@ -659,6 +659,18 @@ export function mapTerminalSuccessors(
|
||||
id: makeInstructionId(0),
|
||||
};
|
||||
}
|
||||
case "label": {
|
||||
const block = fn(terminal.block);
|
||||
const fallthrough =
|
||||
terminal.fallthrough !== null ? fn(terminal.fallthrough) : null;
|
||||
return {
|
||||
kind: "label",
|
||||
block,
|
||||
fallthrough,
|
||||
id: makeInstructionId(0),
|
||||
loc: terminal.loc,
|
||||
};
|
||||
}
|
||||
case "unsupported": {
|
||||
return terminal;
|
||||
}
|
||||
@@ -726,6 +738,10 @@ export function* eachTerminalSuccessor(terminal: Terminal): Iterable<BlockId> {
|
||||
yield terminal.init;
|
||||
break;
|
||||
}
|
||||
case "label": {
|
||||
yield terminal.block;
|
||||
break;
|
||||
}
|
||||
case "unsupported":
|
||||
break;
|
||||
default: {
|
||||
@@ -767,6 +783,7 @@ export function mapTerminalOperands(
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "label":
|
||||
case "optional-call":
|
||||
case "ternary":
|
||||
case "logical":
|
||||
@@ -815,6 +832,7 @@ export function* eachTerminalOperand(terminal: Terminal): Iterable<Place> {
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "label":
|
||||
case "optional-call":
|
||||
case "ternary":
|
||||
case "logical":
|
||||
|
||||
@@ -29,6 +29,7 @@ import {
|
||||
ReactiveValue,
|
||||
Terminal,
|
||||
} from "../HIR/HIR";
|
||||
import todo from "../Utils/todo";
|
||||
import { assertExhaustive } from "../Utils/utils";
|
||||
|
||||
/**
|
||||
@@ -529,6 +530,9 @@ class Driver {
|
||||
|
||||
break;
|
||||
}
|
||||
case "label": {
|
||||
todo("Support label terminals");
|
||||
}
|
||||
case "optional-call":
|
||||
case "ternary":
|
||||
case "logical": {
|
||||
|
||||
@@ -131,6 +131,10 @@ function printTerminalLabel(terminal: Terminal): string {
|
||||
case "for-of":
|
||||
buffer.push("ForOf");
|
||||
break;
|
||||
case "label": {
|
||||
buffer.push("Label");
|
||||
break;
|
||||
}
|
||||
case "unsupported": {
|
||||
break;
|
||||
}
|
||||
@@ -224,6 +228,15 @@ function printTerminalArrows(blockId: BlockId, terminal: Terminal): string {
|
||||
buffer.push(printJumpArrow(blockId, terminal.loop, "loop"));
|
||||
break;
|
||||
}
|
||||
case "label": {
|
||||
buffer.push(printJumpArrow(blockId, terminal.block, "block"));
|
||||
if (terminal.fallthrough != null) {
|
||||
buffer.push(
|
||||
printJumpArrow(blockId, terminal.fallthrough, "fallthrough")
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "throw":
|
||||
case "return":
|
||||
case "unsupported": {
|
||||
|
||||
Reference in New Issue
Block a user