// Copyright (c) 2017, the R8 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.

package com.android.tools.r8.ir.code;

import com.android.tools.r8.errors.Unimplemented;
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DebugLocalInfo;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.InternalOptions;
import com.google.common.collect.Sets;
import java.util.ListIterator;
import java.util.Set;

public interface InstructionListIterator
    extends InstructionIterator, ListIterator<Instruction>, PreviousUntilIterator<Instruction> {

  void addThrowingInstructionToPossiblyThrowingBlock(
      IRCode code,
      ListIterator<BasicBlock> blockIterator,
      Instruction instruction,
      InternalOptions options);

  default void addBefore(Instruction instruction) {
    previous();
    add(instruction);
    next();
  }

  /** See {@link #replaceCurrentInstruction(Instruction, Set)}. */
  default void replaceCurrentInstruction(Instruction newInstruction) {
    replaceCurrentInstruction(newInstruction, null);
  }

  /**
   * Replace the current instruction (aka the {@link Instruction} returned by the previous call to
   * {@link #next} with the passed in <code>newInstruction</code>.
   *
   * <p>The current instruction will be completely detached from the instruction stream with uses of
   * its in-values removed.
   *
   * <p>If the current instruction produces an out-value the new instruction must also produce an
   * out-value, and all uses of the current instructions out-value will be replaced by the new
   * instructions out-value.
   *
   * <p>The debug information of the current instruction will be attached to the new instruction.
   *
   * @param newInstruction the instruction to insert instead of the current.
   * @param affectedValues if non-null, all users of the out value will be added to this set.
   */
  void replaceCurrentInstruction(Instruction newInstruction, Set<Value> affectedValues);

  // Do not show a deprecation warning for InstructionListIterator.remove().
  @SuppressWarnings("deprecation")
  @Override
  void remove();

  // Removes the current instruction, even if it has an out-value that is used.
  default void removeInstructionIgnoreOutValue() {
    throw new Unimplemented();
  }

  /**
   * Safe removal function that will insert a DebugLocalRead to take over the debug values if any
   * are associated with the current instruction.
   */
  void removeOrReplaceByDebugLocalRead();

  default boolean hasInsertionPosition() {
    return false;
  }

  default void setInsertionPosition(Position position) {
    // Intentionally empty.
  }

  default void unsetInsertionPosition() {
    // Intentionally empty.
  }

  default Value insertConstNullInstruction(IRCode code, InternalOptions options) {
    return insertConstNumberInstruction(code, options, 0, TypeElement.getNull());
  }

  default Value insertConstIntInstruction(IRCode code, InternalOptions options, int value) {
    return insertConstNumberInstruction(code, options, value, TypeElement.getInt());
  }

  // This method can be used for any numeric constant, but also for null (value 0, null type).
  Value insertConstNumberInstruction(
      IRCode code, InternalOptions options, long value, TypeElement type);

  Value insertConstStringInstruction(AppView<?> appView, IRCode code, DexString value);

  boolean replaceCurrentInstructionByNullCheckIfPossible(AppView<?> appView, ProgramMethod context);

  boolean replaceCurrentInstructionByInitClassIfPossible(
      AppView<AppInfoWithLiveness> appView, IRCode code, DexType type);

  void replaceCurrentInstructionWithConstClass(
      AppView<?> appView, IRCode code, DexType type, DebugLocalInfo localInfo);

  void replaceCurrentInstructionWithConstInt(IRCode code, int value);

  void replaceCurrentInstructionWithConstString(AppView<?> appView, IRCode code, DexString value);

  default void replaceCurrentInstructionWithConstString(
      AppView<?> appView, IRCode code, String value) {
    replaceCurrentInstructionWithConstString(
        appView, code, appView.dexItemFactory().createString(value));
  }

  void replaceCurrentInstructionWithStaticGet(
      AppView<?> appView, IRCode code, DexField field, Set<Value> affectedValues);

  void replaceCurrentInstructionWithThrow(
      AppView<?> appView,
      IRCode code,
      ListIterator<BasicBlock> blockIterator,
      Value exceptionValue,
      Set<BasicBlock> blocksToRemove,
      Set<Value> affectedValues);

  /**
   * Replace the current instruction with null throwing instructions.
   *
   * @param appView with hierarchy info through which we can test if the guard is subtype of NPE.
   * @param code the IR code for the block this iterator originates from.
   * @param blockIterator basic block iterator used to iterate the blocks.
   * @param blocksToRemove set passed where blocks that were detached from the graph, but not
   *     removed yet are added. When inserting `throw null`, catch handlers whose guard does not
   *     catch NPE will be removed, but not yet removed using the passed block <code>blockIterator
   *     </code>. When iterating using <code>blockIterator</code> after then method returns the
   *     blocks in this set must be skipped when iterating with the active <code>blockIterator
   *     </code> and ultimately removed.
   * @param affectedValues set passed where values depending on detached blocks will be added.
   */
  void replaceCurrentInstructionWithThrowNull(
      AppView<? extends AppInfoWithClassHierarchy> appView,
      IRCode code,
      ListIterator<BasicBlock> blockIterator,
      Set<BasicBlock> blocksToRemove,
      Set<Value> affectedValues);

  /**
   * Split the block into two blocks at the point of the {@link ListIterator} cursor. The existing
   * block will have all the instructions before the cursor, and the new block all the instructions
   * after the cursor.
   *
   * <p>If the current block has catch handlers these catch handlers will be attached to the block
   * containing the throwing instruction after the split.
   *
   * @param code the IR code for the block this iterator originates from.
   * @param blockIterator basic block iterator used to iterate the blocks. This must be positioned
   *     just after the block for which this is the instruction iterator. After this method returns
   *     it will be positioned just after the basic block returned. Calling {@link #remove} without
   *     further navigation will remove that block.
   * @param keepCatchHandlers whether to keep catch handlers on the original block.
   * @return Returns the new block with the instructions after the cursor.
   */
  BasicBlock split(IRCode code, ListIterator<BasicBlock> blockIterator, boolean keepCatchHandlers);

  default BasicBlock split(IRCode code, ListIterator<BasicBlock> blockIterator) {
    return split(code, blockIterator, hasPrevious() && peekPrevious().instructionTypeCanThrow());
  }

  default BasicBlock split(IRCode code) {
    return split(code, null);
  }

  BasicBlock splitCopyCatchHandlers(
      IRCode code, ListIterator<BasicBlock> blockIterator, InternalOptions options);

  /**
   * Split the block into three blocks. The first split is at the point of the {@link ListIterator}
   * cursor and the second split is <code>instructions</code> after the cursor. The existing
   * block will have all the instructions before the cursor, and the two new blocks all the
   * instructions after the cursor.
   *
   * If the current block have catch handlers these catch handlers will be attached to the block
   * containing the throwing instruction after the split.
   *
   * @param code the IR code for the block this iterator originates from.
   * @param instructions the number of instructions to include in the second block.
   * @param blockIterator basic block iterator used to iterate the blocks. This must be positioned
   * just after the block for this is the instruction iterator. After this method returns it will be
   * positioned just after the second block inserted. Calling {@link #remove} without further
   * navigation will remove that block.
   * @return Returns the new block with the instructions after the cursor.
   */
  // TODO(sgjesse): Refactor to avoid the need for passing code and blockIterator.
  BasicBlock split(IRCode code, int instructions, ListIterator<BasicBlock> blockIterator);

  /**
   * See {@link #split(IRCode, int, ListIterator)}.
   */
  default BasicBlock split(IRCode code, int instructions) {
    return split(code, instructions, null);
  }

  /**
   * Inline the code in {@code inlinee} into {@code code}, replacing the invoke instruction at the
   * position after the cursor.
   *
   * <p>The instruction at the position after cursor must be an invoke that matches the signature
   * for the code in {@code inlinee}.
   *
   * <p>With one exception (see below) both the calling code and the inlinee can have catch
   * handlers.
   *
   * <p><strong>EXCEPTION:</strong> If the invoke instruction is covered by catch handlers, and the
   * code for {@code inlinee} always throws (does not have a normal return) inlining is currently
   * <strong>NOT</strong> supported.
   *
   * @param appView {@link AppView} to retrieve class definition.
   * @param code the IR code for the block this iterator originates from.
   * @param inlinee the IR code for the block this iterator originates from.
   * @param blockIterator basic block iterator used to iterate the blocks. This must be positioned
   *     just after the block for which this is the instruction iterator. After this method returns
   *     it will be positioned just after the basic block returned.
   * @param blocksToRemove list passed where blocks that were detached from the graph, but not
   *     removed are added. When inlining an inlinee that always throws blocks in the <code>code
   *     </code> can be detached, and not simply removed using the passed <code>blockIterator
   *     </code>. When iterating using <code>blockIterator</code> after then method returns the
   *     blocks in this list must be skipped when iterating with the active <code>blockIterator
   *     </code> and ultimately removed.
   * @param downcast tells the inliner to issue a check cast operation.
   * @return the basic block with the instructions right after the inlining. This can be a block
   *     which can also be in the <code>blocksToRemove</code> list.
   */
  // TODO(sgjesse): Refactor to avoid the need for passing code.
  // TODO(sgjesse): Refactor to avoid the need for passing blocksToRemove.
  // TODO(sgjesse): Maybe don't return a BasicBlock, as it can be in blocksToRemove.
  // TODO(sgjesse): Maybe find a better place for this method.
  // TODO(sgjesse): Support inlinee with throwing instructions for invokes with existing handlers.
  BasicBlock inlineInvoke(
      AppView<?> appView,
      IRCode code,
      IRCode inlinee,
      ListIterator<BasicBlock> blockIterator,
      Set<BasicBlock> blocksToRemove,
      DexType downcast);

  /** See {@link #inlineInvoke(AppView, IRCode, IRCode, ListIterator, Set, DexType)}. */
  default BasicBlock inlineInvoke(AppView<?> appView, IRCode code, IRCode inlinee) {
    Set<BasicBlock> blocksToRemove = Sets.newIdentityHashSet();
    BasicBlock result = inlineInvoke(appView, code, inlinee, null, blocksToRemove, null);
    code.removeBlocks(blocksToRemove);
    return result;
  }
}
