"ValueBlock" for while test node

The instructions of a while test node cannot just be pushed to the previous 
block. This creates a new block for the test node and then during code gen 
converts the statements pushed to the "value block" into expressions.
This commit is contained in:
Jan Kassens
2022-12-06 11:28:15 -05:00
parent 3a1124fe14
commit db740366f8
10 changed files with 79 additions and 24 deletions
+23
View File
@@ -100,6 +100,10 @@ class CodegenVisitor
this.depth++;
return [];
}
enterValueBlock(): t.Statement[] {
this.depth++;
return [];
}
visitValue(value: InstructionValue): t.Expression {
return codegenInstructionValue(this.temp, value);
}
@@ -237,6 +241,25 @@ class CodegenVisitor
this.depth--;
return t.blockStatement(block);
}
leaveValueBlock(block: t.Statement[], place: t.Expression): t.Expression {
this.depth--;
if (block.length === 0) {
return place;
}
const expressions = block.map((stmt) => {
switch (stmt.type) {
case "ExpressionStatement":
return stmt.expression;
default:
todoInvariant(
false,
`Handle conversion of ${stmt.type} to expression`
);
}
});
expressions.push(place);
return t.sequenceExpression(expressions);
}
}
function codegenLabel(id: BlockId): string {
+16 -7
View File
@@ -239,15 +239,20 @@ class Driver<TBlock, TValue, TItem, TCase> {
testTerminal.kind === "if",
"Expected while loop test block to end in an if"
);
// const bodyLength = blockValue.length;
const testValueBlock = this.visitor.enterValueBlock();
for (const instr of testBlock.instructions) {
this.visitInstr(instr, blockValue);
const value = this.visitor.visitValue(instr.value, instr.id);
const item = this.visitor.visitInstruction(instr, value);
this.visitor.appendBlock(testValueBlock, item);
}
// invariant(
// body.length === bodyLength,
// "Expected test to produce only temporaries"
// );
const testValue = this.visitPlace(testTerminal.test, terminal.id);
const testValueLast = this.visitor.visitValue(
testTerminal.test,
testTerminal.id
);
const testValue = this.visitor.leaveValueBlock(
testValueBlock,
testValueLast
);
const fallthroughId =
terminal.fallthrough !== null &&
!this.cx.isScheduled(terminal.fallthrough)
@@ -644,6 +649,10 @@ export interface Visitor<TBlock, TValue, TItem, TCase> {
*/
enterBlock(): TBlock;
enterValueBlock(): TBlock;
leaveValueBlock(block: TBlock, value: TValue): TValue;
/**
* Convert an InstructionValue into the visitor's own representation
* of a value.
@@ -189,8 +189,12 @@ class ScopeDependenciesVisitor
}
enterBlock(): void {}
enterValueBlock(): void {}
visitImplicitTerminal(): void | null {}
visitCase(test: InstructionValue, block: void): void {}
appendBlock(block: void, item: void, label?: BlockId | undefined): void {}
leaveBlock(block: void): void {}
leaveValueBlock(block: void, value: InstructionValue): InstructionValue {
return value;
}
}
@@ -254,6 +254,12 @@ class MergeOverlappingReactiveScopesVisitor
enterBlock(): void {
this.scopes.push(new BlockScope());
}
enterValueBlock(): void {
this.enterBlock();
}
leaveValueBlock(block: void, value: void): void {
this.leaveBlock();
}
visitValue(value: InstructionValue, id: InstructionId): void {
this.visitId(id);
for (const operand of eachInstructionValueOperand(value)) {
@@ -355,6 +361,14 @@ class AlignReactiveScopesToBlockScopeRangeVisitor
}
}
enterValueBlock(): void {
this.enterBlock();
}
leaveValueBlock(block: void, value: void): void {
this.leaveBlock();
}
visitInstruction(instruction: Instruction, value: void): void {
const scope = getInstructionScope(instruction);
if (scope !== null) {
+6
View File
@@ -32,6 +32,12 @@ class PrintVisitor implements Visitor<Array<string>, string, string, string> {
this.depth++;
return [];
}
enterValueBlock(): string[] {
return this.enterBlock();
}
leaveValueBlock(block: string[], value: string): string {
return this.leaveBlock(block);
}
visitValue(value: InstructionValue): string {
return printMixedHIR(value);
}
@@ -31,7 +31,7 @@ bb1:
sum$21_@3[0:14]: phi(bb0: sum$16_@3, bb3: sum$22_@3)
[8] Reassign mutate value$18_@3[0:14] = Call mutate queue$14_@3.pop()
[9] Const mutate $19_@6 = null
[10] Const mutate $20_@7[10:14] = Binary read value$18_@3 != read $19_@6
[10] Const mutate $20_@7[10:12] = Binary read value$18_@3 != read $19_@6
[11] If (read $20_@7) then:bb3 else:bb2
bb3:
predecessor blocks: bb1
@@ -40,7 +40,7 @@ bb3:
bb2:
predecessor blocks: bb1
[14] Return read sum$21_@3
scope7 [10:14]:
scope7 [10:12]:
- read $19_@6
```
@@ -64,7 +64,7 @@ flowchart TB
bb1_instrs["
[8] Reassign mutate value$18_@3[0:14] = Call mutate queue$14_@3.pop()
[9] Const mutate $19_@6 = null
[10] Const mutate $20_@7[10:14] = Binary read value$18_@3 != read $19_@6
[10] Const mutate $20_@7[10:12] = Binary read value$18_@3 != read $19_@6
"]
bb1_instrs --> bb1_terminal(["If (read $20_@7)"])
end
@@ -95,8 +95,7 @@ function f$0(reader$1) {
const queue$2 = [1, 2, 3];
let value$6 = 0;
let sum$7 = 0;
value$6 = queue$2.pop();
bb2: while (value$6 != null) {
bb2: while (((value$6 = queue$2.pop()), value$6 != null)) {
sum$7 = sum$7 + value$6;
}
@@ -108,7 +108,7 @@ bb1:
b$20_@0[0:23]: phi(bb0: b$14_@0, bb4: b$23_@0)
c$22_@0[0:23]: phi(bb0: c$15_@0, bb4: c$25_@0)
d$24_@0[0:23]: phi(bb0: d$16_@0, bb4: d$26_@0)
[6] Const mutate $17_@1[6:17] = true
[6] Const mutate $17_@1[6:8] = true
[7] If (read $17_@1) then:bb3 else:bb2
bb3:
predecessor blocks: bb1
@@ -163,7 +163,7 @@ flowchart TB
end
subgraph bb1
bb1_instrs["
[6] Const mutate $17_@1[6:17] = true
[6] Const mutate $17_@1[6:8] = true
"]
bb1_instrs --> bb1_terminal(["If (read $17_@1)"])
end
@@ -99,7 +99,7 @@ bb0:
[5] While test=bb1 loop=bb3 fallthrough=bb2
bb1:
predecessor blocks: bb0 bb4
[6] Const mutate $16_@2[6:12] = true
[6] Const mutate $16_@2[6:8] = true
[7] If (read $16_@2) then:bb3 else:bb2
bb3:
predecessor blocks: bb1
@@ -145,7 +145,7 @@ flowchart TB
end
subgraph bb1
bb1_instrs["
[6] Const mutate $16_@2[6:12] = true
[6] Const mutate $16_@2[6:8] = true
"]
bb1_instrs --> bb1_terminal(["If (read $16_@2)"])
end
@@ -17,12 +17,12 @@ function foo() {
```
bb0:
[1] Let mutate x$5_@0[1:3] = 1
[1] Let mutate x$5_@0 = 1
[2] While test=bb1 loop=bb3 fallthrough=bb2
bb1:
predecessor blocks: bb0 bb3
[3] Const mutate $6_@1 = 10
[4] Const mutate $8_@2[4:9] = Binary read x$5_@0 < read $6_@1
[4] Const mutate $8_@2[4:6] = Binary read x$5_@0 < read $6_@1
[5] If (read $8_@2) then:bb3 else:bb2
bb3:
predecessor blocks: bb1
@@ -32,7 +32,7 @@ bb3:
bb2:
predecessor blocks: bb1
[9] Return read x$5_@0
scope2 [4:9]:
scope2 [4:6]:
- read x$5_@0
- read $6_@1
scope3 [6:7]:
@@ -46,14 +46,14 @@ flowchart TB
%% Basic Blocks
subgraph bb0
bb0_instrs["
[1] Let mutate x$5_@0[1:3] = 1
[1] Let mutate x$5_@0 = 1
"]
bb0_instrs --> bb0_terminal(["While"])
end
subgraph bb1
bb1_instrs["
[3] Const mutate $6_@1 = 10
[4] Const mutate $8_@2[4:9] = Binary read x$5_@0 < read $6_@1
[4] Const mutate $8_@2[4:6] = Binary read x$5_@0 < read $6_@1
"]
bb1_instrs --> bb1_terminal(["If (read $8_@2)"])
end
@@ -23,7 +23,7 @@ bb1:
predecessor blocks: bb0 bb3
x$7_@0[0:9]: phi(bb0: x$5_@0, bb3: x$10_@0)
[3] Const mutate $6_@1 = 10
[4] Const mutate $8_@2[4:9] = Binary read x$7_@0 < read $6_@1
[4] Const mutate $8_@2[4:6] = Binary read x$7_@0 < read $6_@1
[5] If (read $8_@2) then:bb3 else:bb2
bb3:
predecessor blocks: bb1
@@ -33,7 +33,7 @@ bb3:
bb2:
predecessor blocks: bb1
[9] Return read x$7_@0
scope2 [4:9]:
scope2 [4:6]:
- read $6_@1
```
@@ -51,7 +51,7 @@ flowchart TB
subgraph bb1
bb1_instrs["
[3] Const mutate $6_@1 = 10
[4] Const mutate $8_@2[4:9] = Binary read x$7_@0 < read $6_@1
[4] Const mutate $8_@2[4:6] = Binary read x$7_@0 < read $6_@1
"]
bb1_instrs --> bb1_terminal(["If (read $8_@2)"])
end