mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
[storelocal] Instruction lvalue is just a Place
This commit is contained in:
@@ -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,
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -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":
|
||||
|
||||
Reference in New Issue
Block a user