Scaffolding for ExpressionStatement instruction kind

Adds an `ExpressionStatement` instruction variant to model values that are 
otherwise "unused" but which we don't want to remove. The next diff changes 
BuildHIR to use this where appropriate.
This commit is contained in:
Joe Savona
2023-04-26 11:27:35 -07:00
parent 894cf6e37b
commit 2cb1c72305
9 changed files with 35 additions and 2 deletions
+8
View File
@@ -702,6 +702,14 @@ export type InstructionValue =
value: Place; // the collection
loc: SourceLocation;
}
// Represents a value that is unused but which we want to ensure is not dropped
// Examples include logical or ternary expressions that appear as expression statements,
// that appear only for their side effects
| {
kind: "ExpressionStatement";
value: Place;
loc: SourceLocation;
}
/**
* Catch-all for statements such as type imports, nested class declarations, etc
* which are not directly represented, but included for completeness and to allow
+4
View File
@@ -474,6 +474,10 @@ export function printInstructionValue(instrValue: ReactiveValue): string {
value = `NextIterableOf ${printPlace(instrValue.value)}`;
break;
}
case "ExpressionStatement": {
value = `ExpressionStatement ${printPlace(instrValue.value)}`;
break;
}
default: {
assertExhaustive(
instrValue,
+8
View File
@@ -180,6 +180,10 @@ export function* eachInstructionValueOperand(
yield instrValue.value;
break;
}
case "ExpressionStatement": {
yield instrValue.value;
break;
}
case "RegExpLiteral":
case "LoadGlobal":
case "UnsupportedNode":
@@ -443,6 +447,10 @@ export function mapInstructionOperands(
instrValue.value = fn(instrValue.value);
break;
}
case "ExpressionStatement": {
instrValue.value = fn(instrValue.value);
break;
}
case "RegExpLiteral":
case "LoadGlobal":
case "UnsupportedNode":
@@ -807,6 +807,7 @@ function inferBlock(
state.alias(lvalue, instrValue.value);
continue;
}
case "ExpressionStatement":
case "TypeCastExpression": {
// A type cast expression has no effect at runtime, so it's equivalent to a raw
// identifier:
@@ -190,6 +190,11 @@ function pruneableValue(value: InstructionValue, state: State): boolean {
}
return true;
}
case "ExpressionStatement": {
// We create ExpressionStatements specifically for expressions that would otherwise
// be dropped but which we don't want to eliminate.
return false;
}
case "Await":
case "CallExpression":
case "ComputedDelete":
@@ -996,6 +996,10 @@ function codegenInstructionValue(
value = codegenPlace(cx, instrValue.value);
break;
}
case "ExpressionStatement": {
value = codegenPlace(cx, instrValue.value);
break;
}
case "DeclareLocal":
case "Destructure":
case "StoreLocal": {
@@ -234,7 +234,8 @@ function mayAllocate(value: InstructionValue): boolean {
case "UnaryExpression":
case "TemplateLiteral":
case "Primitive":
case "NextIterableOf": {
case "NextIterableOf":
case "ExpressionStatement": {
return false;
}
case "RegExpLiteral":
@@ -436,7 +436,8 @@ function computeMemoizationInputs(
}
case "Await":
case "TypeCastExpression":
case "NextIterableOf": {
case "NextIterableOf":
case "ExpressionStatement": {
return {
// Indirection for the inner value, memoized if the value is
lvalues:
@@ -210,6 +210,7 @@ function* generateInstructionTypes(
case "TemplateLiteral":
case "Await":
case "NextIterableOf":
case "ExpressionStatement":
case "UnsupportedNode":
break;
default: