[storelocal] Instruction lvalue is just a Place
Joe Savona committed
Mar 2, 2023 at 14:19 UTC
36d1fa2569dd544d2e1b69215feceaf3c25747f3
30 files changed
+143
-217
compiler/forget/src/HIR/BuildHIR.ts
+35
-56
@@ -614,7 +614,7 @@ function lowerStatement(
614
value = buildTemporaryPlace(builder, id.node.loc ?? GeneratedSource);
615
builder.push({
616
id: makeInstructionId(0),
617
- lvalue: { place: { ...value }, kind: InstructionKind.Const },
617
+ lvalue: { ...value },
618
value: {
619
kind: "Primitive",
620
value: undefined,
@@ -647,7 +647,7 @@ function lowerStatement(
647
);
648
builder.push({
649
id: makeInstructionId(0),
650
- lvalue: { kind: InstructionKind.Const, place },
650
+ lvalue: place,
651
value,
652
loc: stmt.node.loc ?? GeneratedSource,
653
});
@@ -746,13 +746,10 @@ function lowerStatement(
746
});
747
builder.push({
748
id: makeInstructionId(0),
749
- lvalue: {
750
- place: buildTemporaryPlace(
751
- builder,
752
- stmtPath.node.loc ?? GeneratedSource
753
- ),
754
- kind: InstructionKind.Const,
755
- },
749
+ lvalue: buildTemporaryPlace(
750
+ builder,
751
+ stmtPath.node.loc ?? GeneratedSource
752
+ ),
753
loc: stmtPath.node.loc ?? GeneratedSource,
754
value: {
755
kind: "UnsupportedNode",
@@ -1043,7 +1040,7 @@ function lowerExpression(
1040
const consequentBlock = builder.enter("value", (_blockId) => {
1041
builder.push({
1042
id: makeInstructionId(0),
1046
- lvalue: { kind: InstructionKind.Reassign, place: { ...place } },
1043
+ lvalue: { ...place },
1044
value: lowerExpression(builder, expr.get("consequent")),
1045
loc: exprLoc,
1046
});
@@ -1058,7 +1055,7 @@ function lowerExpression(
1055
const alternateBlock = builder.enter("value", (_blockId) => {
1056
builder.push({
1057
id: makeInstructionId(0),
1061
- lvalue: { kind: InstructionKind.Reassign, place: { ...place } },
1058
+ lvalue: { ...place },
1059
value: lowerExpression(builder, expr.get("alternate")),
1060
loc: exprLoc,
1061
});
@@ -1106,7 +1103,7 @@ function lowerExpression(
1103
const consequent = builder.enter("value", () => {
1104
builder.push({
1105
id: makeInstructionId(0),
1109
- lvalue: { kind: InstructionKind.Reassign, place: { ...place } },
1106
+ lvalue: { ...place },
1107
value: {
1108
kind: "LoadLocal",
1109
place: { ...leftPlace },
@@ -1124,7 +1121,7 @@ function lowerExpression(
1121
const alternate = builder.enter("value", () => {
1122
builder.push({
1123
id: makeInstructionId(0),
1127
- lvalue: { kind: InstructionKind.Reassign, place: { ...place } },
1124
+ lvalue: { ...place },
1125
value: lowerExpression(builder, expr.get("right")),
1126
loc: exprLoc,
1127
});
@@ -1148,7 +1145,7 @@ function lowerExpression(
1145
);
1146
builder.push({
1147
id: makeInstructionId(0),
1151
- lvalue: { kind: InstructionKind.Reassign, place: { ...leftPlace } },
1148
+ lvalue: { ...leftPlace },
1149
value: lowerExpression(builder, expr.get("left")),
1150
loc: exprLoc,
1151
});
@@ -1225,8 +1222,7 @@ function lowerExpression(
1222
builder.push({
1223
id: makeInstructionId(0),
1224
lvalue: {
1228
- place: { ...binaryPlace },
1229
- kind: InstructionKind.Const,
1225
+ ...binaryPlace,
1226
},
1227
value: {
1228
kind: "BinaryExpression",
@@ -1240,7 +1236,7 @@ function lowerExpression(
1236
const result = buildTemporaryPlace(builder, exprLoc);
1237
builder.push({
1238
id: makeInstructionId(0),
1243
- lvalue: { place: { ...result }, kind: InstructionKind.Const },
1239
+ lvalue: { ...result },
1240
value: {
1241
kind: "StoreLocal",
1242
lvalue: {
@@ -1270,8 +1266,7 @@ function lowerExpression(
1266
builder.push({
1267
id: makeInstructionId(0),
1268
lvalue: {
1273
- place: { ...previousValuePlace },
1274
- kind: InstructionKind.Const,
1269
+ ...previousValuePlace,
1270
},
1271
value,
1272
loc: leftExpr.node.loc ?? GeneratedSource,
@@ -1281,8 +1276,7 @@ function lowerExpression(
1276
builder.push({
1277
id: makeInstructionId(0),
1278
lvalue: {
1284
- place: { ...newValuePlace },
1285
- kind: InstructionKind.Const,
1279
+ ...newValuePlace,
1280
},
1281
value: {
1282
kind: "BinaryExpression",
@@ -1332,7 +1326,7 @@ function lowerExpression(
1326
const place: Place = buildTemporaryPlace(builder, exprLoc);
1327
builder.push({
1328
id: makeInstructionId(0),
1335
- lvalue: { place: { ...place }, kind: InstructionKind.Const },
1329
+ lvalue: { ...place },
1330
value,
1331
loc: exprLoc,
1332
});
@@ -1581,7 +1575,7 @@ function lowerExpression(
1575
);
1576
builder.push({
1577
id: makeInstructionId(0),
1584
- lvalue: { place: { ...primitiveTemp }, kind: InstructionKind.Const },
1578
+ lvalue: { ...primitiveTemp },
1579
value: {
1580
kind: "Primitive",
1581
value: 1,
@@ -1599,7 +1593,7 @@ function lowerExpression(
1593
);
1594
builder.push({
1595
id: makeInstructionId(0),
1602
- lvalue: { place: { ...temp }, kind: InstructionKind.Const },
1596
+ lvalue: { ...temp },
1597
value: {
1598
kind: "BinaryExpression",
1599
operator: expr.node.operator === "++" ? "+" : "-",
@@ -1611,16 +1605,10 @@ function lowerExpression(
1605
});
1606
builder.push({
1607
id: makeInstructionId(0),
1614
- lvalue: {
1615
- place: buildTemporaryPlace(builder, exprLoc),
1616
- kind: InstructionKind.Const,
1617
- },
1608
+ lvalue: buildTemporaryPlace(builder, exprLoc),
1609
value: {
1610
kind: "StoreLocal",
1620
- lvalue: {
1621
- place: { ...identifier },
1622
- kind: InstructionKind.Reassign,
1623
- },
1611
+ lvalue: { place: { ...identifier }, kind: InstructionKind.Reassign },
1612
value: { ...temp },
1613
loc: exprLoc,
1614
},
@@ -1723,7 +1711,7 @@ function lowerJsxElementName(
1711
loc: exprLoc,
1712
},
1713
loc: exprLoc,
1726
- lvalue: { place: { ...place }, kind: InstructionKind.Const },
1714
+ lvalue: { ...place },
1715
});
1716
return { ...place };
1717
}
@@ -1740,9 +1728,9 @@ function lowerJsxElementName(
1728
loc: exprLoc,
1729
},
1730
loc: exprLoc,
1743
- lvalue: { place, kind: InstructionKind.Const },
1731
+ lvalue: { ...place },
1732
});
1745
- return { ...place };
1733
+ return place;
1734
}
1735
}
1736
@@ -1777,7 +1765,7 @@ function lowerJsxElement(
1765
loc: exprLoc,
1766
},
1767
loc: exprLoc,
1780
- lvalue: { place: { ...place }, kind: InstructionKind.Const },
1768
+ lvalue: { ...place },
1769
});
1770
return { ...place };
1771
}
@@ -1792,7 +1780,7 @@ function lowerJsxElement(
1780
loc: exprLoc,
1781
},
1782
loc: exprLoc,
1795
- lvalue: { place: { ...place }, kind: InstructionKind.Const },
1783
+ lvalue: { ...place },
1784
});
1785
return place;
1786
} else {
@@ -1812,7 +1800,7 @@ function lowerJsxElement(
1800
loc: exprLoc,
1801
},
1802
loc: exprLoc,
1815
- lvalue: { place: { ...place }, kind: InstructionKind.Const },
1803
+ lvalue: { ...place },
1804
});
1805
return place;
1806
}
@@ -1832,7 +1820,7 @@ function lowerExpressionToTemporary(
1820
id: makeInstructionId(0),
1821
value: value,
1822
loc: exprLoc,
1835
- lvalue: { place: { ...place }, kind: InstructionKind.Const },
1823
+ lvalue: { ...place },
1824
});
1825
return place;
1826
}
@@ -1851,7 +1839,7 @@ function lowerExpressionToPlace(
1839
id: makeInstructionId(0),
1840
value: value,
1841
loc: exprLoc,
1854
- lvalue: { place: { ...place }, kind: InstructionKind.Const },
1842
+ lvalue: { ...place },
1843
});
1844
return place;
1845
}
@@ -1869,10 +1857,7 @@ function lowerExpressionToVoid(
1857
id: makeInstructionId(0),
1858
value: instr,
1859
loc: exprLoc,
1872
- lvalue: {
1873
- place: buildTemporaryPlace(builder, exprLoc),
1874
- kind: InstructionKind.Const,
1875
- },
1860
+ lvalue: buildTemporaryPlace(builder, exprLoc),
1861
});
1862
}
1863
@@ -1899,10 +1884,7 @@ function lowerIdentifier(
1884
id: makeInstructionId(0),
1885
value,
1886
loc: place.loc,
1902
- lvalue: {
1903
- place: { ...place },
1904
- kind: InstructionKind.Const,
1905
- },
1887
+ lvalue: { ...place },
1888
});
1889
return place;
1890
}
@@ -1972,13 +1954,10 @@ function lowerAssignment(
1954
};
1955
builder.push({
1956
id: makeInstructionId(0),
1975
- lvalue: { place: { ...temporary }, kind },
1957
+ lvalue: { ...temporary },
1958
value: {
1959
kind: "StoreLocal",
1978
- lvalue: {
1979
- place: { ...place },
1980
- kind,
1981
- },
1960
+ lvalue: { place: { ...place }, kind },
1961
value,
1962
loc,
1963
},
@@ -2050,7 +2029,7 @@ function lowerAssignment(
2029
);
2030
builder.push({
2031
id: makeInstructionId(0),
2053
- lvalue: { place: { ...property }, kind: InstructionKind.Const },
2032
+ lvalue: { ...property },
2033
value: {
2034
kind: "Primitive",
2035
value: i,
@@ -2061,7 +2040,7 @@ function lowerAssignment(
2040
const propertyPlace = buildTemporaryPlace(builder, property.loc);
2041
builder.push({
2042
id: makeInstructionId(0),
2064
- lvalue: { place: { ...propertyPlace }, kind: InstructionKind.Const },
2043
+ lvalue: { ...propertyPlace },
2044
value: {
2045
kind: "ComputedLoad",
2046
loc,
@@ -2123,7 +2102,7 @@ function lowerAssignment(
2102
);
2103
builder.push({
2104
id: makeInstructionId(0),
2126
- lvalue: { place: { ...propertyPlace }, kind: InstructionKind.Const },
2105
+ lvalue: { ...propertyPlace },
2106
value: {
2107
kind: "PropertyLoad",
2108
loc,
compiler/forget/src/HIR/HIR.ts
+2
-2
@@ -81,7 +81,7 @@ export type ReactiveTerminalStatement<
81
82
export type ReactiveInstruction = {
83
id: InstructionId;
84
- lvalue: LValue | null;
84
+ lvalue: Place | null;
85
value: ReactiveValue;
86
loc: SourceLocation;
87
};
@@ -365,7 +365,7 @@ export type TernaryTerminal = {
365
*/
366
export type Instruction = {
367
id: InstructionId;
368
- lvalue: LValue;
368
+ lvalue: Place;
369
value: InstructionValue;
370
loc: SourceLocation;
371
};
compiler/forget/src/HIR/MergeConsecutiveBlocks.ts
+4
-8
@@ -12,7 +12,6 @@ import {
12
GeneratedSource,
13
HIRFunction,
14
Instruction,
15
- InstructionKind,
15
} from "./HIR";
16
17
/**
@@ -60,13 +59,10 @@ export function mergeConsecutiveBlocks(fn: HIRFunction): void {
59
const instr: Instruction = {
60
id: predecessor.terminal.id,
61
lvalue: {
63
- place: {
64
- kind: "Identifier",
65
- identifier: phi.id,
66
- effect: Effect.Mutate,
67
- loc: GeneratedSource,
68
- },
69
- kind: InstructionKind.Const,
62
+ kind: "Identifier",
63
+ identifier: phi.id,
64
+ effect: Effect.Mutate,
65
+ loc: GeneratedSource,
66
},
67
value: {
68
kind: "LoadLocal",
compiler/forget/src/HIR/PrintHIR.ts
+1
-1
@@ -106,7 +106,7 @@ export function printInstruction(instr: ReactiveInstruction): string {
106
const value = printInstructionValue(instr.value);
107
108
if (instr.lvalue !== null) {
109
- return `${id} ${printLValue(instr.lvalue)} = ${value}`;
109
+ return `${id} ${printPlace(instr.lvalue)} = ${value}`;
110
} else {
111
return `${id} ${value}`;
112
}
compiler/forget/src/HIR/ValidateConsistentIdentifiers.ts
+4
-8
@@ -29,17 +29,13 @@ export function validateConsistentIdentifiers(fn: HIRFunction): void {
29
}
30
}
31
for (const instr of block.instructions) {
32
- if (instr.lvalue.place.identifier.name !== null) {
32
+ if (instr.lvalue.identifier.name !== null) {
33
CompilerError.invariant(
34
- `Expected all lvalues to be temporaries, found '${instr.lvalue.place.identifier.name}'`,
35
- instr.lvalue.place.loc
34
+ `Expected all lvalues to be temporaries, found '${instr.lvalue.identifier.name}'`,
35
+ instr.lvalue.loc
36
);
37
}
38
- validate(
39
- identifiers,
40
- instr.lvalue.place.identifier,
41
- instr.lvalue.place.loc
42
- );
38
+ validate(identifiers, instr.lvalue.identifier, instr.lvalue.loc);
39
for (const operand of eachInstructionValueOperand(instr.value)) {
40
validate(identifiers, operand.identifier, operand.loc);
41
}
compiler/forget/src/HIR/visitors.ts
+1
-1
@@ -594,7 +594,7 @@ export function* eachBlockOperand(block: BasicBlock): Iterable<Place> {
594
for (const instr of block.instructions) {
595
yield* eachInstructionOperand(instr);
596
if (instr.lvalue != null) {
597
- yield instr.lvalue.place;
597
+ yield instr.lvalue;
598
}
599
}
600
yield* eachTerminalOperand(block.terminal);
compiler/forget/src/Inference/AnalyseFunctions.ts
+3
-3
@@ -56,15 +56,15 @@ export default function analyseFunctions(func: HIRFunction) {
56
}
57
case "PropertyLoad": {
58
state.declareProperty(
59
- instr.lvalue.place,
59
+ instr.lvalue,
60
instr.value.object,
61
instr.value.property
62
);
63
break;
64
}
65
case "LoadLocal": {
66
- if (instr.lvalue.place.identifier.name === null) {
67
- state.declareTemporary(instr.lvalue.place, instr.value.place);
66
+ if (instr.lvalue.identifier.name === null) {
67
+ state.declareTemporary(instr.lvalue, instr.value.place);
68
}
69
break;
70
}
compiler/forget/src/Inference/InferAlias.ts
+1
-1
@@ -49,5 +49,5 @@ function inferInstr(instr: Instruction, aliases: DisjointSet<Identifier>) {
49
return;
50
}
51
52
- aliases.union([lvalue.place.identifier, alias.identifier]);
52
+ aliases.union([lvalue.identifier, alias.identifier]);
53
}
compiler/forget/src/Inference/InferAliasForStores.ts
+2
-2
@@ -21,7 +21,7 @@ export function inferAliasForStores(
21
for (const [_, block] of func.body.blocks) {
22
for (const instr of block.instructions) {
23
const { value, lvalue } = instr;
24
- if (lvalue.place.effect !== Effect.Store) {
24
+ if (lvalue.effect !== Effect.Store) {
25
continue;
26
}
27
if (value.kind === "StoreLocal") {
@@ -32,7 +32,7 @@ export function inferAliasForStores(
32
operand.effect === Effect.Capture ||
33
operand.effect === Effect.Store
34
) {
35
- maybeAlias(aliases, lvalue.place, operand, instr.id);
35
+ maybeAlias(aliases, lvalue, operand, instr.id);
36
}
37
}
38
}
compiler/forget/src/Inference/InferMutableLifetimes.ts
+1
-1
@@ -129,7 +129,7 @@ export function inferMutableLifetimes(
129
}
130
}
131
132
- const lvalueId = instr.lvalue.place.identifier;
132
+ const lvalueId = instr.lvalue.identifier;
133
134
// lvalue start being mutable when they're initially assigned a
135
// value.
compiler/forget/src/Inference/InferReferenceEffects.ts
+22
-22
@@ -655,8 +655,8 @@ function inferBlock(
655
);
656
}
657
state.initialize(instrValue, ValueKind.Mutable);
658
- state.define(instr.lvalue.place, instrValue);
659
- instr.lvalue.place.effect = Effect.Store;
658
+ state.define(instr.lvalue, instrValue);
659
+ instr.lvalue.effect = Effect.Store;
660
continue;
661
}
662
case "PropertyCall": {
@@ -676,8 +676,8 @@ function inferBlock(
676
state.reference(arg, Effect.Mutate);
677
}
678
state.initialize(instrValue, ValueKind.Mutable);
679
- state.define(instr.lvalue.place, instrValue);
680
- instr.lvalue.place.effect = Effect.Mutate;
679
+ state.define(instr.lvalue, instrValue);
680
+ instr.lvalue.effect = Effect.Mutate;
681
continue;
682
}
683
case "ComputedCall": {
@@ -698,8 +698,8 @@ function inferBlock(
698
state.reference(arg, Effect.Mutate);
699
}
700
state.initialize(instrValue, ValueKind.Mutable);
701
- state.define(instr.lvalue.place, instrValue);
702
- instr.lvalue.place.effect = Effect.Mutate;
701
+ state.define(instr.lvalue, instrValue);
702
+ instr.lvalue.effect = Effect.Mutate;
703
continue;
704
}
705
case "PropertyStore": {
@@ -711,8 +711,8 @@ function inferBlock(
711
state.reference(instrValue.object, Effect.Store);
712
713
const lvalue = instr.lvalue;
714
- state.alias(lvalue.place, instrValue.value);
715
- lvalue.place.effect = Effect.Store;
714
+ state.alias(lvalue, instrValue.value);
715
+ lvalue.effect = Effect.Store;
716
continue;
717
}
718
case "PropertyLoad": {
@@ -729,9 +729,9 @@ function inferBlock(
729
730
state.reference(instrValue.object, Effect.Read);
731
const lvalue = instr.lvalue;
732
- lvalue.place.effect = Effect.Mutate;
732
+ lvalue.effect = Effect.Mutate;
733
state.initialize(instrValue, state.kind(instrValue.object));
734
- state.define(lvalue.place, instrValue);
734
+ state.define(lvalue, instrValue);
735
continue;
736
}
737
case "ComputedStore": {
@@ -744,8 +744,8 @@ function inferBlock(
744
state.reference(instrValue.object, Effect.Store);
745
746
const lvalue = instr.lvalue;
747
- state.alias(lvalue.place, instrValue.value);
748
- lvalue.place.effect = Effect.Store;
747
+ state.alias(lvalue, instrValue.value);
748
+ lvalue.effect = Effect.Store;
749
continue;
750
}
751
case "ComputedLoad": {
@@ -763,9 +763,9 @@ function inferBlock(
763
state.reference(instrValue.object, Effect.Read);
764
state.reference(instrValue.property, Effect.Read);
765
const lvalue = instr.lvalue;
766
- lvalue.place.effect = Effect.Mutate;
766
+ lvalue.effect = Effect.Mutate;
767
state.initialize(instrValue, state.kind(instrValue.object));
768
- state.define(lvalue.place, instrValue);
768
+ state.define(lvalue, instrValue);
769
continue;
770
}
771
case "TypeCastExpression": {
@@ -778,16 +778,16 @@ function inferBlock(
778
state.initialize(instrValue, state.kind(instrValue.value));
779
state.reference(instrValue.value, Effect.Read);
780
const lvalue = instr.lvalue;
781
- lvalue.place.effect = Effect.Mutate;
782
- state.alias(lvalue.place, instrValue.value);
781
+ lvalue.effect = Effect.Mutate;
782
+ state.alias(lvalue, instrValue.value);
783
continue;
784
}
785
case "LoadLocal": {
786
state.reference(instrValue.place, Effect.Capture);
787
const lvalue = instr.lvalue;
788
- lvalue.place.effect = Effect.Mutate;
788
+ lvalue.effect = Effect.Mutate;
789
// direct aliasing: `a = b`;
790
- state.alias(lvalue.place, instrValue.place);
790
+ state.alias(lvalue, instrValue.place);
791
continue;
792
}
793
case "StoreLocal": {
@@ -799,8 +799,8 @@ function inferBlock(
799
state.reference(instrValue.value, effect);
800
801
const lvalue = instr.lvalue;
802
- state.alias(lvalue.place, instrValue.value);
803
- lvalue.place.effect = Effect.Store;
802
+ state.alias(lvalue, instrValue.value);
803
+ lvalue.effect = Effect.Store;
804
state.alias(instrValue.lvalue.place, instrValue.value);
805
instrValue.lvalue.place.effect = Effect.Store;
806
continue;
@@ -820,8 +820,8 @@ function inferBlock(
820
}
821
822
state.initialize(instrValue, valueKind);
823
- state.define(instr.lvalue.place, instrValue);
824
- instr.lvalue.place.effect = lvalueEffect;
823
+ state.define(instr.lvalue, instrValue);
824
+ instr.lvalue.effect = lvalueEffect;
825
}
826
827
const effect =
compiler/forget/src/Optimization/ConstantPropagation.ts
+1
-1
@@ -105,7 +105,7 @@ function applyConstantPropagation(fn: HIRFunction): boolean {
105
const value = evaluateInstruction(constants, instr);
106
if (value !== null) {
107
instr.value = value;
108
- constants.set(instr.lvalue.place.identifier.id, value);
108
+ constants.set(instr.lvalue.identifier.id, value);
109
}
110
}
111
compiler/forget/src/Optimization/DeadCodeElimination.ts
+3
-3
@@ -39,14 +39,14 @@ export function deadCodeElimination(fn: HIRFunction): void {
39
for (let i = block.instructions.length - 1; i >= 0; i--) {
40
const instr = block.instructions[i]!;
41
if (
42
- !used.has(instr.lvalue.place.identifier) &&
42
+ !used.has(instr.lvalue.identifier) &&
43
pruneableValue(instr.value, used) &&
44
// Can't prune the last value of a value block, that's its value!
45
!(block.kind !== "block" && i === block.instructions.length - 1)
46
) {
47
continue;
48
}
49
- used.add(instr.lvalue.place.identifier);
49
+ used.add(instr.lvalue.identifier);
50
for (const operand of eachInstructionValueOperand(instr.value)) {
51
used.add(operand.identifier);
52
}
@@ -67,7 +67,7 @@ export function deadCodeElimination(fn: HIRFunction): void {
67
}
68
}
69
retainWhere(block.instructions, (instr) =>
70
- used.has(instr.lvalue.place.identifier)
70
+ used.has(instr.lvalue.identifier)
71
);
72
}
73
}
compiler/forget/src/ReactiveScopes/AlignReactiveScopesToBlockScopes.ts
+2
-7
@@ -7,7 +7,6 @@
7
8
import {
9
InstructionId,
10
- LValue,
10
Place,
11
ReactiveBlock,
12
ReactiveFunction,
@@ -74,12 +73,8 @@ class Visitor extends ReactiveFunctionVisitor<Context> {
73
state.visitScope(scope);
74
}
75
}
77
- override visitLValue(
78
- id: InstructionId,
79
- lvalue: LValue,
80
- state: Context
81
- ): void {
82
- const scope = getPlaceScope(id, lvalue.place);
76
+ override visitLValue(id: InstructionId, lvalue: Place, state: Context): void {
77
+ const scope = getPlaceScope(id, lvalue);
78
if (scope !== null) {
79
state.visitScope(scope);
80
}
compiler/forget/src/ReactiveScopes/BuildReactiveBlocks.ts
+1
-1
@@ -188,7 +188,7 @@ export function getInstructionScope({
188
"Expected lvalues to not be null when assigning scopes. " +
189
"Pruning lvalues too early can result in missing scope information."
190
);
191
- const lvalueScope = getPlaceScope(id, lvalue.place);
191
+ const lvalueScope = getPlaceScope(id, lvalue);
192
if (lvalueScope !== null) {
193
return lvalueScope;
194
}
compiler/forget/src/ReactiveScopes/BuildReactiveFunction.ts
+5
-6
@@ -18,7 +18,6 @@ import {
18
} from "../HIR";
19
import {
20
HIRFunction,
21
- InstructionKind,
21
ReactiveBreakTerminal,
22
ReactiveContinueTerminal,
23
ReactiveFunction,
@@ -471,7 +470,7 @@ class Driver {
470
kind: "instruction",
471
instruction: {
472
id: terminal.id,
474
- lvalue: { kind: InstructionKind.Const, place },
473
+ lvalue: place,
474
value,
475
loc: terminal.loc,
476
},
@@ -544,7 +543,7 @@ class Driver {
543
const instr = defaultBlock.instructions[0]!;
544
return {
545
block: defaultBlock.id,
547
- place: instr.lvalue!.place,
546
+ place: instr.lvalue!,
547
value: instr.value,
548
id: instr.id,
549
};
@@ -559,7 +558,7 @@ class Driver {
558
};
559
return {
560
block: defaultBlock.id,
562
- place: instr.lvalue!.place,
561
+ place: instr.lvalue!,
562
value: sequence,
563
id: instr.id,
564
};
@@ -578,7 +577,7 @@ class Driver {
577
{
578
id: init.id,
579
loc,
581
- lvalue: { kind: InstructionKind.Const, place: init.place },
580
+ lvalue: init.place,
581
value: init.value,
582
},
583
],
@@ -621,7 +620,7 @@ class Driver {
620
{
621
id: test.id,
622
loc: terminal.loc,
624
- lvalue: { kind: InstructionKind.Const, place: test.place },
623
+ lvalue: test.place,
624
value: test.value,
625
},
626
],
compiler/forget/src/ReactiveScopes/CodegenReactiveFunction.ts
+17
-28
@@ -488,38 +488,27 @@ function codegenInstruction(
488
if (instr.lvalue === null) {
489
return t.expressionStatement(value);
490
}
491
- if (instr.lvalue.place.identifier.name === null) {
491
+ if (instr.lvalue.identifier.name === null) {
492
// temporary
493
- cx.temp.set(instr.lvalue.place.identifier.id, value);
493
+ cx.temp.set(instr.lvalue.identifier.id, value);
494
return t.emptyStatement();
495
} else {
496
- if (instr.lvalue.kind !== InstructionKind.Const) {
497
- CompilerError.invariant(
498
- `Expected all instruction lvalues to be const declarations`,
499
- instr.lvalue.place.loc
500
- );
501
- }
502
- const kind = cx.hasDeclared(instr.lvalue.place.identifier)
496
+ const kind = cx.hasDeclared(instr.lvalue.identifier)
497
? InstructionKind.Reassign
504
- : instr.lvalue.kind;
505
- switch (kind) {
506
- case InstructionKind.Const: {
507
- return createVariableDeclaration(instr.loc, "const", [
508
- t.variableDeclarator(codegenLVal(instr.lvalue), value),
509
- ]);
510
- }
511
- case InstructionKind.Reassign: {
512
- return createExpressionStatement(
513
- instr.loc,
514
- t.assignmentExpression("=", codegenLVal(instr.lvalue), value)
515
- );
516
- }
517
- default: {
518
- assertExhaustive(
519
- kind,
520
- `Unexpected instruction kind '${instr.lvalue.kind}'`
521
- );
522
- }
498
+ : InstructionKind.Const;
499
+ if (cx.hasDeclared(instr.lvalue.identifier)) {
500
+ return createExpressionStatement(
501
+ instr.loc,
502
+ t.assignmentExpression(
503
+ "=",
504
+ convertIdentifier(instr.lvalue.identifier),
505
+ value
506
+ )
507
+ );
508
+ } else {
509
+ return createVariableDeclaration(instr.loc, "const", [
510
+ t.variableDeclarator(convertIdentifier(instr.lvalue.identifier), value),
511
+ ]);
512
}
513
}
514
}
compiler/forget/src/ReactiveScopes/InferReactiveIdentifiers.ts
+2
-2
@@ -63,7 +63,7 @@ class Visitor extends ReactiveFunctionVisitor<State> {
63
// allow treating safe hooks as non-reactive.
64
hasReactiveInput = true;
65
}
66
- state.reactivityMap.set(lval.place.identifier.id, hasReactiveInput);
66
+ state.reactivityMap.set(lval.identifier.id, hasReactiveInput);
67
68
if (hasReactiveInput) {
69
// all mutating effects must also be marked as reactive
@@ -98,7 +98,7 @@ class Visitor extends ReactiveFunctionVisitor<State> {
98
if (instr.lvalue !== null) {
99
if (instr.value.kind === "LoadLocal") {
100
state.temporaries.set(
101
- instr.lvalue.place.identifier.id,
101
+ instr.lvalue.identifier.id,
102
instr.value.place.identifier.id
103
);
104
}
compiler/forget/src/ReactiveScopes/InferReactiveScopeVariables.ts
+2
-2
@@ -98,9 +98,9 @@ export function inferReactiveScopeVariables(fn: HIRFunction): void {
98
99
for (const instr of block.instructions) {
100
const operands: Array<Identifier> = [];
101
- const range = instr.lvalue.place.identifier.mutableRange;
101
+ const range = instr.lvalue.identifier.mutableRange;
102
if (range.end > range.start + 1 || mayAllocate(instr.value)) {
103
- operands.push(instr.lvalue!.place.identifier);
103
+ operands.push(instr.lvalue!.identifier);
104
}
105
if (instr.value.kind === "StoreLocal") {
106
if (
compiler/forget/src/ReactiveScopes/MergeOverlappingReactiveScopes.ts
+2
-7
@@ -7,7 +7,6 @@
7
8
import {
9
InstructionId,
10
- LValue,
10
makeInstructionId,
11
Place,
12
ReactiveBlock,
@@ -113,12 +112,8 @@ class Visitor extends ReactiveFunctionVisitor<Context> {
112
override visitPlace(id: InstructionId, place: Place, state: Context): void {
113
state.visitPlace(id, place);
114
}
116
- override visitLValue(
117
- id: InstructionId,
118
- lvalue: LValue,
119
- state: Context
120
- ): void {
121
- state.visitPlace(id, lvalue.place);
115
+ override visitLValue(id: InstructionId, lvalue: Place, state: Context): void {
116
+ state.visitPlace(id, lvalue);
117
}
118
override visitBlock(block: ReactiveBlock, state: Context): void {
119
state.enter(() => {
compiler/forget/src/ReactiveScopes/PrintReactiveFunction.ts
+3
-2
@@ -17,7 +17,6 @@ import {
17
import {
18
printIdentifier,
19
printInstructionValue,
20
- printLValue,
20
printPlace,
21
} from "../HIR/PrintHIR";
22
import { assertExhaustive } from "../Utils/utils";
@@ -85,7 +84,9 @@ function printReactiveInstruction(
84
const id = `[${instruction.id}]`;
85
86
if (instruction.lvalue !== null) {
88
- writer.write(`${id} ${printLValue(instruction.lvalue)} = `);
87
+ writer.write(
88
+ `${id} ${printIdentifier(instruction.lvalue.identifier)} = `
89
+ );
90
printReactiveValue(writer, instruction.value);
91
writer.newline();
92
} else {
compiler/forget/src/ReactiveScopes/PromoteUsedTemporaries.ts
+2
-2
@@ -56,10 +56,10 @@ class Visitor extends ReactiveFunctionVisitor<VisitorState> {
56
this.traverseInstruction(instruction, state);
57
if (
58
instruction.lvalue !== null &&
59
- instruction.lvalue.place.identifier.name === null &&
59
+ instruction.lvalue.identifier.name === null &&
60
instruction.value.kind !== "LoadLocal"
61
) {
62
- state.temporaries.set(instruction.lvalue.place.identifier, 0);
62
+ state.temporaries.set(instruction.lvalue.identifier, 0);
63
}
64
}
65
}
compiler/forget/src/ReactiveScopes/PropagateScopeDependencies.ts
+5
-6
@@ -11,7 +11,6 @@ import {
11
IdentifierId,
12
InstructionId,
13
InstructionKind,
14
- LValue,
14
makeInstructionId,
15
Place,
16
ReactiveBlock,
@@ -680,20 +679,20 @@ function visitInstructionValue(
679
context: Context,
680
id: InstructionId,
681
value: ReactiveValue,
683
- lvalue: LValue | null
682
+ lvalue: Place | null
683
): void {
684
if (value.kind === "LoadLocal" && lvalue !== null) {
685
if (
686
value.place.identifier.name !== null &&
688
- lvalue.place.identifier.name === null
687
+ lvalue.identifier.name === null
688
) {
690
- context.declareTemporary(lvalue.place, value.place);
689
+ context.declareTemporary(lvalue, value.place);
690
} else {
691
context.visitOperand(value.place);
692
}
693
} else if (value.kind === "PropertyLoad") {
694
if (lvalue !== null) {
696
- context.declareProperty(lvalue.place, value.object, value.property);
695
+ context.declareProperty(lvalue, value.object, value.property);
696
} else {
697
context.visitProperty(value.object, value.property);
698
}
@@ -717,7 +716,7 @@ function visitInstruction(context: Context, instr: ReactiveInstruction): void {
716
if (lvalue == null) {
717
return;
718
}
720
- context.declare(lvalue.place.identifier, {
719
+ context.declare(lvalue.identifier, {
720
id: instr.id,
721
scope: context.currentScope,
722
});
compiler/forget/src/ReactiveScopes/PruneTemporaryLValues.ts
+2
-4
@@ -8,7 +8,6 @@
8
import {
9
Identifier,
10
InstructionId,
11
- InstructionKind,
11
Place,
12
ReactiveFunction,
13
ReactiveInstruction,
@@ -40,10 +39,9 @@ class Visitor extends ReactiveFunctionVisitor<LValues> {
39
this.traverseInstruction(instruction, state);
40
if (
41
instruction.lvalue !== null &&
43
- instruction.lvalue.kind === InstructionKind.Const &&
44
- instruction.lvalue.place.identifier.name === null
42
+ instruction.lvalue.identifier.name === null
43
) {
46
- state.set(instruction.lvalue.place.identifier, instruction);
44
+ state.set(instruction.lvalue.identifier, instruction);
45
}
46
}
47
}
compiler/forget/src/ReactiveScopes/RenameVariables.ts
+1
-1
@@ -60,7 +60,7 @@ class Visitor extends ReactiveFunctionVisitor<Scopes> {
60
state.visit(operand.identifier);
61
}
62
if (instruction.lvalue !== null) {
63
- state.visit(instruction.lvalue.place.identifier);
63
+ state.visit(instruction.lvalue.identifier);
64
}
65
}
66
override visitScope(scope: ReactiveScopeBlock, state: Scopes): void {
compiler/forget/src/ReactiveScopes/visitors.ts
+1
-2
@@ -7,7 +7,6 @@
7
8
import {
9
InstructionId,
10
- LValue,
10
Place,
11
ReactiveBlock,
12
ReactiveFunction,
@@ -31,7 +30,7 @@ export function visitReactiveFunction<TState>(
30
31
export class ReactiveFunctionVisitor<TState = void> {
32
visitID(_id: InstructionId, _state: TState): void {}
34
- visitLValue(_id: InstructionId, _lvalue: LValue, _state: TState): void {}
33
+ visitLValue(_id: InstructionId, _lvalue: Place, _state: TState): void {}
34
visitPlace(_id: InstructionId, _place: Place, _state: TState): void {}
35
36
visitValue(id: InstructionId, value: ReactiveValue, state: TState): void {
compiler/forget/src/SSA/EliminateRedundantPhi.ts
+1
-1
@@ -82,7 +82,7 @@ export function eliminateRedundantPhi(fn: HIRFunction) {
82
for (const place of eachInstructionOperand(instr)) {
83
rewritePlace(place, rewrites);
84
}
85
- rewritePlace(instr.lvalue.place, rewrites);
85
+ rewritePlace(instr.lvalue, rewrites);
86
}
87
88
// Rewrite all terminal operands
compiler/forget/src/SSA/EnterSSA.ts
+2
-5
@@ -7,7 +7,6 @@ import {
7
HIRFunction,
8
Identifier,
9
IdentifierId,
10
- InstructionKind,
10
makeInstructionId,
11
makeType,
12
Phi,
@@ -215,7 +214,6 @@ export default function enterSSA(func: HIRFunction): void {
214
if (instr.value.kind === "StoreLocal") {
215
const oldPlace = instr.value.lvalue.place;
216
const newPlace = builder.definePlace(oldPlace);
218
- instr.lvalue.kind = InstructionKind.Const;
217
instr.value.lvalue.place = newPlace;
218
219
instr.value.value = builder.getPlace(instr.value.value);
@@ -223,10 +221,9 @@ export default function enterSSA(func: HIRFunction): void {
221
mapInstructionOperands(instr, (place) => builder.getPlace(place));
222
}
223
226
- const oldPlace = instr.lvalue.place;
224
+ const oldPlace = instr.lvalue;
225
const newPlace = builder.definePlace(oldPlace);
228
- instr.lvalue.kind = InstructionKind.Const;
229
- instr.lvalue.place = newPlace;
226
+ instr.lvalue = newPlace;
227
}
228
229
mapTerminalOperands(block.terminal, (place) => builder.getPlace(place));
compiler/forget/src/SSA/LeaveSSA.ts
+13
-30
@@ -112,17 +112,6 @@ export function leaveSSA(fn: HIRFunction): void {
112
// `let` or `reassign` where possible.
113
const { lvalue, value } = instr;
114
if (
115
- lvalue.kind === InstructionKind.Const &&
116
- rewrites.has(lvalue.place.identifier)
117
- ) {
118
- // For rewrites, the declaration of the canonical identifier has to be `let`,
119
- // all other assignments are reassignments (which we annotate for codegen
120
- // purposes).
121
- lvalue.kind =
122
- rewrites.get(lvalue.place.identifier) === lvalue.place.identifier
123
- ? InstructionKind.Let
124
- : InstructionKind.Reassign;
125
- } else if (
115
value.kind === "StoreLocal" &&
116
value.lvalue.place.identifier.name != null
117
) {
@@ -147,7 +136,7 @@ export function leaveSSA(fn: HIRFunction): void {
136
? InstructionKind.Let
137
: InstructionKind.Reassign;
138
}
150
- rewritePlace(lvalue.place, rewrites, declarations);
139
+ rewritePlace(lvalue, rewrites, declarations);
140
for (const operand of eachInstructionValueOperand(instr.value)) {
141
rewritePlace(operand, rewrites, declarations);
142
}
@@ -260,10 +249,7 @@ export function leaveSSA(fn: HIRFunction): void {
249
};
250
block.instructions.push({
251
id: block.terminal.id,
263
- lvalue: {
264
- place: { ...initValue, effect: Effect.Mutate },
265
- kind: InstructionKind.Const,
266
- },
252
+ lvalue: { ...initValue, effect: Effect.Mutate },
253
value: {
254
kind: "Primitive",
255
// TODO: consider leaving the variable uninitialized rather than explicitly undefined.
@@ -295,22 +281,19 @@ export function leaveSSA(fn: HIRFunction): void {
281
// the if) to the phi, so it's safe to reuse the terminal's id.
282
id: block.terminal.id,
283
lvalue: {
298
- place: {
299
- kind: "Identifier",
300
- identifier: {
301
- id: fn.env.nextIdentifierId,
302
- mutableRange: {
303
- start: block.terminal.id,
304
- end: makeInstructionId(block.terminal.id + 1),
305
- },
306
- name: null,
307
- scope: null,
308
- type: phi.id.type,
284
+ kind: "Identifier",
285
+ identifier: {
286
+ id: fn.env.nextIdentifierId,
287
+ mutableRange: {
288
+ start: block.terminal.id,
289
+ end: makeInstructionId(block.terminal.id + 1),
290
},
310
- effect: Effect.Mutate,
311
- loc: GeneratedSource,
291
+ name: null,
292
+ scope: null,
293
+ type: phi.id.type,
294
},
313
- kind: InstructionKind.Const,
295
+ effect: Effect.Mutate,
296
+ loc: GeneratedSource,
297
},
298
value: {
299
kind: "StoreLocal",
compiler/forget/src/TypeInference/InferTypes.ts
+2
-2
@@ -54,7 +54,7 @@ function apply(func: HIRFunction, unifier: Unifier) {
54
place.identifier.type = unifier.get(place.identifier.type);
55
}
56
const { lvalue } = instr;
57
- lvalue.place.identifier.type = unifier.get(lvalue.place.identifier.type);
57
+ lvalue.identifier.type = unifier.get(lvalue.identifier.type);
58
}
59
}
60
}
@@ -93,7 +93,7 @@ function* generateInstructionTypes(
93
instr: Instruction
94
): Generator<TypeEquation, void, undefined> {
95
const { lvalue, value } = instr;
96
- const left = lvalue.place.identifier.type;
96
+ const left = lvalue.identifier.type;
97
98
switch (value.kind) {
99
case "JSXText":