// 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.

part of ssa;

abstract class HVisitor<R> {
  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 visitBoolify(HBoolify node);
  R visitBoundsCheck(HBoundsCheck node);
  R visitBreak(HBreak node);
  R visitConstant(HConstant node);
  R visitContinue(HContinue node);
  R visitDivide(HDivide node);
  R visitExit(HExit node);
  R visitExitTry(HExitTry node);
  R visitFieldGet(HFieldGet node);
  R visitFieldSet(HFieldSet node);
  R visitForeign(HForeign node);
  R visitForeignNew(HForeignNew 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 visitIs(HIs node);
  R visitIsViaInterceptor(HIsViaInterceptor 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 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 visitTypeConversion(HTypeConversion node);
  R visitTypeKnown(HTypeKnown node);
  R visitYield(HYield node);
  R visitReadTypeVariable(HReadTypeVariable node);
  R visitFunctionType(HFunctionType node);
  R visitVoidType(HVoidType node);
  R visitInterfaceType(HInterfaceType node);
  R visitDynamicType(HDynamicType node);
}

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

    visitBasicBlockAndSuccessors(graph.entry);
  }

  visitPostDominatorTree(HGraph graph) {
    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);
  }

  visitBasicBlock(HBasicBlock block);
}

abstract class HInstructionVisitor extends HGraphVisitor {
  HBasicBlock currentBlock;

  visitInstruction(HInstruction node);

  visitBasicBlock(HBasicBlock node) {
    void visitInstructionList(HInstructionList list) {
      HInstruction instruction = list.first;
      while (instruction != null) {
        visitInstruction(instruction);
        instruction = instruction.next;
        assert(instruction != list.first);
      }
    }

    currentBlock = node;
    visitInstructionList(node);
  }
}

class HGraph {
  HBasicBlock entry;
  HBasicBlock exit;
  HThis thisInstruction;
  /// Receiver parameter, set for methods using interceptor calling convention.
  HParameterValue explicitReceiverParameter;
  bool isRecursiveMethod = false;
  bool calledInLoop = false;
  final List<HBasicBlock> blocks;

  // 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()
      : blocks = new List<HBasicBlock>(),
        constants = new Map<ConstantValue, HConstant>() {
    entry = addNewBlock();
    // The exit block will be added later, so it has an id that is
    // after all others in the system.
    exit = new HBasicBlock();
  }

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

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

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

  HConstant addConstant(ConstantValue constant, Compiler compiler) {
    HConstant result = constants[constant];
    if (result == null) {
      TypeMask type = computeTypeMask(compiler, constant);
      result = new HConstant.internal(constant, type);
      entry.addAtExit(result);
      constants[constant] = result;
    } else if (result.block == null) {
      // The constant was not used anymore.
      entry.addAtExit(result);
    }
    return result;
  }

  HConstant addDeferredConstant(ConstantValue constant, PrefixElement prefix,
                                Compiler compiler) {
    ConstantValue wrapper = new DeferredConstantValue(constant, prefix);
    compiler.deferredLoadTask.registerConstantDeferredUse(wrapper, prefix);
    return addConstant(wrapper, compiler);
  }

  HConstant addConstantInt(int i, Compiler compiler) {
    return addConstant(compiler.backend.constantSystem.createInt(i), compiler);
  }

  HConstant addConstantDouble(double d, Compiler compiler) {
    return addConstant(
        compiler.backend.constantSystem.createDouble(d), compiler);
  }

  HConstant addConstantString(ast.DartString str,
                              Compiler compiler) {
    return addConstant(
        compiler.backend.constantSystem.createString(str),
        compiler);
  }

  HConstant addConstantBool(bool value, Compiler compiler) {
    return addConstant(
        compiler.backend.constantSystem.createBool(value), compiler);
  }

  HConstant addConstantNull(Compiler compiler) {
    return addConstant(compiler.backend.constantSystem.createNull(), compiler);
  }

  void finalize() {
    addBlock(exit);
    exit.open();
    exit.close(new 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]);
        }
      }
    }
  }

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

class HBaseVisitor extends HGraphVisitor implements HVisitor {
  HBasicBlock currentBlock;

  visitBasicBlock(HBasicBlock node) {
    currentBlock = node;

    HInstruction instruction = node.first;
    while (instruction != null) {
      instruction.accept(this);
      instruction = instruction.next;
    }
  }

  visitInstruction(HInstruction instruction) {}

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

  visitAdd(HAdd node) => visitBinaryArithmetic(node);
  visitBitAnd(HBitAnd node) => visitBinaryBitOp(node);
  visitBitNot(HBitNot node) => visitInvokeUnary(node);
  visitBitOr(HBitOr node) => visitBinaryBitOp(node);
  visitBitXor(HBitXor node) => visitBinaryBitOp(node);
  visitBoolify(HBoolify node) => visitInstruction(node);
  visitBoundsCheck(HBoundsCheck node) => visitCheck(node);
  visitBreak(HBreak node) => visitJump(node);
  visitContinue(HContinue node) => visitJump(node);
  visitCheck(HCheck node) => visitInstruction(node);
  visitConstant(HConstant node) => visitInstruction(node);
  visitDivide(HDivide node) => visitBinaryArithmetic(node);
  visitExit(HExit node) => visitControlFlow(node);
  visitExitTry(HExitTry node) => visitControlFlow(node);
  visitFieldGet(HFieldGet node) => visitFieldAccess(node);
  visitFieldSet(HFieldSet node) => visitFieldAccess(node);
  visitForeign(HForeign node) => visitInstruction(node);
  visitForeignNew(HForeignNew node) => visitForeign(node);
  visitGoto(HGoto node) => visitControlFlow(node);
  visitGreater(HGreater node) => visitRelational(node);
  visitGreaterEqual(HGreaterEqual node) => visitRelational(node);
  visitIdentity(HIdentity node) => visitRelational(node);
  visitIf(HIf node) => visitConditionalBranch(node);
  visitIndex(HIndex node) => visitInstruction(node);
  visitIndexAssign(HIndexAssign node) => visitInstruction(node);
  visitInterceptor(HInterceptor node) => visitInstruction(node);
  visitInvokeClosure(HInvokeClosure node)
      => visitInvokeDynamic(node);
  visitInvokeConstructorBody(HInvokeConstructorBody node)
      => visitInvokeStatic(node);
  visitInvokeDynamicMethod(HInvokeDynamicMethod node)
      => visitInvokeDynamic(node);
  visitInvokeDynamicGetter(HInvokeDynamicGetter node)
      => visitInvokeDynamicField(node);
  visitInvokeDynamicSetter(HInvokeDynamicSetter node)
      => visitInvokeDynamicField(node);
  visitInvokeStatic(HInvokeStatic node) => visitInvoke(node);
  visitInvokeSuper(HInvokeSuper node) => visitInvokeStatic(node);
  visitJump(HJump node) => visitControlFlow(node);
  visitLazyStatic(HLazyStatic node) => visitInstruction(node);
  visitLess(HLess node) => visitRelational(node);
  visitLessEqual(HLessEqual node) => visitRelational(node);
  visitLiteralList(HLiteralList node) => visitInstruction(node);
  visitLocalAccess(HLocalAccess node) => visitInstruction(node);
  visitLocalGet(HLocalGet node) => visitLocalAccess(node);
  visitLocalSet(HLocalSet node) => visitLocalAccess(node);
  visitLocalValue(HLocalValue node) => visitInstruction(node);
  visitLoopBranch(HLoopBranch node) => visitConditionalBranch(node);
  visitNegate(HNegate node) => visitInvokeUnary(node);
  visitNot(HNot node) => visitInstruction(node);
  visitOneShotInterceptor(HOneShotInterceptor node)
      => visitInvokeDynamic(node);
  visitPhi(HPhi node) => visitInstruction(node);
  visitMultiply(HMultiply node) => visitBinaryArithmetic(node);
  visitParameterValue(HParameterValue node) => visitLocalValue(node);
  visitRangeConversion(HRangeConversion node) => visitCheck(node);
  visitReadModifyWrite(HReadModifyWrite node) => visitInstruction(node);
  visitReturn(HReturn node) => visitControlFlow(node);
  visitShiftLeft(HShiftLeft node) => visitBinaryBitOp(node);
  visitShiftRight(HShiftRight node) => visitBinaryBitOp(node);
  visitSubtract(HSubtract node) => visitBinaryArithmetic(node);
  visitSwitch(HSwitch node) => visitControlFlow(node);
  visitStatic(HStatic node) => visitInstruction(node);
  visitStaticStore(HStaticStore node) => visitInstruction(node);
  visitStringConcat(HStringConcat node) => visitInstruction(node);
  visitStringify(HStringify node) => visitInstruction(node);
  visitThis(HThis node) => visitParameterValue(node);
  visitThrow(HThrow node) => visitControlFlow(node);
  visitThrowExpression(HThrowExpression node) => visitInstruction(node);
  visitTruncatingDivide(HTruncatingDivide node) => visitBinaryArithmetic(node);
  visitTry(HTry node) => visitControlFlow(node);
  visitIs(HIs node) => visitInstruction(node);
  visitIsViaInterceptor(HIsViaInterceptor node) => visitInstruction(node);
  visitTypeConversion(HTypeConversion node) => visitCheck(node);
  visitTypeKnown(HTypeKnown node) => visitCheck(node);
  visitReadTypeVariable(HReadTypeVariable node) => visitInstruction(node);
  visitFunctionType(HFunctionType node) => visitInstruction(node);
  visitVoidType(HVoidType node) => visitInstruction(node);
  visitInterfaceType(HInterfaceType node) => visitInstruction(node);
  visitDynamicType(HDynamicType node) => visitInstruction(node);
  visitAwait(HAwait node) => visitInstruction(node);
  visitYield(HYield 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) {
    assert(start != null);
    assert(end != null);
    assert(block != null);
    return start.id <= block.id && block.id <= end.id;
  }
}

