// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

// We might want to change the initialization of HInstruction so that
// `HInstruction.inputs` is initialized to `[]` in the field declaration, and
// the subclasses add the input instructions to the existing List. This would
// guarantee that `HInstruction.inputs` is a monomorphic. Experiments suggest
// that this would improve the SSA time by ~2%. The suggestion to use
// super-parameters is unhelpful if we do this, so the suggestion is suppressed.
//
// ignore_for_file: use_super_parameters

// ignore: implementation_imports
import 'package:front_end/src/api_unstable/dart2js.dart' show Link;

import '../closure.dart';
import '../common.dart';
import '../common/elements.dart';
import '../constants/constant_system.dart' as constant_system;
import '../constants/values.dart';
import '../diagnostics/spannable_with_entity.dart';
import '../elements/entities.dart';
import '../elements/jumps.dart';
import '../elements/types.dart';
import '../inferrer/abstract_value_domain.dart';
import '../io/source_information.dart';
import '../js/js.dart' as js;
import '../js_backend/specialized_checks.dart' show IsTestSpecialization;
import '../js_model/js_world.dart' show JClosedWorld;
import '../js_model/type_recipe.dart'
    show TypeEnvironmentStructure, TypeRecipe, TypeExpressionRecipe;
import '../native/behavior.dart';
import '../options.dart';
import '../universe/selector.dart' show Selector;
import '../universe/side_effects.dart' show SideEffects;
import '../util/util.dart';
import 'invoke_dynamic_specializers.dart';
import 'validate.dart';

abstract class HVisitor<R> {
  R visitAbs(HAbs node);
  R visitAdd(HAdd node);
  R visitAwait(HAwait node);
  R visitBitAnd(HBitAnd node);
  R visitBitNot(HBitNot node);
  R visitBitOr(HBitOr node);
  R visitBitXor(HBitXor node);
  R visitBoundsCheck(HBoundsCheck node);
  R visitBreak(HBreak node);
  R visitCharCodeAt(HCharCodeAt node);
  R visitConstant(HConstant node);
  R visitContinue(HContinue node);
  R visitCreate(HCreate node);
  R visitCreateBox(HCreateBox node);
  R visitDivide(HDivide node);
  R visitExit(HExit node);
  R visitExitTry(HExitTry node);
  R visitFieldGet(HFieldGet node);
  R visitFieldSet(HFieldSet node);
  R visitFunctionReference(HFunctionReference node);
  R visitInvokeExternal(HInvokeExternal node);
  R visitForeignCode(HForeignCode node);
  R visitGetLength(HGetLength node);
  R visitGoto(HGoto node);
  R visitGreater(HGreater node);
  R visitGreaterEqual(HGreaterEqual node);
  R visitIdentity(HIdentity node);
  R visitIf(HIf node);
  R visitIndex(HIndex node);
  R visitIndexAssign(HIndexAssign node);
  R visitInterceptor(HInterceptor node);
  R visitInvokeClosure(HInvokeClosure node);
  R visitInvokeDynamicGetter(HInvokeDynamicGetter node);
  R visitInvokeDynamicMethod(HInvokeDynamicMethod node);
  R visitInvokeDynamicSetter(HInvokeDynamicSetter node);
  R visitInvokeStatic(HInvokeStatic node);
  R visitInvokeSuper(HInvokeSuper node);
  R visitInvokeConstructorBody(HInvokeConstructorBody node);
  R visitInvokeGeneratorBody(HInvokeGeneratorBody node);
  R visitIsLateSentinel(HIsLateSentinel node);
  R visitLateValue(HLateValue node);
  R visitLazyStatic(HLazyStatic node);
  R visitLess(HLess node);
  R visitLessEqual(HLessEqual node);
  R visitLiteralList(HLiteralList node);
  R visitLocalGet(HLocalGet node);
  R visitLocalSet(HLocalSet node);
  R visitLocalValue(HLocalValue node);
  R visitLoopBranch(HLoopBranch node);
  R visitMultiply(HMultiply node);
  R visitNegate(HNegate node);
  R visitNot(HNot node);
  R visitOneShotInterceptor(HOneShotInterceptor node);
  R visitParameterValue(HParameterValue node);
  R visitPhi(HPhi node);
  R visitRangeConversion(HRangeConversion node);
  R visitReadModifyWrite(HReadModifyWrite node);
  R visitRef(HRef node);
  R visitRemainder(HRemainder node);
  R visitReturn(HReturn node);
  R visitShiftLeft(HShiftLeft node);
  R visitShiftRight(HShiftRight node);
  R visitStatic(HStatic node);
  R visitStaticStore(HStaticStore node);
  R visitStringConcat(HStringConcat node);
  R visitStringify(HStringify node);
  R visitSubtract(HSubtract node);
  R visitSwitch(HSwitch node);
  R visitThis(HThis node);
  R visitThrow(HThrow node);
  R visitThrowExpression(HThrowExpression node);
  R visitTruncatingDivide(HTruncatingDivide node);
  R visitTry(HTry node);
  R visitPrimitiveCheck(HPrimitiveCheck node);
  R visitNullCheck(HNullCheck node);
  R visitLateReadCheck(HLateReadCheck node);
  R visitLateWriteOnceCheck(HLateWriteOnceCheck node);
  R visitLateInitializeOnceCheck(HLateInitializeOnceCheck node);
  R visitTypeKnown(HTypeKnown node);
  R visitYield(HYield node);

  // Instructions for 'dart:_rti'.
  R visitIsTest(HIsTest node);
  R visitIsTestSimple(HIsTestSimple node);
  R visitAsCheck(HAsCheck node);
  R visitAsCheckSimple(HAsCheckSimple node);
  R visitSubtypeCheck(HSubtypeCheck node);
  R visitLoadType(HLoadType node);
  R visitInstanceEnvironment(HInstanceEnvironment node);
  R visitTypeEval(HTypeEval node);
  R visitTypeBind(HTypeBind node);

  R visitArrayFlagsCheck(HArrayFlagsCheck node);
  R visitArrayFlagsGet(HArrayFlagsGet node);
  R visitArrayFlagsSet(HArrayFlagsSet node);
}

abstract class HGraphVisitor {
  void visitDominatorTree(HGraph graph) {
    // Recursion free version of:
    //
    //     void visitBasicBlockAndSuccessors(HBasicBlock block) {
    //       visitBasicBlock(block);
    //       List dominated = block.dominatedBlocks;
    //       for (int i = 0; i < dominated.length; i++) {
    //         visitBasicBlockAndSuccessors(dominated[i]);
    //       }
    //     }
    //     visitBasicBlockAndSuccessors(graph.entry);

    _Frame? frame = _Frame(null);
    frame.block = graph.entry;
    frame.index = 0;

    visitBasicBlock(frame.block);

    while (frame != null) {
      HBasicBlock block = frame.block;
      int index = frame.index;
      if (index < block.dominatedBlocks.length) {
        frame.index = index + 1;
        frame = frame.next ??= _Frame(frame);
        frame.block = block.dominatedBlocks[index];
        frame.index = 0;
        visitBasicBlock(frame.block);
        continue;
      }
      frame = frame.previous;
    }
  }

  void visitPostDominatorTree(HGraph graph) {
    // Recursion-free version of:
    //
    //     void visitBasicBlockAndSuccessors(HBasicBlock block) {
    //       List dominated = block.dominatedBlocks;
    //       for (int i = dominated.length - 1; i >= 0; i--) {
    //         visitBasicBlockAndSuccessors(dominated[i]);
    //       }
    //       visitBasicBlock(block);
    //     }
    //     visitBasicBlockAndSuccessors(graph.entry);

    _Frame? frame = _Frame(null);
    frame.block = graph.entry;
    frame.index = frame.block.dominatedBlocks.length;

    while (frame != null) {
      HBasicBlock block = frame.block;
      int index = frame.index;
      if (index > 0) {
        frame.index = index - 1;
        frame = frame.next ??= _Frame(frame);
        frame.block = block.dominatedBlocks[index - 1];
        frame.index = frame.block.dominatedBlocks.length;
        continue;
      }
      visitBasicBlock(block);
      frame = frame.previous;
    }
  }

  void visitBasicBlock(HBasicBlock block);
}

class _Frame {
  final _Frame? previous;
  _Frame? next;
  late HBasicBlock block;
  late int index;
  _Frame(this.previous);
}

abstract class HInstructionVisitor extends HGraphVisitor {
  HBasicBlock? currentBlock;

  void visitInstruction(HInstruction node);

  @override
  void visitBasicBlock(HBasicBlock node) {
    void visitInstructionList(HInstructionList list) {
      for (
        var instruction = list.first;
        instruction != null;
        instruction = instruction.next
      ) {
        visitInstruction(instruction);
        assert(instruction.next != list.first);
      }
    }

    currentBlock = node;
    visitInstructionList(node);
  }
}

class HGraph {
  late MemberEntity element; // Used for debug printing.
  late HBasicBlock entry;
  late HBasicBlock exit;
  HThis? thisInstruction;

  /// `true` if this graph should be transformed by a sync*/async/async*
  /// rewrite.
  bool needsAsyncRewrite = false;

  /// If this function requires an async rewrite, this is the element type of
  /// the generator.
  DartType? asyncElementType;

  /// Receiver parameter, set for methods using interceptor calling convention.
  HParameterValue? explicitReceiverParameter;
  bool isRecursiveMethod = false;
  bool calledInLoop = false;
  bool isLazyInitializer = false;

  final List<HBasicBlock> blocks = [];

  /// Nodes containing list allocations for which there is a known fixed length.
  // TODO(sigmund,sra): consider not storing this explicitly here (e.g. maybe
  // store it on HInstruction, or maybe this can be computed on demand).
  final Set<HInstruction> allocatedFixedLists = {};

  /// SourceInformation for the 'graph' is the location of the entry
  SourceInformation? sourceInformation;

  // We canonicalize all constants used within a graph so we do not
  // have to worry about them for global value numbering.
  Map<ConstantValue, HConstant> constants = {};

  HGraph() {
    entry = addNewBlock();
    // The exit block will be added later, so it has an id that is
    // after all others in the system.
    exit = HBasicBlock();
  }

  void addBlock(HBasicBlock block) {
    int id = blocks.length;
    block.id = id;
    blocks.add(block);
    assert(identical(blocks[id], block));
  }

  HBasicBlock addNewBlock() {
    HBasicBlock result = HBasicBlock();
    addBlock(result);
    return result;
  }

  HBasicBlock addNewLoopHeaderBlock(
    JumpTarget? target,
    List<LabelDefinition> labels,
  ) {
    HBasicBlock result = addNewBlock();
    result.loopInformation = HLoopInformation(result, target, labels);
    return result;
  }

  HConstant addConstant(
    ConstantValue constant,
    JClosedWorld closedWorld, {
    SourceInformation? sourceInformation,
  }) {
    HConstant? result = constants[constant];
    // TODO(johnniwinther): Support source information per constant reference.
    if (result == null) {
      if (!constant.isConstant) {
        // We use `null` as the value for invalid constant expressions.
        constant = const NullConstantValue();
      }
      AbstractValue type = closedWorld.abstractValueDomain
          .computeAbstractValueForConstant(constant);
      result = HConstant._internal(constant, type)
        ..sourceInformation = sourceInformation;
      entry.addAtExit(result);
      constants[constant] = result;
    } else if (result.block == null) {
      // The constant was not used anymore.
      entry.addAtExit(result);
    }
    return result;
  }

  HConstant addDeferredConstant(
    DeferredGlobalConstantValue constant,
    SourceInformation? sourceInformation,
    JClosedWorld closedWorld,
  ) {
    return addConstant(
      constant,
      closedWorld,
      sourceInformation: sourceInformation,
    );
  }

  HConstant addConstantInt(int i, JClosedWorld closedWorld) {
    return addConstant(constant_system.createIntFromInt(i), closedWorld);
  }

  HConstant addConstantIntAsUnsigned(int i, JClosedWorld closedWorld) {
    return addConstant(
      constant_system.createInt(BigInt.from(i).toUnsigned(64)),
      closedWorld,
    );
  }

  HConstant addConstantDouble(double d, JClosedWorld closedWorld) {
    return addConstant(constant_system.createDouble(d), closedWorld);
  }

  HConstant addConstantString(String str, JClosedWorld closedWorld) {
    return addConstant(constant_system.createString(str), closedWorld);
  }

  HConstant addConstantStringFromName(js.Name name, JClosedWorld closedWorld) {
    return addConstant(JsNameConstantValue(js.quoteName(name)), closedWorld);
  }

  HConstant addConstantBool(bool value, JClosedWorld closedWorld) {
    return addConstant(constant_system.createBool(value), closedWorld);
  }

  HConstant addConstantNull(JClosedWorld closedWorld) {
    return addConstant(constant_system.createNull(), closedWorld);
  }

  HConstant addConstantUnreachable(JClosedWorld closedWorld) {
    // A constant with an empty type used as the HInstruction of an expression
    // in an unreachable context.
    return addConstant(UnreachableConstantValue(), closedWorld);
  }

  HConstant addConstantLateSentinel(
    JClosedWorld closedWorld, {
    SourceInformation? sourceInformation,
  }) => addConstant(
    LateSentinelConstantValue(),
    closedWorld,
    sourceInformation: sourceInformation,
  );

  void finalize() {
    addBlock(exit);
    exit.open();
    exit.close(HExit());
    assignDominators();
  }

  void assignDominators() {
    // Run through the blocks in order of increasing ids so we are
    // guaranteed that we have computed dominators for all blocks
    // higher up in the dominator tree.
    for (int i = 0, length = blocks.length; i < length; i++) {
      HBasicBlock block = blocks[i];
      List<HBasicBlock> predecessors = block.predecessors;
      if (block.isLoopHeader()) {
        block.assignCommonDominator(predecessors[0]);
      } else {
        for (int j = predecessors.length - 1; j >= 0; j--) {
          block.assignCommonDominator(predecessors[j]);
        }
      }
    }
    assignDominatorRanges();
  }

  void assignDominatorRanges() {
    // DFS walk of dominator tree to assign dfs-in and dfs-out numbers to basic
    // blocks. A dominator has a dfs-in..dfs-out range that includes the range
    // of the dominated block. See [HGraphVisitor.visitDominatorTree] for
    // recursion-free schema.
    _Frame? frame = _Frame(null);
    frame.block = entry;
    frame.index = 0;

    int dfsNumber = 0;
    frame.block.dominatorDfsIn = dfsNumber;

    while (frame != null) {
      HBasicBlock block = frame.block;
      int index = frame.index;
      if (index < block.dominatedBlocks.length) {
        frame.index = index + 1;
        frame = frame.next ??= _Frame(frame);
        frame.block = block.dominatedBlocks[index];
        frame.index = 0;
        frame.block.dominatorDfsIn = ++dfsNumber;
        continue;
      }
      block.dominatorDfsOut = dfsNumber;
      frame = frame.previous;
    }
  }

  bool isValid() {
    HValidator validator = HValidator();
    validator.visitGraph(this);
    return validator.isValid;
  }

  @override
  String toString() => 'HGraph($element)';
}

class HBaseVisitor<R> extends HGraphVisitor implements HVisitor<R> {
  HBasicBlock? currentBlock;

  @override
  void visitBasicBlock(HBasicBlock node) {
    currentBlock = node;

    for (
      var instruction = node.first;
      instruction != null;
      instruction = instruction.next
    ) {
      instruction.accept(this);
    }
  }

  R visitInstruction(HInstruction instruction) => null as R;

  R visitBinaryArithmetic(HBinaryArithmetic node) => visitInvokeBinary(node);
  R visitBinaryBitOp(HBinaryBitOp node) => visitInvokeBinary(node);
  R visitInvoke(HInvoke node) => visitInstruction(node);
  R visitInvokeBinary(HInvokeBinary node) => visitInstruction(node);
  R visitInvokeDynamic(HInvokeDynamic node) => visitInvoke(node);
  R visitInvokeDynamicField(HInvokeDynamicField node) =>
      visitInvokeDynamic(node);
  R visitInvokeUnary(HInvokeUnary node) => visitInstruction(node);
  R visitConditionalBranch(HConditionalBranch node) => visitControlFlow(node);
  R visitControlFlow(HControlFlow node) => visitInstruction(node);
  R visitFieldAccess(HFieldAccess node) => visitInstruction(node);
  R visitRelational(HRelational node) => visitInvokeBinary(node);

