[storelocal] Instruction lvalue is just a Place

This commit is contained in:
Joe Savona
2023-03-02 14:19:18 -08:00
parent f4abf0a9ee
commit 36d1fa2569
30 changed files with 143 additions and 217 deletions
+35 -56
View File
@@ -614,7 +614,7 @@ function lowerStatement(
value = buildTemporaryPlace(builder, id.node.loc ?? GeneratedSource);
builder.push({
id: makeInstructionId(0),
lvalue: { place: { ...value }, kind: InstructionKind.Const },
lvalue: { ...value },
value: {
kind: "Primitive",
value: undefined,
@@ -647,7 +647,7 @@ function lowerStatement(
);
builder.push({
id: makeInstructionId(0),
lvalue: { kind: InstructionKind.Const, place },
lvalue: place,
value,
loc: stmt.node.loc ?? GeneratedSource,
});
@@ -746,13 +746,10 @@ function lowerStatement(
});
builder.push({
id: makeInstructionId(0),
lvalue: {
place: buildTemporaryPlace(
builder,
stmtPath.node.loc ?? GeneratedSource
),
kind: InstructionKind.Const,
},
lvalue: buildTemporaryPlace(
builder,
stmtPath.node.loc ?? GeneratedSource
),
loc: stmtPath.node.loc ?? GeneratedSource,
value: {
kind: "UnsupportedNode",
@@ -1043,7 +1040,7 @@ function lowerExpression(
const consequentBlock = builder.enter("value", (_blockId) => {
builder.push({
id: makeInstructionId(0),
lvalue: { kind: InstructionKind.Reassign, place: { ...place } },
lvalue: { ...place },
value: lowerExpression(builder, expr.get("consequent")),
loc: exprLoc,
});
@@ -1058,7 +1055,7 @@ function lowerExpression(
const alternateBlock = builder.enter("value", (_blockId) => {
builder.push({
id: makeInstructionId(0),
lvalue: { kind: InstructionKind.Reassign, place: { ...place } },
lvalue: { ...place },
value: lowerExpression(builder, expr.get("alternate")),
loc: exprLoc,
});
@@ -1106,7 +1103,7 @@ function lowerExpression(
const consequent = builder.enter("value", () => {
builder.push({
id: makeInstructionId(0),
lvalue: { kind: InstructionKind.Reassign, place: { ...place } },
lvalue: { ...place },
value: {
kind: "LoadLocal",
place: { ...leftPlace },
@@ -1124,7 +1121,7 @@ function lowerExpression(
const alternate = builder.enter("value", () => {
builder.push({
id: makeInstructionId(0),
lvalue: { kind: InstructionKind.Reassign, place: { ...place } },
lvalue: { ...place },
value: lowerExpression(builder, expr.get("right")),
loc: exprLoc,
});
@@ -1148,7 +1145,7 @@ function lowerExpression(
);
builder.push({
id: makeInstructionId(0),
lvalue: { kind: InstructionKind.Reassign, place: { ...leftPlace } },
lvalue: { ...leftPlace },
value: lowerExpression(builder, expr.get("left")),
loc: exprLoc,
});
@@ -1225,8 +1222,7 @@ function lowerExpression(
builder.push({
id: makeInstructionId(0),
lvalue: {
place: { ...binaryPlace },
kind: InstructionKind.Const,
...binaryPlace,
},
value: {
kind: "BinaryExpression",
@@ -1240,7 +1236,7 @@ function lowerExpression(
const result = buildTemporaryPlace(builder, exprLoc);
builder.push({
id: makeInstructionId(0),
lvalue: { place: { ...result }, kind: InstructionKind.Const },
lvalue: { ...result },
value: {
kind: "StoreLocal",
lvalue: {
@@ -1270,8 +1266,7 @@ function lowerExpression(
builder.push({
id: makeInstructionId(0),
lvalue: {
place: { ...previousValuePlace },
kind: InstructionKind.Const,
...previousValuePlace,
},
value,
loc: leftExpr.node.loc ?? GeneratedSource,
@@ -1281,8 +1276,7 @@ function lowerExpression(
builder.push({
id: makeInstructionId(0),
lvalue: {
place: { ...newValuePlace },
kind: InstructionKind.Const,
...newValuePlace,
},
value: {
kind: "BinaryExpression",
@@ -1332,7 +1326,7 @@ function lowerExpression(
const place: Place = buildTemporaryPlace(builder, exprLoc);
builder.push({
id: makeInstructionId(0),
lvalue: { place: { ...place }, kind: InstructionKind.Const },
lvalue: { ...place },
value,
loc: exprLoc,
});
@@ -1581,7 +1575,7 @@ function lowerExpression(
);
builder.push({
id: makeInstructionId(0),
lvalue: { place: { ...primitiveTemp }, kind: InstructionKind.Const },
lvalue: { ...primitiveTemp },
value: {
kind: "Primitive",
value: 1,
@@ -1599,7 +1593,7 @@ function lowerExpression(
);
builder.push({
id: makeInstructionId(0),
lvalue: { place: { ...temp }, kind: InstructionKind.Const },
lvalue: { ...temp },
value: {
kind: "BinaryExpression",
operator: expr.node.operator === "++" ? "+" : "-",
@@ -1611,16 +1605,10 @@ function lowerExpression(
});
builder.push({
id: makeInstructionId(0),
lvalue: {
place: buildTemporaryPlace(builder, exprLoc),
kind: InstructionKind.Const,
},
lvalue: buildTemporaryPlace(builder, exprLoc),
value: {
kind: "StoreLocal",
lvalue: {
place: { ...identifier },
kind: InstructionKind.Reassign,
},
lvalue: { place: { ...identifier }, kind: InstructionKind.Reassign },
value: { ...temp },
loc: exprLoc,
},
@@ -1723,7 +1711,7 @@ function lowerJsxElementName(
loc: exprLoc,
},
loc: exprLoc,
lvalue: { place: { ...place }, kind: InstructionKind.Const },
lvalue: { ...place },
});
return { ...place };
}
@@ -1740,9 +1728,9 @@ function lowerJsxElementName(
loc: exprLoc,
},
loc: exprLoc,
lvalue: { place, kind: InstructionKind.Const },
lvalue: { ...place },
});
return { ...place };
return place;
}
}
@@ -1777,7 +1765,7 @@ function lowerJsxElement(
loc: exprLoc,
},
loc: exprLoc,
lvalue: { place: { ...place }, kind: InstructionKind.Const },
lvalue: { ...place },
});
return { ...place };
}
@@ -1792,7 +1780,7 @@ function lowerJsxElement(
loc: exprLoc,
},
loc: exprLoc,
lvalue: { place: { ...place }, kind: InstructionKind.Const },
lvalue: { ...place },
});
return place;
} else {
@@ -1812,7 +1800,7 @@ function lowerJsxElement(
loc: exprLoc,
},
loc: exprLoc,
lvalue: { place: { ...place }, kind: InstructionKind.Const },
lvalue: { ...place },
});
return place;
}
@@ -1832,7 +1820,7 @@ function lowerExpressionToTemporary(
id: makeInstructionId(0),
value: value,
loc: exprLoc,
lvalue: { place: { ...place }, kind: InstructionKind.Const },
lvalue: { ...place },
});
return place;
}
@@ -1851,7 +1839,7 @@ function lowerExpressionToPlace(
id: makeInstructionId(0),
value: value,
loc: exprLoc,
lvalue: { place: { ...place }, kind: InstructionKind.Const },
lvalue: { ...place },
});
return place;
}
@@ -1869,10 +1857,7 @@ function lowerExpressionToVoid(
id: makeInstructionId(0),
value: instr,
loc: exprLoc,
lvalue: {
place: buildTemporaryPlace(builder, exprLoc),
kind: InstructionKind.Const,
},
lvalue: buildTemporaryPlace(builder, exprLoc),
});
}
@@ -1899,10 +1884,7 @@ function lowerIdentifier(
id: makeInstructionId(0),
value,
loc: place.loc,
lvalue: {
place: { ...place },
kind: InstructionKind.Const,
},
lvalue: { ...place },
});
return place;
}
@@ -1972,13 +1954,10 @@ function lowerAssignment(
};
builder.push({
id: makeInstructionId(0),
lvalue: { place: { ...temporary }, kind },
lvalue: { ...temporary },
value: {
kind: "StoreLocal",
lvalue: {
place: { ...place },
kind,
},
lvalue: { place: { ...place }, kind },
value,
loc,
},
@@ -2050,7 +2029,7 @@ function lowerAssignment(
);
builder.push({
id: makeInstructionId(0),
lvalue: { place: { ...property }, kind: InstructionKind.Const },
lvalue: { ...property },
value: {
kind: "Primitive",
value: i,
@@ -2061,7 +2040,7 @@ function lowerAssignment(
const propertyPlace = buildTemporaryPlace(builder, property.loc);
builder.push({
id: makeInstructionId(0),
lvalue: { place: { ...propertyPlace }, kind: InstructionKind.Const },
lvalue: { ...propertyPlace },
value: {
kind: "ComputedLoad",
loc,
@@ -2123,7 +2102,7 @@ function lowerAssignment(
);
builder.push({
id: makeInstructionId(0),
lvalue: { place: { ...propertyPlace }, kind: InstructionKind.Const },
lvalue: { ...propertyPlace },
value: {
kind: "PropertyLoad",
loc,
+2 -2
View File
@@ -81,7 +81,7 @@ export type ReactiveTerminalStatement<
export type ReactiveInstruction = {
id: InstructionId;
lvalue: LValue | null;
lvalue: Place | null;
value: ReactiveValue;
loc: SourceLocation;
};
@@ -365,7 +365,7 @@ export type TernaryTerminal = {
*/
export type Instruction = {
id: InstructionId;
lvalue: LValue;
lvalue: Place;
value: InstructionValue;
loc: SourceLocation;
};
@@ -12,7 +12,6 @@ import {
GeneratedSource,
HIRFunction,
Instruction,
InstructionKind,
} from "./HIR";
/**
@@ -60,13 +59,10 @@ export function mergeConsecutiveBlocks(fn: HIRFunction): void {
const instr: Instruction = {
id: predecessor.terminal.id,
lvalue: {
place: {
kind: "Identifier",
identifier: phi.id,
effect: Effect.Mutate,
loc: GeneratedSource,
},
kind: InstructionKind.Const,
kind: "Identifier",
identifier: phi.id,
effect: Effect.Mutate,
loc: GeneratedSource,
},
value: {
kind: "LoadLocal",
+1 -1
View File
@@ -106,7 +106,7 @@ export function printInstruction(instr: ReactiveInstruction): string {
const value = printInstructionValue(instr.value);
if (instr.lvalue !== null) {
return `${id} ${printLValue(instr.lvalue)} = ${value}`;
return `${id} ${printPlace(instr.lvalue)} = ${value}`;
} else {
return `${id} ${value}`;
}
@@ -29,17 +29,13 @@ export function validateConsistentIdentifiers(fn: HIRFunction): void {
}
}
for (const instr of block.instructions) {
if (instr.lvalue.place.identifier.name !== null) {
if (instr.lvalue.identifier.name !== null) {
CompilerError.invariant(
`Expected all lvalues to be temporaries, found '${instr.lvalue.place.identifier.name}'`,
instr.lvalue.place.loc
`Expected all lvalues to be temporaries, found '${instr.lvalue.identifier.name}'`,
instr.lvalue.loc
);
}
validate(
identifiers,
instr.lvalue.place.identifier,
instr.lvalue.place.loc
);
validate(identifiers, instr.lvalue.identifier, instr.lvalue.loc);
for (const operand of eachInstructionValueOperand(instr.value)) {
validate(identifiers, operand.identifier, operand.loc);
}
+1 -1
View File
@@ -594,7 +594,7 @@ export function* eachBlockOperand(block: BasicBlock): Iterable<Place> {
for (const instr of block.instructions) {
yield* eachInstructionOperand(instr);
if (instr.lvalue != null) {
yield instr.lvalue.place;
yield instr.lvalue;
}
}
yield* eachTerminalOperand(block.terminal);
@@ -56,15 +56,15 @@ export default function analyseFunctions(func: HIRFunction) {
}
case "PropertyLoad": {
state.declareProperty(
instr.lvalue.place,
instr.lvalue,
instr.value.object,
instr.value.property
);
break;
}
case "LoadLocal": {
if (instr.lvalue.place.identifier.name === null) {
state.declareTemporary(instr.lvalue.place, instr.value.place);
if (instr.lvalue.identifier.name === null) {
state.declareTemporary(instr.lvalue, instr.value.place);
}
break;
}
+1 -1
View File
@@ -49,5 +49,5 @@ function inferInstr(instr: Instruction, aliases: DisjointSet<Identifier>) {
return;
}
aliases.union([lvalue.place.identifier, alias.identifier]);
aliases.union([lvalue.identifier, alias.identifier]);
}
@@ -21,7 +21,7 @@ export function inferAliasForStores(
for (const [_, block] of func.body.blocks) {
for (const instr of block.instructions) {
const { value, lvalue } = instr;
if (lvalue.place.effect !== Effect.Store) {
if (lvalue.effect !== Effect.Store) {
continue;
}
if (value.kind === "StoreLocal") {
@@ -32,7 +32,7 @@ export function inferAliasForStores(
operand.effect === Effect.Capture ||
operand.effect === Effect.Store
) {
maybeAlias(aliases, lvalue.place, operand, instr.id);
maybeAlias(aliases, lvalue, operand, instr.id);
}
}
}
@@ -129,7 +129,7 @@ export function inferMutableLifetimes(
}
}
const lvalueId = instr.lvalue.place.identifier;
const lvalueId = instr.lvalue.identifier;
// lvalue start being mutable when they're initially assigned a
// value.
@@ -655,8 +655,8 @@ function inferBlock(
);
}
state.initialize(instrValue, ValueKind.Mutable);
state.define(instr.lvalue.place, instrValue);
instr.lvalue.place.effect = Effect.Store;
state.define(instr.lvalue, instrValue);
instr.lvalue.effect = Effect.Store;
continue;
}
case "PropertyCall": {
@@ -676,8 +676,8 @@ function inferBlock(
state.reference(arg, Effect.Mutate);
}
state.initialize(instrValue, ValueKind.Mutable);
state.define(instr.lvalue.place, instrValue);
instr.lvalue.place.effect = Effect.Mutate;
state.define(instr.lvalue, instrValue);
instr.lvalue.effect = Effect.Mutate;
continue;
}
case "ComputedCall": {
@@ -698,8 +698,8 @@ function inferBlock(
state.reference(arg, Effect.Mutate);
}
state.initialize(instrValue, ValueKind.Mutable);
state.define(instr.lvalue.place, instrValue);
instr.lvalue.place.effect = Effect.Mutate;
state.define(instr.lvalue, instrValue);
instr.lvalue.effect = Effect.Mutate;
continue;
}
case "PropertyStore": {
@@ -711,8 +711,8 @@ function inferBlock(
state.reference(instrValue.object, Effect.Store);
const lvalue = instr.lvalue;
state.alias(lvalue.place, instrValue.value);
lvalue.place.effect = Effect.Store;
state.alias(lvalue, instrValue.value);
lvalue.effect = Effect.Store;
continue;
}
case "PropertyLoad": {
@@ -729,9 +729,9 @@ function inferBlock(
state.reference(instrValue.object, Effect.Read);
const lvalue = instr.lvalue;
lvalue.place.effect = Effect.Mutate;
lvalue.effect = Effect.Mutate;
state.initialize(instrValue, state.kind(instrValue.object));
state.define(lvalue.place, instrValue);
state.define(lvalue, instrValue);
continue;
}
case "ComputedStore": {
@@ -744,8 +744,8 @@ function inferBlock(
state.reference(instrValue.object, Effect.Store);
const lvalue = instr.lvalue;
state.alias(lvalue.place, instrValue.value);
lvalue.place.effect = Effect.Store;
state.alias(lvalue, instrValue.value);
lvalue.effect = Effect.Store;
continue;
}
case "ComputedLoad": {
@@ -763,9 +763,9 @@ function inferBlock(
state.reference(instrValue.object, Effect.Read);
state.reference(instrValue.property, Effect.Read);
const lvalue = instr.lvalue;
lvalue.place.effect = Effect.Mutate;
lvalue.effect = Effect.Mutate;
state.initialize(instrValue, state.kind(instrValue.object));
state.define(lvalue.place, instrValue);
state.define(lvalue, instrValue);
continue;
}
case "TypeCastExpression": {
@@ -778,16 +778,16 @@ function inferBlock(
state.initialize(instrValue, state.kind(instrValue.value));
state.reference(instrValue.value, Effect.Read);
const lvalue = instr.lvalue;
lvalue.place.effect = Effect.Mutate;
state.alias(lvalue.place, instrValue.value);
lvalue.effect = Effect.Mutate;
state.alias(lvalue, instrValue.value);
continue;
}
case "LoadLocal": {
state.reference(instrValue.place, Effect.Capture);
const lvalue = instr.lvalue;
lvalue.place.effect = Effect.Mutate;
lvalue.effect = Effect.Mutate;
// direct aliasing: `a = b`;
state.alias(lvalue.place, instrValue.place);
state.alias(lvalue, instrValue.place);
continue;
}
case "StoreLocal": {
@@ -799,8 +799,8 @@ function inferBlock(
state.reference(instrValue.value, effect);
const lvalue = instr.lvalue;
state.alias(lvalue.place, instrValue.value);
lvalue.place.effect = Effect.Store;
state.alias(lvalue, instrValue.value);
lvalue.effect = Effect.Store;
state.alias(instrValue.lvalue.place, instrValue.value);
instrValue.lvalue.place.effect = Effect.Store;
continue;
@@ -820,8 +820,8 @@ function inferBlock(
}
state.initialize(instrValue, valueKind);
state.define(instr.lvalue.place, instrValue);
instr.lvalue.place.effect = lvalueEffect;
state.define(instr.lvalue, instrValue);
instr.lvalue.effect = lvalueEffect;
}
const effect =
@@ -105,7 +105,7 @@ function applyConstantPropagation(fn: HIRFunction): boolean {
const value = evaluateInstruction(constants, instr);
if (value !== null) {
instr.value = value;
constants.set(instr.lvalue.place.identifier.id, value);
constants.set(instr.lvalue.identifier.id, value);
}
}
@@ -39,14 +39,14 @@ export function deadCodeElimination(fn: HIRFunction): void {
for (let i = block.instructions.length - 1; i >= 0; i--) {
const instr = block.instructions[i]!;
if (
!used.has(instr.lvalue.place.identifier) &&
!used.has(instr.lvalue.identifier) &&
pruneableValue(instr.value, used) &&
// Can't prune the last value of a value block, that's its value!
!(block.kind !== "block" && i === block.instructions.length - 1)
) {
continue;
}
used.add(instr.lvalue.place.identifier);
used.add(instr.lvalue.identifier);
for (const operand of eachInstructionValueOperand(instr.value)) {
used.add(operand.identifier);
}
@@ -67,7 +67,7 @@ export function deadCodeElimination(fn: HIRFunction): void {
}
}
retainWhere(block.instructions, (instr) =>
used.has(instr.lvalue.place.identifier)
used.has(instr.lvalue.identifier)
);
}
}
@@ -7,7 +7,6 @@
import {
InstructionId,
LValue,
Place,
ReactiveBlock,
ReactiveFunction,
@@ -74,12 +73,8 @@ class Visitor extends ReactiveFunctionVisitor<Context> {
state.visitScope(scope);
}
}
override visitLValue(
id: InstructionId,
lvalue: LValue,
state: Context
): void {
const scope = getPlaceScope(id, lvalue.place);
override visitLValue(id: InstructionId, lvalue: Place, state: Context): void {
const scope = getPlaceScope(id, lvalue);
if (scope !== null) {
state.visitScope(scope);
}
@@ -188,7 +188,7 @@ export function getInstructionScope({
"Expected lvalues to not be null when assigning scopes. " +
"Pruning lvalues too early can result in missing scope information."
);
const lvalueScope = getPlaceScope(id, lvalue.place);
const lvalueScope = getPlaceScope(id, lvalue);
if (lvalueScope !== null) {
return lvalueScope;
}
@@ -18,7 +18,6 @@ import {
} from "../HIR";
import {
HIRFunction,
InstructionKind,
ReactiveBreakTerminal,
ReactiveContinueTerminal,
ReactiveFunction,
@@ -471,7 +470,7 @@ class Driver {
kind: "instruction",
instruction: {
id: terminal.id,
lvalue: { kind: InstructionKind.Const, place },
lvalue: place,
value,
loc: terminal.loc,
},
@@ -544,7 +543,7 @@ class Driver {
const instr = defaultBlock.instructions[0]!;
return {
block: defaultBlock.id,
place: instr.lvalue!.place,
place: instr.lvalue!,
value: instr.value,
id: instr.id,
};
@@ -559,7 +558,7 @@ class Driver {
};
return {
block: defaultBlock.id,
place: instr.lvalue!.place,
place: instr.lvalue!,
value: sequence,
id: instr.id,
};
@@ -578,7 +577,7 @@ class Driver {
{
id: init.id,
loc,
lvalue: { kind: InstructionKind.Const, place: init.place },
lvalue: init.place,
value: init.value,
},
],
@@ -621,7 +620,7 @@ class Driver {
{
id: test.id,
loc: terminal.loc,
lvalue: { kind: InstructionKind.Const, place: test.place },
lvalue: test.place,
value: test.value,
},
],
@@ -488,38 +488,27 @@ function codegenInstruction(
if (instr.lvalue === null) {
return t.expressionStatement(value);
}
if (instr.lvalue.place.identifier.name === null) {
if (instr.lvalue.identifier.name === null) {
// temporary
cx.temp.set(instr.lvalue.place.identifier.id, value);
cx.temp.set(instr.lvalue.identifier.id, value);
return t.emptyStatement();
} else {
if (instr.lvalue.kind !== InstructionKind.Const) {
CompilerError.invariant(
`Expected all instruction lvalues to be const declarations`,
instr.lvalue.place.loc
);
}
const kind = cx.hasDeclared(instr.lvalue.place.identifier)
const kind = cx.hasDeclared(instr.lvalue.identifier)
? InstructionKind.Reassign
: instr.lvalue.kind;
switch (kind) {
case InstructionKind.Const: {
return createVariableDeclaration(instr.loc, "const", [
t.variableDeclarator(codegenLVal(instr.lvalue), value),
]);
}
case InstructionKind.Reassign: {
return createExpressionStatement(
instr.loc,
t.assignmentExpression("=", codegenLVal(instr.lvalue), value)
);
}
default: {
assertExhaustive(
kind,
`Unexpected instruction kind '${instr.lvalue.kind}'`
);
}
: InstructionKind.Const;
if (cx.hasDeclared(instr.lvalue.identifier)) {
return createExpressionStatement(
instr.loc,
t.assignmentExpression(
"=",
convertIdentifier(instr.lvalue.identifier),
value
)
);
} else {
return createVariableDeclaration(instr.loc, "const", [
t.variableDeclarator(convertIdentifier(instr.lvalue.identifier), value),
]);
}
}
}
@@ -63,7 +63,7 @@ class Visitor extends ReactiveFunctionVisitor<State> {
// allow treating safe hooks as non-reactive.
hasReactiveInput = true;
}
state.reactivityMap.set(lval.place.identifier.id, hasReactiveInput);
state.reactivityMap.set(lval.identifier.id, hasReactiveInput);
if (hasReactiveInput) {
// all mutating effects must also be marked as reactive
@@ -98,7 +98,7 @@ class Visitor extends ReactiveFunctionVisitor<State> {
if (instr.lvalue !== null) {
if (instr.value.kind === "LoadLocal") {
state.temporaries.set(
instr.lvalue.place.identifier.id,
instr.lvalue.identifier.id,
instr.value.place.identifier.id
);
}
@@ -98,9 +98,9 @@ export function inferReactiveScopeVariables(fn: HIRFunction): void {
for (const instr of block.instructions) {
const operands: Array<Identifier> = [];
const range = instr.lvalue.place.identifier.mutableRange;
const range = instr.lvalue.identifier.mutableRange;
if (range.end > range.start + 1 || mayAllocate(instr.value)) {
operands.push(instr.lvalue!.place.identifier);
operands.push(instr.lvalue!.identifier);
}
if (instr.value.kind === "StoreLocal") {
if (
@@ -7,7 +7,6 @@
import {
InstructionId,
LValue,
makeInstructionId,
Place,
ReactiveBlock,
@@ -113,12 +112,8 @@ class Visitor extends ReactiveFunctionVisitor<Context> {
override visitPlace(id: InstructionId, place: Place, state: Context): void {
state.visitPlace(id, place);
}
override visitLValue(
id: InstructionId,
lvalue: LValue,
state: Context
): void {
state.visitPlace(id, lvalue.place);
override visitLValue(id: InstructionId, lvalue: Place, state: Context): void {
state.visitPlace(id, lvalue);
}
override visitBlock(block: ReactiveBlock, state: Context): void {
state.enter(() => {
@@ -17,7 +17,6 @@ import {
import {
printIdentifier,
printInstructionValue,
printLValue,
printPlace,
} from "../HIR/PrintHIR";
import { assertExhaustive } from "../Utils/utils";
@@ -85,7 +84,9 @@ function printReactiveInstruction(
const id = `[${instruction.id}]`;
if (instruction.lvalue !== null) {
writer.write(`${id} ${printLValue(instruction.lvalue)} = `);
writer.write(
`${id} ${printIdentifier(instruction.lvalue.identifier)} = `
);
printReactiveValue(writer, instruction.value);
writer.newline();
} else {
@@ -56,10 +56,10 @@ class Visitor extends ReactiveFunctionVisitor<VisitorState> {
this.traverseInstruction(instruction, state);
if (
instruction.lvalue !== null &&
instruction.lvalue.place.identifier.name === null &&
instruction.lvalue.identifier.name === null &&
instruction.value.kind !== "LoadLocal"
) {
state.temporaries.set(instruction.lvalue.place.identifier, 0);
state.temporaries.set(instruction.lvalue.identifier, 0);
}
}
}
@@ -11,7 +11,6 @@ import {
IdentifierId,
InstructionId,
InstructionKind,
LValue,
makeInstructionId,
Place,
ReactiveBlock,
@@ -680,20 +679,20 @@ function visitInstructionValue(
context: Context,
id: InstructionId,
value: ReactiveValue,
lvalue: LValue | null
lvalue: Place | null
): void {
if (value.kind === "LoadLocal" && lvalue !== null) {
if (
value.place.identifier.name !== null &&
lvalue.place.identifier.name === null
lvalue.identifier.name === null
) {
context.declareTemporary(lvalue.place, value.place);
context.declareTemporary(lvalue, value.place);
} else {
context.visitOperand(value.place);
}
} else if (value.kind === "PropertyLoad") {
if (lvalue !== null) {
context.declareProperty(lvalue.place, value.object, value.property);
context.declareProperty(lvalue, value.object, value.property);
} else {
context.visitProperty(value.object, value.property);
}
@@ -717,7 +716,7 @@ function visitInstruction(context: Context, instr: ReactiveInstruction): void {
if (lvalue == null) {
return;
}
context.declare(lvalue.place.identifier, {
context.declare(lvalue.identifier, {
id: instr.id,
scope: context.currentScope,
});
@@ -8,7 +8,6 @@
import {
Identifier,
InstructionId,
InstructionKind,
Place,
ReactiveFunction,
ReactiveInstruction,
@@ -40,10 +39,9 @@ class Visitor extends ReactiveFunctionVisitor<LValues> {
this.traverseInstruction(instruction, state);
if (
instruction.lvalue !== null &&
instruction.lvalue.kind === InstructionKind.Const &&
instruction.lvalue.place.identifier.name === null
instruction.lvalue.identifier.name === null
) {
state.set(instruction.lvalue.place.identifier, instruction);
state.set(instruction.lvalue.identifier, instruction);
}
}
}
@@ -60,7 +60,7 @@ class Visitor extends ReactiveFunctionVisitor<Scopes> {
state.visit(operand.identifier);
}
if (instruction.lvalue !== null) {
state.visit(instruction.lvalue.place.identifier);
state.visit(instruction.lvalue.identifier);
}
}
override visitScope(scope: ReactiveScopeBlock, state: Scopes): void {
@@ -7,7 +7,6 @@
import {
InstructionId,
LValue,
Place,
ReactiveBlock,
ReactiveFunction,
@@ -31,7 +30,7 @@ export function visitReactiveFunction<TState>(
export class ReactiveFunctionVisitor<TState = void> {
visitID(_id: InstructionId, _state: TState): void {}
visitLValue(_id: InstructionId, _lvalue: LValue, _state: TState): void {}
visitLValue(_id: InstructionId, _lvalue: Place, _state: TState): void {}
visitPlace(_id: InstructionId, _place: Place, _state: TState): void {}
visitValue(id: InstructionId, value: ReactiveValue, state: TState): void {
@@ -82,7 +82,7 @@ export function eliminateRedundantPhi(fn: HIRFunction) {
for (const place of eachInstructionOperand(instr)) {
rewritePlace(place, rewrites);
}
rewritePlace(instr.lvalue.place, rewrites);
rewritePlace(instr.lvalue, rewrites);
}
// Rewrite all terminal operands
+2 -5
View File
@@ -7,7 +7,6 @@ import {
HIRFunction,
Identifier,
IdentifierId,
InstructionKind,
makeInstructionId,
makeType,
Phi,
@@ -215,7 +214,6 @@ export default function enterSSA(func: HIRFunction): void {
if (instr.value.kind === "StoreLocal") {
const oldPlace = instr.value.lvalue.place;
const newPlace = builder.definePlace(oldPlace);
instr.lvalue.kind = InstructionKind.Const;
instr.value.lvalue.place = newPlace;
instr.value.value = builder.getPlace(instr.value.value);
@@ -223,10 +221,9 @@ export default function enterSSA(func: HIRFunction): void {
mapInstructionOperands(instr, (place) => builder.getPlace(place));
}
const oldPlace = instr.lvalue.place;
const oldPlace = instr.lvalue;
const newPlace = builder.definePlace(oldPlace);
instr.lvalue.kind = InstructionKind.Const;
instr.lvalue.place = newPlace;
instr.lvalue = newPlace;
}
mapTerminalOperands(block.terminal, (place) => builder.getPlace(place));
+13 -30
View File
@@ -112,17 +112,6 @@ export function leaveSSA(fn: HIRFunction): void {
// `let` or `reassign` where possible.
const { lvalue, value } = instr;
if (
lvalue.kind === InstructionKind.Const &&
rewrites.has(lvalue.place.identifier)
) {
// For rewrites, the declaration of the canonical identifier has to be `let`,
// all other assignments are reassignments (which we annotate for codegen
// purposes).
lvalue.kind =
rewrites.get(lvalue.place.identifier) === lvalue.place.identifier
? InstructionKind.Let
: InstructionKind.Reassign;
} else if (
value.kind === "StoreLocal" &&
value.lvalue.place.identifier.name != null
) {
@@ -147,7 +136,7 @@ export function leaveSSA(fn: HIRFunction): void {
? InstructionKind.Let
: InstructionKind.Reassign;
}
rewritePlace(lvalue.place, rewrites, declarations);
rewritePlace(lvalue, rewrites, declarations);
for (const operand of eachInstructionValueOperand(instr.value)) {
rewritePlace(operand, rewrites, declarations);
}
@@ -260,10 +249,7 @@ export function leaveSSA(fn: HIRFunction): void {
};
block.instructions.push({
id: block.terminal.id,
lvalue: {
place: { ...initValue, effect: Effect.Mutate },
kind: InstructionKind.Const,
},
lvalue: { ...initValue, effect: Effect.Mutate },
value: {
kind: "Primitive",
// TODO: consider leaving the variable uninitialized rather than explicitly undefined.
@@ -295,22 +281,19 @@ export function leaveSSA(fn: HIRFunction): void {
// the if) to the phi, so it's safe to reuse the terminal's id.
id: block.terminal.id,
lvalue: {
place: {
kind: "Identifier",
identifier: {
id: fn.env.nextIdentifierId,
mutableRange: {
start: block.terminal.id,
end: makeInstructionId(block.terminal.id + 1),
},
name: null,
scope: null,
type: phi.id.type,
kind: "Identifier",
identifier: {
id: fn.env.nextIdentifierId,
mutableRange: {
start: block.terminal.id,
end: makeInstructionId(block.terminal.id + 1),
},
effect: Effect.Mutate,
loc: GeneratedSource,
name: null,
scope: null,
type: phi.id.type,
},
kind: InstructionKind.Const,
effect: Effect.Mutate,
loc: GeneratedSource,
},
value: {
kind: "StoreLocal",
@@ -54,7 +54,7 @@ function apply(func: HIRFunction, unifier: Unifier) {
place.identifier.type = unifier.get(place.identifier.type);
}
const { lvalue } = instr;
lvalue.place.identifier.type = unifier.get(lvalue.place.identifier.type);
lvalue.identifier.type = unifier.get(lvalue.identifier.type);
}
}
}
@@ -93,7 +93,7 @@ function* generateInstructionTypes(
instr: Instruction
): Generator<TypeEquation, void, undefined> {
const { lvalue, value } = instr;
const left = lvalue.place.identifier.type;
const left = lvalue.identifier.type;
switch (value.kind) {
case "JSXText":