class SubExpression extends SubGraph {
  const SubExpression(HBasicBlock start, HBasicBlock end)
      : super(start, 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 = null;
  HInstruction last = null;

  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(contains(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) {
    HInstruction cursor = first;
    while (cursor != null) {
      if (identical(cursor, instruction)) return true;
      cursor = cursor.next;
    }
    return false;
  }
}

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;

  static const int STATUS_NEW = 0;
  static const int STATUS_OPEN = 1;
  static const int STATUS_CLOSED = 2;
  int status = STATUS_NEW;

  HInstructionList phis;

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

  final List<HBasicBlock> predecessors;
  List<HBasicBlock> successors;

  HBasicBlock dominator = null;
  final List<HBasicBlock> dominatedBlocks;

  HBasicBlock() : this.withId(null);
  HBasicBlock.withId(this.id)
      : phis = new HInstructionList(),
        predecessors = <HBasicBlock>[],
        successors = const <HBasicBlock>[],
        dominatedBlocks = <HBasicBlock>[];

  int get hashCode => id;

  bool isNew() => status == STATUS_NEW;
  bool isOpen() => status == STATUS_OPEN;
  bool isClosed() => status == STATUS_CLOSED;

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

  void setBlockFlow(HBlockInformation blockInfo, HBasicBlock continuation) {
    blockFlow = new 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 = STATUS_OPEN;
  }

  void close(HControlFlow end) {
    assert(isOpen());
    addAfter(last, end);
    status = STATUS_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.length == 0 || 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);
  }

  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<HCheck>();
    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 != null && block.id != null);
    assert(dominatedBlocks.indexOf(block) < 0);
    // 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 != null && block.id != null);
    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 f(HPhi phi)) {
    HPhi current = phis.first;
    while (current != null) {
      HInstruction saved = current.next;
      f(current);
      current = saved;
    }
  }

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

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

  Map<HBasicBlock, bool> dominatesCache;

  bool dominates(HBasicBlock other) {
    if (dominatesCache == null) {
      dominatesCache = new Map<HBasicBlock, bool>();
    } else {
      bool res = dominatesCache[other];
      if (res != null) return res;
    }
    do {
      if (identical(this, other)) return dominatesCache[other] = true;
      other = other.dominator;
    } while (other != null && other.id >= id);
    return dominatesCache[other] = false;
  }
}

abstract class HInstruction implements Spannable {
  Entity sourceElement;
  SourceInformation sourceInformation;

  final int id;
  static int idCounter;

  final List<HInstruction> inputs;
  final List<HInstruction> usedBy;

  HBasicBlock block;
  HInstruction previous = null;
  HInstruction next = null;

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

  // Type codes.
  static const int UNDEFINED_TYPECODE = -1;
  static const int BOOLIFY_TYPECODE = 0;
  static const int TYPE_GUARD_TYPECODE = 1;
  static const int BOUNDS_CHECK_TYPECODE = 2;
  static const int INTEGER_CHECK_TYPECODE = 3;
  static const int INTERCEPTOR_TYPECODE = 4;
  static const int ADD_TYPECODE = 5;
  static const int DIVIDE_TYPECODE = 6;
  static const int MULTIPLY_TYPECODE = 7;
  static const int SUBTRACT_TYPECODE = 8;
  static const int SHIFT_LEFT_TYPECODE = 9;
  static const int BIT_OR_TYPECODE = 10;
  static const int BIT_AND_TYPECODE = 11;
  static const int BIT_XOR_TYPECODE = 12;
  static const int NEGATE_TYPECODE = 13;
  static const int BIT_NOT_TYPECODE = 14;
  static const int NOT_TYPECODE = 15;
  static const int IDENTITY_TYPECODE = 16;
  static const int GREATER_TYPECODE = 17;
  static const int GREATER_EQUAL_TYPECODE = 18;
  static const int LESS_TYPECODE = 19;
  static const int LESS_EQUAL_TYPECODE = 20;
  static const int STATIC_TYPECODE = 21;
  static const int STATIC_STORE_TYPECODE = 22;
  static const int FIELD_GET_TYPECODE = 23;
  static const int TYPE_CONVERSION_TYPECODE = 24;
  static const int TYPE_KNOWN_TYPECODE = 25;
  static const int INVOKE_STATIC_TYPECODE = 26;
  static const int INDEX_TYPECODE = 27;
  static const int IS_TYPECODE = 28;
  static const int INVOKE_DYNAMIC_TYPECODE = 29;
  static const int SHIFT_RIGHT_TYPECODE = 30;
  static const int READ_TYPE_VARIABLE_TYPECODE = 31;
  static const int FUNCTION_TYPE_TYPECODE = 32;
  static const int VOID_TYPE_TYPECODE = 33;
  static const int INTERFACE_TYPE_TYPECODE = 34;
  static const int DYNAMIC_TYPE_TYPECODE = 35;
  static const int TRUNCATING_DIVIDE_TYPECODE = 36;
  static const int IS_VIA_INTERCEPTOR_TYPECODE = 37;

  HInstruction(this.inputs, this.instructionType)
      : id = idCounter++, usedBy = <HInstruction>[] {
    assert(inputs.every((e) => e != null));
  }

  int get hashCode => id;

  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() {
    return !sideEffects.hasSideEffects()
        && !sideEffects.dependsOnSomething()
        && !canThrow();
  }

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

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

  /// Does this node potentially affect control flow.
  bool isControlFlow() => false;

  bool isExact() => instructionType.isExact || isNull();

  bool canBeNull() => instructionType.isNullable;

  bool isNull() => instructionType.isEmpty && instructionType.isNullable;
  bool isConflicting() {
    return instructionType.isEmpty && !instructionType.isNullable;
  }

  bool canBePrimitive(Compiler compiler) {
    return canBePrimitiveNumber(compiler)
        || canBePrimitiveArray(compiler)
        || canBePrimitiveBoolean(compiler)
        || canBePrimitiveString(compiler)
        || isNull();
  }

  bool canBePrimitiveNumber(Compiler compiler) {
    ClassWorld classWorld = compiler.world;
    JavaScriptBackend backend = compiler.backend;
    // TODO(sra): It should be possible to test only jsDoubleClass and
    // jsUInt31Class, since all others are superclasses of these two.
    return instructionType.contains(backend.jsNumberClass, classWorld)
        || instructionType.contains(backend.jsIntClass, classWorld)
        || instructionType.contains(backend.jsPositiveIntClass, classWorld)
        || instructionType.contains(backend.jsUInt32Class, classWorld)
        || instructionType.contains(backend.jsUInt31Class, classWorld)
        || instructionType.contains(backend.jsDoubleClass, classWorld);
  }

  bool canBePrimitiveBoolean(Compiler compiler) {
    ClassWorld classWorld = compiler.world;
    JavaScriptBackend backend = compiler.backend;
    return instructionType.contains(backend.jsBoolClass, classWorld);
  }

  bool canBePrimitiveArray(Compiler compiler) {
    ClassWorld classWorld = compiler.world;
    JavaScriptBackend backend = compiler.backend;
    return instructionType.contains(backend.jsArrayClass, classWorld)
        || instructionType.contains(backend.jsFixedArrayClass, classWorld)
        || instructionType.contains(backend.jsExtendableArrayClass, classWorld);
  }

  bool isIndexablePrimitive(Compiler compiler) {
    ClassWorld classWorld = compiler.world;
    JavaScriptBackend backend = compiler.backend;
    return instructionType.containsOnlyString(classWorld)
        || instructionType.satisfies(backend.jsIndexableClass, classWorld);
  }

  bool isFixedArray(Compiler compiler) {
    JavaScriptBackend backend = compiler.backend;
    return instructionType.containsOnly(backend.jsFixedArrayClass);
  }

  bool isExtendableArray(Compiler compiler) {
    JavaScriptBackend backend = compiler.backend;
    return instructionType.containsOnly(backend.jsExtendableArrayClass);
  }

  bool isMutableArray(Compiler compiler) {
    ClassWorld classWorld = compiler.world;
    JavaScriptBackend backend = compiler.backend;
    return instructionType.satisfies(backend.jsMutableArrayClass, classWorld);
  }

  bool isReadableArray(Compiler compiler) {
    ClassWorld classWorld = compiler.world;
    JavaScriptBackend backend = compiler.backend;
    return instructionType.satisfies(backend.jsArrayClass, classWorld);
  }

  bool isMutableIndexable(Compiler compiler) {
    ClassWorld classWorld = compiler.world;
    JavaScriptBackend backend = compiler.backend;
    return instructionType.satisfies(
        backend.jsMutableIndexableClass, classWorld);
  }

  bool isArray(Compiler compiler) => isReadableArray(compiler);

  bool canBePrimitiveString(Compiler compiler) {
    ClassWorld classWorld = compiler.world;
    JavaScriptBackend backend = compiler.backend;
    return instructionType.contains(backend.jsStringClass, classWorld);
  }

  bool isInteger(Compiler compiler) {
    ClassWorld classWorld = compiler.world;
    return instructionType.containsOnlyInt(classWorld)
        && !instructionType.isNullable;
  }