  @override
  R visitAbs(HAbs node) => visitInvokeUnary(node);
  @override
  R visitAdd(HAdd node) => visitBinaryArithmetic(node);
  @override
  R visitBitAnd(HBitAnd node) => visitBinaryBitOp(node);
  @override
  R visitBitNot(HBitNot node) => visitInvokeUnary(node);
  @override
  R visitBitOr(HBitOr node) => visitBinaryBitOp(node);
  @override
  R visitBitXor(HBitXor node) => visitBinaryBitOp(node);
  @override
  R visitBoundsCheck(HBoundsCheck node) => visitCheck(node);
  @override
  R visitBreak(HBreak node) => visitJump(node);
  @override
  R visitContinue(HContinue node) => visitJump(node);
  @override
  R visitCharCodeAt(HCharCodeAt node) => visitInstruction(node);
  R visitCheck(HCheck node) => visitInstruction(node);
  @override
  R visitConstant(HConstant node) => visitInstruction(node);
  @override
  R visitCreate(HCreate node) => visitInstruction(node);
  @override
  R visitCreateBox(HCreateBox node) => visitInstruction(node);
  @override
  R visitDivide(HDivide node) => visitBinaryArithmetic(node);
  @override
  R visitExit(HExit node) => visitControlFlow(node);
  @override
  R visitExitTry(HExitTry node) => visitControlFlow(node);
  @override
  R visitFieldGet(HFieldGet node) => visitFieldAccess(node);
  @override
  R visitFieldSet(HFieldSet node) => visitFieldAccess(node);
  @override
  R visitFunctionReference(HFunctionReference node) => visitInstruction(node);
  @override
  R visitInvokeExternal(HInvokeExternal node) => visitInstruction(node);
  @override
  R visitForeignCode(HForeignCode node) => visitInstruction(node);
  @override
  R visitGetLength(HGetLength node) => visitInstruction(node);
  @override
  R visitGoto(HGoto node) => visitControlFlow(node);
  @override
  R visitGreater(HGreater node) => visitRelational(node);
  @override
  R visitGreaterEqual(HGreaterEqual node) => visitRelational(node);
  @override
  R visitIdentity(HIdentity node) => visitRelational(node);
  @override
  R visitIf(HIf node) => visitConditionalBranch(node);
  @override
  R visitIndex(HIndex node) => visitInstruction(node);
  @override
  R visitIndexAssign(HIndexAssign node) => visitInstruction(node);
  @override
  R visitInterceptor(HInterceptor node) => visitInstruction(node);
  @override
  R visitInvokeClosure(HInvokeClosure node) => visitInvokeDynamic(node);
  @override
  R visitInvokeConstructorBody(HInvokeConstructorBody node) =>
      visitInvokeStatic(node);
  @override
  R visitInvokeGeneratorBody(HInvokeGeneratorBody node) =>
      visitInvokeStatic(node);
  @override
  R visitInvokeDynamicMethod(HInvokeDynamicMethod node) =>
      visitInvokeDynamic(node);
  @override
  R visitInvokeDynamicGetter(HInvokeDynamicGetter node) =>
      visitInvokeDynamicField(node);
  @override
  R visitInvokeDynamicSetter(HInvokeDynamicSetter node) =>
      visitInvokeDynamicField(node);
  @override
  R visitInvokeStatic(HInvokeStatic node) => visitInvoke(node);
  @override
  R visitInvokeSuper(HInvokeSuper node) => visitInvokeStatic(node);
  R visitJump(HJump node) => visitControlFlow(node);
  @override
  R visitLazyStatic(HLazyStatic node) => visitInstruction(node);
  @override
  R visitLess(HLess node) => visitRelational(node);
  @override
  R visitLessEqual(HLessEqual node) => visitRelational(node);
  @override
  R visitLiteralList(HLiteralList node) => visitInstruction(node);
  R visitLocalAccess(HLocalAccess node) => visitInstruction(node);
  @override
  R visitLocalGet(HLocalGet node) => visitLocalAccess(node);
  @override
  R visitLocalSet(HLocalSet node) => visitLocalAccess(node);
  @override
  R visitLocalValue(HLocalValue node) => visitInstruction(node);
  @override
  R visitLoopBranch(HLoopBranch node) => visitConditionalBranch(node);
  @override
  R visitNegate(HNegate node) => visitInvokeUnary(node);
  @override
  R visitNot(HNot node) => visitInstruction(node);
  @override
  R visitOneShotInterceptor(HOneShotInterceptor node) =>
      visitInvokeDynamic(node);
  @override
  R visitPhi(HPhi node) => visitInstruction(node);
  @override
  R visitMultiply(HMultiply node) => visitBinaryArithmetic(node);
  @override
  R visitParameterValue(HParameterValue node) => visitLocalValue(node);
  @override
  R visitRangeConversion(HRangeConversion node) => visitCheck(node);
  @override
  R visitReadModifyWrite(HReadModifyWrite node) => visitInstruction(node);
  @override
  R visitRef(HRef node) => node.value.accept(this);
  @override
  R visitRemainder(HRemainder node) => visitBinaryArithmetic(node);
  @override
  R visitReturn(HReturn node) => visitControlFlow(node);
  @override
  R visitShiftLeft(HShiftLeft node) => visitBinaryBitOp(node);
  @override
  R visitShiftRight(HShiftRight node) => visitBinaryBitOp(node);
  @override
  R visitSubtract(HSubtract node) => visitBinaryArithmetic(node);
  @override
  R visitSwitch(HSwitch node) => visitControlFlow(node);
  @override
  R visitStatic(HStatic node) => visitInstruction(node);
  @override
  R visitStaticStore(HStaticStore node) => visitInstruction(node);
  @override
  R visitStringConcat(HStringConcat node) => visitInstruction(node);
  @override
  R visitStringify(HStringify node) => visitInstruction(node);
  @override
  R visitThis(HThis node) => visitParameterValue(node);
  @override
  R visitThrow(HThrow node) => visitControlFlow(node);
  @override
  R visitThrowExpression(HThrowExpression node) => visitInstruction(node);
  @override
  R visitTruncatingDivide(HTruncatingDivide node) =>
      visitBinaryArithmetic(node);
  @override
  R visitTry(HTry node) => visitControlFlow(node);
  @override
  R visitIsLateSentinel(HIsLateSentinel node) => visitInstruction(node);
  @override
  R visitLateValue(HLateValue node) => visitInstruction(node);
  @override
  R visitNullCheck(HNullCheck node) => visitCheck(node);
  R visitLateCheck(HLateCheck node) => visitCheck(node);
  @override
  R visitLateReadCheck(HLateReadCheck node) => visitLateCheck(node);
  @override
  R visitLateWriteOnceCheck(HLateWriteOnceCheck node) => visitLateCheck(node);
  @override
  R visitLateInitializeOnceCheck(HLateInitializeOnceCheck node) =>
      visitLateCheck(node);
  @override
  R visitPrimitiveCheck(HPrimitiveCheck node) => visitCheck(node);
  @override
  R visitTypeKnown(HTypeKnown node) => visitCheck(node);
  @override
  R visitAwait(HAwait node) => visitInstruction(node);
  @override
  R visitYield(HYield node) => visitInstruction(node);

  @override
  R visitIsTest(HIsTest node) => visitInstruction(node);
  @override
  R visitIsTestSimple(HIsTestSimple node) => visitInstruction(node);
  @override
  R visitAsCheck(HAsCheck node) => visitCheck(node);
  @override
  R visitAsCheckSimple(HAsCheckSimple node) => visitCheck(node);
  @override
  R visitSubtypeCheck(HSubtypeCheck node) => visitCheck(node);
  @override
  R visitLoadType(HLoadType node) => visitInstruction(node);
  @override
  R visitInstanceEnvironment(HInstanceEnvironment node) =>
      visitInstruction(node);
  @override
  R visitTypeEval(HTypeEval node) => visitInstruction(node);
  @override
  R visitTypeBind(HTypeBind node) => visitInstruction(node);

  @override
  R visitArrayFlagsCheck(HArrayFlagsCheck node) => visitCheck(node);
  @override
  R visitArrayFlagsGet(HArrayFlagsGet node) => visitInstruction(node);
  @override
  R visitArrayFlagsSet(HArrayFlagsSet node) => visitInstruction(node);
}

class SubGraph {
  // The first and last block of the sub-graph.
  final HBasicBlock start;
  final HBasicBlock end;

  const SubGraph(this.start, this.end);

  bool contains(HBasicBlock block) {
    return start.id <= block.id && block.id <= end.id;
  }
}

class SubExpression extends SubGraph {
  const SubExpression(super.start, super.end);

  /// Find the condition expression if this sub-expression is a condition.
  HInstruction? get conditionExpression {
    HInstruction? last = end.last;
    if (last is HConditionalBranch || last is HSwitch) return last!.inputs[0];
    return null;
  }
}

class HInstructionList {
  HInstruction? first;
  HInstruction? last;

  bool get isEmpty {
    return first == null;
  }

  void internalAddAfter(HInstruction? cursor, HInstruction instruction) {
    if (cursor == null) {
      assert(isEmpty);
      first = last = instruction;
    } else if (identical(cursor, last)) {
      last!.next = instruction;
      instruction.previous = last;
      last = instruction;
    } else {
      instruction.previous = cursor;
      instruction.next = cursor.next;
      cursor.next!.previous = instruction;
      cursor.next = instruction;
    }
  }

  void internalAddBefore(HInstruction? cursor, HInstruction instruction) {
    if (cursor == null) {
      assert(isEmpty);
      first = last = instruction;
    } else if (identical(cursor, first)) {
      first!.previous = instruction;
      instruction.next = first;
      first = instruction;
    } else {
      instruction.next = cursor;
      instruction.previous = cursor.previous;
      cursor.previous!.next = instruction;
      cursor.previous = instruction;
    }
  }

  void detach(HInstruction instruction) {
    assert(_truncatedContainsForAssert(instruction));
    assert(instruction.isInBasicBlock());
    if (instruction.previous == null) {
      first = instruction.next;
    } else {
      instruction.previous!.next = instruction.next;
    }
    if (instruction.next == null) {
      last = instruction.previous;
    } else {
      instruction.next!.previous = instruction.previous;
    }
    instruction.previous = null;
    instruction.next = null;
  }

  void remove(HInstruction instruction) {
    assert(instruction.usedBy.isEmpty);
    detach(instruction);
  }

  /// Linear search for [instruction].
  bool contains(HInstruction instruction) {
    for (var cursor = first; cursor != null; cursor = cursor.next) {
      if (identical(cursor, instruction)) return true;
    }

    return false;
  }

  /// Linear search for [instruction], up to a limit of 100. Returns whether
  /// the instruction is found or the list is too big.
  ///
  /// This is used for assertions only: some tests have pathological cases where
  /// the basic blocks are huge (50K nodes!), and we found that checking for
  /// [contains] within our assertions made compilation really slow.
  bool _truncatedContainsForAssert(HInstruction instruction) {
    int count = 0;
    for (var cursor = first; cursor != null; cursor = cursor.next) {
      count++;
      if (count > 100) return true;
      if (identical(cursor, instruction)) return true;
    }

    return false;
  }
}

class HPhiList extends HInstructionList {
  HPhi? get firstPhi => first as HPhi?;
  HPhi? get lastPhi => last as HPhi?;
}

enum _BasicBlockStatus { new_, open, closed }

class HBasicBlock extends HInstructionList {
  // The [id] must be such that any successor's id is greater than
  // this [id]. The exception are back-edges.
  int id = -1;

  _BasicBlockStatus _status = _BasicBlockStatus.new_;

  var phis = HPhiList();

  HLoopInformation? loopInformation;
  HBlockFlow? blockFlow;
  HBasicBlock? parentLoopHeader;
  bool isLive = true;

  final List<HBasicBlock> predecessors = [];
  List<HBasicBlock> successors = const [];

  HBasicBlock? dominator;
  final List<HBasicBlock> dominatedBlocks = [];
  int dominatorDfsIn = -1;
  int dominatorDfsOut = -1;

  HBasicBlock();

  @override
  int get hashCode => id;

  @override
  bool operator ==(other) => identical(this, other);

  bool get isNew => _status == _BasicBlockStatus.new_;
  bool get isOpen => _status == _BasicBlockStatus.open;
  bool get isClosed => _status == _BasicBlockStatus.closed;

  bool isLoopHeader() {
    return loopInformation != null;
  }

  void setBlockFlow(HBlockInformation blockInfo, HBasicBlock? continuation) {
    blockFlow = HBlockFlow(blockInfo, continuation);
  }

  bool isLabeledBlock() =>
      blockFlow != null && blockFlow!.body is HLabeledBlockInformation;

  HBasicBlock? get enclosingLoopHeader {
    if (isLoopHeader()) return this;
    return parentLoopHeader;
  }

  void open() {
    assert(isNew);
    _status = _BasicBlockStatus.open;
  }

  void close(HControlFlow end) {
    assert(isOpen);
    addAfter(last, end);
    _status = _BasicBlockStatus.closed;
  }

  void addAtEntry(HInstruction instruction) {
    assert(instruction is! HPhi);
    internalAddBefore(first, instruction);
    instruction.notifyAddedToBlock(this);
  }

  void addAtExit(HInstruction instruction) {
    assert(isClosed);
    assert(last is HControlFlow);
    assert(instruction is! HPhi);
    internalAddBefore(last, instruction);
    instruction.notifyAddedToBlock(this);
  }

  void moveAtExit(HInstruction instruction) {
    assert(instruction is! HPhi);
    assert(instruction.isInBasicBlock());
    assert(isClosed);
    assert(last is HControlFlow);
    internalAddBefore(last, instruction);
    instruction.block = this;
    assert(isValid());
  }

  void add(HInstruction instruction) {
    assert(instruction is! HControlFlow);
    assert(instruction is! HPhi);
    internalAddAfter(last, instruction);
    instruction.notifyAddedToBlock(this);
  }

  void addPhi(HPhi phi) {
    assert(phi.inputs.isEmpty || phi.inputs.length == predecessors.length);
    assert(phi.block == null);
    phis.internalAddAfter(phis.last, phi);
    phi.notifyAddedToBlock(this);
  }

  void removePhi(HPhi phi) {
    phis.remove(phi);
    assert(phi.block == this);
    phi.notifyRemovedFromBlock();
  }

  void addAfter(HInstruction? cursor, HInstruction instruction) {
    assert(cursor is! HPhi);
    assert(instruction is! HPhi);
    assert(isOpen || isClosed);
    internalAddAfter(cursor, instruction);
    instruction.notifyAddedToBlock(this);
  }

  void addBefore(HInstruction? cursor, HInstruction instruction) {
    assert(cursor is! HPhi);
    assert(instruction is! HPhi);
    assert(isOpen || isClosed);
    internalAddBefore(cursor, instruction);
    instruction.notifyAddedToBlock(this);
  }

  @override
  void remove(HInstruction instruction) {
    assert(isOpen || isClosed);
    assert(instruction is! HPhi);
    super.remove(instruction);
    assert(instruction.block == this);
    instruction.notifyRemovedFromBlock();
  }

  void addSuccessor(HBasicBlock block) {
    if (successors.isEmpty) {
      successors = [block];
    } else {
      successors.add(block);
    }
    block.predecessors.add(this);
  }

  void postProcessLoopHeader() {
    assert(isLoopHeader());
    // Only the first entry into the loop is from outside the
    // loop. All other entries must be back edges.
    for (int i = 1, length = predecessors.length; i < length; i++) {
      loopInformation!.addBackEdge(predecessors[i]);
    }
  }

  /// Rewrites all uses of the [from] instruction to using the [to]
  /// instruction instead.
  void rewrite(HInstruction from, HInstruction to) {
    for (HInstruction use in from.usedBy) {
      use.rewriteInput(from, to);
    }
    to.usedBy.addAll(from.usedBy);
    from.usedBy.clear();
  }

  /// Rewrites all uses of the [from] instruction to using either the
  /// [to] instruction, or a [HCheck] instruction that has better type
  /// information on [to], and that dominates the user.
  void rewriteWithBetterUser(HInstruction? from, HInstruction to) {
    // BUG(11841): Turn this method into a phase to be run after GVN phases.
    Link<HCheck> better = const Link();
    for (HInstruction user in to.usedBy) {
      if (user == from || user is! HCheck) continue;
      HCheck check = user;
      if (check.checkedInput == to) {
        better = better.prepend(user);
      }
    }

    if (better.isEmpty) return rewrite(from!, to);

    L1:
    for (HInstruction user in from!.usedBy) {
      for (HCheck check in better) {
        if (check.dominates(user)) {
          user.rewriteInput(from, check);
          check.usedBy.add(user);
          continue L1;
        }
      }
      user.rewriteInput(from, to);
      to.usedBy.add(user);
    }
    from.usedBy.clear();
  }

  bool isExitBlock() {
    return identical(first, last) && first is HExit;
  }

  void addDominatedBlock(HBasicBlock block) {
    assert(isClosed);
    assert(id >= 0 && block.id >= 0);
    assert(!dominatedBlocks.contains(block));
    // Keep the list of dominated blocks sorted such that if there are two
    // succeeding blocks in the list, the predecessor is before the successor.
    // Assume that we add the dominated blocks in the right order.
    int index = dominatedBlocks.length;
    while (index > 0 && dominatedBlocks[index - 1].id > block.id) {
      index--;
    }
    if (index == dominatedBlocks.length) {
      dominatedBlocks.add(block);
    } else {
      dominatedBlocks.insert(index, block);
    }
    assert(block.dominator == null);
    block.dominator = this;
  }

  void removeDominatedBlock(HBasicBlock block) {
    assert(isClosed);
    assert(id >= 0 && block.id >= 0);
    int index = dominatedBlocks.indexOf(block);
    assert(index >= 0);
    if (index == dominatedBlocks.length - 1) {
      dominatedBlocks.removeLast();
    } else {
      dominatedBlocks.removeRange(index, index + 1);
    }
    assert(identical(block.dominator, this));
    block.dominator = null;
  }

  void assignCommonDominator(HBasicBlock predecessor) {
    assert(isClosed);
    if (dominator == null) {
      // If this basic block doesn't have a dominator yet we use the
      // given predecessor as the dominator.
      predecessor.addDominatedBlock(this);
    } else if (predecessor.dominator != null) {
      // If the predecessor has a dominator and this basic block has a
      // dominator, we find a common parent in the dominator tree and
      // use that as the dominator.
      HBasicBlock block0 = dominator!;
      HBasicBlock block1 = predecessor;
      while (!identical(block0, block1)) {
        if (block0.id > block1.id) {
          block0 = block0.dominator!;
        } else {
          block1 = block1.dominator!;
        }
        //assert(block0 != null && block1 != null);
      }
      if (!identical(dominator, block0)) {
        dominator!.removeDominatedBlock(this);
        block0.addDominatedBlock(this);
      }
    }
  }

  void forEachPhi(void Function(HPhi phi) f) {
    var current = phis.firstPhi;
    while (current != null) {
      final next = current.nextPhi;
      f(current);
      current = next;
    }
  }

  void forEachInstruction(void Function(HInstruction instruction) f) {
    var current = first;
    while (current != null) {
      final next = current.next;
      f(current);
      current = next;
    }
  }

  bool isValid() {
    assert(isClosed);
    HValidator validator = HValidator();
    validator.visitBasicBlock(this);
    return validator.isValid;
  }

  bool dominates(HBasicBlock other) {
    return dominatorDfsIn <= other.dominatorDfsIn &&
        other.dominatorDfsOut <= dominatorDfsOut;
  }

  @override
  String toString() => 'HBasicBlock($id)';
}

enum _GvnType {
  undefined,
  boundsCheck,
  interceptor,
  add,
  divide,
  multiply,
  subtract,
  shiftLeft,
  bitOr,
  bitAnd,
  bitXor,
  negate,
  bitNot,
  not,
  identity,
  greater,
  greaterEqual,
  less,
  lessEqual,
  static,
  staticStore,
  fieldGet,
  functionReference,
  typeKnown,
  invokeStatic,
  index_,
  invokeDynamic,
  shiftRight,
  truncatingDivide,
  invokeExternal,
  foreignCode,
  remainder,
  getLength,
  abs,
  nullCheck,
  primitiveCheck,
  isTest,
  isTestSimple,
  asCheck,
  asCheckSimple,
  subtypeCheck,
  loadType,
  instanceEnvironment,
  typeEval,
  typeBind,
  isLateSentinel,
  stringConcat,
  stringify,
  lateReadCheck,
  lateWriteOnceCheck,
  lateInitializeOnceCheck,
  charCodeAt,
  arrayFlagsGet,
  arrayFlagsCheck,
}

abstract class HInstruction implements SpannableWithEntity {
  Entity? sourceElement;
  SourceInformation? sourceInformation;

  final int id = idCounter++;
  static int idCounter = 0;

  // A HInstruction owns its [inputs] list. A fresh list is created in every
  // base class constructor to ensure that [inputs] is always a growable
  // List. Although many instructions have a fixed number of inputs (including
  // zero inputs), having a uniform growable representation is more flexible for
  // editing, and allows hundreds of method calls on [inputs] to be
  // devirtualized.
  final List<HInstruction> inputs;

  // Instructions that uses this instruction. A user is [usedBy] once per input
  // that is this instruction.
  //
  //     y = [x, x + 1, x];
  //
  // The [usedBy] for the instruction `x` has three elements, one for the
  // addition instruction and two for the list literal instruction, in no
  // particilar order.
  final List<HInstruction> usedBy = [];

  HBasicBlock? block;
  HInstruction? previous;
  HInstruction? next;

  /// Type of the instruction.
  late AbstractValue instructionType;

  final SideEffects sideEffects = SideEffects.empty();
  bool _useGvn = false;

  // TODO(sra): Consider whether to reduce instruction size by collecting all
  // these instruction flags into a bitmask.
  bool _allowCSE = false;
  bool _allowDCE = false;

