[SSA] Fix identifierID hack

Rather than starting from 1000, start from the last used identifier id.
This commit is contained in:
Sathya Gunasekaran
2022-10-18 18:57:34 +01:00
parent 379251c65f
commit b9ce8bdcfd
16 changed files with 184 additions and 156 deletions
+6 -3
View File
@@ -20,7 +20,7 @@ import {
Terminal,
ThrowTerminal,
} from "./HIR";
import HIRBuilder from "./HIRBuilder";
import HIRBuilder, { Environment } from "./HIRBuilder";
import todo, { todoInvariant } from "./todo";
// *******************************************************************************************
@@ -46,8 +46,11 @@ const GLOBALS: Map<string, t.Identifier> = new Map([
* TODO: consider modeling control-flow at expression level for even more fine-
* grained reactivity.
*/
export function lower(func: NodePath<t.Function>): HIRFunction {
const builder = new HIRBuilder();
export function lower(
func: NodePath<t.Function>,
env: Environment
): HIRFunction {
const builder = new HIRBuilder(env);
const id =
func.isFunctionDeclaration() && func.node.id != null
-8
View File
@@ -292,11 +292,3 @@ export function makeScopeId(id: number): ScopeId {
*/
const opaqueIdentifierId = Symbol();
export type IdentifierId = number & { [opaqueIdentifierId]: "IdentifierId" };
export function makeIdentifierId(id: number): IdentifierId {
invariant(
id >= 0 && Number.isInteger(id),
"Expected identifier id to be a non-negative integer"
);
return id as IdentifierId;
}
+27 -4
View File
@@ -16,7 +16,6 @@ import {
IdentifierId,
Instruction,
makeBlockId,
makeIdentifierId,
Terminal,
} from "./HIR";
@@ -56,6 +55,22 @@ function newBlock(id: BlockId): WipBlock {
return { id, instructions: [] };
}
export class Environment {
#nextIdentifer: number = 0;
#makeIdentifierId(id: number): IdentifierId {
invariant(
id >= 0 && Number.isInteger(id),
"Expected identifier id to be a non-negative integer"
);
return id as IdentifierId;
}
get nextIdentifierId(): IdentifierId {
return this.#makeIdentifierId(this.#nextIdentifer++);
}
}
/**
* Helper class for constructing a CFG
*/
@@ -65,8 +80,16 @@ export default class HIRBuilder {
#current: WipBlock = newBlock(makeBlockId(0));
#entry: BlockId = makeBlockId(0);
#scopes: Array<Scope> = [];
#nextIdentifier: IdentifierId = makeIdentifierId(0);
#bindings: Map<t.Identifier, Identifier> = new Map();
#env: Environment;
get nextIdentifierId() {
return this.#env.nextIdentifierId;
}
constructor(env: Environment) {
this.#env = env;
}
debug(): string {
return JSON.stringify(
@@ -88,7 +111,7 @@ export default class HIRBuilder {
}
makeTemporary(): Identifier {
const id = makeIdentifierId(this.#nextIdentifier++);
const id = this.nextIdentifierId;
return {
id,
name: null,
@@ -98,7 +121,7 @@ export default class HIRBuilder {
resolveIdentifier(node: t.Identifier): Identifier {
let identifier = this.#bindings.get(node);
if (identifier == null) {
const id = makeIdentifierId(this.#nextIdentifier++);
const id = this.nextIdentifierId;
identifier = { id, name: node.name };
this.#bindings.set(node, identifier);
}
+14 -6
View File
@@ -8,10 +8,10 @@ import {
IdentifierId,
Instruction,
InstructionKind,
makeIdentifierId,
Phi,
Place,
} from "./HIR";
import { Environment } from "./HIRBuilder";
type IncompletePhi = {
old: Place;
@@ -29,6 +29,15 @@ class SSABuilder {
#states: Map<BasicBlock, State> = new Map();
#current: BasicBlock | null = null;
visitedBlocks: Set<BasicBlock> = new Set();
#env: Environment;
constructor(env: Environment) {
this.#env = env;
}
get nextIdentifierId() {
return this.#env.nextIdentifierId;
}
// Hack(gsn): Start from the last stored id in HIRBuilder.
// Need to refactor makeTemporary and relevant state out of HIR Builder.
@@ -47,7 +56,7 @@ class SSABuilder {
makePlace(oldPlace: Place): Place {
const identifier = {
...oldPlace.identifier,
id: makeIdentifierId(this.#id++),
id: this.nextIdentifierId,
};
return {
...oldPlace,
@@ -58,7 +67,7 @@ class SSABuilder {
makePlaceForPhi(oldPlace: Place): Place {
const identifier = {
...oldPlace.identifier,
id: makeIdentifierId(this.#id++),
id: this.nextIdentifierId,
};
return {
identifier,
@@ -173,9 +182,8 @@ class SSABuilder {
}
}
export default function buildSSA(func: HIRFunction) {
const builder = new SSABuilder();
export default function buildSSA(func: HIRFunction, env: Environment) {
const builder = new SSABuilder(env);
function visit(blockId: BlockId) {
const block = func.body.blocks.get(blockId)!;
if (builder.visitedBlocks.has(block)) {
@@ -21,30 +21,30 @@ function foo() {
```
bb0:
Let mutate x$1000 = 1
Let mutate y$1001 = 2
Const mutate $1002 = 2
Const mutate $1003 = Binary mutate y$1001 === mutate $1002
If (mutate $1003) then:bb2 else:bb1
Let mutate x$7 = 1
Let mutate y$8 = 2
Const mutate $9 = 2
Const mutate $10 = Binary mutate y$8 === mutate $9
If (mutate $10) then:bb2 else:bb1
bb2:
predecessor blocks: bb0
Reassign mutate x$1011 = 3
Reassign mutate x$18 = 3
Goto bb1
bb1:
predecessor blocks: bb0 bb2
Const mutate y$1005: phi(bb0: mutate y$1001, bb2: mutate y$1001)
Const mutate x$1010: phi(bb0: mutate x$1000, bb2: mutate x$1011)
Const mutate $1004 = 3
Const mutate $1006 = Binary mutate y$1005 === mutate $1004
If (mutate $1006) then:bb4 else:bb3
Const mutate y$12: phi(bb0: mutate y$8, bb2: mutate y$8)
Const mutate x$17: phi(bb0: mutate x$7, bb2: mutate x$18)
Const mutate $11 = 3
Const mutate $13 = Binary mutate y$12 === mutate $11
If (mutate $13) then:bb4 else:bb3
bb4:
predecessor blocks: bb1
Reassign mutate x$1009 = 5
Reassign mutate x$16 = 5
Goto bb3
bb3:
predecessor blocks: bb1 bb4
Const mutate x$1007: phi(bb1: mutate x$1010, bb4: mutate x$1009)
Reassign mutate y$1008 = mutate x$1007
Const mutate x$14: phi(bb1: mutate x$17, bb4: mutate x$16)
Reassign mutate y$15 = mutate x$14
Return
```
@@ -52,17 +52,17 @@ bb3:
```javascript
function foo$0() {
let x$1000 = 1;
let y$1001 = 2;
if (y$1001 === 2) {
x$1011 = 3;
let x$7 = 1;
let y$8 = 2;
if (y$8 === 2) {
x$18 = 3;
("<<TODO: handle complex control flow in codegen>>");
}
if (y$1005 === 3) {
x$1009 = 5;
if (y$12 === 3) {
x$16 = 5;
("<<TODO: handle complex control flow in codegen>>");
}
y$1008 = x$1007;
y$15 = x$14;
return;
}
@@ -18,19 +18,19 @@ function foo() {
```
bb0:
Let mutate x$1000 = 1
Let mutate y$1001 = 2
Const mutate $1002 = 2
Const mutate $1003 = Binary mutate y$1001 === mutate $1002
If (mutate $1003) then:bb2 else:bb1
Let mutate x$5 = 1
Let mutate y$6 = 2
Const mutate $7 = 2
Const mutate $8 = Binary mutate y$6 === mutate $7
If (mutate $8) then:bb2 else:bb1
bb2:
predecessor blocks: bb0
Reassign mutate x$1006 = 3
Reassign mutate x$11 = 3
Goto bb1
bb1:
predecessor blocks: bb0 bb2
Const mutate x$1004: phi(bb0: mutate x$1000, bb2: mutate x$1006)
Reassign mutate y$1005 = mutate x$1004
Const mutate x$9: phi(bb0: mutate x$5, bb2: mutate x$11)
Reassign mutate y$10 = mutate x$9
Return
```
@@ -38,13 +38,13 @@ bb1:
```javascript
function foo$0() {
let x$1000 = 1;
let y$1001 = 2;
if (y$1001 === 2) {
x$1006 = 3;
let x$5 = 1;
let y$6 = 2;
if (y$6 === 2) {
x$11 = 3;
("<<TODO: handle complex control flow in codegen>>");
}
y$1005 = x$1004;
y$10 = x$9;
return;
}
@@ -16,29 +16,29 @@ function foo() {
```
bb0:
Let mutate x$1000 = 0
Let mutate x$5 = 0
Goto bb1
bb1:
predecessor blocks: bb0 bb4
Const mutate x$1002: phi(bb0: mutate x$1000, bb4: mutate x$1005)
Const mutate $1001 = 10
Const mutate $1003 = Binary mutate x$1002 < mutate $1001
If (mutate $1003) then:bb4 else:bb2
Const mutate x$7: phi(bb0: mutate x$5, bb4: mutate x$10)
Const mutate $6 = 10
Const mutate $8 = Binary mutate x$7 < mutate $6
If (mutate $8) then:bb4 else:bb2
bb4:
predecessor blocks: bb1
Const mutate $1004 = 1
Reassign mutate x$1005 = Binary mutate x$1002 + mutate $1004
Const mutate $9 = 1
Reassign mutate x$10 = Binary mutate x$7 + mutate $9
Goto bb1
bb2:
predecessor blocks: bb1
Return mutate x$1002
Return mutate x$7
```
## Code
```javascript
function foo$0() {
let x$1000 = 0;
let x$5 = 0;
("<<TODO: handle complex control flow in codegen>>");
}
@@ -19,16 +19,16 @@ function foo() {
```
bb0:
Let mutate x$1000 = 1
Let mutate y$1001 = 2
If (mutate y$1001) then:bb2 else:bb3
Let mutate x$5 = 1
Let mutate y$6 = 2
If (mutate y$6) then:bb2 else:bb3
bb2:
predecessor blocks: bb0
Let mutate z$1003 = Binary mutate x$1000 + mutate y$1001
Let mutate z$8 = Binary mutate x$5 + mutate y$6
Goto bb1
bb3:
predecessor blocks: bb0
Let mutate z$1002 = mutate x$1000
Let mutate z$7 = mutate x$5
Goto bb1
bb1:
predecessor blocks: bb3 bb2
@@ -39,13 +39,13 @@ bb1:
```javascript
function foo$0() {
let x$1000 = 1;
let y$1001 = 2;
if (y$1001) {
let z$1003 = x$1000 + y$1001;
let x$5 = 1;
let y$6 = 2;
if (y$6) {
let z$8 = x$5 + y$6;
("<<TODO: handle complex control flow in codegen>>");
} else {
let z$1002 = x$1000;
let z$7 = x$5;
("<<TODO: handle complex control flow in codegen>>");
}
return;
@@ -17,30 +17,30 @@ function foo() {
```
bb0:
Let mutate x$1000 = 1
Const mutate $1001 = 1
Const mutate $1002 = Binary mutate x$1000 === mutate $1001
If (mutate $1002) then:bb2 else:bb1
Let mutate x$4 = 1
Const mutate $5 = 1
Const mutate $6 = Binary mutate x$4 === mutate $5
If (mutate $6) then:bb2 else:bb1
bb2:
predecessor blocks: bb0
Reassign mutate x$1004 = 2
Reassign mutate x$8 = 2
Goto bb1
bb1:
predecessor blocks: bb0 bb2
Const mutate x$1003: phi(bb0: mutate x$1000, bb2: mutate x$1004)
Return mutate x$1003
Const mutate x$7: phi(bb0: mutate x$4, bb2: mutate x$8)
Return mutate x$7
```
## Code
```javascript
function foo$0() {
let x$1000 = 1;
if (x$1000 === 1) {
x$1004 = 2;
let x$4 = 1;
if (x$4 === 1) {
x$8 = 2;
("<<TODO: handle complex control flow in codegen>>");
}
return x$1003;
return x$7;
}
```
@@ -20,22 +20,22 @@ function foo() {
```
bb0:
Let mutate y$1000 = 2
Const mutate $1001 = 1
Const mutate $1002 = Binary mutate y$1000 > mutate $1001
If (mutate $1002) then:bb2 else:bb3
Let mutate y$5 = 2
Const mutate $6 = 1
Const mutate $7 = Binary mutate y$5 > mutate $6
If (mutate $7) then:bb2 else:bb3
bb2:
predecessor blocks: bb0
Reassign mutate y$1006 = 1
Reassign mutate y$11 = 1
Goto bb1
bb3:
predecessor blocks: bb0
Reassign mutate y$1003 = 2
Reassign mutate y$8 = 2
Goto bb1
bb1:
predecessor blocks: bb3 bb2
Const mutate y$1004: phi(bb3: mutate y$1003, bb2: mutate y$1006)
Let mutate x$1005 = mutate y$1004
Const mutate y$9: phi(bb3: mutate y$8, bb2: mutate y$11)
Let mutate x$10 = mutate y$9
Return
```
@@ -43,15 +43,15 @@ bb1:
```javascript
function foo$0() {
let y$1000 = 2;
if (y$1000 > 1) {
y$1006 = 1;
let y$5 = 2;
if (y$5 > 1) {
y$11 = 1;
("<<TODO: handle complex control flow in codegen>>");
} else {
y$1003 = 2;
y$8 = 2;
("<<TODO: handle complex control flow in codegen>>");
}
let x$1005 = y$1004;
let x$10 = y$9;
return;
}
@@ -13,8 +13,8 @@ function foo() {
```
bb0:
Let mutate x$1000 = 1
Let mutate y$1001 = 2
Let mutate x$3 = 1
Let mutate y$4 = 2
Return
```
@@ -22,8 +22,8 @@ bb0:
```javascript
function foo$0() {
let x$1000 = 1;
let y$1001 = 2;
let x$3 = 1;
let y$4 = 2;
return;
}
@@ -17,12 +17,12 @@ function foo() {
```
bb0:
Let mutate x$1000 = 1
Let mutate y$1001 = 2
If (mutate y$1001) then:bb2 else:bb1
Let mutate x$4 = 1
Let mutate y$5 = 2
If (mutate y$5) then:bb2 else:bb1
bb2:
predecessor blocks: bb0
Let mutate z$1002 = Binary mutate x$1000 + mutate y$1001
Let mutate z$6 = Binary mutate x$4 + mutate y$5
Goto bb1
bb1:
predecessor blocks: bb0 bb2
@@ -33,10 +33,10 @@ bb1:
```javascript
function foo$0() {
let x$1000 = 1;
let y$1001 = 2;
if (y$1001) {
let z$1002 = x$1000 + y$1001;
let x$4 = 1;
let y$5 = 2;
if (y$5) {
let z$6 = x$4 + y$5;
("<<TODO: handle complex control flow in codegen>>");
}
return;
@@ -28,34 +28,34 @@ function foo() {
```
bb0:
Let mutate x$1000 = 1
Const mutate $1001 = 2
Const mutate $1002 = Binary mutate x$1000 === mutate $1001
Const mutate $1003 = 1
Const mutate $1004 = Binary mutate x$1000 === mutate $1003
Switch (mutate x$1000)
Case mutate $1004: bb5
Case mutate $1002: bb3
Let mutate x$10 = 1
Const mutate $11 = 2
Const mutate $12 = Binary mutate x$10 === mutate $11
Const mutate $13 = 1
Const mutate $14 = Binary mutate x$10 === mutate $13
Switch (mutate x$10)
Case mutate $14: bb5
Case mutate $12: bb3
Default: bb2
bb5:
predecessor blocks: bb0
Const mutate $1011 = 1
Reassign mutate x$1012 = Binary mutate x$1000 + mutate $1011
Const mutate $21 = 1
Reassign mutate x$22 = Binary mutate x$10 + mutate $21
Goto bb1
bb3:
predecessor blocks: bb0
Const mutate $1009 = 2
Reassign mutate x$1010 = Binary mutate x$1000 + mutate $1009
Const mutate $19 = 2
Reassign mutate x$20 = Binary mutate x$10 + mutate $19
Goto bb1
bb2:
predecessor blocks: bb0
Const mutate $1005 = 3
Reassign mutate x$1006 = Binary mutate x$1000 + mutate $1005
Const mutate $15 = 3
Reassign mutate x$16 = Binary mutate x$10 + mutate $15
Goto bb1
bb1:
predecessor blocks: bb5 bb3 bb2
Const mutate x$1007: phi(bb5: mutate x$1012, bb3: mutate x$1010, bb2: mutate x$1006)
Let mutate y$1008 = mutate x$1007
Const mutate x$17: phi(bb5: mutate x$22, bb3: mutate x$20, bb2: mutate x$16)
Let mutate y$18 = mutate x$17
Return
```
@@ -63,22 +63,22 @@ bb1:
```javascript
function foo$0() {
let x$1000 = 1;
switch (x$1000) {
case x$1000 === 1: {
x$1012 = x$1000 + 1;
let x$10 = 1;
switch (x$10) {
case x$10 === 1: {
x$22 = x$10 + 1;
("<<TODO: handle complex control flow in codegen>>");
}
case x$1000 === 2: {
x$1010 = x$1000 + 2;
case x$10 === 2: {
x$20 = x$10 + 2;
("<<TODO: handle complex control flow in codegen>>");
}
default: {
x$1006 = x$1000 + 3;
x$16 = x$10 + 3;
("<<TODO: handle complex control flow in codegen>>");
}
}
let y$1008 = x$1007;
let y$18 = x$17;
return;
}
@@ -16,30 +16,30 @@ function foo() {
```
bb0:
Let mutate x$1000 = 1
Const mutate $1001 = 1
Const mutate $1002 = Binary mutate x$1000 === mutate $1001
If (mutate $1002) then:bb2 else:bb1
Let mutate x$4 = 1
Const mutate $5 = 1
Const mutate $6 = Binary mutate x$4 === mutate $5
If (mutate $6) then:bb2 else:bb1
bb2:
predecessor blocks: bb0
Reassign mutate x$1004 = 2
Reassign mutate x$8 = 2
Goto bb1
bb1:
predecessor blocks: bb0 bb2
Const mutate x$1003: phi(bb0: mutate x$1000, bb2: mutate x$1004)
Throw mutate x$1003
Const mutate x$7: phi(bb0: mutate x$4, bb2: mutate x$8)
Throw mutate x$7
```
## Code
```javascript
function foo$0() {
let x$1000 = 1;
if (x$1000 === 1) {
x$1004 = 2;
let x$4 = 1;
if (x$4 === 1) {
x$8 = 2;
("<<TODO: handle complex control flow in codegen>>");
}
throw x$1003;
throw x$7;
}
```
@@ -17,29 +17,29 @@ function foo() {
```
bb0:
Let mutate x$1000 = 1
Let mutate x$5 = 1
Goto bb1
bb1:
predecessor blocks: bb0 bb3
Const mutate x$1002: phi(bb0: mutate x$1000, bb3: mutate x$1005)
Const mutate $1001 = 10
Const mutate $1003 = Binary mutate x$1002 < mutate $1001
If (mutate $1003) then:bb3 else:bb2
Const mutate x$7: phi(bb0: mutate x$5, bb3: mutate x$10)
Const mutate $6 = 10
Const mutate $8 = Binary mutate x$7 < mutate $6
If (mutate $8) then:bb3 else:bb2
bb3:
predecessor blocks: bb1
Const mutate $1004 = 1
Reassign mutate x$1005 = Binary mutate x$1002 + mutate $1004
Const mutate $9 = 1
Reassign mutate x$10 = Binary mutate x$7 + mutate $9
Goto bb1
bb2:
predecessor blocks: bb1
Return mutate x$1002
Return mutate x$7
```
## Code
```javascript
function foo$0() {
let x$1000 = 1;
let x$5 = 1;
("<<TODO: handle complex control flow in codegen>>");
}
+4 -2
View File
@@ -17,6 +17,7 @@ import prettier from "prettier";
import { lower } from "../HIR/BuildHIR";
import codegen from "../HIR/Codegen";
import { HIRFunction } from "../HIR/HIR";
import { Environment } from "../HIR/HIRBuilder";
import inferReferenceEffects from "../HIR/InferReferenceEffects";
import printHIR from "../HIR/PrintHIR";
import buildSSA from "../HIR/SSAify";
@@ -44,10 +45,11 @@ describe("React Forget (HIR version)", () => {
traverse(ast, {
FunctionDeclaration: {
enter(nodePath) {
const ir: HIRFunction = lower(nodePath);
const env: Environment = new Environment();
const ir: HIRFunction = lower(nodePath, env);
inferReferenceEffects(ir);
if (file.startsWith("ssa")) {
buildSSA(ir);
buildSSA(ir, env);
}
// const lifetimeGraph = buildDefUseGraph(ir);
const textHIR = printHIR(ir.body);