  bool isUInt32(Compiler compiler) {
    ClassWorld classWorld = compiler.world;
    JavaScriptBackend backend = compiler.backend;
    return !instructionType.isNullable
        && instructionType.satisfies(backend.jsUInt32Class, classWorld);
  }

  bool isUInt31(Compiler compiler) {
    ClassWorld classWorld = compiler.world;
    JavaScriptBackend backend = compiler.backend;
    return !instructionType.isNullable
        && instructionType.satisfies(backend.jsUInt31Class, classWorld);
  }

  bool isPositiveInteger(Compiler compiler) {
    ClassWorld classWorld = compiler.world;
    JavaScriptBackend backend = compiler.backend;
    return !instructionType.isNullable
        && instructionType.satisfies(backend.jsPositiveIntClass, classWorld);
  }

  bool isPositiveIntegerOrNull(Compiler compiler) {
    ClassWorld classWorld = compiler.world;
    JavaScriptBackend backend = compiler.backend;
    return instructionType.satisfies(backend.jsPositiveIntClass, classWorld);
  }

  bool isIntegerOrNull(Compiler compiler) {
    ClassWorld classWorld = compiler.world;
    return instructionType.containsOnlyInt(classWorld);
  }

  bool isNumber(Compiler compiler) {
    ClassWorld classWorld = compiler.world;
    return instructionType.containsOnlyNum(classWorld)
        && !instructionType.isNullable;
  }

  bool isNumberOrNull(Compiler compiler) {
    ClassWorld classWorld = compiler.world;
    return instructionType.containsOnlyNum(classWorld);
  }

  bool isDouble(Compiler compiler) {
    ClassWorld classWorld = compiler.world;
    return instructionType.containsOnlyDouble(classWorld)
        && !instructionType.isNullable;
  }

  bool isDoubleOrNull(Compiler compiler) {
    ClassWorld classWorld = compiler.world;
    return instructionType.containsOnlyDouble(classWorld);
  }

  bool isBoolean(Compiler compiler) {
    ClassWorld classWorld = compiler.world;
    return instructionType.containsOnlyBool(classWorld)
        && !instructionType.isNullable;
  }

  bool isBooleanOrNull(Compiler compiler) {
    ClassWorld classWorld = compiler.world;
    return instructionType.containsOnlyBool(classWorld);
  }

  bool isString(Compiler compiler) {
    ClassWorld classWorld = compiler.world;
    return instructionType.containsOnlyString(classWorld)
        && !instructionType.isNullable;
  }

  bool isStringOrNull(Compiler compiler) {
    ClassWorld classWorld = compiler.world;
    return instructionType.containsOnlyString(classWorld);
  }

  bool isPrimitive(Compiler compiler) {
    return (isPrimitiveOrNull(compiler) && !instructionType.isNullable)
        || isNull();
  }

  bool isPrimitiveOrNull(Compiler compiler) {
    return isIndexablePrimitive(compiler)
        || isNumberOrNull(compiler)
        || isBooleanOrNull(compiler)
        || isNull();
  }

  /**
   * Type of the instruction.
   */
  TypeMask instructionType;

  Selector get selector => null;
  HInstruction getDartReceiver(Compiler compiler) => null;
  bool onlyThrowsNSM() => false;

  bool isInBasicBlock() => block != null;