  // Main constructor copies the list of inputs to ensure ownership.
  HInstruction(List<HInstruction> initialInputs, this.instructionType)
    : inputs = [...initialInputs];

  // Convenience constructors that avoid an intermediate list.
  HInstruction._noInput(this.instructionType) : inputs = [];
  HInstruction._oneInput(HInstruction input, this.instructionType)
    : inputs = [input];
  HInstruction._twoInputs(
    HInstruction input1,
    HInstruction input2,
    this.instructionType,
  ) : inputs = [input1, input2];

  HInstruction._noType() : inputs = [];

  @override
  Entity? get sourceEntity => sourceElement;

  @override
  SourceSpan? get sourceSpan => sourceInformation?.sourceSpan;

  @override
  int get hashCode => id;

  @override
  bool operator ==(other) => identical(this, other);

  bool useGvn() => _useGvn;
  void setUseGvn() {
    _useGvn = true;
  }

  bool get isMovable => useGvn();

  /// A pure instruction is an instruction that does not have any side
  /// effect, nor any dependency. They can be moved anywhere in the
  /// graph.
  bool isPure(AbstractValueDomain domain) {
    return !sideEffects.hasSideEffects() &&
        !sideEffects.dependsOnSomething() &&
        !canThrow(domain);
  }

  /// `true` if an instruction can be eliminated as a common subexpression -
  /// when the instruction is equivalent to an earlier instruction may be
  /// replaced by the value of the earlier instruction. Equivalent means that
  /// the instruction has exactly the same inputs.
  ///
  /// This property is set on function invocations on the basis of annotations
  /// and program analysis.  Usually, `allowCSE` means that the instruction is
  /// idempotent - a second equivalent instruction returns the same value as the
  /// first instruction without additional observable effects.
  ///
  ///  If an instruction is pure, it should be marked as `useGvn` instead.
  bool get allowCSE => _allowCSE;

  /// `true` if the instruction may be removed when the value is unused.
  ///
  /// This property is set on function invocations on the basis of annotations
  /// and program analysis.  Usually `allowDCE` means that the instruction has
  /// no observable effect.
  bool get allowDCE => _allowDCE;

  /// An instruction is an 'allocation' is it is the sole alias for an object.
  /// This applies to instructions that allocate new objects and can be extended
  /// to methods that return other allocations without escaping them.
  bool isAllocation(AbstractValueDomain domain) => false;

  /// Overridden by [HCheck] to return the actual non-[HCheck]
  /// instruction it checks against.
  HInstruction nonCheck() => this;

  /// Can this node throw an exception?
  bool canThrow(AbstractValueDomain domain) => false;

  bool isValue(AbstractValueDomain domain) =>
      domain.isPrimitiveValue(instructionType);

  AbstractBool isNull(AbstractValueDomain domain) =>
      domain.isNull(instructionType);

  AbstractBool isLateSentinel(AbstractValueDomain domain) =>
      domain.isLateSentinel(instructionType);

  AbstractBool isConflicting(AbstractValueDomain domain) =>
      domain.isEmpty(instructionType);

  AbstractBool isPrimitive(AbstractValueDomain domain) =>
      domain.isPrimitive(instructionType);

  AbstractBool isPrimitiveNumber(AbstractValueDomain domain) =>
      domain.isPrimitiveNumber(instructionType);

  AbstractBool isPrimitiveBoolean(AbstractValueDomain domain) =>
      domain.isPrimitiveBoolean(instructionType);

  AbstractBool isIndexablePrimitive(AbstractValueDomain domain) =>
      domain.isIndexablePrimitive(instructionType);

  AbstractBool isGrowableArray(AbstractValueDomain domain) =>
      domain.isGrowableArray(instructionType);

  AbstractBool isModifiableArray(AbstractValueDomain domain) =>
      domain.isModifiableArray(instructionType);

  AbstractBool isMutableIndexable(AbstractValueDomain domain) =>
      domain.isMutableIndexable(instructionType);

  AbstractBool isArray(AbstractValueDomain domain) =>
      domain.isArray(instructionType);

  AbstractBool isPrimitiveString(AbstractValueDomain domain) =>
      domain.isPrimitiveString(instructionType);

  AbstractBool isInteger(AbstractValueDomain domain) =>
      domain.isInteger(instructionType);

  AbstractBool isUInt32(AbstractValueDomain domain) =>
      domain.isUInt32(instructionType);

  AbstractBool isUInt31(AbstractValueDomain domain) =>
      domain.isUInt31(instructionType);

  AbstractBool isPositiveInteger(AbstractValueDomain domain) =>
      domain.isPositiveInteger(instructionType);

  AbstractBool isPositiveIntegerOrNull(AbstractValueDomain domain) =>
      domain.isPositiveIntegerOrNull(instructionType);

  AbstractBool isIntegerOrNull(AbstractValueDomain domain) =>
      domain.isIntegerOrNull(instructionType);

  AbstractBool isNumber(AbstractValueDomain domain) =>
      domain.isNumber(instructionType);

  AbstractBool isNumberOrNull(AbstractValueDomain domain) =>
      domain.isNumberOrNull(instructionType);

  AbstractBool isBoolean(AbstractValueDomain domain) =>
      domain.isBoolean(instructionType);

  AbstractBool isBooleanOrNull(AbstractValueDomain domain) =>
      domain.isBooleanOrNull(instructionType);

  AbstractBool isString(AbstractValueDomain domain) =>
      domain.isString(instructionType);

  AbstractBool isStringOrNull(AbstractValueDomain domain) =>
      domain.isStringOrNull(instructionType);

  AbstractBool isPrimitiveOrNull(AbstractValueDomain domain) =>
      domain.isPrimitiveOrNull(instructionType);

  HInstruction? getDartReceiver() => null;
  bool onlyThrowsNSM() => false;

  bool isInBasicBlock() => block != null;

  bool gvnEquals(HInstruction other) {
    // Check that the type and the sideEffects match.
    bool hasSameType = typeEquals(other);
    assert(hasSameType == (_gvnType == other._gvnType));
    if (!hasSameType) return false;
    // Check the data first to ensure we are considering the same element or
    // selector.
    if (!dataEquals(other)) return false;
    assert((useGvn() && other.useGvn()) || (allowCSE && other.allowCSE));
    if (sideEffects != other.sideEffects) return false;
    // Check that the inputs match.
    final int inputsLength = inputs.length;
    final List<HInstruction> otherInputs = other.inputs;
    if (inputsLength != otherInputs.length) return false;
    for (int i = 0; i < inputsLength; i++) {
      if (!identical(inputs[i].nonCheck(), otherInputs[i].nonCheck())) {
        return false;
      }
    }
    return true;
  }

  int gvnHashCode() {
    int result = _gvnType.index;
    int length = inputs.length;
    for (int i = 0; i < length; i++) {
      result = (result * 19) + (inputs[i].nonCheck().id) + (result >> 7);
    }
    return result;
  }

  // These methods should be overwritten by instructions that
  // participate in global value numbering or allowCSE.
  _GvnType get _gvnType => _GvnType.undefined;
  bool typeEquals(covariant HInstruction other) => false;
  bool dataEquals(covariant HInstruction other) => false;

  R accept<R>(HVisitor<R> visitor);

  void notifyAddedToBlock(HBasicBlock targetBlock) {
    assert(!isInBasicBlock());
    assert(block == null);
    // Add [this] to the inputs' uses.
    for (int i = 0; i < inputs.length; i++) {
      assert(inputs[i].isInBasicBlock());
      inputs[i].usedBy.add(this);
    }
    block = targetBlock;
    assert(isValid());
  }

  void notifyRemovedFromBlock() {
    assert(isInBasicBlock());
    assert(usedBy.isEmpty);

    // Remove [this] from the inputs' uses.
    for (int i = 0; i < inputs.length; i++) {
      inputs[i].removeUser(this);
    }
    block = null;
    assert(isValid());
  }

  /// Do a in-place change of [from] to [to]. Warning: this function
  /// does not update [inputs] and [usedBy]. Use [changeUse] instead.
  void rewriteInput(HInstruction? from, HInstruction to) {
    for (int i = 0; i < inputs.length; i++) {
      if (identical(inputs[i], from)) inputs[i] = to;
    }
  }

  /// Removes all occurrences of [instruction] from [list].
  void removeFromList(List<HInstruction> list, HInstruction instruction) {
    int length = list.length;
    int i = 0;
    while (i < length) {
      if (instruction == list[i]) {
        list[i] = list[length - 1];
        length--;
      } else {
        i++;
      }
    }
    list.length = length;
  }

  /// Removes all occurrences of [user] from [usedBy].
  void removeUser(HInstruction user) {
    removeFromList(usedBy, user);
  }

  // Change all uses of [oldInput] by [this] to [newInput]. Also updates the
  // [usedBy] of [oldInput] and [newInput].
  void changeUse(HInstruction oldInput, HInstruction newInput) {
    assert(!identical(oldInput, newInput));
    for (int i = 0; i < inputs.length; i++) {
      if (identical(inputs[i], oldInput)) {
        inputs[i] = newInput;
        newInput.usedBy.add(this);
      }
    }
    removeFromList(oldInput.usedBy, this);
  }

  /// Replace a single input.
  ///
  /// Use [changeUse] to change all inputs that are the same value.
  void replaceInput(int index, HInstruction replacement) {
    assert(replacement.isInBasicBlock());
    inputs[index].usedBy.remove(this);
    inputs[index] = replacement;
    replacement.usedBy.add(this);
  }

  /// Remove a single input.
  void removeInput(int index) {
    inputs[index].usedBy.remove(this);
    inputs.removeAt(index);
  }

  void replaceAllUsersDominatedBy(
    HInstruction cursor,
    HInstruction newInstruction,
  ) {
    DominatedUses.of(this, cursor).replaceWith(newInstruction);
  }

  void moveBefore(HInstruction other) {
    assert(this is! HControlFlow);
    assert(this is! HPhi);
    assert(other is! HPhi);
    block!.detach(this);
    other.block!.internalAddBefore(other, this);
    block = other.block;
  }

  bool isConstantBoolean() => false;
  bool isConstantNull() => false;
  bool isConstantNumber() => false;
  bool isConstantInteger() => false;
  bool isConstantString() => false;
  bool isConstantFalse() => false;
  bool isConstantTrue() => false;

  bool isValid() {
    HValidator validator = HValidator();
    validator.currentBlock = block;
    validator.visitInstruction(this);
    return validator.isValid;
  }

  bool isCodeMotionInvariant() => false;

  /// Returns `true` when this HInstruction might be compiled to a JavaScript
  /// statement, `false` when always compiled to a JavaScript expression.
  ///
  /// Some checks are marked as statements even though the generated code is an
  /// expression. This is done when the value of the generated expression does
  /// not correspond to the value of the check (usually one of its inputs).
  bool isJsStatement() => false;

  bool dominates(HInstruction other) {
    // An instruction does not dominates itself.
    if (this == other) return false;
    if (block != other.block) return block!.dominates(other.block!);

    for (var current = next; current != null; current = current.next) {
      if (current == other) return true;
    }
    return false;
  }

  /// Return whether the instructions do not belong to a loop or
  /// belong to the same loop.
  bool hasSameLoopHeaderAs(HInstruction other) {
    return block!.enclosingLoopHeader == other.block!.enclosingLoopHeader;
  }

  @override
  String toString() => '$runtimeType()';
}

mixin HasSettableAllowCSE on HInstruction {
  set allowCSE(bool value) {
    _allowCSE = value;
  }
}

mixin HasSettableAllowDCE on HInstruction {
  set allowDCE(bool value) {
    _allowDCE = value;
  }
}

/// An interface implemented by certain kinds of [HInstruction]. This makes it
/// possible to discover which annotations were in force in the code from which
/// the instruction originated.
// TODO(sra): It would be easier to use a mostly-shared Map-like structure that
// surfaces the ambient annotations at any point in the code.
abstract class InstructionContext {
  MemberEntity? instructionContext;
}

/// The set of uses of [source] that are dominated by [dominator].
class DominatedUses {
  final HInstruction _source;

  // Two list of matching length holding (instruction, input-index) pairs for
  // the dominated uses.
  final List<HInstruction> _instructions = [];
  final List<int> _indexes = [];

  DominatedUses._(this._source);

  /// The uses of [source] that are dominated by [dominator].
  ///
  /// The uses by [dominator] are included in the result, unless
  /// [excludeDominator] is `true`, so `true` selects uses following
  /// [dominator].
  ///
  /// The uses include the in-edges of a HPhi node that corresponds to a
  /// dominated block. (There can be many such edges on a single phi at the exit
  /// of a loop with many break statements).  If [excludePhiOutEdges] is `true`
  /// then these edge uses are not included.
  static DominatedUses of(
    HInstruction source,
    HInstruction dominator, {
    bool excludeDominator = false,
    bool excludePhiOutEdges = false,
  }) {
    return DominatedUses._(source)
      .._compute(source, dominator, excludeDominator, excludePhiOutEdges);
  }

  bool get isEmpty => _instructions.isEmpty;
  bool get isNotEmpty => !isEmpty;
  int get length => _instructions.length;

  /// Changes all the uses in the set to [replacement].
  void replaceWith(HInstruction replacement) {
    assert(replacement.isInBasicBlock());
    assert(!identical(replacement, _source));
    if (isEmpty) return;

    for (int i = 0; i < _instructions.length; i++) {
      HInstruction user = _instructions[i];
      int index = _indexes[i];
      assert(
        identical(user.inputs[index], _source),
        'Input $index of $user changed.'
        '\n  Found: ${user.inputs[index]}\n  Expected: $_source',
      );
      user.inputs[index] = replacement;
      replacement.usedBy.add(user);
    }

    // The following loop is a more efficient implementation of:
    //
    //     for (final user in _instructions) {
    //       _source.usedBy.remove(user);
    //     }
    //
    // `List.remove` searches the list to find the key, and then scans the rest
    // of the list to move the elements up one position.  Repeating this is
    // quadratic.
    //
    // The code below combines searching for the next element with move-up
    // scanning for the previous element(s) to remove several elements in one
    // pass, provided elements of `_instructions` are in the same order as in
    // `usedBy`. This is usually the case since the DominatedUses set is
    // constructed from `_source.usedBy`.

    final usedBy = _source.usedBy;
    int instructionsIndex = 0;
    while (instructionsIndex < _instructions.length) {
      HInstruction nextToRemove = _instructions[instructionsIndex];
      int readIndex = 0, writeIndex = 0;
      while (readIndex < usedBy.length) {
        final user = usedBy[readIndex++];
        if (identical(user, nextToRemove)) {
          instructionsIndex++;
          if (instructionsIndex < _instructions.length) {
            nextToRemove = _instructions[instructionsIndex];
          } else {
            // Copy rest of the list elements up as-is.
            while (readIndex < usedBy.length) {
              usedBy[writeIndex++] = usedBy[readIndex++];
            }
            break;
          }
        } else {
          usedBy[writeIndex++] = user;
        }
      }
      assert(writeIndex < readIndex, 'Should remove at least one per pass');
      usedBy.length = writeIndex;
    }
  }

  bool get isSingleton => _instructions.length == 1;

  HInstruction get single => _instructions.single;

  Iterable<HInstruction> get instructions => _instructions;

  void _addUse(HInstruction user, int inputIndex) {
    _instructions.add(user);
    _indexes.add(inputIndex);
  }

  void _compute(
    HInstruction source,
    HInstruction dominator,
    bool excludeDominator,
    bool excludePhiOutEdges,
  ) {
    assert(dominator is! HPhi);

    // Keep track of all instructions that we have to deal with later and count
    // the number of them that are in the dominator's block.
    Set<HInstruction> users = Setlet();
    Set<HInstruction> seen = Setlet();
    int usersInDominatorBlock = 0;

    HBasicBlock dominatorBlock = dominator.block!;

    // Run through all the users and see if they are dominated, or potentially
    // dominated, or partially dominated by [dominator]. It is easier to
    // de-duplicate [usedBy] and process all inputs of an instruction than to
    // track the repeated elements of usedBy and match them up by index.
    for (HInstruction current in source.usedBy) {
      if (!seen.add(current)) continue;
      HBasicBlock currentBlock = current.block!;
      if (identical(currentBlock, dominatorBlock)) {
        // Ignore phi nodes of the dominator instruction block, they come before
        // the dominator instruction.
        if (current is! HPhi) {
          users.add(current);
          usersInDominatorBlock++;
        }
      } else if (dominatorBlock.dominates(currentBlock)) {
        users.add(current);
      } else if (!excludePhiOutEdges && current is HPhi) {
        // A non-dominated HPhi.
        // See if there a dominated edge into the phi. The input must be
        // [source] and the position must correspond to a dominated block.
        List<HBasicBlock> predecessors = currentBlock.predecessors;
        for (int i = 0; i < predecessors.length; i++) {
          if (current.inputs[i] != source) continue;
          HBasicBlock predecessor = predecessors[i];
          if (dominatorBlock.dominates(predecessor)) {
            _addUse(current, i);
          }
        }
      }
    }

    // Run through all the instructions before [dominator] and remove them from
    // the users set.
    if (usersInDominatorBlock > 0) {
      for (
        var current = dominatorBlock.first;
        !identical(current, dominator);
        current = current!.next
      ) {
        if (users.remove(current)) {
          if (--usersInDominatorBlock == 0) break;
        }
      }
      if (excludeDominator) {
        users.remove(dominator);
      }
    }

    // Convert users into a list of (user, input-index) uses.
    for (HInstruction user in users) {
      var inputs = user.inputs;
      for (int i = 0; i < inputs.length; i++) {
        if (inputs[i] == source) {
          _addUse(user, i);
        }
      }
    }
  }
}

/// A reference to a [HInstruction] that can hold its own source information.
///
/// This used for attaching source information to reads of locals.
class HRef extends HInstruction {
  HRef(HInstruction value, SourceInformation sourceInformation)
    : super._oneInput(value, value.instructionType) {
    this.sourceInformation = sourceInformation;
  }

  HInstruction get value => inputs[0];

  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitRef(this);

  @override
  String toString() => 'HRef($value)';
}

/// Marker interface for late instructions. Late instructions are used after the
/// main optimization phases. They capture codegen decisions just prior to
/// generating JavaScript.
abstract interface class HLateInstruction {}

/// Interface for instructions where the output is constrained to be one of the
/// inputs. Used for checks, where the SSA value of the check represents the
/// same value as the input, but restricted in some way, e.g., being of a
/// refined type or in a checked range.
abstract interface class HOutputConstrainedToAnInput implements HInstruction {
  /// The input which is the 'same' as the output.
  HInstruction get constrainedInput;
}

/// A [HCheck] instruction is an instruction that might do a dynamic check at
/// runtime on an input instruction. To have proper instruction dependencies in
/// the graph, instructions that depend on the check being done reference the
/// [HCheck] instruction instead of the input instruction.
abstract class HCheck extends HInstruction
    implements HOutputConstrainedToAnInput {
  HCheck(super.inputs, super.type) {
    setUseGvn();
  }
  HCheck._oneInput(super.input, super.type) : super._oneInput() {
    setUseGvn();
  }
  HCheck._twoInputs(super.input1, super.input2, super.type)
    : super._twoInputs() {
    setUseGvn();
  }

  HInstruction get checkedInput => inputs[0];

  @override
  HInstruction get constrainedInput => checkedInput;

  @override
  bool isJsStatement() => true;

  @override
  bool canThrow(AbstractValueDomain domain) => true;

  @override
  HInstruction nonCheck() => checkedInput.nonCheck();
}

