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:
Joe Savona
2022-11-30 10:24:51 -08:00
parent aa2b152ea8
commit 509aa9f0e5
5 changed files with 38 additions and 18 deletions
+18 -5
View File
@@ -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
+8 -8
View File
@@ -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 {
+7 -2
View File
@@ -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 {