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:
Joe Savona
2023-04-05 16:26:36 -07:00
parent 592b911e7f
commit b087635e5d
6 changed files with 56 additions and 1 deletions
+10 -1
View File
@@ -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
+4
View File
@@ -667,6 +667,10 @@ export function reversePostorderBlocks(func: HIR): void {
visit(terminal.init);
break;
}
case "label": {
visit(terminal.block);
break;
}
case "unsupported": {
break;
}
+7
View File
@@ -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;
+18
View File
@@ -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": {