enum StaticBoundsChecks {
  alwaysFalse,
  fullCheck,
  alwaysAboveZero,
  alwaysBelowLength,
  alwaysTrue,
}

class HBoundsCheck extends HCheck {
  /// Details which tests have been done statically during compilation.
  /// Default is that all checks must be performed dynamically.
  StaticBoundsChecks staticChecks = StaticBoundsChecks.fullCheck;

  HBoundsCheck(
    HInstruction index,
    HInstruction length,
    HInstruction array,
    AbstractValue type,
  ) : super([index, length, array], type);

  HInstruction get index => inputs[0];
  HInstruction get length => inputs[1];
  HInstruction get array => inputs[2];
  // There can be an additional fourth input which is the index to report to
  // [ioore]. This is used by the expansion of [JSArray.removeLast].
  HInstruction get reportedIndex => inputs.length > 3 ? inputs[3] : index;

  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitBoundsCheck(this);
  @override
  _GvnType get _gvnType => _GvnType.boundsCheck;
  @override
  bool typeEquals(other) => other is HBoundsCheck;
  @override
  bool dataEquals(HInstruction other) => true;
}

abstract class HConditionalBranch extends HControlFlow {
  HConditionalBranch(HInstruction condition) {
    inputs.add(condition);
  }
  HInstruction get condition => inputs[0];
  HBasicBlock get trueBranch => block!.successors[0];
  HBasicBlock get falseBranch => block!.successors[1];
}

abstract class HControlFlow extends HInstruction {
  HControlFlow() : super._noType();

  @override
  bool isJsStatement() => true;

  /// HControlFlow instructions don't have an abstract value.
  @override
  AbstractValue get instructionType =>
      throw UnsupportedError('HControlFlow.instructionType');
}

// Allocates and initializes an instance.
class HCreate extends HInstruction {
  final ClassEntity element;

  /// Does this instruction have reified type information as the last input?
  final bool hasRtiInput;

  /// If this field is not `null`, this call is from an inlined constructor and
  /// we have to register the instantiated type in the code generator. The
  /// [instructionType] of this node is not enough, because we also need the
  /// type arguments. See also [SsaFromAstMixin.currentInlinedInstantiations].
  List<InterfaceType>? instantiatedTypes;

  /// If this node creates a closure class, [callMethod] is the call method of
  /// the closure class.
  FunctionEntity? callMethod;

  HCreate(
    this.element,
    super.inputs,
    super.type,
    SourceInformation? sourceInformation, {
    this.instantiatedTypes,
    this.hasRtiInput = false,
    this.callMethod,
  }) {
    this.sourceInformation = sourceInformation;
  }

  @override
  bool isAllocation(AbstractValueDomain domain) => true;

  HInstruction get rtiInput {
    assert(hasRtiInput);
    return inputs.last;
  }

  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitCreate(this);

  @override
  String toString() => 'HCreate($element, $instantiatedTypes)';
}

// Allocates a box to hold mutated captured variables.
class HCreateBox extends HInstruction {
  HCreateBox(super.type) : super._noInput();

  @override
  bool isAllocation(AbstractValueDomain domain) => true;

  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitCreateBox(this);

  @override
  String toString() => 'HCreateBox()';
}

abstract class HInvoke extends HInstruction
    with HasSettableAllowCSE, HasSettableAllowDCE {
  bool _isAllocation = false;

  /// [isInterceptedCall] is true if this invocation uses the interceptor
  /// calling convention where the first input is the methods and the second
  /// input is the Dart receiver.
  bool isInterceptedCall = false;

  /// [_isCallOnInterceptor] is true if this invocation uses the interceptor
  /// calling convention *and* the interceptor input is an interceptor, and not
  /// the receiver. A call has `isInterceptedCall == true` and
  /// `_isCallOnInterceptor == false` after the 'self interceptor' optimization.
  bool _isCallOnInterceptor = false;

  HInvoke(super.inputs, super.type) : super() {
    sideEffects.setAllSideEffects();
    sideEffects.setDependsOnSomething();
  }
  static const int argumentsOffset = 1;

  @override
  bool canThrow(AbstractValueDomain domain) => true;

  @override
  bool isAllocation(AbstractValueDomain domain) => _isAllocation;

  void setAllocation(bool value) {
    _isAllocation = value;
  }

  bool get isCallOnInterceptor => _isCallOnInterceptor;

  /// Update 'isCallOnInterceptor'. An intercepted call can go through
  /// refinements that drop references to unneeded values or arguments:
  ///
  ///     interceptor.foo(receiver, ...); // isCallOnInterceptor = true
  /// -->
  ///     receiver.foo(receiver, ...);    // isCallOnInterceptor = false
  /// -->
  ///     receiver.foo(dummy, ...);       // isCallOnInterceptor = false
  void updateIsCallOnInterceptor() {
    if (isInterceptedCall && _isCallOnInterceptor) {
      final interceptor = inputs[0].nonCheck();
      final receiver = inputs[1].nonCheck();
      if (interceptor == receiver) {
        _isCallOnInterceptor = false;
      } else if (receiver case HConstant(
        constant: DummyInterceptorConstantValue(),
      )) {
        _isCallOnInterceptor = false;
      }
    }
  }
}

abstract class HInvokeDynamic extends HInvoke implements InstructionContext {
  final InvokeDynamicSpecializer specializer;

  Selector _selector;
  AbstractValue _receiverType;
  final AbstractValue _originalReceiverType;

  /// Static type at call-site, often better than union-over-targets.
  AbstractValue? staticType;

  /// `true` if the type parameters at the call are known to be invariant with
  /// respect to the type parameters of the receiver instance. This corresponds
  /// to the [ir.InstanceInvocation.isInvariant] property.  Parametric
  /// covariance checks of the target may be omitted. If the target has explicit
  /// `covariant` checks, these might still need to be checked.
  bool isInvariant = false;

  /// `true` for an indexed getter or setter if the index is known to be in
  /// range. This corresponds to the [ir.InstanceInvocation.isBoundsSafe]
  /// property but and may updated with additional analysis.
  bool isBoundsSafe = false;

  // Cached target when non-nullable receiver type and selector determine a
  // single target. This is in effect a direct call (except for a possible
  // `null` receiver). The element should only be set if the inputs are correct
  // for a direct call. These constraints exclude caching a target when the call
  // needs defaulted arguments, is `noSuchMethod` (legacy), or is a call-through
  // stub.
  MemberEntity? element;

  @override
  MemberEntity? instructionContext;

  HInvokeDynamic(
    Selector selector,
    this._receiverType,
    this.element,
    List<HInstruction> inputs,
    bool isIntercepted,
    AbstractValue resultType,
  ) : _selector = selector,
      _originalReceiverType = _receiverType,
      specializer = isIntercepted
          ? InvokeDynamicSpecializer.lookupSpecializer(selector)
          : const InvokeDynamicSpecializer(),
      super(inputs, resultType) {
    isInterceptedCall = isIntercepted;
    _isCallOnInterceptor = isIntercepted;
    updateIsCallOnInterceptor();
  }

  Selector get selector => _selector;

  set selector(Selector selector) {
    _selector = selector;
    element = null; // Cached element would no longer match new selector.
  }

  AbstractValue get receiverType => _receiverType;

  void updateReceiverType(
    AbstractValueDomain abstractValueDomain,
    AbstractValue value,
  ) {
    _receiverType = abstractValueDomain.intersection(
      _originalReceiverType,
      value,
    );
  }

  /// Returns [value] narrowed by the [staticType].
  AbstractValue computeInstructionType(
    AbstractValue value,
    AbstractValueDomain abstractValueDomain,
  ) {
    if (staticType == null) return value;

    // When the receiver might be a LegacyJavaScriptObject, we don't trust the
    // static type.  Global type inference is conservative for legacy js-interop
    // methods, so we should be conservative here too.
    if (_possiblyLegacyJavaScriptObject(
      selector,
      receiverType,
      abstractValueDomain,
    )) {
      return value;
    }

    final narrowed = abstractValueDomain.intersection(value, staticType!);
    // Preserve the sentinel in [value] since the static type does not include
    // a sentinel and the intersection would remove it.
    return abstractValueDomain.isLateSentinel(value).isPotentiallyTrue
        ? abstractValueDomain.includeLateSentinel(narrowed)
        : narrowed;
  }

  static bool _possiblyLegacyJavaScriptObject(
    Selector selector,
    AbstractValue type,
    AbstractValueDomain domain,
  ) {
    // Legacy js-interop cannot override `[]`.
    if (selector.isIndex) return false;
    if (domain.isPrimitiveOrNull(type).isDefinitelyTrue) return false;
    if (domain.isInterceptor(type).isDefinitelyFalse) return false;
    // We get here for typed_data classes.
    // TODO(sra): Test against LegacyJavaScriptObject explicitly.
    // TODO(sra): Ensure that regular closures are not conflated with
    // JavaScriptFunction which also implements `Function`.
    return true;
  }

  @override
  String toString() => 'invoke dynamic: selector=$selector, mask=$receiverType';

  HInstruction get receiver => inputs[0];

  @override
  HInstruction getDartReceiver() {
    return _isCallOnInterceptor ? inputs[1] : inputs[0];
  }

  /// The type arguments passed in this dynamic invocation.
  List<DartType> get typeArguments;

  @override
  _GvnType get _gvnType => _GvnType.invokeDynamic;

  @override
  bool typeEquals(other) => other is HInvokeDynamic;

  @override
  bool dataEquals(HInvokeDynamic other) {
    return selector == other.selector &&
        (useGvn() == other.useGvn() || allowCSE == other.allowCSE);
  }
}

class HInvokeClosure extends HInvokeDynamic {
  @override
  final List<DartType> typeArguments;

  HInvokeClosure(
    Selector selector,
    AbstractValue receiverType,
    List<HInstruction> inputs,
    AbstractValue resultType,
    this.typeArguments,
  ) : super(selector, receiverType, null, inputs, false, resultType) {
    assert(selector.isMaybeClosureCall);
    assert(selector.callStructure.typeArgumentCount == typeArguments.length);
    assert(!isInterceptedCall);
  }
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitInvokeClosure(this);
}

class HInvokeDynamicMethod extends HInvokeDynamic {
  @override
  final List<DartType> typeArguments;

  HInvokeDynamicMethod(
    Selector selector,
    AbstractValue receiverType,
    List<HInstruction> inputs,
    AbstractValue resultType,
    this.typeArguments,
    SourceInformation? sourceInformation, {
    bool isIntercepted = false,
  }) : super(selector, receiverType, null, inputs, isIntercepted, resultType) {
    this.sourceInformation = sourceInformation;
    assert(selector.callStructure.typeArgumentCount == typeArguments.length);
  }

  @override
  String toString() =>
      'invoke dynamic method: selector=$selector, mask=$receiverType';
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitInvokeDynamicMethod(this);
}

abstract class HInvokeDynamicField extends HInvokeDynamic {
  HInvokeDynamicField(
    Selector selector,
    AbstractValue receiverType,
    MemberEntity? element,
    List<HInstruction> inputs,
    bool isIntercepted,
    AbstractValue resultType,
  ) : super(selector, receiverType, element, inputs, isIntercepted, resultType);

  @override
  String toString() =>
      'invoke dynamic field: selector=$selector, mask=$receiverType';
}

class HInvokeDynamicGetter extends HInvokeDynamicField {
  HInvokeDynamicGetter(
    Selector selector,
    AbstractValue receiverType,
    MemberEntity? element,
    List<HInstruction> inputs,
    bool isIntercepted,
    AbstractValue resultType,
    SourceInformation? sourceInformation,
  ) : super(
        selector,
        receiverType,
        element,
        inputs,
        isIntercepted,
        resultType,
      ) {
    this.sourceInformation = sourceInformation;
  }

  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitInvokeDynamicGetter(this);

  bool get isTearOff => element != null && element!.isFunction;

  @override
  List<DartType> get typeArguments => const [];

  // There might be an interceptor input, so `inputs.last` is the dart receiver.
  @override
  bool canThrow(AbstractValueDomain domain) => isTearOff
      ? inputs.last.isNull(domain).isPotentiallyTrue
      : super.canThrow(domain);

  @override
  String toString() =>
      'invoke dynamic getter: selector=$selector, mask=$receiverType';
}

class HInvokeDynamicSetter extends HInvokeDynamicField {
  /// If `true` a call to the setter is needed for checking the type even
  /// though the target field is known.
  bool needsCheck = false;

  HInvokeDynamicSetter(
    Selector selector,
    AbstractValue receiverType,
    MemberEntity? element,
    List<HInstruction> inputs,
    bool isIntercepted,
    // TODO(johnniwinther): The result type for a setter should be the empty
    // type.
    AbstractValue resultType,
    SourceInformation? sourceInformation,
  ) : super(
        selector,
        receiverType,
        element,
        inputs,
        isIntercepted,
        resultType,
      ) {
    this.sourceInformation = sourceInformation;
  }

  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitInvokeDynamicSetter(this);

  @override
  List<DartType> get typeArguments => const [];

  @override
  String toString() =>
      'invoke dynamic setter: selector=$selector, mask=$receiverType, element=$element';
}

class HInvokeStatic extends HInvoke {
  final MemberEntity element;

  /// The type arguments passed in this static invocation.
  final List<DartType> typeArguments;

  bool targetCanThrow;

  @override
  bool canThrow(AbstractValueDomain domain) => targetCanThrow;

  /// If this instruction is a call to a constructor, [instantiatedTypes]
  /// contains the type(s) used in the (Dart) `New` expression(s). The
  /// [instructionType] of this node is not enough, because we also need the
  /// type arguments. See also [SsaFromAstMixin.currentInlinedInstantiations].
  List<InterfaceType>? instantiatedTypes;

  /// The first input must be the target.
  HInvokeStatic(
    this.element,
    List<HInstruction> inputs,
    AbstractValue type,
    this.typeArguments, {
    this.targetCanThrow = true,
    bool isIntercepted = false,
  }) : super(inputs, type) {
    isInterceptedCall = isIntercepted;
    _isCallOnInterceptor = isIntercepted;
    updateIsCallOnInterceptor();
  }

  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitInvokeStatic(this);

  @override
  _GvnType get _gvnType => _GvnType.invokeStatic;
  @override
  bool typeEquals(other) => other is HInvokeStatic;
  @override
  bool dataEquals(HInvokeStatic other) => element == other.element;

  @override
  String toString() => 'invoke static: $element';
}

class HInvokeSuper extends HInvokeStatic {
  /// The class where the call to super is being done.
  final ClassEntity caller;
  final bool isSetter;
  final Selector selector;

  HInvokeSuper(
    MemberEntity element,
    this.caller,
    this.selector,
    List<HInstruction> inputs,
    bool isIntercepted,
    AbstractValue type,
    List<DartType> typeArguments,
    SourceInformation? sourceInformation, {
    required this.isSetter,
  }) : super(
         element,
         inputs,
         type,
         typeArguments,
         isIntercepted: isIntercepted,
       ) {
    this.sourceInformation = sourceInformation;
  }

  HInstruction get receiver => inputs[0];
  @override
  HInstruction getDartReceiver() {
    return isCallOnInterceptor ? inputs[1] : inputs[0];
  }

  @override
  String toString() => 'invoke super: $element';
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitInvokeSuper(this);

  HInstruction get value {
    assert(isSetter);
    // The 'inputs' are [receiver, value] or [interceptor, receiver, value].
    return inputs.last;
  }
}

class HInvokeConstructorBody extends HInvokeStatic {
  // The 'inputs' are
  //     [receiver, arg1, ..., argN] or
  //     [interceptor, receiver, arg1, ... argN].
  HInvokeConstructorBody(
    ConstructorBodyEntity element,
    List<HInstruction> inputs,
    AbstractValue type,
    SourceInformation? sourceInformation,
  ) : super(element, inputs, type, const []) {
    this.sourceInformation = sourceInformation;
  }

  @override
  String toString() => 'invoke constructor body: ${element.name}';
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitInvokeConstructorBody(this);
}

class HInvokeGeneratorBody extends HInvokeStatic {
  // Directly call the JGeneratorBody method. The generator body can be a static
  // method or a member. The target is directly called.
  // The 'inputs' are
  //     [arg1, ..., argN] or
  //     [receiver, arg1, ..., argN] or
  //     [interceptor, receiver, arg1, ... argN].
  // The 'inputs' may or may not have an additional type argument used for
  // creating the generator (T for new Completer<T>() inside the body).
  HInvokeGeneratorBody(
    FunctionEntity element,
    List<HInstruction> inputs,
    AbstractValue type,
    SourceInformation? sourceInformation,
  ) : super(element, inputs, type, const []) {
    this.sourceInformation = sourceInformation;
  }

  @override
  String toString() => 'HInvokeGeneratorBody(${element.name})';
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitInvokeGeneratorBody(this);
}

abstract class HFieldAccess extends HInstruction {
  final FieldEntity element;

  HFieldAccess(this.element, List<HInstruction> inputs, AbstractValue type)
    : super(inputs, type);

  HInstruction get receiver => inputs[0];
}

class HFieldGet extends HFieldAccess {
  final bool isAssignable;

  HFieldGet(
    FieldEntity element,
    HInstruction receiver,
    AbstractValue type,
    SourceInformation? sourceInformation, {
    required this.isAssignable,
  }) : super(element, [receiver], type) {
    this.sourceInformation = sourceInformation;
    sideEffects.clearAllSideEffects();
    sideEffects.clearAllDependencies();
    setUseGvn();
    if (isAssignable) {
      sideEffects.setDependsOnInstancePropertyStore();
    }
  }

  @override
  bool canThrow(AbstractValueDomain domain) =>
      receiver.isNull(domain).isPotentiallyTrue;

  @override
  HInstruction getDartReceiver() => receiver;
  @override
  bool onlyThrowsNSM() => true;

  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitFieldGet(this);

  @override
  _GvnType get _gvnType => _GvnType.fieldGet;
  @override
  bool typeEquals(other) => other is HFieldGet;
  @override
  bool dataEquals(HFieldGet other) => element == other.element;
  @override
  String toString() => "FieldGet(element=$element,type=$instructionType)";
}

class HFieldSet extends HFieldAccess {
  HFieldSet(FieldEntity element, HInstruction receiver, HInstruction value)
    : super(element, [receiver, value], value.instructionType) {
    sideEffects.clearAllSideEffects();
    sideEffects.clearAllDependencies();
    sideEffects.setChangesInstanceProperty();
  }

  @override
  bool canThrow(AbstractValueDomain domain) =>
      receiver.isNull(domain).isPotentiallyTrue;

  @override
  HInstruction getDartReceiver() => receiver;
  @override
  bool onlyThrowsNSM() => true;

  HInstruction get value => inputs[1];
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitFieldSet(this);

  @override
  String toString() => "FieldSet(element=$element,type=$instructionType)";
}

