18
Phi,
19
Place,
20
} from "../HIR/HIR";
21
-import { printPlace } from "../HIR/PrintHIR";
21
+import { printIdentifier, printPlace } from "../HIR/PrintHIR";
22
import {
23
eachInstructionLValue,
24
eachInstructionValueOperand,
375
terminal.kind === "for-of" ||
376
terminal.kind === "for-in"
377
) {
378
- const init = fn.body.blocks.get(terminal.init)!;
378
+ let init = fn.body.blocks.get(terminal.init)!;
379
pushPhis(init);
380
381
+ // The first block after the end of the init
382
+ let initContinuation =
383
+ terminal.kind === "for" ? terminal.test : terminal.loop;
384
/*
385
* To avoid generating a let binding for the initializer prior to the loop,
383
- * check to see if the for declares an iterator variable
386
+ * check to see if the for declares an iterator variable.
387
*/
385
- const initIdentifier = init.instructions.at(-1);
386
- if (
387
- initIdentifier !== undefined &&
388
- initIdentifier.value.kind === "StoreLocal"
389
- ) {
390
- const value = initIdentifier.value;
391
- if (value.lvalue.place.identifier.name !== null) {
392
- const originalLVal = declarations.get(
393
- value.lvalue.place.identifier.name.value
394
- );
395
- if (originalLVal === undefined) {
396
- declarations.set(value.lvalue.place.identifier.name.value, {
397
- lvalue: value.lvalue,
398
- place: value.lvalue.place,
399
- });
400
- value.lvalue.kind = InstructionKind.Const;
388
+ while (init.id !== initContinuation) {
389
+ for (const instr of init.instructions) {
390
+ if (
391
+ instr.value.kind === "StoreLocal" &&
392
+ instr.value.lvalue.kind !== InstructionKind.Reassign
393
+ ) {
394
+ const value = instr.value;
395
+ if (value.lvalue.place.identifier.name !== null) {
396
+ const originalLVal = declarations.get(
397
+ value.lvalue.place.identifier.name.value
398
+ );
399
+ if (originalLVal === undefined) {
400
+ declarations.set(value.lvalue.place.identifier.name.value, {
401
+ lvalue: value.lvalue,
402
+ place: value.lvalue.place,
403
+ });
404
+ value.lvalue.kind = InstructionKind.Const;
405
+ }
406
+ }
407
}
408
}
409
+
410
+ let next: BlockId | null = null;
411
+ switch (init.terminal.kind) {
412
+ case "maybe-throw": {
413
+ next = init.terminal.continuation;
414
+ break;
415
+ }
416
+ case "goto": {
417
+ next = init.terminal.block;
418
+ break;
419
+ }
420
+ default: {
421
+ break;
422
+ }
423
+ }
424
+ if (next === null) {
425
+ break;
426
+ }
427
+
428
+ init = fn.body.blocks.get(next)!;
429
}
430
431
if (terminal.kind === "for" && terminal.update !== null) {
472
CompilerError.invariant(declaration != null, {
473
loc: null,
474
reason: "Expected a declaration for all variables",
449
- description: null,
475
+ description: `${printIdentifier(phi.id)} in block bb${phiBlock.id}`,
476
suggestions: null,
477
});
478
if (isPhiMutatedAfterCreation) {