Opaque InstructionId type
[ghstack-poisoned] closes #797
Joseph Savona committed
Nov 21, 2022 at 11:47 UTC
9948e389f15596be642e006c92f1c4c35968082c
6 files changed
+65
-32
compiler/forget/src/HIR/BuildHIR.ts
+14
-13
@@ -17,6 +17,7 @@ import {
17
IfTerminal,
18
InstructionKind,
19
InstructionValue,
20
+ makeInstructionId,
21
Place,
22
ReturnTerminal,
23
SourceLocation,
@@ -606,7 +607,7 @@ function lowerStatement(
607
};
608
}
609
builder.push({
609
- id: 0,
610
+ id: makeInstructionId(0),
611
lvalue: { place: id, kind },
612
value,
613
loc: declaration.node.loc ?? GeneratedSource,
@@ -623,7 +624,7 @@ function lowerStatement(
624
return;
625
}
626
builder.push({
626
- id: 0,
627
+ id: makeInstructionId(0),
628
lvalue: null,
629
value,
630
loc: stmt.node.loc ?? GeneratedSource,
@@ -662,7 +663,7 @@ function lowerStatement(
663
case "TSTypeAliasDeclaration":
664
case "WithStatement": {
665
builder.push({
665
- id: 0,
666
+ id: makeInstructionId(0),
667
lvalue: null,
668
loc: stmtPath.node.loc ?? GeneratedSource,
669
value: {
@@ -862,7 +863,7 @@ function lowerExpression(
863
loc: left.loc,
864
};
865
builder.push({
865
- id: 0,
866
+ id: makeInstructionId(0),
867
value: {
868
kind: "Primitive",
869
value: null,
@@ -880,7 +881,7 @@ function lowerExpression(
881
loc: left.loc,
882
};
883
builder.push({
883
- id: 0,
884
+ id: makeInstructionId(0),
885
lvalue: {
886
place: { ...condPlace },
887
kind: InstructionKind.Const,
@@ -918,7 +919,7 @@ function lowerExpression(
919
if (operator === "=") {
920
const right = lowerExpression(builder, expr.get("right"));
921
builder.push({
921
- id: 0,
922
+ id: makeInstructionId(0),
923
lvalue: { place: left, kind: InstructionKind.Reassign },
924
value: right,
925
loc: exprLoc,
@@ -948,7 +949,7 @@ function lowerExpression(
949
950
const right = lowerExpressionToPlace(builder, expr.get("right"));
951
builder.push({
951
- id: 0,
952
+ id: makeInstructionId(0),
953
lvalue: { place: left, kind: InstructionKind.Reassign },
954
value: {
955
kind: "BinaryExpression",
@@ -1059,7 +1060,7 @@ function lowerConditional(
1060
const consequentBlock = builder.enter((blockId) => {
1061
let value = consequent();
1062
builder.push({
1062
- id: 0,
1063
+ id: makeInstructionId(0),
1064
value,
1065
lvalue: { place: { ...place }, kind: InstructionKind.Const },
1066
loc: value.loc,
@@ -1074,7 +1075,7 @@ function lowerConditional(
1075
const alternateBlock = builder.enter((blockId) => {
1076
let value = alternate();
1077
builder.push({
1077
- id: 0,
1078
+ id: makeInstructionId(0),
1079
value,
1080
lvalue: { place: { ...place }, kind: InstructionKind.Const },
1081
loc: value.loc,
@@ -1131,7 +1132,7 @@ function lowerJsxElementName(
1132
loc: exprLoc,
1133
};
1134
builder.push({
1134
- id: 0,
1135
+ id: makeInstructionId(0),
1136
value: {
1137
kind: "Primitive",
1138
value: tag,
@@ -1171,7 +1172,7 @@ function lowerJsxElement(
1172
loc: exprLoc,
1173
};
1174
builder.push({
1174
- id: 0,
1175
+ id: makeInstructionId(0),
1176
value: {
1177
kind: "JSXText",
1178
value: exprPath.node.value,
@@ -1194,7 +1195,7 @@ function lowerJsxElement(
1195
loc: exprLoc,
1196
};
1197
builder.push({
1197
- id: 0,
1198
+ id: makeInstructionId(0),
1199
value: {
1200
kind: "OtherStatement",
1201
node: exprNode,
@@ -1224,7 +1225,7 @@ function lowerExpressionToPlace(
1225
loc: exprLoc,
1226
};
1227
builder.push({
1227
- id: 0,
1228
+ id: makeInstructionId(0),
1229
value: instr,
1230
loc: exprLoc,
1231
lvalue: { place: { ...place }, kind: InstructionKind.Const },
compiler/forget/src/HIR/EnterSSA.ts
+3
-2
@@ -4,6 +4,7 @@ import {
4
HIRFunction,
5
Identifier,
6
IdentifierId,
7
+ makeInstructionId,
8
Phi,
9
Place,
10
} from "./HIR";
@@ -53,8 +54,8 @@ class SSABuilder {
54
preSsaId: oldId.id,
55
name: oldId.name,
56
mutableRange: {
56
- start: 0,
57
- end: 0,
57
+ start: makeInstructionId(0),
58
+ end: makeInstructionId(0),
59
},
60
scope: null, // reset along w the mutable range
61
};
compiler/forget/src/HIR/HIR.ts
+18
-3
@@ -170,7 +170,7 @@ export type WhileTerminal = {
170
* or may occur only for side-effects (many expression statements).
171
*/
172
export type Instruction = {
173
- id: number;
173
+ id: InstructionId;
174
lvalue: LValue | null;
175
value: InstructionValue;
176
loc: SourceLocation;
@@ -270,8 +270,8 @@ export type Primitive = {
270
* the value is not mutable).
271
*/
272
export type MutableRange = {
273
- start: number;
274
- end: number;
273
+ start: InstructionId;
274
+ end: InstructionId;
275
};
276
277
/**
@@ -360,3 +360,18 @@ export function makeIdentifierId(id: number): IdentifierId {
360
);
361
return id as IdentifierId;
362
}
363
+
364
+/**
365
+ * Simulated opaque type for InstructionId to prevent using normal numbers as ids
366
+ * accidentally.
367
+ */
368
+const opaqueInstructionId = Symbol();
369
+export type InstructionId = number & { [opaqueInstructionId]: "IdentifierId" };
370
+
371
+export function makeInstructionId(id: number): InstructionId {
372
+ invariant(
373
+ id >= 0 && Number.isInteger(id),
374
+ "Expected instruction id to be a non-negative integer"
375
+ );
376
+ return id as InstructionId;
377
+}
compiler/forget/src/HIR/HIRBuilder.ts
+7
-3
@@ -18,6 +18,7 @@ import {
18
Instruction,
19
makeBlockId,
20
makeIdentifierId,
21
+ makeInstructionId,
22
Terminal,
23
} from "./HIR";
24
import { printInstruction } from "./PrintHIR";
@@ -112,7 +113,7 @@ export default class HIRBuilder {
113
preSsaId: null,
114
id,
115
name: null,
115
- mutableRange: { start: 0, end: 0 },
116
+ mutableRange: { start: makeInstructionId(0), end: makeInstructionId(0) },
117
scope: null,
118
};
119
}
@@ -125,7 +126,10 @@ export default class HIRBuilder {
126
preSsaId: null,
127
id,
128
name: node.name,
128
- mutableRange: { start: 0, end: 0 },
129
+ mutableRange: {
130
+ start: makeInstructionId(0),
131
+ end: makeInstructionId(0),
132
+ },
133
scope: null,
134
};
135
this.#bindings.set(node, identifier);
@@ -502,7 +506,7 @@ function markInstructionIds(func: HIR) {
506
for (const [_, block] of func.blocks) {
507
for (const instr of block.instructions) {
508
invariant(instr.id === 0, `${printInstruction(instr)} already visited!`);
505
- instr.id = ++id;
509
+ instr.id = makeInstructionId(++id);
510
}
511
}
512
}
compiler/forget/src/HIR/InferMutableLifetimes.ts
+17
-7
@@ -8,7 +8,15 @@
8
import invariant from "invariant";
9
import { assertExhaustive } from "../Common/utils";
10
import DisjointSet from "./DisjointSet";
11
-import { Effect, HIRFunction, Identifier, Instruction, Place } from "./HIR";
11
+import {
12
+ Effect,
13
+ HIRFunction,
14
+ Identifier,
15
+ Instruction,
16
+ InstructionId,
17
+ makeInstructionId,
18
+ Place,
19
+} from "./HIR";
20
import { printInstruction, printPlace } from "./PrintHIR";
21
import { eachInstructionOperand } from "./visitors";
22
@@ -68,7 +76,7 @@ function inferPlace(place: Place, instr: Instruction) {
76
case Effect.Freeze:
77
return;
78
case Effect.Mutate: {
71
- place.identifier.mutableRange.end = instr.id + 1;
79
+ place.identifier.mutableRange.end = makeInstructionId(instr.id + 1);
80
return;
81
}
82
default:
@@ -92,8 +100,8 @@ export function inferMutableRanges(func: HIRFunction) {
100
"Expected phi to have set start/end range values"
101
);
102
phi.id.mutableRange = {
95
- start,
96
- end,
103
+ start: makeInstructionId(start),
104
+ end: makeInstructionId(end),
105
};
106
}
107
@@ -126,7 +134,7 @@ export function inferMutableRanges(func: HIRFunction) {
134
135
// Let's be optimistic and assume this lvalue is not mutable by
136
// default.
129
- lvalueId.mutableRange.end = instr.id + 1;
137
+ lvalueId.mutableRange.end = makeInstructionId(instr.id + 1);
138
} else {
139
inferPlace(instr.lvalue.place, instr);
140
}
@@ -138,7 +146,7 @@ export function inferMutableRanges(func: HIRFunction) {
146
// Store the mutable range and set of identifiers for each scope
147
const aliasIndentifiers: Map<
148
number,
141
- { end: number; identifiers: Set<Identifier> }
149
+ { end: InstructionId; identifiers: Set<Identifier> }
150
> = new Map();
151
152
aliases.forEach((identifier, groupIdentifier) => {
@@ -156,7 +164,9 @@ export function inferMutableRanges(func: HIRFunction) {
164
};
165
aliasIndentifiers.set(aliasId, alias);
166
} else {
159
- alias.end = Math.max(alias.end, identifier.mutableRange.end);
167
+ alias.end = makeInstructionId(
168
+ Math.max(alias.end, identifier.mutableRange.end)
169
+ );
170
}
171
alias.identifiers.add(identifier);
172
});
compiler/forget/src/HIR/InferReactiveScopeVariables.ts
+6
-4
@@ -10,6 +10,7 @@ import {
10
HIRFunction,
11
Identifier,
12
Instruction,
13
+ makeInstructionId,
14
makeScopeId,
15
MutableRange,
16
Place,
@@ -125,11 +126,12 @@ export function inferReactiveScopeVariables(fn: HIRFunction) {
126
};
127
scopeVariables.set(scopeId, scope);
128
} else {
128
- scope.range.start = Math.min(
129
- scope.range.start,
130
- identifier.mutableRange.start
129
+ scope.range.start = makeInstructionId(
130
+ Math.min(scope.range.start, identifier.mutableRange.start)
131
+ );
132
+ scope.range.end = makeInstructionId(
133
+ Math.max(scope.range.end, identifier.mutableRange.end)
134
);
132
- scope.range.end = Math.max(scope.range.end, identifier.mutableRange.end);
135
}
136
scope.variables.add(identifier);
137
});