// Raw reference to a function.
class HFunctionReference extends HInstruction {
  FunctionEntity element;
  HFunctionReference(this.element, super.type) : super._noInput() {
    sideEffects.clearAllSideEffects();
    sideEffects.clearAllDependencies();
    setUseGvn();
  }

  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitFunctionReference(this);

  @override
  _GvnType get _gvnType => _GvnType.functionReference;
  @override
  bool typeEquals(other) => other is HFunctionReference;
  @override
  bool dataEquals(HFunctionReference other) => element == other.element;
  @override
  String toString() => "FunctionReference($element)";
}

class HGetLength extends HInstruction {
  final bool isAssignable;
  HGetLength(super.receiver, super.type, {required this.isAssignable})
    : super._oneInput() {
    sideEffects.clearAllSideEffects();
    sideEffects.clearAllDependencies();
    setUseGvn();
    if (isAssignable) {
      sideEffects.setDependsOnInstancePropertyStore();
    }
  }

  HInstruction get receiver => inputs.single;

  @override
  bool canThrow(AbstractValueDomain domain) =>
      receiver.isNull(domain).isPotentiallyTrue;

  @override
  HInstruction getDartReceiver() => receiver;
  @override
  bool onlyThrowsNSM() => true;

  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitGetLength(this);

  @override
  _GvnType get _gvnType => _GvnType.getLength;
  @override
  bool typeEquals(other) => other is HGetLength;
  @override
  bool dataEquals(HGetLength other) => true;
  @override
  String toString() => "GetLength()";
}

enum ReadModifyWriteKind { assign, prefix, postfix }

/// HReadModifyWrite is a late stage instruction for a field (property) update
/// via an assignment operation or pre- or post-increment.
class HReadModifyWrite extends HInstruction implements HLateInstruction {
  final FieldEntity element;
  final String jsOp;
  final ReadModifyWriteKind opKind;

  HReadModifyWrite._(
    this.element,
    this.jsOp,
    this.opKind,
    super.inputs,
    super.type,
  ) {
    sideEffects.clearAllSideEffects();
    sideEffects.clearAllDependencies();
    sideEffects.setChangesInstanceProperty();
    sideEffects.setDependsOnInstancePropertyStore();
  }

  HReadModifyWrite.assignOp(
    FieldEntity element,
    String jsOp,
    HInstruction receiver,
    HInstruction operand,
    AbstractValue type,
  ) : this._(element, jsOp, ReadModifyWriteKind.assign, [
        receiver,
        operand,
      ], type);

  HReadModifyWrite.preOp(
    FieldEntity element,
    String jsOp,
    HInstruction receiver,
    AbstractValue type,
  ) : this._(element, jsOp, ReadModifyWriteKind.prefix, [receiver], type);

  HReadModifyWrite.postOp(
    FieldEntity element,
    String jsOp,
    HInstruction receiver,
    AbstractValue type,
  ) : this._(element, jsOp, ReadModifyWriteKind.postfix, [receiver], type);

  HInstruction get receiver => inputs[0];

  bool get isPreOp => opKind == ReadModifyWriteKind.prefix;
  bool get isPostOp => opKind == ReadModifyWriteKind.postfix;
  bool get isAssignOp => opKind == ReadModifyWriteKind.assign;

  @override
  bool canThrow(AbstractValueDomain domain) =>
      receiver.isNull(domain).isPotentiallyTrue;

  @override
  HInstruction getDartReceiver() => receiver;
  @override
  bool onlyThrowsNSM() => true;

  HInstruction get value => inputs[1];
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitReadModifyWrite(this);

  @override
  String toString() => "ReadModifyWrite $jsOp $opKind $element";
}

abstract class HLocalAccess extends HInstruction {
  final Local variable;

  HLocalAccess(this.variable, List<HInstruction> inputs, AbstractValue type)
    : super(inputs, type);

  HInstruction get receiver => inputs[0];
}

class HLocalGet extends HLocalAccess {
  // No need to use GVN for a [HLocalGet], it is just a local
  // access.
  HLocalGet(
    Local variable,
    HLocalValue local,
    AbstractValue type,
    SourceInformation? sourceInformation,
  ) : super(variable, [local], type) {
    this.sourceInformation = sourceInformation;
  }

  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitLocalGet(this);

  HLocalValue get local => inputs[0] as HLocalValue;

  @override
  String toString() => 'HLocalGet($local).$hashCode';
}

class HLocalSet extends HLocalAccess {
  HLocalSet(
    Local variable,
    HLocalValue local,
    HInstruction value,
    AbstractValue type,
  ) : super(variable, [local, value], type);

  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitLocalSet(this);

  HLocalValue get local => inputs[0] as HLocalValue;
  HInstruction get value => inputs[1];
}

/// Invocation of a native or JS-interop method.
///
/// Includes various invocations where the JavaScript form is similar to the
/// Dart form:
///
///     receiver.property          // An instance getter
///     receiver.property = value  // An instance setter
///     receiver.method(arg)       // An instance method
///
///     Class.property             // A static getter
///     Class.property = value     // A static setter
///     Class.method(arg)          // A static method
///     new Class(arg)             // A constructor
///
/// HInvokeDynamicMethod can be lowered to HInvokeExternal with the same
/// [element]. The difference is a HInvokeDynamicMethod is a call to a
/// Dart-calling-convention stub identified by [element] that contains a call to
/// the external method, whereas a HInvokeExternal instruction is a direct
/// JavaScript call to the external method identified by [element].
class HInvokeExternal extends HInvoke {
  final FunctionEntity element;

  // The following fields are functions of [element] that are extracted for
  // convenience.
  final NativeBehavior? nativeBehavior;
  final NativeThrowBehavior throwBehavior;

  HInvokeExternal(
    this.element,
    List<HInstruction> inputs,
    AbstractValue type,
    this.nativeBehavior, {
    SourceInformation? sourceInformation,
  }) : throwBehavior = nativeBehavior?.throwBehavior ?? NativeThrowBehavior.may,
       super(inputs, type) {
    if (nativeBehavior == null) {
      sideEffects.setAllSideEffects();
      sideEffects.setDependsOnSomething();
    } else {
      sideEffects.add(nativeBehavior!.sideEffects);
    }
    if (nativeBehavior != null && nativeBehavior!.useGvn) {
      setUseGvn();
    }
    this.sourceInformation = sourceInformation;
  }

  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitInvokeExternal(this);

  @override
  bool isJsStatement() => false;

  @override
  bool canThrow(AbstractValueDomain domain) {
    if (element.isInstanceMember) {
      if (inputs.isNotEmpty) {
        return inputs.first.isNull(domain).isPotentiallyTrue
            ? throwBehavior.canThrow
            : throwBehavior.onNonNull.canThrow;
      }
    }
    return throwBehavior.canThrow;
  }

  @override
  bool onlyThrowsNSM() => throwBehavior.isOnlyNullNSMGuard;

  @override
  bool isAllocation(AbstractValueDomain domain) =>
      nativeBehavior != null &&
      nativeBehavior!.isAllocation &&
      isNull(domain).isDefinitelyFalse;

  /// Returns `true` if the call will throw an NoSuchMethod error if [receiver]
  /// is `null` before having any other side-effects.
  bool isNullGuardFor(HInstruction receiver) {
    if (!element.isInstanceMember) return false;
    if (inputs.isEmpty) return false;
    if (inputs.first.nonCheck() != receiver.nonCheck()) return false;
    return true;
  }

  @override
  _GvnType get _gvnType => _GvnType.invokeExternal;
  @override
  bool typeEquals(other) => other is HInvokeExternal;
  @override
  bool dataEquals(HInvokeExternal other) {
    return element == other.element;
  }

  @override
  String toString() => 'HInvokeExternal($element)';
}

abstract class HForeign extends HInstruction {
  HForeign(AbstractValue type, List<HInstruction> inputs) : super(inputs, type);

  bool get isStatement => false;
  NativeBehavior? get nativeBehavior => null;

  @override
  bool canThrow(AbstractValueDomain domain) {
    return sideEffects.hasSideEffects() || sideEffects.dependsOnSomething();
  }
}

class HForeignCode extends HForeign {
  final js.Template codeTemplate;
  @override
  final bool isStatement;
  @override
  final NativeBehavior? nativeBehavior;
  late final NativeThrowBehavior throwBehavior;

  HForeignCode(
    this.codeTemplate,
    AbstractValue type,
    List<HInstruction> inputs, {
    this.isStatement = false,
    SideEffects? effects,
    this.nativeBehavior,
    NativeThrowBehavior? throwBehavior,
  }) : throwBehavior =
           throwBehavior ??
           nativeBehavior?.throwBehavior ??
           NativeThrowBehavior.may,
       super(type, inputs) {
    effects ??= nativeBehavior?.sideEffects;

    if (effects != null) sideEffects.add(effects);
    if (nativeBehavior?.useGvn == true) {
      setUseGvn();
    }
  }

  HForeignCode.statement(
    js.Template codeTemplate,
    List<HInstruction> inputs,
    SideEffects effects,
    NativeBehavior nativeBehavior,
    AbstractValue type,
  ) : this(
        codeTemplate,
        type,
        inputs,
        isStatement: true,
        effects: effects,
        nativeBehavior: nativeBehavior,
      );

  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitForeignCode(this);

  @override
  bool isJsStatement() => isStatement;

  @override
  bool canThrow(AbstractValueDomain domain) {
    if (inputs.isNotEmpty) {
      return inputs.first.isNull(domain).isPotentiallyTrue
          ? throwBehavior.canThrow
          : throwBehavior.onNonNull.canThrow;
    }
    return throwBehavior.canThrow;
  }

  @override
  bool onlyThrowsNSM() => throwBehavior.isOnlyNullNSMGuard;

  @override
  bool isAllocation(AbstractValueDomain domain) =>
      nativeBehavior != null &&
      nativeBehavior!.isAllocation &&
      isNull(domain).isDefinitelyFalse;

  /// Returns `true` if the template will throw an NoSuchMethod error if
  /// [receiver] is `null` before having any other side-effects.
  bool isNullGuardFor(HInstruction? receiver) {
    if (!throwBehavior.isNullNSMGuard) return false;
    if (inputs.isEmpty) return false;
    if (inputs.first.nonCheck() != receiver!.nonCheck()) return false;
    return true;
  }

  @override
  _GvnType get _gvnType => _GvnType.foreignCode;
  @override
  bool typeEquals(other) => other is HForeignCode;
  @override
  bool dataEquals(HForeignCode other) {
    if (codeTemplate.source == null) {
      return other.codeTemplate.source == null &&
          // The ASTs will be equal if identical, and in some limited other
          // cases, like a ModularExpression.
          codeTemplate.ast == other.codeTemplate.ast;
    }
    return codeTemplate.source == other.codeTemplate.source;
  }

  @override
  String toString() => 'HForeignCode("${codeTemplate.source}")';
}

abstract class HInvokeBinary extends HInstruction {
  HInvokeBinary(super.left, super.right, super.type) : super._twoInputs() {
    sideEffects.clearAllSideEffects();
    sideEffects.clearAllDependencies();
    setUseGvn();
  }

  HInstruction get left => inputs[0];
  HInstruction get right => inputs[1];

  constant_system.BinaryOperation operation();
}

abstract class HBinaryArithmetic extends HInvokeBinary {
  HBinaryArithmetic(HInstruction left, HInstruction right, AbstractValue type)
    : super(left, right, type);
  @override
  constant_system.BinaryOperation operation();
}

class HAdd extends HBinaryArithmetic {
  HAdd(HInstruction left, HInstruction right, AbstractValue type)
    : super(left, right, type);
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitAdd(this);

  @override
  constant_system.BinaryOperation operation() => constant_system.add;
  @override
  _GvnType get _gvnType => _GvnType.add;
  @override
  bool typeEquals(other) => other is HAdd;
  @override
  bool dataEquals(HInstruction other) => true;
}

class HDivide extends HBinaryArithmetic {
  HDivide(HInstruction left, HInstruction right, AbstractValue type)
    : super(left, right, type);
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitDivide(this);

  @override
  constant_system.BinaryOperation operation() => constant_system.divide;
  @override
  _GvnType get _gvnType => _GvnType.divide;
  @override
  bool typeEquals(other) => other is HDivide;
  @override
  bool dataEquals(HInstruction other) => true;
}

class HMultiply extends HBinaryArithmetic {
  HMultiply(HInstruction left, HInstruction right, AbstractValue type)
    : super(left, right, type);
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitMultiply(this);

  @override
  constant_system.BinaryOperation operation() => constant_system.multiply;
  @override
  _GvnType get _gvnType => _GvnType.multiply;
  @override
  bool typeEquals(other) => other is HMultiply;
  @override
  bool dataEquals(HInstruction other) => true;
}

class HSubtract extends HBinaryArithmetic {
  HSubtract(HInstruction left, HInstruction right, AbstractValue type)
    : super(left, right, type);
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitSubtract(this);

  @override
  constant_system.BinaryOperation operation() => constant_system.subtract;
  @override
  _GvnType get _gvnType => _GvnType.subtract;
  @override
  bool typeEquals(other) => other is HSubtract;
  @override
  bool dataEquals(HInstruction other) => true;
}

class HTruncatingDivide extends HBinaryArithmetic {
  HTruncatingDivide(HInstruction left, HInstruction right, AbstractValue type)
    : super(left, right, type);
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitTruncatingDivide(this);

  @override
  constant_system.BinaryOperation operation() =>
      constant_system.truncatingDivide;
  @override
  _GvnType get _gvnType => _GvnType.truncatingDivide;
  @override
  bool typeEquals(other) => other is HTruncatingDivide;
  @override
  bool dataEquals(HInstruction other) => true;
}

class HRemainder extends HBinaryArithmetic {
  HRemainder(HInstruction left, HInstruction right, AbstractValue type)
    : super(left, right, type);
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitRemainder(this);

  @override
  constant_system.BinaryOperation operation() => constant_system.remainder;
  @override
  _GvnType get _gvnType => _GvnType.remainder;
  @override
  bool typeEquals(other) => other is HRemainder;
  @override
  bool dataEquals(HInstruction other) => true;
}

/// An [HSwitch] instruction has one input for the incoming
/// value, and one input per constant that it can switch on.
/// Its block has one successor per constant, and one for the default.
class HSwitch extends HControlFlow {
  HSwitch(HInstruction input) {
    inputs.add(input);
  }

  HConstant constant(int index) => inputs[index + 1] as HConstant;
  HInstruction get expression => inputs[0];

  /// Provides the target to jump to if none of the constants match
  /// the expression. If the switch had no default case, this is the
  /// following join-block.
  HBasicBlock get defaultTarget => block!.successors.last;

  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitSwitch(this);

  @override
  String toString() => "HSwitch cases = $inputs";
}

abstract class HBinaryBitOp extends HInvokeBinary {
  /// JavaScript bitwise operations like `&` produce a 32-bit signed results but
  /// the Dart-web operations produce an unsigned result. Conversion to unsigned
  /// might be unnecessary (e.g. the inputs are such that JavaScript operation
  /// cannot produce a negative value). During instruction selection we
  /// determine if conversion is unnecessary.
  bool requiresUintConversion = true;

  HBinaryBitOp(HInstruction left, HInstruction right, AbstractValue type)
    : super(left, right, type);
}

class HShiftLeft extends HBinaryBitOp {
  HShiftLeft(HInstruction left, HInstruction right, AbstractValue type)
    : super(left, right, type);
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitShiftLeft(this);

  @override
  constant_system.BinaryOperation operation() => constant_system.shiftLeft;
  @override
  _GvnType get _gvnType => _GvnType.shiftLeft;
  @override
  bool typeEquals(other) => other is HShiftLeft;
  @override
  bool dataEquals(HInstruction other) => true;
}

class HShiftRight extends HBinaryBitOp {
  HShiftRight(HInstruction left, HInstruction right, AbstractValue type)
    : super(left, right, type);
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitShiftRight(this);

  @override
  constant_system.BinaryOperation operation() => constant_system.shiftRight;
  @override
  _GvnType get _gvnType => _GvnType.shiftRight;
  @override
  bool typeEquals(other) => other is HShiftRight;
  @override
  bool dataEquals(HInstruction other) => true;
}

class HBitOr extends HBinaryBitOp {
  HBitOr(HInstruction left, HInstruction right, AbstractValue type)
    : super(left, right, type);
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitBitOr(this);

  @override
  constant_system.BinaryOperation operation() => constant_system.bitOr;
  @override
  _GvnType get _gvnType => _GvnType.bitOr;
  @override
  bool typeEquals(other) => other is HBitOr;
  @override
  bool dataEquals(HInstruction other) => true;
}

class HBitAnd extends HBinaryBitOp {
  HBitAnd(HInstruction left, HInstruction right, AbstractValue type)
    : super(left, right, type);
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitBitAnd(this);

  @override
  constant_system.BinaryOperation operation() => constant_system.bitAnd;
  @override
  _GvnType get _gvnType => _GvnType.bitAnd;
  @override
  bool typeEquals(other) => other is HBitAnd;
  @override
  bool dataEquals(HInstruction other) => true;
}

class HBitXor extends HBinaryBitOp {
  HBitXor(HInstruction left, HInstruction right, AbstractValue type)
    : super(left, right, type);
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitBitXor(this);

  @override
  constant_system.BinaryOperation operation() => constant_system.bitXor;
  @override
  _GvnType get _gvnType => _GvnType.bitXor;
  @override
  bool typeEquals(other) => other is HBitXor;
  @override
  bool dataEquals(HInstruction other) => true;
}

abstract class HInvokeUnary extends HInstruction {
  HInvokeUnary(super.input, super.type) : super._oneInput() {
    sideEffects.clearAllSideEffects();
    sideEffects.clearAllDependencies();
    setUseGvn();
  }

  HInstruction get operand => inputs[0];

  constant_system.UnaryOperation operation();
}

class HNegate extends HInvokeUnary {
  HNegate(HInstruction input, AbstractValue type) : super(input, type);
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitNegate(this);

  @override
  constant_system.UnaryOperation operation() => constant_system.negate;
  @override
  _GvnType get _gvnType => _GvnType.negate;
  @override
  bool typeEquals(other) => other is HNegate;
  @override
  bool dataEquals(HInstruction other) => true;
}

class HAbs extends HInvokeUnary {
  HAbs(HInstruction input, AbstractValue type) : super(input, type);
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitAbs(this);

  @override
  constant_system.UnaryOperation operation() => constant_system.abs;
  @override
  _GvnType get _gvnType => _GvnType.abs;
  @override
  bool typeEquals(other) => other is HAbs;
  @override
  bool dataEquals(HInstruction other) => true;
}

class HBitNot extends HInvokeUnary {
  /// JavaScript `~` produces a 32-bit signed result the Dart-web operation
  /// produces an unsigned result. Conversion to unsigned might be unnecessary
  /// (e.g. the value is immediately masked). During instruction selection we
  /// determine if conversion is unnecessary.
  bool requiresUintConversion = true;

  HBitNot(HInstruction input, AbstractValue type) : super(input, type);
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitBitNot(this);

