From 509aa9f0e504ead3133a5f7c75e2be5becbb69ab Mon Sep 17 00:00:00 2001 From: Joe Savona Date: Wed, 30 Nov 2022 10:24:51 -0800 Subject: [PATCH] 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). --- compiler/forget/src/HIR/Codegen.ts | 23 +++++++++++++++---- compiler/forget/src/HIR/HIRTreeVisitor.ts | 16 ++++++------- .../src/HIR/InferReactiveScopeDependencies.ts | 3 ++- .../forget/src/HIR/InferReactiveScopes.ts | 5 ++-- compiler/forget/src/HIR/PrintHIRTree.ts | 9 ++++++-- 5 files changed, 38 insertions(+), 18 deletions(-) diff --git a/compiler/forget/src/HIR/Codegen.ts b/compiler/forget/src/HIR/Codegen.ts index e73d04bd15..24ed547639 100644 --- a/compiler/forget/src/HIR/Codegen.ts +++ b/compiler/forget/src/HIR/Codegen.ts @@ -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 diff --git a/compiler/forget/src/HIR/HIRTreeVisitor.ts b/compiler/forget/src/HIR/HIRTreeVisitor.ts index f1541f8030..a6f3bd0c9e 100644 --- a/compiler/forget/src/HIR/HIRTreeVisitor.ts +++ b/compiler/forget/src/HIR/HIRTreeVisitor.ts @@ -138,7 +138,7 @@ class Driver { 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 { test, cases, }), - `bb${fallthroughId}` + fallthroughId ); this.visitBlock(this.cx.ir.blocks.get(fallthroughId)!, blockValue); } else { @@ -290,7 +290,7 @@ class Driver { test: testValue, loop: loopBody, }), - `bb${fallthroughId}` + fallthroughId ); this.visitBlock(this.cx.ir.blocks.get(fallthroughId)!, blockValue); } else { @@ -359,7 +359,7 @@ class Driver { case "labeled": { return this.visitor.visitTerminal({ kind: "break", - label: `bb${target.block}`, + label: target.block, }); } } @@ -375,7 +375,7 @@ class Driver { case "labeled": { return this.visitor.visitTerminal({ kind: "continue", - label: `bb${target.block}`, + label: target.block, }); } case "unlabeled": { @@ -687,7 +687,7 @@ export interface Visitor { * 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 = test: TValue; loop: TItem; } - | { kind: "break"; label: string | null } - | { kind: "continue"; label: string | null }; + | { kind: "break"; label: BlockId | null } + | { kind: "continue"; label: BlockId | null }; diff --git a/compiler/forget/src/HIR/InferReactiveScopeDependencies.ts b/compiler/forget/src/HIR/InferReactiveScopeDependencies.ts index 70607801fa..7aee03ebbf 100644 --- a/compiler/forget/src/HIR/InferReactiveScopeDependencies.ts +++ b/compiler/forget/src/HIR/InferReactiveScopeDependencies.ts @@ -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 {} } diff --git a/compiler/forget/src/HIR/InferReactiveScopes.ts b/compiler/forget/src/HIR/InferReactiveScopes.ts index 73821b5f06..362f846ec9 100644 --- a/compiler/forget/src/HIR/InferReactiveScopes.ts +++ b/compiler/forget/src/HIR/InferReactiveScopes.ts @@ -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 {} 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 { diff --git a/compiler/forget/src/HIR/PrintHIRTree.ts b/compiler/forget/src/HIR/PrintHIRTree.ts index e220e1b29d..cc5bcbde1a 100644 --- a/compiler/forget/src/HIR/PrintHIRTree.ts +++ b/compiler/forget/src/HIR/PrintHIRTree.ts @@ -6,6 +6,7 @@ */ import { assertExhaustive } from "../Common/utils"; +import { BlockId } from "../ControlFlowGraph"; import { HIRFunction, Instruction, @@ -116,13 +117,17 @@ class PrintVisitor implements Visitor, 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 {