Ensure unique BlockId for nested functions
This PR ensures that we use a single id space for the `BlockId`s in both top-level functions as well as any nested FunctionExpressions (note, we already do this for `IdentifierId`). This will make it easier for follow-ups to merge the CFG of nested functions (ie useMemo bodies) with the parent without block id collisions.
Joe Savona committed
Apr 5, 2023 at 09:01 UTC
4505218911f019746172b1b39e1d1184619fad58
2 files changed
+14
-18
compiler/forget/src/HIR/Environment.ts
+7
@@ -7,10 +7,12 @@ import {
7
GlobalRegistry,
8
} from "./Globals";
9
import {
10
+ BlockId,
11
BuiltInType,
12
Effect,
13
FunctionType,
14
IdentifierId,
15
+ makeBlockId,
16
makeIdentifierId,
17
ObjectType,
18
PolyType,
@@ -37,6 +39,7 @@ export class Environment {
39
#globals: GlobalRegistry;
40
#shapes: ShapeRegistry;
41
#nextIdentifer: number = 0;
42
+ #nextBlock: number = 0;
43
44
constructor(config: EnvironmentConfig | null) {
45
this.#shapes = DEFAULT_SHAPES;
@@ -62,6 +65,10 @@ export class Environment {
65
return makeIdentifierId(this.#nextIdentifer++);
66
}
67
68
+ get nextBlockId(): BlockId {
69
+ return makeBlockId(this.#nextBlock++);
70
+ }
71
+
72
getGlobalDeclaration(name: string): Global | null {
73
let resolvedGlobal: Global | null = this.#globals.get(name) ?? null;
74
if (resolvedGlobal === null) {
compiler/forget/src/HIR/HIRBuilder.ts
+7
-18
@@ -76,9 +76,8 @@ function newBlock(id: BlockId, kind: BlockKind): WipBlock {
76
*/
77
export default class HIRBuilder {
78
#completed: Map<BlockId, BasicBlock> = new Map();
79
- #nextId: BlockId = makeBlockId(1);
80
- #current: WipBlock = newBlock(makeBlockId(0), "block");
81
- #entry: BlockId = makeBlockId(0);
79
+ #current: WipBlock;
80
+ #entry: BlockId;
81
#scopes: Array<Scope> = [];
82
#context: t.Identifier[];
83
#bindings: Map<string, { node: t.Identifier; identifier: Identifier }> =
@@ -107,18 +106,8 @@ export default class HIRBuilder {
106
this.#env = env;
107
this.parentFunction = parentFunction;
108
this.#context = context;
110
- }
111
-
112
- debug(): string {
113
- return JSON.stringify(
114
- {
115
- completed: this.#completed,
116
- current: this.#current,
117
- nextId: this.#nextId,
118
- },
119
- null,
120
- 2
121
- );
109
+ this.#entry = makeBlockId(env.nextBlockId);
110
+ this.#current = newBlock(this.#entry, "block");
111
}
112
113
currentBlockKind(): BlockKind {
@@ -304,7 +293,7 @@ export default class HIRBuilder {
293
preds: new Set(),
294
phis: new Set(),
295
});
307
- const nextId = makeBlockId(this.#nextId++);
296
+ const nextId = this.#env.nextBlockId;
297
this.#current = newBlock(nextId, nextBlockKind);
298
}
299
@@ -331,7 +320,7 @@ export default class HIRBuilder {
320
* call `complete()` to save it without setting it as the current block.
321
*/
322
reserve(kind: BlockKind): WipBlock {
334
- return newBlock(makeBlockId(this.#nextId++), kind);
323
+ return newBlock(makeBlockId(this.#env.nextBlockId), kind);
324
}
325
326
/**
@@ -357,7 +346,7 @@ export default class HIRBuilder {
346
*/
347
enter(nextBlockKind: BlockKind, fn: (blockId: BlockId) => Terminal): BlockId {
348
const current = this.#current;
360
- const nextId = makeBlockId(this.#nextId++);
349
+ const nextId = this.#env.nextBlockId;
350
this.#current = newBlock(nextId, nextBlockKind);
351
const terminal = fn(nextId);
352
const { id: blockId, kind, instructions } = this.#current;