  @override
  constant_system.UnaryOperation operation() => constant_system.bitNot;
  @override
  _GvnType get _gvnType => _GvnType.bitNot;
  @override
  bool typeEquals(other) => other is HBitNot;
  @override
  bool dataEquals(HInstruction other) => true;
}

class HExit extends HControlFlow {
  @override
  String toString() => 'exit';
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitExit(this);
}

class HGoto extends HControlFlow {
  @override
  String toString() => 'goto';
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitGoto(this);
}

abstract class HJump extends HControlFlow {
  final JumpTarget target;
  final LabelDefinition? label;
  HJump(this.target, SourceInformation? sourceInformation) : label = null {
    this.sourceInformation = sourceInformation;
  }
  HJump.toLabel(
    LabelDefinition this.label,
    SourceInformation? sourceInformation,
  ) : target = label.target {
    this.sourceInformation = sourceInformation;
  }
}

class HBreak extends HJump {
  /// Signals that this is a special break instruction for the synthetic loop
  /// generated for a switch statement with continue statements. See
  /// [SsaFromAstMixin.buildComplexSwitchStatement] for detail.
  final bool breakSwitchContinueLoop;

  HBreak(
    JumpTarget target,
    SourceInformation? sourceInformation, {
    this.breakSwitchContinueLoop = false,
  }) : super(target, sourceInformation);

  HBreak.toLabel(LabelDefinition label, SourceInformation? sourceInformation)
    : breakSwitchContinueLoop = false,
      super.toLabel(label, sourceInformation);

  @override
  String toString() => (label != null) ? 'break ${label!.labelName}' : 'break';

  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitBreak(this);
}

class HContinue extends HJump {
  HContinue(JumpTarget target, SourceInformation? sourceInformation)
    : super(target, sourceInformation);

  HContinue.toLabel(LabelDefinition label, SourceInformation? sourceInformation)
    : super.toLabel(label, sourceInformation);

  @override
  String toString() =>
      (label != null) ? 'continue ${label!.labelName}' : 'continue';

  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitContinue(this);
}

class HTry extends HControlFlow {
  HLocalValue? exception;
  HBasicBlock? catchBlock;
  HBasicBlock? finallyBlock;
  @override
  String toString() => 'try';
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitTry(this);
  HBasicBlock get joinBlock => block!.successors.last;
}

// An [HExitTry] control flow node is used when the body of a try or
// the body of a catch contains a return, break or continue. To build
// the control flow graph, we explicitly mark the body that
// leads to one of this instruction a predecessor of catch and
// finally.
class HExitTry extends HControlFlow {
  @override
  String toString() => 'exit try';
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitExitTry(this);
  HBasicBlock get bodyTrySuccessor => block!.successors[0];
}

class HIf extends HConditionalBranch {
  HBlockFlow? blockInformation;
  HIf(super.condition);
  @override
  String toString() => 'if';
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitIf(this);

  HBasicBlock get thenBlock {
    assert(identical(block!.dominatedBlocks[0], block!.successors[0]));
    return block!.successors[0];
  }

  HBasicBlock get elseBlock {
    assert(identical(block!.dominatedBlocks[1], block!.successors[1]));
    return block!.successors[1];
  }

  HBasicBlock? get joinBlock => blockInformation!.continuation;
}

class HLoopBranch extends HConditionalBranch {
  HLoopBranch(super.condition);
  @override
  String toString() => 'loop-branch';
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitLoopBranch(this);
}

class HConstant extends HInstruction {
  final ConstantValue constant;
  HConstant._internal(this.constant, super.constantType) : super._noInput();

  @override
  String toString() => 'literal: ${constant.toStructuredText(null)}';
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitConstant(this);

  @override
  bool isConstantBoolean() => constant is BoolConstantValue;
  @override
  bool isConstantNull() => constant is NullConstantValue;
  @override
  bool isConstantNumber() => constant is NumConstantValue;
  @override
  bool isConstantInteger() => constant is IntConstantValue;
  @override
  bool isConstantString() => constant is StringConstantValue;
  @override
  bool isConstantFalse() => constant is FalseConstantValue;
  @override
  bool isConstantTrue() => constant is TrueConstantValue;

  // Maybe avoid this if the literal is big?
  @override
  bool isCodeMotionInvariant() => true;

  @override
  set instructionType(AbstractValue type) {
    // Only lists can be specialized. The SSA builder uses the
    // inferrer for finding the type of a constant list. We should
    // have the constant know its type instead.
    if (constant is! ListConstantValue) return;
    super.instructionType = type;
  }
}

class HNot extends HInstruction {
  HNot(super.value, super.type) : super._oneInput() {
    setUseGvn();
  }

  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitNot(this);
  @override
  _GvnType get _gvnType => _GvnType.not;
  @override
  bool typeEquals(other) => other is HNot;
  @override
  bool dataEquals(HInstruction other) => true;
}

/// An [HLocalValue] represents a local. Unlike [HParameterValue]s its
/// first use must be in an HLocalSet. That is, [HParameterValue]s have a
/// value from the start, whereas [HLocalValue]s need to be initialized first.
class HLocalValue extends HInstruction {
  HLocalValue(Entity? variable, super.type) : super._noInput() {
    sourceElement = variable;
  }

  @override
  String toString() => 'local ${sourceElement!.name}';
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitLocalValue(this);
}

class HParameterValue extends HLocalValue {
  bool _potentiallyUsedAsVariable = true;

  HParameterValue(Entity? variable, AbstractValue type) : super(variable, type);

  // [HParameterValue]s are either the value of the parameter (in fully SSA
  // converted code), or the mutable variable containing the value (in
  // incompletely SSA converted code, e.g. methods containing exceptions).
  bool usedAsVariable() {
    if (_potentiallyUsedAsVariable) {
      // If the HParameterValue is used as a variable, all of the uses should be
      // HLocalGet or HLocalSet, so this loop exits fast.
      for (HInstruction user in usedBy) {
        if (user is HLocalGet) return true;
        if (user is HLocalSet && user.local == this) return true;
      }
      // An 'ssa-conversion' optimization can make the HParameterValue change
      // from a variable to a value, but there is no transformation that
      // re-introduces the variable.
      // TODO(sra): The builder knows that most parameters are not variables to
      // begin with, so could initialize [_potentiallyUsedAsVariable] to
      // `false`.
      _potentiallyUsedAsVariable = false;
    }
    return false;
  }

  @override
  String toString() => 'parameter ${sourceElement!.name}';
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitParameterValue(this);
}

class HThis extends HParameterValue {
  // [element] can be null for some synthetic members, e.g. `$signature`.
  HThis(ThisLocal? element, AbstractValue type) : super(element, type);

  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitThis(this);

  @override
  bool isCodeMotionInvariant() => true;

  @override
  String toString() => 'this';
}

class HPhi extends HInstruction {
  HPhi? get previousPhi => previous as HPhi?;
  HPhi? get nextPhi => next as HPhi?;

  // The order of the [inputs] must correspond to the order of the
  // predecessor-edges. That is if an input comes from the first predecessor
  // of the surrounding block, then the input must be the first in the [HPhi].
  HPhi(Local? variable, List<HInstruction> inputs, AbstractValue type)
    : super(inputs, type) {
    sourceElement = variable;
  }
  HPhi.noInputs(Local? variable, AbstractValue type) : this(variable, [], type);
  HPhi.singleInput(Local variable, HInstruction input, AbstractValue type)
    : this(variable, [input], type);
  HPhi.manyInputs(
    Local? variable,
    List<HInstruction> inputs,
    AbstractValue type,
  ) : this(variable, inputs, type);

  void addInput(HInstruction input) {
    assert(isInBasicBlock());
    inputs.add(input);
    assert(inputs.length <= block!.predecessors.length);
    input.usedBy.add(this);
  }

  @override
  String toString() => 'phi $id';
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitPhi(this);
}

abstract class HRelational extends HInvokeBinary {
  bool usesBoolifiedInterceptor = false;
  HRelational(HInstruction left, HInstruction right, AbstractValue type)
    : super(left, right, type);
}

class HIdentity extends HRelational {
  // Cached codegen decision.
  String? singleComparisonOp; // null, '===', '=='

  HIdentity(HInstruction left, HInstruction right, AbstractValue type)
    : super(left, right, type);
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitIdentity(this);

  @override
  constant_system.BinaryOperation operation() => constant_system.identity;
  @override
  _GvnType get _gvnType => _GvnType.identity;
  @override
  bool typeEquals(other) => other is HIdentity;
  @override
  bool dataEquals(HInstruction other) => true;
}

class HGreater extends HRelational {
  HGreater(HInstruction left, HInstruction right, AbstractValue type)
    : super(left, right, type);
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitGreater(this);

  @override
  constant_system.BinaryOperation operation() => constant_system.greater;
  @override
  _GvnType get _gvnType => _GvnType.greater;
  @override
  bool typeEquals(other) => other is HGreater;
  @override
  bool dataEquals(HInstruction other) => true;
}

class HGreaterEqual extends HRelational {
  HGreaterEqual(HInstruction left, HInstruction right, AbstractValue type)
    : super(left, right, type);
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitGreaterEqual(this);

  @override
  constant_system.BinaryOperation operation() => constant_system.greaterEqual;
  @override
  _GvnType get _gvnType => _GvnType.greaterEqual;
  @override
  bool typeEquals(other) => other is HGreaterEqual;
  @override
  bool dataEquals(HInstruction other) => true;
}

class HLess extends HRelational {
  HLess(HInstruction left, HInstruction right, AbstractValue type)
    : super(left, right, type);
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitLess(this);

  @override
  constant_system.BinaryOperation operation() => constant_system.less;
  @override
  _GvnType get _gvnType => _GvnType.less;
  @override
  bool typeEquals(other) => other is HLess;
  @override
  bool dataEquals(HInstruction other) => true;
}

class HLessEqual extends HRelational {
  HLessEqual(HInstruction left, HInstruction right, AbstractValue type)
    : super(left, right, type);
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitLessEqual(this);

  @override
  constant_system.BinaryOperation operation() => constant_system.lessEqual;
  @override
  _GvnType get _gvnType => _GvnType.lessEqual;
  @override
  bool typeEquals(other) => other is HLessEqual;
  @override
  bool dataEquals(HInstruction other) => true;
}

/// Return statement, either with or without a value.
class HReturn extends HControlFlow {
  HReturn(HInstruction? value, SourceInformation? sourceInformation) {
    if (value != null) inputs.add(value);
    this.sourceInformation = sourceInformation;
  }
  @override
  String toString() => 'return';
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitReturn(this);
}

class HThrowExpression extends HInstruction {
  final bool withoutHelperFrame;
  HThrowExpression(
    super.value,
    super.type,
    SourceInformation? sourceInformation, {
    this.withoutHelperFrame = false,
  }) : super._oneInput() {
    this.sourceInformation = sourceInformation;
  }
  @override
  String toString() => 'throw expression';
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitThrowExpression(this);
  @override
  bool canThrow(AbstractValueDomain domain) => true;
}

class HAwait extends HInstruction {
  HAwait(super.value, super.type) : super._oneInput() {
    sideEffects.setAllSideEffects();
    sideEffects.setDependsOnSomething();
  }
  @override
  String toString() => 'await';
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitAwait(this);
  // An await will throw if its argument is not a real future.
  @override
  bool canThrow(AbstractValueDomain domain) => true;
}

class HYield extends HInstruction {
  HYield(
    super.value,
    this.hasStar,
    super.type,
    SourceInformation? sourceInformation,
  ) : super._oneInput() {
    this.sourceInformation = sourceInformation;
    sideEffects.setAllSideEffects();
    sideEffects.setDependsOnSomething();
  }
  bool hasStar;
  @override
  String toString() => 'yield';
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitYield(this);
  @override
  bool canThrow(AbstractValueDomain domain) => false;
}

class HThrow extends HControlFlow {
  final bool isRethrow;
  final bool withoutHelperFrame;
  HThrow(
    HInstruction value,
    SourceInformation? sourceInformation, {
    this.isRethrow = false,
    this.withoutHelperFrame = false,
  }) {
    inputs.add(value);
    this.sourceInformation = sourceInformation;
  }
  @override
  String toString() => 'throw';
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitThrow(this);
}

// TODO(johnniwinther): Change this to a "HStaticLoad" of a field when we use
// CFE constants. It has been used for static tear-offs even though these should
// have been constants.
class HStatic extends HInstruction {
  final MemberEntity element;

  HStatic(this.element, super.type, SourceInformation? sourceInformation)
    : super._noInput() {
    sideEffects.clearAllSideEffects();
    sideEffects.clearAllDependencies();
    if (element.isAssignable) {
      sideEffects.setDependsOnStaticPropertyStore();
    }
    setUseGvn();
    this.sourceInformation = sourceInformation;
  }
  @override
  String toString() => 'static ${element.name}';
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitStatic(this);

  @override
  int gvnHashCode() => super.gvnHashCode() ^ element.hashCode;
  @override
  _GvnType get _gvnType => _GvnType.static;
  @override
  bool typeEquals(other) => other is HStatic;
  @override
  bool dataEquals(HStatic other) => element == other.element;
  @override
  bool isCodeMotionInvariant() => !element.isAssignable;
}

class HInterceptor extends HInstruction {
  // This field should originally be null to allow GVN'ing all
  // [HInterceptor] on the same input.
  Set<ClassEntity>? interceptedClasses;

  // inputs[0] is initially the only input, the receiver.

  // inputs[1] is a constant interceptor when the interceptor is a constant
  // except for a `null` receiver.  This is used when the receiver can't be
  // falsy, except for `null`, allowing the generation of code like
  //
  //     (a && C.JSArray_methods).get$first(a)
  //

  HInterceptor(super.receiver, super.type) : super._oneInput() {
    sourceInformation = receiver.sourceInformation;
    sideEffects.clearAllSideEffects();
    sideEffects.clearAllDependencies();
    setUseGvn();
  }

  @override
  String toString() => 'interceptor on $interceptedClasses';
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitInterceptor(this);
  HInstruction get receiver => inputs[0];

  bool get isConditionalConstantInterceptor => inputs.length == 2;
  HConstant get conditionalConstantInterceptor => inputs[1] as HConstant;
  set conditionalConstantInterceptor(HConstant constant) {
    assert(!isConditionalConstantInterceptor);
    inputs.add(constant);
  }

  @override
  _GvnType get _gvnType => _GvnType.interceptor;
  @override
  bool typeEquals(other) => other is HInterceptor;
  @override
  bool dataEquals(HInterceptor other) {
    return interceptedClasses == other.interceptedClasses ||
        (interceptedClasses!.length == other.interceptedClasses!.length &&
            interceptedClasses!.containsAll(other.interceptedClasses!));
  }
}

/// A "one-shot" interceptor is a call to a synthesized method that will fetch
/// the interceptor of its first parameter, and make a call on a given selector
/// with the remaining parameters.
///
/// In order to share the same optimizations with regular interceptor calls,
/// this class extends [HInvokeDynamic] and also has the null constant as the
/// first input.
class HOneShotInterceptor extends HInvokeDynamic {
  @override
  List<DartType> typeArguments;
  Set<ClassEntity>? interceptedClasses;

  HOneShotInterceptor(
    Selector selector,
    AbstractValue receiverType,
    List<HInstruction> inputs,
    AbstractValue resultType,
    this.typeArguments,
    this.interceptedClasses,
  ) : super(selector, receiverType, null, inputs, true, resultType) {
    assert(inputs[0].isConstantNull());
    assert(selector.callStructure.typeArgumentCount == typeArguments.length);
    _isCallOnInterceptor = true;
  }

  @override
  String toString() =>
      'one shot interceptor: selector=$selector, mask=$receiverType';
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitOneShotInterceptor(this);
}

/// An [HLazyStatic] is a static that is initialized lazily at first read.
class HLazyStatic extends HInstruction {
  final FieldEntity element;

  HLazyStatic(this.element, super.type, SourceInformation? sourceInformation)
    : super._noInput() {
    // TODO(4931): The first access has side-effects, but we afterwards we
    // should be able to GVN.
    sideEffects.setAllSideEffects();
    sideEffects.setDependsOnSomething();
    this.sourceInformation = sourceInformation;
  }

  @override
  String toString() => 'lazy static ${element.name}';
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitLazyStatic(this);

  // TODO(4931): We should be able to GVN some lazy static loads.

  @override
  bool isCodeMotionInvariant() => false;
  @override
  bool canThrow(AbstractValueDomain domain) => true;
}

class HStaticStore extends HInstruction {
  FieldEntity element;
  HStaticStore(this.element, HInstruction value)
    : super._oneInput(value, value.instructionType) {
    sideEffects.clearAllSideEffects();
    sideEffects.clearAllDependencies();
    sideEffects.setChangesStaticProperty();
  }
  @override
  String toString() => 'static store ${element.name}';
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitStaticStore(this);

  HInstruction get value => inputs.single;

  @override
  _GvnType get _gvnType => _GvnType.staticStore;
  @override
  bool typeEquals(other) => other is HStaticStore;
  @override
  bool dataEquals(HStaticStore other) => element == other.element;
}

class HLiteralList extends HInstruction {
  HLiteralList(List<HInstruction> inputs, AbstractValue type)
    : super(inputs, type);
  @override
  String toString() => 'literal list';
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitLiteralList(this);

  @override
  bool isAllocation(AbstractValueDomain domain) => true;
}

/// The primitive array indexing operation. Note that this instruction
/// does not throw because we generate the checks explicitly.
class HIndex extends HInstruction {
  HIndex(super.receiver, super.index, super.type) : super._twoInputs() {
    sideEffects.clearAllSideEffects();
    sideEffects.clearAllDependencies();
    sideEffects.setDependsOnIndexStore();
    setUseGvn();
  }

  @override
  String toString() => 'index operator';
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitIndex(this);

  HInstruction get receiver => inputs[0];
  HInstruction get index => inputs[1];

  // Implicit dependency on HBoundsCheck or constraints on index.
  // TODO(27272): Make HIndex dependent on positions of eliminated bounds
  // checks.
  @override
  bool get isMovable => false;

  @override
  HInstruction getDartReceiver() => receiver;
  @override
  bool onlyThrowsNSM() => true;
  @override
  bool canThrow(AbstractValueDomain domain) =>
      receiver.isNull(domain).isPotentiallyTrue;

  @override
  _GvnType get _gvnType => _GvnType.index_;
  @override
  bool typeEquals(HInstruction other) => other is HIndex;
  @override
  bool dataEquals(HIndex other) => true;
}

/// The primitive array assignment operation. Note that this instruction
/// does not throw because we generate the checks explicitly.
class HIndexAssign extends HInstruction {
  HIndexAssign(HInstruction receiver, HInstruction index, HInstruction value)
    : super([receiver, index, value], value.instructionType) {
    sideEffects.clearAllSideEffects();
    sideEffects.clearAllDependencies();
    sideEffects.setChangesIndex();
  }
  @override
  String toString() => 'index assign operator';
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitIndexAssign(this);

  HInstruction get receiver => inputs[0];
  HInstruction get index => inputs[1];
  HInstruction get value => inputs[2];

  // Implicit dependency on HBoundsCheck or constraints on index.
  // TODO(27272): Make HIndex dependent on eliminated bounds checks.
  @override
  bool get isMovable => false;