  bool gvnEquals(HInstruction other) {
    assert(useGvn() && other.useGvn());
    // Check that the type and the sideEffects match.
    bool hasSameType = typeEquals(other);
    assert(hasSameType == (typeCode() == other.typeCode()));
    if (!hasSameType) return false;
    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;
      }
    }
    // Check that the data in the instruction matches.
    return dataEquals(other);
  }

  int gvnHashCode() {
    int result = typeCode();
    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.
  int typeCode() => HInstruction.UNDEFINED_TYPECODE;
  bool typeEquals(HInstruction other) => false;
  bool dataEquals(HInstruction other) => false;

  accept(HVisitor 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);
    }
    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(newInput != null && !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);
  }

  // Compute the set of users of this instruction that is dominated by
  // [other]. If [other] is a user of [this], it is included in the
  // returned set.
  Setlet<HInstruction> dominatedUsers(HInstruction other) {
    // Keep track of all instructions that we have to deal with later
    // and count the number of them that are in the current block.
    Setlet<HInstruction> users = new Setlet<HInstruction>();
    int usersInCurrentBlock = 0;

    // Run through all the users and see if they are dominated or
    // potentially dominated by [other].
    HBasicBlock otherBlock = other.block;
    for (int i = 0, length = usedBy.length; i < length; i++) {
      HInstruction current = usedBy[i];
      if (otherBlock.dominates(current.block)) {
        if (identical(current.block, otherBlock)) usersInCurrentBlock++;
        users.add(current);
      }
    }

    // Run through all the phis in the same block as [other] and remove them
    // from the users set.
    if (usersInCurrentBlock > 0) {
      for (HPhi phi = otherBlock.phis.first; phi != null; phi = phi.next) {
        if (users.contains(phi)) {
          users.remove(phi);
          if (--usersInCurrentBlock == 0) break;
        }
      }
    }

    // Run through all the instructions before [other] and remove them
    // from the users set.
    if (usersInCurrentBlock > 0) {
      HInstruction current = otherBlock.first;
      while (!identical(current, other)) {
        if (users.contains(current)) {
          users.remove(current);
          if (--usersInCurrentBlock == 0) break;
        }
        current = current.next;
      }
    }

    return users;
  }

  void replaceAllUsersDominatedBy(HInstruction cursor,
                                  HInstruction newInstruction) {
    Setlet<HInstruction> users = dominatedUsers(cursor);
    for (HInstruction user in users) {
      user.changeUse(this, 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 isConstant() => false;
  bool isConstantBoolean() => false;
  bool isConstantNull() => false;
  bool isConstantNumber() => false;
  bool isConstantInteger() => false;
  bool isConstantString() => false;
  bool isConstantList() => false;
  bool isConstantMap() => false;
  bool isConstantFalse() => false;
  bool isConstantTrue() => false;

  bool isInterceptor(Compiler compiler) => false;

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

  bool isCodeMotionInvariant() => false;

  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);

    HInstruction current = this.next;
    while (current != null) {
      if (current == other) return true;
      current = current.next;
    }
    return false;
  }

  HInstruction convertType(Compiler compiler, DartType type, int kind) {
    if (type == null) return this;
    type = type.unalias(compiler);
    // Only the builder knows how to create [HTypeConversion]
    // instructions with generics. It has the generic type context
    // available.
    assert(type.kind != TypeKind.TYPE_VARIABLE);
    assert(type.treatAsRaw || type.isFunctionType);
    if (type.isDynamic) return this;
    // The type element is either a class or the void element.
    Element element = type.element;
    if (identical(element, compiler.objectClass)) return this;
    JavaScriptBackend backend = compiler.backend;
    if (type.kind != TypeKind.INTERFACE) {
      return new HTypeConversion(type, kind, backend.dynamicType, this);
    } else if (kind == HTypeConversion.BOOLEAN_CONVERSION_CHECK) {
      // Boolean conversion checks work on non-nullable booleans.
      return new HTypeConversion(type, kind, backend.boolType, this);
    } else if (kind == HTypeConversion.CHECKED_MODE_CHECK && !type.treatAsRaw) {
      throw 'creating compound check to $type (this = ${this})';
    } else {
      TypeMask subtype = new TypeMask.subtype(element.declaration,
                                              compiler.world);
      return new HTypeConversion(type, kind, subtype, this);
    }
  }

  /**
   * 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;
  }
}

/**
 * Late instructions are used after the main optimization phases.  They capture
 * codegen decisions just prior to generating JavaScript.
 */
abstract class HLateInstruction extends HInstruction {
  HLateInstruction(List<HInstruction> inputs, TypeMask type)
      : super(inputs, type);
}

class HBoolify extends HInstruction {
  HBoolify(HInstruction value, TypeMask type)
      : super(<HInstruction>[value], type) {
    setUseGvn();
  }

  accept(HVisitor visitor) => visitor.visitBoolify(this);
  int typeCode() => HInstruction.BOOLIFY_TYPECODE;
  bool typeEquals(other) => other is HBoolify;
  bool dataEquals(HInstruction other) => true;
}

/**
 * A [HCheck] instruction is an instruction that might do a dynamic
 * check at runtime on another instruction. To have proper instruction
 * dependencies in the graph, instructions that depend on the check
 * being done reference the [HCheck] instruction instead of the
 * instruction itself.
 */
abstract class HCheck extends HInstruction {
  HCheck(inputs, type) : super(inputs, type) {
    setUseGvn();
  }
  HInstruction get checkedInput => inputs[0];
  bool isJsStatement() => true;
  bool canThrow() => true;

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

class HBoundsCheck extends HCheck {
  static const int ALWAYS_FALSE = 0;
  static const int FULL_CHECK = 1;
  static const int ALWAYS_ABOVE_ZERO = 2;
  static const int ALWAYS_BELOW_LENGTH = 3;
  static const int ALWAYS_TRUE = 4;
  /**
   * Details which tests have been done statically during compilation.
   * Default is that all checks must be performed dynamically.
   */
  int staticChecks = FULL_CHECK;

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

  HInstruction get length => inputs[1];
  HInstruction get index => inputs[0];
  HInstruction get array => inputs[2];
  bool isControlFlow() => true;

  accept(HVisitor visitor) => visitor.visitBoundsCheck(this);
  int typeCode() => HInstruction.BOUNDS_CHECK_TYPECODE;
  bool typeEquals(other) => other is HBoundsCheck;
  bool dataEquals(HInstruction other) => true;
}

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

abstract class HControlFlow extends HInstruction {
  HControlFlow(inputs) : super(inputs, const TypeMask.nonNullEmpty());
  bool isControlFlow() => true;
  bool isJsStatement() => true;
}

abstract class HInvoke extends HInstruction {
  /**
    * The first argument must be the target: either an [HStatic] node, or
    * the receiver of a method-call. The remaining inputs are the arguments
    * to the invocation.
    */
  HInvoke(List<HInstruction> inputs, type) : super(inputs, type) {
    sideEffects.setAllSideEffects();
    sideEffects.setDependsOnSomething();
  }
  static const int ARGUMENTS_OFFSET = 1;
  bool canThrow() => true;

  /**
   * Returns whether this call is on an intercepted method.
   */
  bool get isInterceptedCall {
    // We know it's a selector call if it follows the interceptor
    // calling convention, which adds the actual receiver as a
    // parameter to the call.
    return (selector != null) && (inputs.length - 2 == selector.argumentCount);
  }
}

abstract class HInvokeDynamic extends HInvoke {
  final InvokeDynamicSpecializer specializer;
  Selector selector;
  Element element;

  HInvokeDynamic(Selector selector,
                 this.element,
                 List<HInstruction> inputs,
                 TypeMask type,
                 [bool isIntercepted = false])
    : super(inputs, type),
      this.selector = selector,
      specializer = isIntercepted
          ? InvokeDynamicSpecializer.lookupSpecializer(selector)
          : const InvokeDynamicSpecializer();
  toString() => 'invoke dynamic: $selector';
  HInstruction get receiver => inputs[0];
  HInstruction getDartReceiver(Compiler compiler) {
    return isCallOnInterceptor(compiler) ? inputs[1] : inputs[0];
  }

  /**
   * Returns whether this call is on an interceptor object.
   */
  bool isCallOnInterceptor(Compiler compiler) {
    return isInterceptedCall && receiver.isInterceptor(compiler);
  }

  int typeCode() => HInstruction.INVOKE_DYNAMIC_TYPECODE;
  bool typeEquals(other) => other is HInvokeDynamic;
  bool dataEquals(HInvokeDynamic other) {
    // Use the name and the kind instead of [Selector.operator==]
    // because we don't need to check the arity (already checked in
    // [gvnEquals]), and the receiver types may not be in sync.
    return selector.name == other.selector.name
        && selector.kind == other.selector.kind;
  }
}

class HInvokeClosure extends HInvokeDynamic {
  HInvokeClosure(Selector selector, List<HInstruction> inputs, TypeMask type)
    : super(selector, null, inputs, type) {
    assert(selector.isClosureCall);
  }
  accept(HVisitor visitor) => visitor.visitInvokeClosure(this);
}

class HInvokeDynamicMethod extends HInvokeDynamic {
  HInvokeDynamicMethod(Selector selector,
                       List<HInstruction> inputs,
                       TypeMask type,
                       [bool isIntercepted = false])
    : super(selector, null, inputs, type, isIntercepted);

  String toString() => 'invoke dynamic method: $selector';
  accept(HVisitor visitor) => visitor.visitInvokeDynamicMethod(this);
}

abstract class HInvokeDynamicField extends HInvokeDynamic {
  HInvokeDynamicField(
      Selector selector, Element element, List<HInstruction> inputs,
      TypeMask type)
      : super(selector, element, inputs, type);
  toString() => 'invoke dynamic field: $selector';
}

class HInvokeDynamicGetter extends HInvokeDynamicField {
  HInvokeDynamicGetter(selector, element, inputs, type)
    : super(selector, element, inputs, type);
  toString() => 'invoke dynamic getter: $selector';
  accept(HVisitor visitor) => visitor.visitInvokeDynamicGetter(this);
}

class HInvokeDynamicSetter extends HInvokeDynamicField {
  HInvokeDynamicSetter(selector, element, inputs, type)
    : super(selector, element, inputs, type);
  toString() => 'invoke dynamic setter: $selector';
  accept(HVisitor visitor) => visitor.visitInvokeDynamicSetter(this);
}

class HInvokeStatic extends HInvoke {
  final Element element;

  final bool targetCanThrow;

  bool canThrow() => 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<DartType> instantiatedTypes;

  /** The first input must be the target. */
  HInvokeStatic(this.element, inputs, TypeMask type,
                {this.targetCanThrow: true})
    : super(inputs, type);

  toString() => 'invoke static: $element';
  accept(HVisitor visitor) => visitor.visitInvokeStatic(this);
  int typeCode() => HInstruction.INVOKE_STATIC_TYPECODE;
}

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

  HInvokeSuper(Element element,
               this.caller,
               this.selector,
               inputs,
               type,
               {this.isSetter})
      : super(element, inputs, type);

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

  /**
   * Returns whether this call is on an interceptor object.
   */
  bool isCallOnInterceptor(Compiler compiler) {
    return isInterceptedCall && receiver.isInterceptor(compiler);
  }

  toString() => 'invoke super: $element';
  accept(HVisitor 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(element, inputs, type)
      : super(element, inputs, type);

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

abstract class HFieldAccess extends HInstruction {
  final Element element;

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

  HInstruction get receiver => inputs[0];
}

class HFieldGet extends HFieldAccess {
  final bool isAssignable;

  HFieldGet(Element element,
            HInstruction receiver,
            TypeMask type,
            {bool isAssignable})
      : this.isAssignable = (isAssignable != null)
            ? isAssignable
            : element.isAssignable,
        super(element, <HInstruction>[receiver], type) {
    sideEffects.clearAllSideEffects();
    sideEffects.clearAllDependencies();
    setUseGvn();
    if (this.isAssignable) {
      sideEffects.setDependsOnInstancePropertyStore();
    }
  }

  bool isInterceptor(Compiler compiler) {
    if (sourceElement == null) return false;
    // In case of a closure inside an interceptor class, [:this:] is
    // stored in the generated closure class, and accessed through a
    // [HFieldGet].
    JavaScriptBackend backend = compiler.backend;
    if (sourceElement is ThisLocal) {
      ThisLocal thisLocal = sourceElement;
      return backend.isInterceptorClass(thisLocal.enclosingClass);
    }
    return false;
  }

  bool canThrow() => receiver.canBeNull();

  HInstruction getDartReceiver(Compiler compiler) => receiver;
  bool onlyThrowsNSM() => true;
  bool get isNullCheck => element == null;

  accept(HVisitor visitor) => visitor.visitFieldGet(this);

  int typeCode() => HInstruction.FIELD_GET_TYPECODE;
  bool typeEquals(other) => other is HFieldGet;
  bool dataEquals(HFieldGet other) => element == other.element;
  String toString() => "FieldGet $element";
}

class HFieldSet extends HFieldAccess {
  HFieldSet(Element element,
            HInstruction receiver,
            HInstruction value)
      : super(element, <HInstruction>[receiver, value],
              const TypeMask.nonNullEmpty()) {
    sideEffects.clearAllSideEffects();
    sideEffects.clearAllDependencies();
    sideEffects.setChangesInstanceProperty();
  }

  bool canThrow() => receiver.canBeNull();

  HInstruction getDartReceiver(Compiler compiler) => receiver;
  bool onlyThrowsNSM() => true;

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

  bool isJsStatement() => true;
  String toString() => "FieldSet $element";
}

/**
 * HReadModifyWrite is a late stage instruction for a field (property) update
 * via an assignment operation or pre- or post-increment.
 */
class HReadModifyWrite extends HLateInstruction {
  static const ASSIGN_OP = 0;
  static const PRE_OP = 1;
  static const POST_OP = 2;
  final Element element;
  final String jsOp;
  final int opKind;

   HReadModifyWrite._(Element this.element, this.jsOp, this.opKind,
      List<HInstruction> inputs, TypeMask type)
      : super(inputs, type) {
    sideEffects.clearAllSideEffects();
    sideEffects.clearAllDependencies();
    sideEffects.setChangesInstanceProperty();
    sideEffects.setDependsOnInstancePropertyStore();
  }

  HReadModifyWrite.assignOp(Element element, String jsOp,
      HInstruction receiver, HInstruction operand, TypeMask type)
      : this._(element, jsOp, ASSIGN_OP,
               <HInstruction>[receiver, operand], type);

  HReadModifyWrite.preOp(Element element, String jsOp,
      HInstruction receiver, TypeMask type)
      : this._(element, jsOp, PRE_OP, <HInstruction>[receiver], type);

  HReadModifyWrite.postOp(Element element, String jsOp,
      HInstruction receiver, TypeMask type)
      : this._(element, jsOp, POST_OP, <HInstruction>[receiver], type);

  HInstruction get receiver => inputs[0];

  bool get isPreOp => opKind == PRE_OP;
  bool get isPostOp => opKind == POST_OP;
  bool get isAssignOp => opKind == ASSIGN_OP;

  bool canThrow() => receiver.canBeNull();

  HInstruction getDartReceiver(Compiler compiler) => receiver;
  bool onlyThrowsNSM() => true;

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

  bool isJsStatement() => isAssignOp;
  String toString() => "ReadModifyWrite $jsOp $opKind $element";
}

abstract class HLocalAccess extends HInstruction {
  final Local variable;

  HLocalAccess(this.variable, List<HInstruction> inputs, TypeMask 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, TypeMask type)
      : super(variable, <HInstruction>[local], type);

  accept(HVisitor visitor) => visitor.visitLocalGet(this);

  HLocalValue get local => inputs[0];
}

class HLocalSet extends HLocalAccess {
  HLocalSet(Local variable, HLocalValue local, HInstruction value)
      : super(variable, <HInstruction>[local, value],
              const TypeMask.nonNullEmpty());

  accept(HVisitor visitor) => visitor.visitLocalSet(this);

  HLocalValue get local => inputs[0];
  HInstruction get value => inputs[1];
  bool isJsStatement() => true;
}

class HForeign extends HInstruction {
  final js.Template codeTemplate;
  final bool isStatement;
  final bool _canThrow;
  final native.NativeBehavior nativeBehavior;

  HForeign(this.codeTemplate,
           TypeMask type,
           List<HInstruction> inputs,
           {this.isStatement: false,
            SideEffects effects,
            native.NativeBehavior nativeBehavior,
            canThrow: false})
      : this.nativeBehavior = nativeBehavior,
        this._canThrow = canThrow,
        super(inputs, type) {
    if (effects == null && nativeBehavior != null) {
      effects = nativeBehavior.sideEffects;
    }
    if (effects != null) sideEffects.add(effects);
  }

  HForeign.statement(codeTemplate, List<HInstruction> inputs,
                     SideEffects effects,
                     native.NativeBehavior nativeBehavior,
                     TypeMask type)
      : this(codeTemplate, type, inputs, isStatement: true,
             effects: effects, nativeBehavior: nativeBehavior);

  accept(HVisitor visitor) => visitor.visitForeign(this);

  bool isJsStatement() => isStatement;
  bool canThrow() {
    return _canThrow
        || sideEffects.hasSideEffects()
        || sideEffects.dependsOnSomething();
  }
}

class HForeignNew extends HForeign {
  ClassElement element;

  /// 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<DartType> instantiatedTypes;

  HForeignNew(this.element, TypeMask type, List<HInstruction> inputs,
              [this.instantiatedTypes])
      : super(null, type, inputs);

  accept(HVisitor visitor) => visitor.visitForeignNew(this);
}

abstract class HInvokeBinary extends HInstruction {
  final Selector selector;
  HInvokeBinary(HInstruction left, HInstruction right, this.selector, type)
      : super(<HInstruction>[left, right], type) {
    sideEffects.clearAllSideEffects();
    sideEffects.clearAllDependencies();
    setUseGvn();
  }

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

  BinaryOperation operation(ConstantSystem constantSystem);
}

abstract class HBinaryArithmetic extends HInvokeBinary {
  HBinaryArithmetic(left, right, selector, type)
      : super(left, right, selector, type);
  BinaryOperation operation(ConstantSystem constantSystem);
}

class HAdd extends HBinaryArithmetic {
  HAdd(left, right, selector, type) : super(left, right, selector, type);
  accept(HVisitor visitor) => visitor.visitAdd(this);

  BinaryOperation operation(ConstantSystem constantSystem)
      => constantSystem.add;
  int typeCode() => HInstruction.ADD_TYPECODE;
  bool typeEquals(other) => other is HAdd;
  bool dataEquals(HInstruction other) => true;
}

class HDivide extends HBinaryArithmetic {
  HDivide(left, right, selector, type) : super(left, right, selector, type);
  accept(HVisitor visitor) => visitor.visitDivide(this);

  BinaryOperation operation(ConstantSystem constantSystem)
      => constantSystem.divide;
  int typeCode() => HInstruction.DIVIDE_TYPECODE;
  bool typeEquals(other) => other is HDivide;
  bool dataEquals(HInstruction other) => true;
}

class HMultiply extends HBinaryArithmetic {
  HMultiply(left, right, selector, type) : super(left, right, selector, type);
  accept(HVisitor visitor) => visitor.visitMultiply(this);

  BinaryOperation operation(ConstantSystem operations)
      => operations.multiply;
  int typeCode() => HInstruction.MULTIPLY_TYPECODE;
  bool typeEquals(other) => other is HMultiply;
  bool dataEquals(HInstruction other) => true;
}

class HSubtract extends HBinaryArithmetic {
  HSubtract(left, right, selector, type) : super(left, right, selector, type);
  accept(HVisitor visitor) => visitor.visitSubtract(this);

  BinaryOperation operation(ConstantSystem constantSystem)
      => constantSystem.subtract;
  int typeCode() => HInstruction.SUBTRACT_TYPECODE;
  bool typeEquals(other) => other is HSubtract;
  bool dataEquals(HInstruction other) => true;
}

class HTruncatingDivide extends HBinaryArithmetic {
  HTruncatingDivide(left, right, selector, type)
      : super(left, right, selector, type);
  accept(HVisitor visitor) => visitor.visitTruncatingDivide(this);

  BinaryOperation operation(ConstantSystem constantSystem)
      => constantSystem.truncatingDivide;
  int typeCode() => HInstruction.TRUNCATING_DIVIDE_TYPECODE;
  bool typeEquals(other) => other is HTruncatingDivide;
  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(List<HInstruction> inputs) : super(inputs);

  HConstant constant(int index) => inputs[index + 1];
  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;

  accept(HVisitor visitor) => visitor.visitSwitch(this);

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

abstract class HBinaryBitOp extends HInvokeBinary {
  HBinaryBitOp(left, right, selector, type)
      : super(left, right, selector, type);
}

class HShiftLeft extends HBinaryBitOp {
  HShiftLeft(left, right, selector, type) : super(left, right, selector, type);
  accept(HVisitor visitor) => visitor.visitShiftLeft(this);

  BinaryOperation operation(ConstantSystem constantSystem)
      => constantSystem.shiftLeft;
  int typeCode() => HInstruction.SHIFT_LEFT_TYPECODE;
  bool typeEquals(other) => other is HShiftLeft;
  bool dataEquals(HInstruction other) => true;
}

class HShiftRight extends HBinaryBitOp {
  HShiftRight(left, right, selector, type) : super(left, right, selector, type);
  accept(HVisitor visitor) => visitor.visitShiftRight(this);

  BinaryOperation operation(ConstantSystem constantSystem)
      => constantSystem.shiftRight;
  int typeCode() => HInstruction.SHIFT_RIGHT_TYPECODE;
  bool typeEquals(other) => other is HShiftRight;
  bool dataEquals(HInstruction other) => true;
}

class HBitOr extends HBinaryBitOp {
  HBitOr(left, right, selector, type) : super(left, right, selector, type);
  accept(HVisitor visitor) => visitor.visitBitOr(this);

  BinaryOperation operation(ConstantSystem constantSystem)
      => constantSystem.bitOr;
  int typeCode() => HInstruction.BIT_OR_TYPECODE;
  bool typeEquals(other) => other is HBitOr;
  bool dataEquals(HInstruction other) => true;
}

class HBitAnd extends HBinaryBitOp {
  HBitAnd(left, right, selector, type) : super(left, right, selector, type);
  accept(HVisitor visitor) => visitor.visitBitAnd(this);

  BinaryOperation operation(ConstantSystem constantSystem)
      => constantSystem.bitAnd;
  int typeCode() => HInstruction.BIT_AND_TYPECODE;
  bool typeEquals(other) => other is HBitAnd;
  bool dataEquals(HInstruction other) => true;
}

class HBitXor extends HBinaryBitOp {
  HBitXor(left, right, selector, type) : super(left, right, selector, type);
  accept(HVisitor visitor) => visitor.visitBitXor(this);

  BinaryOperation operation(ConstantSystem constantSystem)
      => constantSystem.bitXor;
  int typeCode() => HInstruction.BIT_XOR_TYPECODE;
  bool typeEquals(other) => other is HBitXor;
  bool dataEquals(HInstruction other) => true;
}

abstract class HInvokeUnary extends HInstruction {
  final Selector selector;
  HInvokeUnary(HInstruction input, this.selector, type)
      : super(<HInstruction>[input], type) {
    sideEffects.clearAllSideEffects();
    sideEffects.clearAllDependencies();
    setUseGvn();
  }

  HInstruction get operand => inputs[0];

  UnaryOperation operation(ConstantSystem constantSystem);
}

class HNegate extends HInvokeUnary {
  HNegate(input, selector, type) : super(input, selector, type);
  accept(HVisitor visitor) => visitor.visitNegate(this);

  UnaryOperation operation(ConstantSystem constantSystem)
      => constantSystem.negate;
  int typeCode() => HInstruction.NEGATE_TYPECODE;
  bool typeEquals(other) => other is HNegate;
  bool dataEquals(HInstruction other) => true;
}

class HBitNot extends HInvokeUnary {
  HBitNot(input, selector, type) : super(input, selector, type);
  accept(HVisitor visitor) => visitor.visitBitNot(this);

  UnaryOperation operation(ConstantSystem constantSystem)
      => constantSystem.bitNot;
  int typeCode() => HInstruction.BIT_NOT_TYPECODE;
  bool typeEquals(other) => other is HBitNot;
  bool dataEquals(HInstruction other) => true;
}

class HExit extends HControlFlow {
  HExit() : super(const <HInstruction>[]);
  toString() => 'exit';
  accept(HVisitor visitor) => visitor.visitExit(this);
}

class HGoto extends HControlFlow {
  HGoto() : super(const <HInstruction>[]);
  toString() => 'goto';
  accept(HVisitor visitor) => visitor.visitGoto(this);
}

abstract class HJump extends HControlFlow {
  final JumpTarget target;
  final LabelDefinition label;
  HJump(this.target) : label = null, super(const <HInstruction>[]);
  HJump.toLabel(LabelDefinition label)
      : label = label, target = label.target, super(const <HInstruction>[]);
}

class HBreak extends HJump {
  /**
   * Signals that this is a special break instruction for the synthetic loop
   * generatedfor a switch statement with continue statements. See
   * [SsaFromAstMixin.buildComplexSwitchStatement] for detail.
   */
  final bool breakSwitchContinueLoop;
  HBreak(JumpTarget target, {bool this.breakSwitchContinueLoop: false})
      : super(target);
  HBreak.toLabel(LabelDefinition label)
      : breakSwitchContinueLoop = false, super.toLabel(label);
  toString() => (label != null) ? 'break ${label.labelName}' : 'break';
  accept(HVisitor visitor) => visitor.visitBreak(this);
}

class HContinue extends HJump {
  HContinue(JumpTarget target) : super(target);
  HContinue.toLabel(LabelDefinition label) : super.toLabel(label);
  toString() => (label != null) ? 'continue ${label.labelName}' : 'continue';
  accept(HVisitor visitor) => visitor.visitContinue(this);
}

class HTry extends HControlFlow {
  HLocalValue exception;
  HBasicBlock catchBlock;
  HBasicBlock finallyBlock;
  HTry() : super(const <HInstruction>[]);
  toString() => 'try';
  accept(HVisitor visitor) => visitor.visitTry(this);
  HBasicBlock get joinBlock => this.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 {
  HExitTry() : super(const <HInstruction>[]);
  toString() => 'exit try';
  accept(HVisitor visitor) => visitor.visitExitTry(this);
  HBasicBlock get bodyTrySuccessor => block.successors[0];
}

class HIf extends HConditionalBranch {
  HBlockFlow blockInformation = null;
  HIf(HInstruction condition) : super(<HInstruction>[condition]);
  toString() => 'if';
  accept(HVisitor 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 {
  static const int CONDITION_FIRST_LOOP = 0;
  static const int DO_WHILE_LOOP = 1;

  final int kind;
  HLoopBranch(HInstruction condition, [this.kind = CONDITION_FIRST_LOOP])
      : super(<HInstruction>[condition]);
  toString() => 'loop-branch';
  accept(HVisitor visitor) => visitor.visitLoopBranch(this);
}

class HConstant extends HInstruction {
  final ConstantValue constant;
  HConstant.internal(this.constant, TypeMask constantType)
      : super(<HInstruction>[], constantType);

  toString() => 'literal: $constant';
  accept(HVisitor visitor) => visitor.visitConstant(this);

  bool isConstant() => true;
  bool isConstantBoolean() => constant.isBool;
  bool isConstantNull() => constant.isNull;
  bool isConstantNumber() => constant.isNum;
  bool isConstantInteger() => constant.isInt;
  bool isConstantString() => constant.isString;
  bool isConstantList() => constant.isList;
  bool isConstantMap() => constant.isMap;
  bool isConstantFalse() => constant.isFalse;
  bool isConstantTrue() => constant.isTrue;

  bool isInterceptor(Compiler compiler) => constant.isInterceptor;

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

  set instructionType(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 (!isConstantList()) return;
    super.instructionType = type;
  }
}

class HNot extends HInstruction {
  HNot(HInstruction value, TypeMask type) : super(<HInstruction>[value], type) {
    setUseGvn();
  }

  accept(HVisitor visitor) => visitor.visitNot(this);
  int typeCode() => HInstruction.NOT_TYPECODE;
  bool typeEquals(other) => other is HNot;
  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, TypeMask type)
      : super(<HInstruction>[], type) {
    sourceElement = variable;
  }

  toString() => 'local ${sourceElement.name}';
  accept(HVisitor visitor) => visitor.visitLocalValue(this);
}

class HParameterValue extends HLocalValue {
  HParameterValue(Entity variable, type) : super(variable, type);

  toString() => 'parameter ${sourceElement.name}';
  accept(HVisitor visitor) => visitor.visitParameterValue(this);
}

class HThis extends HParameterValue {
  HThis(ThisLocal element, TypeMask type) : super(element, type);

  ThisLocal get sourceElement => super.sourceElement;

  accept(HVisitor visitor) => visitor.visitThis(this);

  bool isCodeMotionInvariant() => true;

  bool isInterceptor(Compiler compiler) {
    JavaScriptBackend backend = compiler.backend;
    return backend.isInterceptorClass(sourceElement.enclosingClass);
  }

  String toString() => 'this';
}

class HPhi extends HInstruction {
  static const IS_NOT_LOGICAL_OPERATOR = 0;
  static const IS_AND = 1;
  static const IS_OR = 2;

  int logicalOperatorType = IS_NOT_LOGICAL_OPERATOR;

  // 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, TypeMask type)
      : super(inputs, type) {
    sourceElement = variable;
  }
  HPhi.noInputs(Local variable, TypeMask type)
      : this(variable, <HInstruction>[], type);
  HPhi.singleInput(Local variable, HInstruction input, TypeMask type)
      : this(variable, <HInstruction>[input], type);
  HPhi.manyInputs(Local variable,
                  List<HInstruction> inputs,
                  TypeMask type)
      : this(variable, inputs, type);

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

  toString() => 'phi';
  accept(HVisitor visitor) => visitor.visitPhi(this);
}

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

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

  HIdentity(left, right, selector, type) : super(left, right, selector, type);
  accept(HVisitor visitor) => visitor.visitIdentity(this);

  BinaryOperation operation(ConstantSystem constantSystem)
      => constantSystem.identity;
  int typeCode() => HInstruction.IDENTITY_TYPECODE;
  bool typeEquals(other) => other is HIdentity;
  bool dataEquals(HInstruction other) => true;
}

class HGreater extends HRelational {
  HGreater(left, right, selector, type) : super(left, right, selector, type);
  accept(HVisitor visitor) => visitor.visitGreater(this);

  BinaryOperation operation(ConstantSystem constantSystem)
      => constantSystem.greater;
  int typeCode() => HInstruction.GREATER_TYPECODE;
  bool typeEquals(other) => other is HGreater;
  bool dataEquals(HInstruction other) => true;
}

class HGreaterEqual extends HRelational {
  HGreaterEqual(left, right, selector, type)
      : super(left, right, selector, type);
  accept(HVisitor visitor) => visitor.visitGreaterEqual(this);

  BinaryOperation operation(ConstantSystem constantSystem)
      => constantSystem.greaterEqual;
  int typeCode() => HInstruction.GREATER_EQUAL_TYPECODE;
  bool typeEquals(other) => other is HGreaterEqual;
  bool dataEquals(HInstruction other) => true;
}

class HLess extends HRelational {
  HLess(left, right, selector, type) : super(left, right, selector, type);
  accept(HVisitor visitor) => visitor.visitLess(this);

  BinaryOperation operation(ConstantSystem constantSystem)
      => constantSystem.less;
  int typeCode() => HInstruction.LESS_TYPECODE;
  bool typeEquals(other) => other is HLess;
  bool dataEquals(HInstruction other) => true;
}

class HLessEqual extends HRelational {
  HLessEqual(left, right, selector, type) : super(left, right, selector, type);
  accept(HVisitor visitor) => visitor.visitLessEqual(this);

  BinaryOperation operation(ConstantSystem constantSystem)
      => constantSystem.lessEqual;
  int typeCode() => HInstruction.LESS_EQUAL_TYPECODE;
  bool typeEquals(other) => other is HLessEqual;
  bool dataEquals(HInstruction other) => true;
}

class HReturn extends HControlFlow {
  HReturn(value) : super(<HInstruction>[value]);
  toString() => 'return';
  accept(HVisitor visitor) => visitor.visitReturn(this);
}

class HThrowExpression extends HInstruction {
  HThrowExpression(value)
      : super(<HInstruction>[value], const TypeMask.nonNullEmpty());
  toString() => 'throw expression';
  accept(HVisitor visitor) => visitor.visitThrowExpression(this);
  bool canThrow() => true;
}

class HAwait extends HInstruction {
  HAwait(HInstruction value, TypeMask type)
      : super(<HInstruction>[value], type);
  toString() => 'await';
  accept(HVisitor visitor) => visitor.visitAwait(this);
  // An await will throw if its argument is not a real future.
  bool canThrow() => true;
  SideEffects sideEffects = new SideEffects();
}

class HYield extends HInstruction {
  HYield(HInstruction value, this.hasStar)
      : super(<HInstruction>[value], const TypeMask.nonNullEmpty());
  bool hasStar;
  toString() => 'yield';
  accept(HVisitor visitor) => visitor.visitYield(this);
  bool canThrow() => false;
  SideEffects sideEffects = new SideEffects();
}

class HThrow extends HControlFlow {
  final bool isRethrow;
  HThrow(value, {this.isRethrow: false}) : super(<HInstruction>[value]);
  toString() => 'throw';
  accept(HVisitor visitor) => visitor.visitThrow(this);
}

class HStatic extends HInstruction {
  final Element element;
  HStatic(this.element, type) : super(<HInstruction>[], type) {
    assert(element != null);
    assert(invariant(this, element.isDeclaration));
    sideEffects.clearAllSideEffects();
    sideEffects.clearAllDependencies();
    if (element.isAssignable) {
      sideEffects.setDependsOnStaticPropertyStore();
    }
    setUseGvn();
  }
  toString() => 'static ${element.name}';
  accept(HVisitor visitor) => visitor.visitStatic(this);

  int gvnHashCode() => super.gvnHashCode() ^ element.hashCode;
  int typeCode() => HInstruction.STATIC_TYPECODE;
  bool typeEquals(other) => other is HStatic;
  bool dataEquals(HStatic other) => element == other.element;
  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<ClassElement> interceptedClasses;
  HInterceptor(HInstruction receiver, TypeMask type)
      : super(<HInstruction>[receiver], type) {
    sideEffects.clearAllSideEffects();
    sideEffects.clearAllDependencies();
    setUseGvn();
  }
  String toString() => 'interceptor on $interceptedClasses';
  accept(HVisitor visitor) => visitor.visitInterceptor(this);
  HInstruction get receiver => inputs[0];
  bool isInterceptor(Compiler compiler) => true;

  int typeCode() => HInstruction.INTERCEPTOR_TYPECODE;
  bool typeEquals(other) => other is HInterceptor;
  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 synthetized 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 {
  Set<ClassElement> interceptedClasses;
  HOneShotInterceptor(Selector selector,
                      List<HInstruction> inputs,
                      TypeMask type,
                      this.interceptedClasses)
      : super(selector, null, inputs, type, true) {
    assert(inputs[0] is HConstant);
    assert(inputs[0].isNull());
  }
  bool isCallOnInterceptor(Compiler compiler) => true;

  String toString() => 'one shot interceptor on $selector';
  accept(HVisitor visitor) => visitor.visitOneShotInterceptor(this);
}

/** An [HLazyStatic] is a static that is initialized lazily at first read. */
class HLazyStatic extends HInstruction {
  final Element element;
  HLazyStatic(this.element, type) : super(<HInstruction>[], type) {
    // TODO(4931): The first access has side-effects, but we afterwards we
    // should be able to GVN.
    sideEffects.setAllSideEffects();
    sideEffects.setDependsOnSomething();
  }

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

  int typeCode() => 30;
  // TODO(4931): can we do better here?
  bool isCodeMotionInvariant() => false;
  bool canThrow() => true;
}

class HStaticStore extends HInstruction {
  Element element;
  HStaticStore(this.element, HInstruction value)
      : super(<HInstruction>[value], const TypeMask.nonNullEmpty()) {
    sideEffects.clearAllSideEffects();
    sideEffects.clearAllDependencies();
    sideEffects.setChangesStaticProperty();
  }
  toString() => 'static store ${element.name}';
  accept(HVisitor visitor) => visitor.visitStaticStore(this);

  int typeCode() => HInstruction.STATIC_STORE_TYPECODE;
  bool typeEquals(other) => other is HStaticStore;
  bool dataEquals(HStaticStore other) => element == other.element;
  bool isJsStatement() => true;
}

class HLiteralList extends HInstruction {
  HLiteralList(List<HInstruction> inputs, TypeMask type) : super(inputs, type);
  toString() => 'literal list';
  accept(HVisitor visitor) => visitor.visitLiteralList(this);
}

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

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

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

  HInstruction getDartReceiver(Compiler compiler) => receiver;
  bool onlyThrowsNSM() => true;
  bool canThrow() => receiver.canBeNull();

  int typeCode() => HInstruction.INDEX_TYPECODE;
  bool typeEquals(HInstruction other) => other is HIndex;
  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 {
  final Selector selector;
  HIndexAssign(HInstruction receiver,
               HInstruction index,
               HInstruction value,
               this.selector)
      : super(<HInstruction>[receiver, index, value],
              const TypeMask.nonNullEmpty()) {
    sideEffects.clearAllSideEffects();
    sideEffects.clearAllDependencies();
    sideEffects.setChangesIndex();
  }
  String toString() => 'index assign operator';
  accept(HVisitor visitor) => visitor.visitIndexAssign(this);

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

  HInstruction getDartReceiver(Compiler compiler) => receiver;
  bool onlyThrowsNSM() => true;
  bool canThrow() => receiver.canBeNull();
}

class HIs extends HInstruction {
  /// A check against a raw type: 'o is int', 'o is A'.
  static const int RAW_CHECK = 0;
  /// A check against a type with type arguments: 'o is List<int>', 'o is C<T>'.
  static const int COMPOUND_CHECK = 1;
  /// A check against a single type variable: 'o is T'.
  static const int VARIABLE_CHECK = 2;

  final DartType typeExpression;
  final int kind;
  final bool useInstanceOf;

  HIs.direct(DartType typeExpression,
             HInstruction expression,
             TypeMask type)
      : this.internal(typeExpression, [expression], RAW_CHECK, type);

  // Pre-verified that the check can be done using 'instanceof'.
  HIs.instanceOf(DartType typeExpression,
                 HInstruction expression,
                 TypeMask type)
      : this.internal(typeExpression, [expression], RAW_CHECK, type,
          useInstanceOf: true);

  HIs.raw(DartType typeExpression,
          HInstruction expression,
          HInterceptor interceptor,
          TypeMask type)
      : this.internal(
            typeExpression, [expression, interceptor], RAW_CHECK, type);

  HIs.compound(DartType typeExpression,
               HInstruction expression,
               HInstruction call,
               TypeMask type)
      : this.internal(typeExpression, [expression, call], COMPOUND_CHECK, type);

  HIs.variable(DartType typeExpression,
               HInstruction expression,
               HInstruction call,
               TypeMask type)
      : this.internal(typeExpression, [expression, call], VARIABLE_CHECK, type);

  HIs.internal(this.typeExpression, List<HInstruction> inputs, this.kind,
      TypeMask type, {bool this.useInstanceOf: false})
      : super(inputs, type) {
    assert(kind >= RAW_CHECK && kind <= VARIABLE_CHECK);
    setUseGvn();
  }

  HInstruction get expression => inputs[0];

  HInstruction get interceptor {
    assert(kind == RAW_CHECK);
    return inputs.length > 1 ? inputs[1] : null;
  }

  HInstruction get checkCall {
    assert(kind == VARIABLE_CHECK || kind == COMPOUND_CHECK);
    return inputs[1];
  }

  bool get isRawCheck => kind == RAW_CHECK;
  bool get isVariableCheck => kind == VARIABLE_CHECK;
  bool get isCompoundCheck => kind == COMPOUND_CHECK;

  accept(HVisitor visitor) => visitor.visitIs(this);

  toString() => "$expression is $typeExpression";

  int typeCode() => HInstruction.IS_TYPECODE;

  bool typeEquals(HInstruction other) => other is HIs;

  bool dataEquals(HIs other) {
    return typeExpression == other.typeExpression
        && kind == other.kind;
  }
}

/**
 * HIsViaInterceptor is a late-stage instruction for a type test that can be
 * done entirely on an interceptor.  It is not a HCheck because the checked
 * input is not one of the inputs.
 */
class HIsViaInterceptor extends HLateInstruction {
  final DartType typeExpression;
   HIsViaInterceptor(this.typeExpression, HInstruction interceptor,
                     TypeMask type)
       : super(<HInstruction>[interceptor], type) {
    setUseGvn();
  }

  HInstruction get interceptor => inputs[0];

  accept(HVisitor visitor) => visitor.visitIsViaInterceptor(this);
  toString() => "$interceptor is $typeExpression";
  int typeCode() => HInstruction.IS_VIA_INTERCEPTOR_TYPECODE;
  bool typeEquals(HInstruction other) => other is HIsViaInterceptor;
  bool dataEquals(HIs other) {
    return typeExpression == other.typeExpression;
  }
}

class HTypeConversion extends HCheck {
  final DartType typeExpression;
  final int kind;
  final Selector receiverTypeCheckSelector;
  final bool contextIsTypeArguments;
  TypeMask checkedType;  // Not final because we refine it.

  static const int CHECKED_MODE_CHECK = 0;
  static const int ARGUMENT_TYPE_CHECK = 1;
  static const int CAST_TYPE_CHECK = 2;
  static const int BOOLEAN_CONVERSION_CHECK = 3;
  static const int RECEIVER_TYPE_CHECK = 4;

  HTypeConversion(this.typeExpression, this.kind,
                  TypeMask type, HInstruction input,
                  [this.receiverTypeCheckSelector])
      : contextIsTypeArguments = false,
        checkedType = type,
        super(<HInstruction>[input], type) {
    assert(!isReceiverTypeCheck || receiverTypeCheckSelector != null);
    assert(typeExpression == null ||
           typeExpression.kind != TypeKind.TYPEDEF);
    sourceElement = input.sourceElement;
  }

  HTypeConversion.withTypeRepresentation(this.typeExpression, this.kind,
                                         TypeMask type, HInstruction input,
                                         HInstruction typeRepresentation)
      : contextIsTypeArguments = false,
        checkedType = type,
        super(<HInstruction>[input, typeRepresentation],type),
        receiverTypeCheckSelector = null {
    assert(typeExpression.kind != TypeKind.TYPEDEF);
    sourceElement = input.sourceElement;
  }

  HTypeConversion.withContext(this.typeExpression, this.kind,
                              TypeMask type, HInstruction input,
                              HInstruction context,
                              {bool this.contextIsTypeArguments})
      : super(<HInstruction>[input, context], type),
        checkedType = type,
        receiverTypeCheckSelector = null {
    assert(typeExpression.kind != TypeKind.TYPEDEF);
    sourceElement = input.sourceElement;
  }

  bool get hasTypeRepresentation {
    return typeExpression.isInterfaceType && inputs.length > 1;
  }
  HInstruction get typeRepresentation => inputs[1];

  bool get hasContext {
    return typeExpression.isFunctionType && inputs.length > 1;
  }
  HInstruction get context => inputs[1];

  HInstruction convertType(Compiler compiler, DartType type, int kind) {
    if (typeExpression == type) return this;
    return super.convertType(compiler, type, kind);
  }

  bool get isCheckedModeCheck {
    return kind == CHECKED_MODE_CHECK
        || kind == BOOLEAN_CONVERSION_CHECK;
  }
  bool get isArgumentTypeCheck => kind == ARGUMENT_TYPE_CHECK;
  bool get isReceiverTypeCheck => kind == RECEIVER_TYPE_CHECK;
  bool get isCastTypeCheck => kind == CAST_TYPE_CHECK;
  bool get isBooleanConversionCheck => kind == BOOLEAN_CONVERSION_CHECK;

  accept(HVisitor visitor) => visitor.visitTypeConversion(this);

  bool isJsStatement() => isControlFlow();
  bool isControlFlow() => isArgumentTypeCheck || isReceiverTypeCheck;

  int typeCode() => HInstruction.TYPE_CONVERSION_TYPECODE;
  bool typeEquals(HInstruction other) => other is HTypeConversion;
  bool isCodeMotionInvariant() => false;

  bool dataEquals(HTypeConversion other) {
    return kind == other.kind
        && typeExpression == other.typeExpression
        && checkedType == other.checkedType
        && receiverTypeCheckSelector == other.receiverTypeCheckSelector;
  }
}

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

  HTypeKnown.pinned(TypeMask knownType, HInstruction input)
      : this.knownType = knownType,
        this._isMovable = false,
        super(<HInstruction>[input], knownType);

  HTypeKnown.witnessed(TypeMask knownType, HInstruction input,
                       HInstruction witness)
      : this.knownType = knownType,
        this._isMovable = true,
        super(<HInstruction>[input, witness], knownType);

  toString() => 'TypeKnown $knownType';
  accept(HVisitor visitor) => visitor.visitTypeKnown(this);

  bool isJsStatement() => false;
  bool isControlFlow() => false;
  bool canThrow() => false;

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

  int typeCode() => HInstruction.TYPE_KNOWN_TYPECODE;
  bool typeEquals(HInstruction other) => other is HTypeKnown;
  bool isCodeMotionInvariant() => true;
  bool get isMovable => _isMovable && useGvn();

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

class HRangeConversion extends HCheck {
  HRangeConversion(HInstruction input, type)
      : super(<HInstruction>[input], type) {
    sourceElement = input.sourceElement;
  }

  bool get isMovable => false;

  accept(HVisitor visitor) => visitor.visitRangeConversion(this);
}

class HStringConcat extends HInstruction {
  final ast.Node node;
  HStringConcat(HInstruction left, HInstruction right, this.node, TypeMask type)
      : super(<HInstruction>[left, right], type) {
    // TODO(sra): Until Issue 9293 is fixed, this false dependency keeps the
    // concats bunched with stringified inputs for much better looking code with
    // fewer temps.
    sideEffects.setDependsOnSomething();
  }

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

  accept(HVisitor visitor) => visitor.visitStringConcat(this);
  toString() => "string concat";
}

/**
 * The part of string interpolation which converts and interpolated expression
 * into a String value.
 */
class HStringify extends HInstruction {
  final ast.Node node;
  HStringify(HInstruction input, this.node, TypeMask type)
      : super(<HInstruction>[input], type) {
    sideEffects.setAllSideEffects();
    sideEffects.setDependsOnSomething();
  }

  accept(HVisitor visitor) => visitor.visitStringify(this);
  toString() => "stringify";
}

/** 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)
      : blocks = new List<HBasicBlock>(),
        backEdges = new List<HBasicBlock>();

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

  // 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;
  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 {
  bool accept(HStatementInformationVisitor visitor);
}


/**
 * Information about an expression-like structure.
 */
abstract class HExpressionInformation extends HBlockInformation {
  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 visitAndOrInfo(HAndOrBlockInformation info);
  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);

  HBasicBlock get start => subGraph.start;
  HBasicBlock get end => subGraph.end;

  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);

  HBasicBlock get start => subExpression.start;
  HBasicBlock get end => subExpression.end;

  HInstruction get conditionExpression => subExpression.conditionExpression;

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

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

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

  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,
                           List<LabelDefinition> labels,
                           {this.isContinue: false}) :
      this.labels = labels, this.target = labels[0].target;

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

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

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

class LoopTypeVisitor extends ast.Visitor {
  const LoopTypeVisitor();
  int visitNode(ast.Node node) => HLoopBlockInformation.NOT_A_LOOP;
  int visitWhile(ast.While node) => HLoopBlockInformation.WHILE_LOOP;
  int visitFor(ast.For node) => HLoopBlockInformation.FOR_LOOP;
  int visitDoWhile(ast.DoWhile node) => HLoopBlockInformation.DO_WHILE_LOOP;
  int visitForIn(ast.ForIn node) => HLoopBlockInformation.FOR_IN_LOOP;
  int visitSwitchStatement(ast.SwitchStatement node) =>
      HLoopBlockInformation.SWITCH_CONTINUE_LOOP;
}

class HLoopBlockInformation implements HStatementInformation {
  static const int WHILE_LOOP = 0;
  static const int FOR_LOOP = 1;
  static const int DO_WHILE_LOOP = 2;
  static const int FOR_IN_LOOP = 3;
  static const int SWITCH_CONTINUE_LOOP = 4;
  static const int NOT_A_LOOP = -1;

  final int 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 == DO_WHILE_LOOP ? body.start : condition.start).isLoopHeader());
  }

  HBasicBlock get start {
    if (initializer != null) return initializer.start;
    if (kind == DO_WHILE_LOOP) {
      return body.start;
    }
    return condition.start;
  }

  HBasicBlock get loopHeader {
    return kind == DO_WHILE_LOOP ? body.start : condition.start;
  }

  HBasicBlock get end {
    if (updates != null) return updates.end;
    if (kind == DO_WHILE_LOOP && condition != null) {
      return condition.end;
    }
    return body.end;
  }

  static int loopType(ast.Node node) {
    return node.accept(const LoopTypeVisitor());
  }

  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);

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

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

class HAndOrBlockInformation implements HExpressionInformation {
  final bool isAnd;
  final HExpressionInformation left;
  final HExpressionInformation right;
  HAndOrBlockInformation(this.isAnd,
                         this.left,
                         this.right);

  HBasicBlock get start => left.start;
  HBasicBlock get end => right.end;

  // We don't currently use HAndOrBlockInformation.
  HInstruction get conditionExpression {
    return null;
  }
  bool accept(HExpressionInformationVisitor visitor) =>
    visitor.visitAndOrInfo(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);

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

  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;

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

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

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

class HReadTypeVariable extends HInstruction {
  /// The type variable being read.
  final TypeVariableType dartType;

  final bool hasReceiver;

  HReadTypeVariable(this.dartType,
                    HInstruction receiver,
                    TypeMask instructionType)
      : hasReceiver = true,
        super(<HInstruction>[receiver], instructionType) {
    setUseGvn();
  }

  HReadTypeVariable.noReceiver(this.dartType,
                               HInstruction typeArgument,
                               TypeMask instructionType)
      : hasReceiver = false,
        super(<HInstruction>[typeArgument], instructionType) {
    setUseGvn();
  }

  accept(HVisitor visitor) => visitor.visitReadTypeVariable(this);

  bool canThrow() => false;

  int typeCode() => HInstruction.READ_TYPE_VARIABLE_TYPECODE;
  bool typeEquals(HInstruction other) => other is HReadTypeVariable;

  bool dataEquals(HReadTypeVariable other) {
    return dartType.element == other.dartType.element
        && hasReceiver == other.hasReceiver;
  }
}

abstract class HRuntimeType extends HInstruction {
  final DartType dartType;

  HRuntimeType(List<HInstruction> inputs,
               this.dartType,
               TypeMask instructionType)
      : super(inputs, instructionType) {
    setUseGvn();
  }

  bool canThrow() => false;

  int typeCode() {
    throw 'abstract method';
  }

  bool typeEquals(HInstruction other) {
    throw 'abstract method';
  }

  bool dataEquals(HRuntimeType other) {
    return dartType == other.dartType;
  }
}

class HFunctionType extends HRuntimeType {
  HFunctionType(List<HInstruction> inputs,
                FunctionType dartType,
                TypeMask instructionType)
      : super(inputs, dartType, instructionType);

  accept(HVisitor visitor) => visitor.visitFunctionType(this);

  int typeCode() => HInstruction.FUNCTION_TYPE_TYPECODE;

  bool typeEquals(HInstruction other) => other is HFunctionType;
}

class HVoidType extends HRuntimeType {
  HVoidType(VoidType dartType, TypeMask instructionType)
      : super(const <HInstruction>[], dartType, instructionType);

  accept(HVisitor visitor) => visitor.visitVoidType(this);

  int typeCode() => HInstruction.VOID_TYPE_TYPECODE;

  bool typeEquals(HInstruction other) => other is HVoidType;
}

class HInterfaceType extends HRuntimeType {
  HInterfaceType(List<HInstruction> inputs,
                 InterfaceType dartType,
                 TypeMask instructionType)
      : super(inputs, dartType, instructionType);

  accept(HVisitor visitor) => visitor.visitInterfaceType(this);

  int typeCode() => HInstruction.INTERFACE_TYPE_TYPECODE;

  bool typeEquals(HInstruction other) => other is HInterfaceType;
}

class HDynamicType extends HRuntimeType {
  HDynamicType(DynamicType dartType, TypeMask instructionType)
      : super(const <HInstruction>[], dartType, instructionType);

  accept(HVisitor visitor) => visitor.visitDynamicType(this);

  int typeCode() => HInstruction.DYNAMIC_TYPE_TYPECODE;

  bool typeEquals(HInstruction other) => other is HDynamicType;
}
