[hir] Refactor out LoweredFunction from FunctionExpression

This commit is contained in:
Sathya Gunasekaran
2023-09-15 17:16:04 +01:00
parent 3bda9f78c3
commit 88f65d44a7
13 changed files with 35 additions and 29 deletions
@@ -2737,8 +2737,7 @@ function lowerFunctionExpression(
return {
kind: "FunctionExpression",
name,
loweredFunc,
dependencies: captured.refs,
loweredFunc: { func: loweredFunc, dependencies: captured.refs },
expr: expr.node,
loc: exprLoc,
};
@@ -557,11 +557,15 @@ export type ObjectProperty = {
place: Place;
};
export type LoweredFunction = {
dependencies: Array<Place>;
func: HIRFunction;
};
export type ObjectMethod = {
kind: "ObjectMethod";
dependencies: Array<Place>;
loweredFunc: HIRFunction;
loc: SourceLocation;
loweredFunc: LoweredFunction;
};
export enum InstructionKind {
@@ -844,8 +848,7 @@ export type JsxAttribute =
export type FunctionExpression = {
kind: "FunctionExpression";
name: string | null;
dependencies: Array<Place>;
loweredFunc: HIRFunction;
loweredFunc: LoweredFunction;
expr: t.ArrowFunctionExpression | t.FunctionExpression;
loc: SourceLocation;
};
@@ -33,7 +33,7 @@ export function mergeConsecutiveBlocks(fn: HIRFunction): void {
for (const [, block] of fn.body.blocks) {
for (const instr of block.instructions) {
if (instr.value.kind === "FunctionExpression") {
mergeConsecutiveBlocks(instr.value.loweredFunc);
mergeConsecutiveBlocks(instr.value.loweredFunc.func);
}
}
@@ -463,14 +463,14 @@ export function printInstructionValue(instrValue: ReactiveValue): string {
break;
}
case "FunctionExpression": {
const fn = printFunction(instrValue.loweredFunc)
const fn = printFunction(instrValue.loweredFunc.func)
.split("\n")
.map((line) => ` ${line}`)
.join("\n");
const deps = instrValue.dependencies
const deps = instrValue.loweredFunc.dependencies
.map((dep) => printPlace(dep))
.join(",");
const context = instrValue.loweredFunc.context
const context = instrValue.loweredFunc.func.context
.map((dep) => printPlace(dep))
.join(",");
value = `Function @deps[${deps}] @context[${context}]:\n${fn}`;
@@ -170,7 +170,7 @@ export function* eachInstructionValueOperand(
break;
}
case "FunctionExpression": {
yield* instrValue.dependencies;
yield* instrValue.loweredFunc.dependencies;
break;
}
case "TaggedTemplateExpression": {
@@ -457,7 +457,8 @@ export function mapInstructionOperands(
break;
}
case "FunctionExpression": {
instrValue.dependencies = instrValue.dependencies.map((d) => fn(d));
instrValue.loweredFunc.dependencies =
instrValue.loweredFunc.dependencies.map((d) => fn(d));
break;
}
case "TaggedTemplateExpression": {
@@ -71,7 +71,7 @@ export default function analyseFunctions(func: HIRFunction): void {
for (const instr of block.instructions) {
switch (instr.value.kind) {
case "FunctionExpression": {
lower(instr.value.loweredFunc);
lower(instr.value.loweredFunc.func);
infer(instr.value, state, func.context);
break;
}
@@ -118,7 +118,7 @@ function infer(
context: Place[]
): void {
const mutations = new Map<string, Effect>();
for (const operand of value.loweredFunc.context) {
for (const operand of value.loweredFunc.func.context) {
if (
isMutatedOrReassigned(operand.identifier) &&
operand.identifier.name !== null
@@ -128,7 +128,7 @@ function infer(
operand.identifier.mutableRange.end = operand.identifier.mutableRange.start;
}
for (const dep of value.dependencies) {
for (const dep of value.loweredFunc.dependencies) {
let name: string | null = null;
if (state.properties.has(dep.identifier)) {
@@ -174,7 +174,7 @@ function infer(
const effect = mutations.get(place.identifier.name);
if (effect !== undefined) {
place.effect = effect === Effect.Unknown ? Effect.Capture : effect;
value.dependencies.push(place);
value.loweredFunc.dependencies.push(place);
}
}
}
@@ -99,7 +99,7 @@ export function inlineUseMemo(fn: HIRFunction): void {
continue;
}
if (body.loweredFunc.params.length > 0) {
if (body.loweredFunc.func.params.length > 0) {
CompilerError.invalidReact({
reason: "useMemo callbacks may not accept any arguments",
description: null,
@@ -108,7 +108,10 @@ export function inlineUseMemo(fn: HIRFunction): void {
});
}
if (body.loweredFunc.async || body.loweredFunc.generator) {
if (
body.loweredFunc.func.async ||
body.loweredFunc.func.generator
) {
CompilerError.invalidReact({
reason:
"useMemo callbacks may not be async or generator functions",
@@ -141,7 +144,7 @@ export function inlineUseMemo(fn: HIRFunction): void {
// as if it were a single labeled statement, and replace all returns with gotos
// to the label fallthrough.
const newTerminal: LabelTerminal = {
block: body.loweredFunc.body.entry,
block: body.loweredFunc.func.body.entry,
id: makeInstructionId(0),
kind: "label",
fallthrough: continuationBlockId,
@@ -160,7 +163,7 @@ export function inlineUseMemo(fn: HIRFunction): void {
// Rewrite blocks from the lambda to replace any `return` with a
// store to the result and `goto` the continuation block
for (const [id, block] of body.loweredFunc.body.blocks) {
for (const [id, block] of body.loweredFunc.func.body.blocks) {
block.preds.clear();
rewriteBlock(fn.env, block, continuationBlockId, result);
fn.body.blocks.set(id, block);
@@ -107,7 +107,7 @@ function applyConstantPropagation(
for (const [, block] of fn.body.blocks) {
for (const instr of block.instructions) {
if (instr.value.kind === "FunctionExpression") {
for (const operand of instr.value.dependencies) {
for (const operand of instr.value.loweredFunc.dependencies) {
functionDependencies.add(operand.identifier.id);
}
}
@@ -434,7 +434,7 @@ function evaluateInstruction(
return placeValue;
}
case "FunctionExpression": {
constantPropagationImpl(value.loweredFunc, constants);
constantPropagationImpl(value.loweredFunc.func, constants);
return null;
}
default: {
@@ -1088,7 +1088,7 @@ function codegenInstructionValue(
break;
}
case "FunctionExpression": {
const loweredFunc = instrValue.loweredFunc;
const loweredFunc = instrValue.loweredFunc.func;
const reactiveFunction = buildReactiveFunction(loweredFunc);
pruneUnusedLabels(reactiveFunction);
pruneUnusedLValues(reactiveFunction);
@@ -107,7 +107,7 @@ export function eliminateRedundantPhi(
}
if (instr.value.kind === "FunctionExpression") {
const { context } = instr.value.loweredFunc;
const { context } = instr.value.loweredFunc.func;
for (const place of context) {
rewritePlace(place, rewrites);
}
@@ -115,7 +115,7 @@ export function eliminateRedundantPhi(
// recursive call to:
// - eliminate phi nodes in child node
// - propagate rewrites, which may have changed between iterations
eliminateRedundantPhi(instr.value.loweredFunc, rewrites);
eliminateRedundantPhi(instr.value.loweredFunc.func, rewrites);
}
}
@@ -267,7 +267,7 @@ function enterSSAImpl(
mapInstructionLValues(instr, (lvalue) => builder.definePlace(lvalue));
if (instr.value.kind === "FunctionExpression") {
const loweredFunc = instr.value.loweredFunc;
const loweredFunc = instr.value.loweredFunc.func;
const entry = loweredFunc.body.blocks.get(loweredFunc.body.entry)!;
CompilerError.invariant(entry.preds.size === 0, {
reason:
@@ -69,7 +69,7 @@ function apply(func: HIRFunction, unifier: Unifier): void {
lvalue.identifier.type = unifier.get(lvalue.identifier.type);
if (value.kind === "FunctionExpression") {
apply(value.loweredFunc, unifier);
apply(value.loweredFunc.func, unifier);
}
}
}
@@ -256,7 +256,7 @@ function* generateInstructionTypes(
}
case "FunctionExpression": {
yield* generate(value.loweredFunc);
yield* generate(value.loweredFunc.func);
break;
}
@@ -68,7 +68,7 @@ export function validateFrozenLambdas(fn: HIRFunction): void {
switch (instr.value.kind) {
case "FunctionExpression": {
if (
instr.value.dependencies.some(
instr.value.loweredFunc.dependencies.some(
(place) =>
place.effect === Effect.Mutate &&
!isRefValueType(place.identifier) &&