  @override
  HInstruction getDartReceiver() => receiver;
  @override
  bool onlyThrowsNSM() => true;
  @override
  bool canThrow(AbstractValueDomain domain) =>
      receiver.isNull(domain).isPotentiallyTrue;
}

class HCharCodeAt extends HInstruction {
  HCharCodeAt(super.receiver, super.index, super.type) : super._twoInputs();

  @override
  String toString() => 'HCharCodeAt';
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitCharCodeAt(this);

  HInstruction get receiver => inputs[0];
  HInstruction get index => inputs[1];

  // Implicit dependency on HBoundsCheck or constraints on index.
  // TODO(27272): Make HCharCodeAt dependent on positions of eliminated bounds
  // checks.
  @override
  bool get isMovable => false;

  @override
  HInstruction getDartReceiver() => receiver;
  @override
  bool onlyThrowsNSM() => true;
  @override
  bool canThrow(AbstractValueDomain domain) =>
      receiver.isNull(domain).isPotentiallyTrue;

  @override
  _GvnType get _gvnType => _GvnType.charCodeAt;
  @override
  bool typeEquals(other) => other is HCharCodeAt;
  @override
  bool dataEquals(HCharCodeAt other) => true;
}

/// HLateValue is a late-stage instruction that can be used to force a value
/// into a temporary.
///
/// HLateValue is useful for naming values that would otherwise be generated at
/// use site, for example, if 'this' is used many times, replacing uses of
/// 'this' with HLateValue(HThis) will have the effect of copying 'this' to a
/// temporary which will reduce the size of minified code.
class HLateValue extends HInstruction implements HLateInstruction {
  HLateValue(HInstruction target)
    : super._oneInput(target, target.instructionType);

  HInstruction get target => inputs.single;

  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitLateValue(this);
  @override
  String toString() => 'HLateValue($target)';
}

enum PrimitiveCheckKind { argumentType, receiverType }

/// Check for receiver or argument type when lowering operation to a primitive,
/// e.g. lowering `+` to [HAdd].
///
/// With sound null safety, `a + b` will require `a` and `b` to be non-nullable
/// and these checks will become explicit in the source (e.g. `a! + b!`). At
/// that time, this check should be removed. If needed, the `!` check can be
/// optimized to give the same signals to the JavaScript VM.
class HPrimitiveCheck extends HCheck {
  final DartType typeExpression;
  final PrimitiveCheckKind kind;

  // [receiverTypeCheckSelector] is the selector used for a receiver type check
  // on open-coded operators, e.g. the not-null check on `x` in `x + 1` would be
  // compiled to the following, for which we need the selector `$add`.
  //
  //     if (typeof x != "number") x.$add();
  //
  final Selector? receiverTypeCheckSelector;

  final AbstractValue checkedType;

  HPrimitiveCheck(
    this.typeExpression,
    this.kind,
    AbstractValue type,
    HInstruction input,
    SourceInformation? sourceInformation, {
    this.receiverTypeCheckSelector,
  }) : checkedType = type,
       super._oneInput(input, type) {
    assert(isReceiverTypeCheck == (receiverTypeCheckSelector != null));
    sourceElement = input.sourceElement;
    this.sourceInformation = sourceInformation;
  }

  bool get isArgumentTypeCheck => kind == PrimitiveCheckKind.argumentType;
  bool get isReceiverTypeCheck => kind == PrimitiveCheckKind.receiverType;

  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitPrimitiveCheck(this);

  @override
  bool isJsStatement() => true;

  @override
  _GvnType get _gvnType => _GvnType.primitiveCheck;
  @override
  bool typeEquals(HInstruction other) => other is HPrimitiveCheck;
  @override
  bool isCodeMotionInvariant() => false;

  @override
  bool dataEquals(HPrimitiveCheck other) {
    return kind == other.kind &&
        checkedType == other.checkedType &&
        receiverTypeCheckSelector == other.receiverTypeCheckSelector;
  }

  bool isRedundant(JClosedWorld closedWorld) {
    AbstractValueDomain abstractValueDomain = closedWorld.abstractValueDomain;
    // Type is refined from `dynamic`, so it might become non-redundant.
    if (abstractValueDomain.containsAll(checkedType).isPotentiallyTrue) {
      return false;
    }
    AbstractValue inputType = checkedInput.instructionType;
    return abstractValueDomain.isIn(inputType, checkedType).isDefinitelyTrue;
  }

  @override
  String toString() =>
      'HPrimitiveCheck(checkedType=$checkedType, kind=$kind, '
      'checkedInput=$checkedInput)';
}

/// A check that the input is not null. This corresponds to the postfix
/// null-check operator '!'.
///
/// A null check is inserted on the receiver when inlining an instance method or
/// field getter or setter when the receiver might be null. In these cases, the
/// [selector] and [field] members are assigned.
class HNullCheck extends HCheck {
  // A sticky check is not optimized away on the basis of the input type.
  final bool sticky;
  Selector? selector;
  FieldEntity? field;

  HNullCheck(super.input, super.type, {this.sticky = false})
    : super._oneInput();

  @override
  bool isJsStatement() => true;

  @override
  bool isCodeMotionInvariant() => false;

  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitNullCheck(this);

  @override
  _GvnType get _gvnType => _GvnType.nullCheck;
  @override
  bool typeEquals(HInstruction other) => other is HNullCheck;
  @override
  bool dataEquals(HNullCheck other) => true;

  bool isRedundant(JClosedWorld closedWorld) {
    if (sticky) return false;
    AbstractValueDomain abstractValueDomain = closedWorld.abstractValueDomain;
    AbstractValue inputType = checkedInput.instructionType;
    return abstractValueDomain.isNull(inputType).isDefinitelyFalse;
  }

  @override
  String toString() {
    String stickyString = sticky ? 'sticky, ' : '';
    String fieldString = field == null ? '' : ', $field';
    String selectorString = selector == null ? '' : ', $selector';
    return 'HNullCheck($stickyString$checkedInput$fieldString$selectorString)';
  }
}

/// A check for a late sentinel to determine if a late field may be read from or
/// written to.
abstract class HLateCheck extends HCheck {
  // Checks may be 'trusted' and result in no runtime check. This is done by
  // compiling with the checks in place and removing them after optimizations.
  final bool isTrusted;

  HLateCheck(
    HInstruction input,
    HInstruction? name,
    this.isTrusted,
    AbstractValue type,
  ) : super([input, if (name != null) name], type);

  bool get hasName => inputs.length > 1;

  HInstruction get name {
    if (hasName) return inputs[1];
    throw StateError('HLateCheck.name: no name');
  }

  @override
  bool isCodeMotionInvariant() => false;
}

/// A check that a late field has been initialized and can therefore be read.
class HLateReadCheck extends HLateCheck {
  HLateReadCheck(
    HInstruction input,
    HInstruction? name,
    bool isTrusted,
    AbstractValue type,
  ) : super(input, name, isTrusted, type);

  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitLateReadCheck(this);

  @override
  _GvnType get _gvnType => _GvnType.lateReadCheck;

  @override
  bool typeEquals(HInstruction other) => other is HLateReadCheck;

  @override
  bool dataEquals(HLateReadCheck other) => isTrusted == other.isTrusted;

  bool isRedundant(JClosedWorld closedWorld) {
    AbstractValueDomain abstractValueDomain = closedWorld.abstractValueDomain;
    AbstractValue inputType = checkedInput.instructionType;
    return abstractValueDomain.isLateSentinel(inputType).isDefinitelyFalse;
  }

  @override
  String toString() {
    return 'HLateReadCheck($checkedInput)';
  }
}

/// A check that a late final field has not been initialized yet and can
/// therefore be written to.
///
/// The difference between [HLateWriteOnceCheck] and [HLateInitializeOnceCheck]
/// is that the latter occurs on writes performed as part of the initializer
/// expression.
class HLateWriteOnceCheck extends HLateCheck {
  HLateWriteOnceCheck(
    HInstruction input,
    HInstruction? name,
    bool isTrusted,
    AbstractValue type,
  ) : super(input, name, isTrusted, type);

  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitLateWriteOnceCheck(this);

  @override
  _GvnType get _gvnType => _GvnType.lateWriteOnceCheck;

  @override
  bool typeEquals(HInstruction other) => other is HLateWriteOnceCheck;

  @override
  bool dataEquals(HLateWriteOnceCheck other) => isTrusted == other.isTrusted;

  bool isRedundant(JClosedWorld closedWorld) {
    AbstractValueDomain abstractValueDomain = closedWorld.abstractValueDomain;
    AbstractValue inputType = checkedInput.instructionType;
    return abstractValueDomain.isLateSentinel(inputType).isDefinitelyTrue;
  }

  @override
  String toString() {
    return 'HLateWriteOnceCheck($checkedInput)';
  }
}

/// A check that a late final field has not been initialized yet and can
/// therefore be initialized.
///
/// The difference between [HLateWriteOnceCheck] and [HLateInitializeOnceCheck]
/// is that the latter occurs on writes performed as part of the initializer
/// expression.
class HLateInitializeOnceCheck extends HLateCheck {
  HLateInitializeOnceCheck(
    HInstruction input,
    HInstruction? name,
    bool isTrusted,
    AbstractValue type,
  ) : super(input, name, isTrusted, type);

  @override
  R accept<R>(HVisitor<R> visitor) =>
      visitor.visitLateInitializeOnceCheck(this);

  @override
  _GvnType get _gvnType => _GvnType.lateInitializeOnceCheck;

  @override
  bool typeEquals(HInstruction other) => other is HLateInitializeOnceCheck;

  @override
  bool dataEquals(HLateInitializeOnceCheck other) =>
      isTrusted == other.isTrusted;

  bool isRedundant(JClosedWorld closedWorld) {
    AbstractValueDomain abstractValueDomain = closedWorld.abstractValueDomain;
    AbstractValue inputType = checkedInput.instructionType;
    return abstractValueDomain.isLateSentinel(inputType).isDefinitelyTrue;
  }

  @override
  String toString() {
    return 'HLateInitializeOnceCheck($checkedInput)';
  }
}

/// The [HTypeKnown] instruction marks a value with a refined type.
class HTypeKnown extends HCheck {
  final AbstractValue knownType;
  final bool _isMovable;

  HTypeKnown.pinned(this.knownType, HInstruction input)
    : _isMovable = false,
      super._oneInput(input, knownType);

  HTypeKnown.witnessed(this.knownType, HInstruction input, HInstruction witness)
    : _isMovable = true,
      super._twoInputs(input, witness, knownType);

  @override
  String toString() => 'TypeKnown $knownType';
  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitTypeKnown(this);

  @override
  bool isJsStatement() => false;

  @override
  bool canThrow(AbstractValueDomain domain) => false;

  bool get isPinned => inputs.length == 1;

  HInstruction? get witness => inputs.length == 2 ? inputs[1] : null;

  @override
  _GvnType get _gvnType => _GvnType.typeKnown;
  @override
  bool typeEquals(HInstruction other) => other is HTypeKnown;
  @override
  bool isCodeMotionInvariant() => true;
  @override
  bool get isMovable => _isMovable && useGvn();

  @override
  bool dataEquals(HTypeKnown other) {
    return knownType == other.knownType &&
        instructionType == other.instructionType;
  }

  bool isRedundant(JClosedWorld closedWorld) {
    AbstractValueDomain abstractValueDomain = closedWorld.abstractValueDomain;
    AbstractValue inputType = checkedInput.instructionType;
    return abstractValueDomain.isIn(inputType, knownType).isDefinitelyTrue;
  }
}

class HRangeConversion extends HCheck {
  HRangeConversion(super.input, super.type) : super._oneInput() {
    sourceElement = checkedInput.sourceElement;
  }

  @override
  bool get isMovable => false;

  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitRangeConversion(this);
}

class HStringConcat extends HInstruction {
  HStringConcat(super.left, super.right, super.type) : super._twoInputs() {
    setUseGvn();
  }

  HInstruction get left => inputs[0];
  HInstruction get right => inputs[1];

  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitStringConcat(this);
  @override
  String toString() => "string concat";

  @override
  _GvnType get _gvnType => _GvnType.stringConcat;
  @override
  bool typeEquals(HInstruction other) => other is HStringConcat;
  @override
  bool dataEquals(HStringConcat other) => true;
}

/// The part of string interpolation which converts and interpolated expression
/// into a String value.
class HStringify extends HInstruction {
  bool _isPure = false; // Some special cases are pure, e.g. int argument.
  HStringify(super.input, super.resultType) : super._oneInput() {
    sideEffects.setAllSideEffects();
    sideEffects.setDependsOnSomething();
  }

  void setPure() {
    sideEffects.clearAllDependencies();
    sideEffects.clearAllSideEffects();
    _isPure = true;
    setUseGvn();
  }

  @override
  bool canThrow(AbstractValueDomain domain) => !_isPure;

  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitStringify(this);
  @override
  String toString() => "stringify";

  @override
  _GvnType get _gvnType => _GvnType.stringify;
  @override
  bool typeEquals(HInstruction other) => other is HStringify;
  @override
  bool dataEquals(HStringify other) => _isPure == other._isPure;
}

/// Non-block-based (aka. traditional) loop information.
class HLoopInformation {
  final HBasicBlock header;
  final List<HBasicBlock> blocks = [];
  final List<HBasicBlock> backEdges = [];
  final List<LabelDefinition> labels;
  final JumpTarget? target;

  /// Corresponding block information for the loop.
  HLoopBlockInformation? loopBlockInformation;

  HLoopInformation(this.header, this.target, this.labels);

  void addBackEdge(HBasicBlock predecessor) {
    backEdges.add(predecessor);
    List<HBasicBlock> workQueue = [predecessor];
    do {
      HBasicBlock current = workQueue.removeLast();
      addBlock(current, workQueue);
    } while (workQueue.isNotEmpty);
  }

  // Adds a block and transitively all its predecessors in the loop as
  // loop blocks.
  void addBlock(HBasicBlock block, List<HBasicBlock> workQueue) {
    if (identical(block, header)) return;
    HBasicBlock? parentHeader = block.parentLoopHeader;
    if (identical(parentHeader, header)) {
      // Nothing to do in this case.
    } else if (parentHeader != null) {
      workQueue.add(parentHeader);
    } else {
      block.parentLoopHeader = header;
      blocks.add(block);
      workQueue.addAll(block.predecessors);
    }
  }
}

/// Embedding of a [HBlockInformation] for block-structure based traversal
/// in a dominator based flow traversal by attaching it to a basic block.
/// To go back to dominator-based traversal, a [HSubGraphBlockInformation]
/// structure can be added in the block structure.
class HBlockFlow {
  final HBlockInformation body;
  final HBasicBlock? continuation; // `null` if all paths throw.
  HBlockFlow(this.body, this.continuation);
}

/// Information about a syntactic-like structure.
abstract class HBlockInformation {
  HBasicBlock get start;
  HBasicBlock get end;
  bool accept(HBlockInformationVisitor visitor);
}

/// Information about a statement-like structure.
abstract class HStatementInformation extends HBlockInformation {
  @override
  bool accept(HStatementInformationVisitor visitor);
}

/// Information about an expression-like structure.
abstract class HExpressionInformation extends HBlockInformation {
  @override
  bool accept(HExpressionInformationVisitor visitor);
  HInstruction? get conditionExpression;
}

abstract class HStatementInformationVisitor {
  bool visitLabeledBlockInfo(HLabeledBlockInformation info);
  bool visitLoopInfo(HLoopBlockInformation info);
  bool visitIfInfo(HIfBlockInformation info);
  bool visitTryInfo(HTryBlockInformation info);
  bool visitSwitchInfo(HSwitchBlockInformation info);
  bool visitSequenceInfo(HStatementSequenceInformation info);
  // Pseudo-structure embedding a dominator-based traversal into
  // the block-structure traversal. This will eventually go away.
  bool visitSubGraphInfo(HSubGraphBlockInformation info);
}

abstract class HExpressionInformationVisitor {
  bool visitSubExpressionInfo(HSubExpressionBlockInformation info);
}

abstract class HBlockInformationVisitor
    implements HStatementInformationVisitor, HExpressionInformationVisitor {}

/// Generic class wrapping a [SubGraph] as a block-information until
/// all structures are handled properly.
class HSubGraphBlockInformation implements HStatementInformation {
  final SubGraph? subGraph;
  HSubGraphBlockInformation(this.subGraph);

  @override
  HBasicBlock get start => subGraph!.start;
  @override
  HBasicBlock get end => subGraph!.end;

  @override
  bool accept(HStatementInformationVisitor visitor) =>
      visitor.visitSubGraphInfo(this);
}

/// Generic class wrapping a [SubExpression] as a block-information until
/// expressions structures are handled properly.
class HSubExpressionBlockInformation implements HExpressionInformation {
  final SubExpression? subExpression;
  HSubExpressionBlockInformation(this.subExpression);

  @override
  HBasicBlock get start => subExpression!.start;
  @override
  HBasicBlock get end => subExpression!.end;

  @override
  HInstruction? get conditionExpression => subExpression!.conditionExpression;

  @override
  bool accept(HExpressionInformationVisitor visitor) =>
      visitor.visitSubExpressionInfo(this);
}

/// A sequence of separate statements.
class HStatementSequenceInformation implements HStatementInformation {
  final List<HStatementInformation> statements;
  HStatementSequenceInformation(this.statements);

  @override
  HBasicBlock get start => statements[0].start;
  @override
  HBasicBlock get end => statements.last.end;

  @override
  bool accept(HStatementInformationVisitor visitor) =>
      visitor.visitSequenceInfo(this);
}

class HLabeledBlockInformation implements HStatementInformation {
  final HStatementInformation body;
  final List<LabelDefinition> labels;
  final JumpTarget? target;
  final bool isContinue;

  HLabeledBlockInformation(this.body, this.labels, {this.isContinue = false})
    : target = labels[0].target;

  HLabeledBlockInformation.implicit(
    this.body,
    this.target, {
    this.isContinue = false,
  }) : labels = const [];

  @override
  HBasicBlock get start => body.start;
  @override
  HBasicBlock get end => body.end;

  @override
  bool accept(HStatementInformationVisitor visitor) =>
      visitor.visitLabeledBlockInfo(this);
}

enum LoopBlockInformationKind {
  notALoop,
  whileLoop,
  forLoop,
  doWhileLoop,
  forInLoop,
  switchContinueLoop,
}

class HLoopBlockInformation implements HStatementInformation {
  final LoopBlockInformationKind kind;
  final HExpressionInformation? initializer;
  final HExpressionInformation? condition;
  final HStatementInformation? body;
  final HExpressionInformation? updates;
  final JumpTarget? target;
  final List<LabelDefinition> labels;
  final SourceInformation? sourceInformation;

  HLoopBlockInformation(
    this.kind,
    this.initializer,
    this.condition,
    this.body,
    this.updates,
    this.target,
    this.labels,
    this.sourceInformation,
  ) {
    assert(
      (kind == LoopBlockInformationKind.doWhileLoop
              ? body!.start
              : condition!.start)
          .isLoopHeader(),
    );
  }

  @override
  HBasicBlock get start {
    if (initializer != null) return initializer!.start;
    if (kind == LoopBlockInformationKind.doWhileLoop) {
      return body!.start;
    }
    return condition!.start;
  }

  HBasicBlock get loopHeader {
    return kind == LoopBlockInformationKind.doWhileLoop
        ? body!.start
        : condition!.start;
  }

  @override
  HBasicBlock get end {
    if (updates != null) return updates!.end;
    if (kind == LoopBlockInformationKind.doWhileLoop && condition != null) {
      return condition!.end;
    }
    return body!.end;
  }

  @override
  bool accept(HStatementInformationVisitor visitor) =>
      visitor.visitLoopInfo(this);
}

class HIfBlockInformation implements HStatementInformation {
  final HExpressionInformation? condition;
  final HStatementInformation? thenGraph;
  final HStatementInformation? elseGraph;
  HIfBlockInformation(this.condition, this.thenGraph, this.elseGraph);

  @override
  HBasicBlock get start => condition!.start;
  @override
  HBasicBlock get end => elseGraph == null ? thenGraph!.end : elseGraph!.end;

  @override
  bool accept(HStatementInformationVisitor visitor) =>
      visitor.visitIfInfo(this);
}

class HTryBlockInformation implements HStatementInformation {
  final HStatementInformation? body;
  final HLocalValue? catchVariable;
  final HStatementInformation? catchBlock;
  final HStatementInformation? finallyBlock;
  HTryBlockInformation(
    this.body,
    this.catchVariable,
    this.catchBlock,
    this.finallyBlock,
  );

  @override
  HBasicBlock get start => body!.start;
  @override
  HBasicBlock get end =>
      finallyBlock == null ? catchBlock!.end : finallyBlock!.end;

  @override
  bool accept(HStatementInformationVisitor visitor) =>
      visitor.visitTryInfo(this);
}

class HSwitchBlockInformation implements HStatementInformation {
  final HExpressionInformation expression;
  final List<HStatementInformation> statements;
  final JumpTarget? target;
  final List<LabelDefinition> labels;
  final SourceInformation? sourceInformation;

  HSwitchBlockInformation(
    this.expression,
    this.statements,
    this.target,
    this.labels,
    this.sourceInformation,
  );

  @override
  HBasicBlock get start => expression.start;
  @override
  HBasicBlock get end {
    // We don't create a switch block if there are no cases.
    assert(statements.isNotEmpty);
    return statements.last.end;
  }

  @override
  bool accept(HStatementInformationVisitor visitor) =>
      visitor.visitSwitchInfo(this);
}

// -----------------------------------------------------------------------------

/// Is-test using Rti form of type expression.
///
/// This instruction can be used for any type. Tests for simple types are
/// lowered to other instructions, so this instruction remains for types that
/// depend on type variables and complex types.
class HIsTest extends HInstruction {
  final AbstractValueWithPrecision checkedAbstractValue;
  DartType dartType;

  HIsTest(
    this.dartType,
    this.checkedAbstractValue,
    super.rti,
    super.checked,
    super.instructionType,
  ) : super._twoInputs() {
    setUseGvn();
  }

  // The type input is first to facilitate the `type.is(value)` codegen pattern.
  HInstruction get typeInput => inputs[0];
  HInstruction get checkedInput => inputs[1];

  AbstractBool evaluate(JClosedWorld closedWorld, CompilerOptions options) =>
      _typeTest(
        checkedInput,
        dartType,
        checkedAbstractValue,
        closedWorld,
        options,
        isCast: false,
      );

  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitIsTest(this);

  @override
  _GvnType get _gvnType => _GvnType.isTest;

  @override
  bool typeEquals(HInstruction other) => other is HIsTest;

  @override
  bool dataEquals(HIsTest other) => true;

  @override
  String toString() => 'HIsTest()';
}

/// Simple is-test for a known type that can be achieved without reference to an
/// Rti describing the type.
class HIsTestSimple extends HInstruction {
  final DartType dartType;
  final AbstractValueWithPrecision checkedAbstractValue;
  final IsTestSpecialization specialization;

  HIsTestSimple(
    this.dartType,
    this.checkedAbstractValue,
    this.specialization,
    super.checked,
    super.type,
  ) : super._oneInput() {
    setUseGvn();
  }

  HInstruction get checkedInput => inputs[0];

  AbstractBool evaluate(JClosedWorld closedWorld, CompilerOptions options) =>
      _typeTest(
        checkedInput,
        dartType,
        checkedAbstractValue,
        closedWorld,
        options,
        isCast: false,
      );

  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitIsTestSimple(this);

  @override
  _GvnType get _gvnType => _GvnType.isTestSimple;

  @override
  bool typeEquals(HInstruction other) => other is HIsTestSimple;

  @override
  bool dataEquals(HIsTestSimple other) => dartType == other.dartType;

  @override
  String toString() => 'HIsTestSimple()';
}

AbstractBool _typeTest(
  HInstruction expression,
  DartType dartType,
  AbstractValueWithPrecision checkedAbstractValue,
  JClosedWorld closedWorld,
  CompilerOptions options, {
  required bool isCast,
}) {
  JCommonElements commonElements = closedWorld.commonElements;
  DartTypes dartTypes = closedWorld.dartTypes;
  AbstractValueDomain abstractValueDomain = closedWorld.abstractValueDomain;
  AbstractValue subsetType = expression.instructionType;
  AbstractValue supersetType = checkedAbstractValue.abstractValue;
  AbstractBool expressionIsNull = expression.isNull(abstractValueDomain);

  bool nullIs(DartType type) =>
      dartTypes.isTopType(type) ||
      type is NullableType ||
      type is FutureOrType && nullIs(type.typeArgument) ||
      type.isNull;

  if (!isCast) {
    if (expressionIsNull.isDefinitelyTrue) {
      if (dartType.containsFreeTypeVariables) return AbstractBool.maybe;
      return AbstractBool.trueOrFalse(nullIs(dartType));
    }
    if (expressionIsNull.isPotentiallyTrue) {
      if (dartType.isObject) return AbstractBool.maybe;
    }
  } else if (expressionIsNull.isDefinitelyTrue && nullIs(dartType)) {
    return AbstractBool.true_;
  }

  if (checkedAbstractValue.isPrecise &&
      abstractValueDomain.isIn(subsetType, supersetType).isDefinitelyTrue) {
    return AbstractBool.true_;
  }

  if (abstractValueDomain
      .areDisjoint(subsetType, supersetType)
      .isDefinitelyTrue) {
    return AbstractBool.false_;
  }

  // TODO(39287): Let the abstract value domain fully handle this.
  // Currently, the abstract value domain cannot (soundly) state that an is-test
  // is definitely false, so we reuse some of the case-by-case logic from the
  // old [HIs] optimization.

  AbstractBool checkInterface(InterfaceType interface) {
    if (expression.isInteger(abstractValueDomain).isDefinitelyTrue) {
      if (dartTypes.isSubtype(commonElements.intType, interface)) {
        return AbstractBool.true_;
      }
      if (interface == commonElements.doubleType) {
        // We let the JS semantics decide for that check. Currently the code we
        // emit will always return true.
        return AbstractBool.maybe;
      }
      return AbstractBool.false_;
    }

    if (expression.isNumber(abstractValueDomain).isDefinitelyTrue) {
      if (dartTypes.isSubtype(commonElements.numType, interface)) {
        return AbstractBool.true_;
      }
      // We cannot just return false, because the expression may be of type int or
      // double.
      return AbstractBool.maybe;
    }

    // We need the raw check because we don't have the notion of generics in the
    // backend. For example, `this` in a class `A<T>` is currently always
    // considered to have the raw type.
    if (dartTypes.treatAsRawType(interface)) {
      return abstractValueDomain.isInstanceOf(subsetType, interface.element);
    }

    return AbstractBool.maybe;
  }

  AbstractBool isNullAsCheck = isCast ? expressionIsNull : AbstractBool.false_;
  AbstractBool isNullIsTest = !isCast ? expressionIsNull : AbstractBool.false_;

  AbstractBool unwrapAndCheck(DartType type) {
    if (dartTypes.isTopType(dartType)) return AbstractBool.true_;
    if (type is NeverType) return AbstractBool.false_;
    if (type is InterfaceType) {
      if (type.isNull) return expressionIsNull;
      return ~(isNullAsCheck | isNullIsTest) & checkInterface(type);
    }
    if (type is NullableType) {
      return unwrapAndCheck(type.baseType);
    }
    if (type is FutureOrType) {
      return unwrapAndCheck(type.typeArgument) | AbstractBool.maybe;
    }
    return AbstractBool.maybe;
  }

  return unwrapAndCheck(dartType);
}

/// Type cast or type check using Rti form of type expression.
class HAsCheck extends HCheck {
  final AbstractValueWithPrecision checkedType;
  DartType checkedTypeExpression;
  final bool isTypeError;

  HAsCheck(
    this.checkedType,
    this.checkedTypeExpression,
    this.isTypeError,
    super.rti,
    super.checked,
    super.instructionType,
  ) : super._twoInputs();

  // The type input is first to facilitate the `type.as(value)` codegen pattern.
  HInstruction get typeInput => inputs[0];
  @override
  HInstruction get checkedInput => inputs[1];

  @override
  bool isJsStatement() => false;

  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitAsCheck(this);

  @override
  _GvnType get _gvnType => _GvnType.asCheck;

  @override
  bool typeEquals(HInstruction other) => other is HAsCheck;

  @override
  bool dataEquals(HAsCheck other) {
    return isTypeError == other.isTypeError;
  }

  bool isRedundant(JClosedWorld closedWorld, CompilerOptions options) =>
      _typeTest(
        checkedInput,
        checkedTypeExpression,
        checkedType,
        closedWorld,
        options,
        isCast: true,
      ).isDefinitelyTrue;

  @override
  String toString() {
    String error = isTypeError ? 'TypeError' : 'CastError';
    return 'HAsCheck($error)';
  }
}

/// Type cast or type check for simple known types that are achieved via a
/// simple static call.
class HAsCheckSimple extends HCheck {
  final DartType dartType;
  final AbstractValueWithPrecision checkedType;
  final bool isTypeError;
  final FunctionEntity method;

  HAsCheckSimple(
    super.checked,
    this.dartType,
    this.checkedType,
    this.isTypeError,
    this.method,
    super.type,
  ) : super._oneInput();

  @override
  HInstruction get checkedInput => inputs[0];

  @override
  bool isJsStatement() => false;

  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitAsCheckSimple(this);

  bool isRedundant(JClosedWorld closedWorld, CompilerOptions options) =>
      _typeTest(
        checkedInput,
        dartType,
        checkedType,
        closedWorld,
        options,
        isCast: true,
      ).isDefinitelyTrue;

  @override
  _GvnType get _gvnType => _GvnType.asCheckSimple;

  @override
  bool typeEquals(HInstruction other) => other is HAsCheckSimple;

  @override
  bool dataEquals(HAsCheckSimple other) {
    return isTypeError == other.isTypeError && dartType == other.dartType;
  }

  @override
  String toString() {
    String error = isTypeError ? 'TypeError' : 'CastError';
    return 'HAsCheckSimple($error)';
  }
}

/// Subtype check comparing two Rti types.
class HSubtypeCheck extends HCheck {
  HSubtypeCheck(super.subtype, super.supertype, super.type)
    : super._twoInputs() {
    setUseGvn();
  }

  HInstruction get typeInput => inputs[1];

  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitSubtypeCheck(this);

  @override
  _GvnType get _gvnType => _GvnType.subtypeCheck;

  @override
  bool typeEquals(HInstruction other) => other is HSubtypeCheck;

  @override
  bool dataEquals(HSubtypeCheck other) => true;

  @override
  String toString() => 'HSubtypeCheck()';
}

/// Common supertype for instructions that generate Rti values.
abstract interface class HRtiInstruction {}

/// Evaluates an Rti type recipe in the global environment.
class HLoadType extends HInstruction implements HRtiInstruction {
  TypeRecipe typeExpression;

  HLoadType(this.typeExpression, super.instructionType) : super._noInput() {
    setUseGvn();
  }

  HLoadType.type(DartType dartType, AbstractValue instructionType)
    : this(TypeExpressionRecipe(dartType), instructionType);

  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitLoadType(this);

  @override
  _GvnType get _gvnType => _GvnType.loadType;

  @override
  bool typeEquals(HInstruction other) => other is HLoadType;

  @override
  bool dataEquals(HLoadType other) {
    return typeExpression == other.typeExpression;
  }

  @override
  String toString() => 'HLoadType($typeExpression)';
}

/// The reified Rti environment stored on a class instance.
///
/// Classes with reified type arguments have the type environment stored on the
/// instance. The reified environment is typically stored as the instance type,
/// e.g. `UnmodifiableListView<int>`.
class HInstanceEnvironment extends HInstruction implements HRtiInstruction {
  late AbstractValue codegenInputType; // Assigned in SsaTypeKnownRemover

  HInstanceEnvironment(super.instance, super.type) : super._oneInput() {
    setUseGvn();
  }

  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitInstanceEnvironment(this);

  @override
  _GvnType get _gvnType => _GvnType.instanceEnvironment;

  @override
  bool typeEquals(HInstruction other) => other is HInstanceEnvironment;

  @override
  bool dataEquals(HInstanceEnvironment other) => true;

  @override
  String toString() => 'HInstanceEnvironment()';
}

/// Evaluates an Rti type recipe in an Rti environment.
class HTypeEval extends HInstruction implements HRtiInstruction {
  TypeEnvironmentStructure envStructure;
  TypeRecipe typeExpression;

  HTypeEval(
    super.environment,
    this.envStructure,
    this.typeExpression,
    super.type,
  ) : super._oneInput() {
    setUseGvn();
  }

  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitTypeEval(this);

  @override
  _GvnType get _gvnType => _GvnType.typeEval;

  @override
  bool typeEquals(HInstruction other) => other is HTypeEval;

  @override
  bool dataEquals(HTypeEval other) {
    return TypeRecipe.yieldsSameType(
      typeExpression,
      envStructure,
      other.typeExpression,
      other.envStructure,
    );
  }

  @override
  String toString() => 'HTypeEval($typeExpression)';
}

/// Extends an Rti type environment with generic function types.
class HTypeBind extends HInstruction implements HRtiInstruction {
  HTypeBind(super.environment, super.typeArguments, super.type)
    : super._twoInputs() {
    setUseGvn();
  }

  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitTypeBind(this);

  @override
  _GvnType get _gvnType => _GvnType.typeBind;

  @override
  bool typeEquals(HInstruction other) => other is HTypeBind;

  @override
  bool dataEquals(HTypeBind other) => true;

  @override
  String toString() => 'HTypeBind()';
}

/// Check Array or TypedData for permission to modify or grow.
///
/// Typical use to check modifiability for `a[i] = 0`. The array flags are
/// checked to see if there is a bit that prohibits modification.
///
///     a = ...
///     f = HArrayFlagsGet(a);
///     a2 = HArrayFlagsCheck(a, f, ArrayFlags.unmodifiableCheck, "[]=", "modify")
///     a2[i] = 0
///
/// HArrayFlagsGet is a separate instruction so that 'loading' the flags from
/// the Array can by hoisted.
class HArrayFlagsCheck extends HCheck {
  HArrayFlagsCheck(
    HInstruction array,
    HInstruction arrayFlags,
    HInstruction checkFlags,
    HInstruction? operation,
    HInstruction? verb,
    AbstractValue type,
  ) : super([
        array,
        arrayFlags,
        checkFlags,
        if (operation != null) operation,
        if (verb != null) verb,
      ], type);

  HInstruction get array => inputs[0];
  HInstruction get arrayFlags => inputs[1];
  HInstruction get checkFlags => inputs[2];

  bool get hasOperation => inputs.length > 3;
  HInstruction get operation => inputs[3];

  bool get hasVerb => inputs.length > 4;
  HInstruction get verb => inputs[4];

  // The checked type is the input type, refined to match the flags.
  AbstractValue computeInstructionType(
    AbstractValue inputType,
    AbstractValueDomain domain,
  ) {
    // TODO(sra): Depending on the checked flags, the output is fixed-length or
    // unmodifiable. Refine the type to the degree an AbstractValue can express
    // that.
    return inputType;
  }

  bool alwaysThrows() {
    if ((arrayFlags, checkFlags) case (
      HConstant(constant: IntConstantValue(intValue: final arrayBits)),
      HConstant(constant: IntConstantValue(intValue: final checkBits)),
    ) when arrayBits & checkBits != BigInt.zero) {
      return true;
    }
    return false;
  }

  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitArrayFlagsCheck(this);

  @override
  bool isJsStatement() => true;

  @override
  _GvnType get _gvnType => _GvnType.arrayFlagsCheck;

  @override
  bool typeEquals(HInstruction other) => other is HArrayFlagsCheck;

  @override
  bool dataEquals(HArrayFlagsCheck other) => true;
}

class HArrayFlagsGet extends HInstruction {
  HArrayFlagsGet(HInstruction array, AbstractValue type)
    : super([array], type) {
    sideEffects.clearAllSideEffects();
    sideEffects.clearAllDependencies();
    // Dependency on HArrayFlagsSet.
    sideEffects.setDependsOnInstancePropertyStore();
    setUseGvn();
  }

  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitArrayFlagsGet(this);

  @override
  _GvnType get _gvnType => _GvnType.arrayFlagsGet;

  @override
  bool typeEquals(HInstruction other) => other is HArrayFlagsGet;

  @override
  bool dataEquals(HArrayFlagsGet other) => true;
}

/// Tag an Array or TypedData object to mark it as unmodifiable or fixed-length.
///
/// The HArrayFlagsSet instruction represents the tagged Array or TypedData
/// object. The instruction type can be different to the `array` input.
/// HArrayFlagsSet is used in a 'linear' style - there are no accesses to the
/// input after this operation.
///
/// To ensure that HArrayFlagsGet (possibly from inlined code) does not float
/// past HArrayFlagsSet, we use the 'instance property' effect.
class HArrayFlagsSet extends HInstruction
    implements HOutputConstrainedToAnInput {
  HArrayFlagsSet(HInstruction array, HInstruction flags, AbstractValue type)
    : super([array, flags], type) {
    // For correct ordering with respect to HArrayFlagsGet:
    sideEffects.setChangesInstanceProperty();
    // Be conservative and make HArrayFlagsSet be a memory fence:
    sideEffects.setAllSideEffects();
    sideEffects.setDependsOnSomething();
  }

  HInstruction get array => inputs[0];
  HInstruction get flags => inputs[1];

  @override
  HInstruction get constrainedInput => array;

  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitArrayFlagsSet(this);

  @override
  bool isJsStatement() => true;
}

class HIsLateSentinel extends HInstruction {
  HIsLateSentinel(super.value, super.type) : super._oneInput() {
    setUseGvn();
  }

  @override
  R accept<R>(HVisitor<R> visitor) => visitor.visitIsLateSentinel(this);

  @override
  _GvnType get _gvnType => _GvnType.isLateSentinel;

  @override
  bool typeEquals(HInstruction other) => other is HIsLateSentinel;

  @override
  bool dataEquals(HIsLateSentinel other) => true;

  @override
  String toString() => 'HIsLateSentinel()';
}
