// Copyright (c) 2016, 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 static com.android.tools.r8.dex.Constants.U4BIT_MAX;
import static com.android.tools.r8.dex.Constants.U8BIT_MAX;

import com.android.tools.r8.cf.LoadStoreHelper;
import com.android.tools.r8.cf.code.CfIf;
import com.android.tools.r8.cf.code.CfIfCmp;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.ir.conversion.CfBuilder;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.utils.CfgPrinter;
import java.util.List;

public class If extends JumpInstruction {

  public enum Type {
    EQ, GE, GT, LE, LT, NE;

    // Returns the comparison type if the operands are swapped.
    public Type forSwappedOperands() {
      switch (this) {
        case EQ:
        case NE:
          return this;
        case GE:
          return Type.LE;
        case GT:
          return Type.LT;
        case LE:
          return Type.GE;
        case LT:
          return Type.GT;
        default:
          throw new Unreachable("Unknown if condition type.");
      }
    }

    public Type inverted() {
      switch (this) {
        case EQ:
          return Type.NE;
        case GE:
          return Type.LT;
        case GT:
          return Type.LE;
        case LE:
          return Type.GT;
        case LT:
          return Type.GE;
        case NE:
          return Type.EQ;
        default:
          throw new Unreachable("Unknown if condition type.");
      }
    }
  }

  private Type type;

  public If(Type type, Value value) {
    super(null, value);
    this.type = type;
  }

  public If(Type type, List<Value> values) {
    super(null, values);
    this.type = type;
  }

  public boolean isZeroTest() {
    return inValues.size() == 1;
  }

  public Type getType() {
    return type;
  }

  public void invert() {
    BasicBlock tmp = getTrueTarget();
    setTrueTarget(fallthroughBlock());
    setFallthroughBlock(tmp);
    type = type.inverted();
  }

  public BasicBlock getTrueTarget() {
    assert getBlock().exit() == this;
    List<BasicBlock> successors = getBlock().getSuccessors();
    assert successors.size() >= 2;
    return successors.get(successors.size() - 2);
  }

  public void setTrueTarget(BasicBlock block) {
    assert getBlock().exit() == this;
    List<BasicBlock> successors = getBlock().getSuccessors();
    assert successors.size() >= 2;
    successors.set(successors.size() - 2, block);
  }

  @Override
  public BasicBlock fallthroughBlock() {
    assert getBlock().exit() == this;
    List<BasicBlock> successors = getBlock().getSuccessors();
    assert successors.size() >= 2;
    return successors.get(successors.size() - 1);
  }

  @Override
  public void setFallthroughBlock(BasicBlock block) {
    List<BasicBlock> successors = getBlock().getSuccessors();
    successors.set(successors.size() - 1, block);
  }

  @Override
  public void buildDex(DexBuilder builder) {
    builder.addIf(this);
  }

  // Estimated size of the resulting dex instruction in code units.
  public static int estimatedDexSize() {
    return 2;
  }

  @Override
  public String toString() {
    return super.toString()
        + " "
        + type
        + " block "
        + getTrueTarget().getNumberAsString()
        + " (fallthrough "
        + fallthroughBlock().getNumberAsString()
        + ")";
  }

  @Override
  public int maxInValueRegister() {
    return isZeroTest() ? U8BIT_MAX : U4BIT_MAX;
  }

  @Override
  public int maxOutValueRegister() {
    assert false : "If instructions define no values.";
    return 0;
  }

  @Override
  public void print(CfgPrinter printer) {
    super.print(printer);
    printer.append(" B").append(getTrueTarget().getNumber());
  }

  @Override
  public boolean identicalNonValueNonPositionParts(Instruction other) {
    if (!other.isIf()) {
      return false;
    }
    If o = other.asIf();
    return o.getTrueTarget() == getTrueTarget()
        && o.fallthroughBlock() == fallthroughBlock()
        && o.type == type;
  }

  @Override
  public int compareNonValueParts(Instruction other) {
    assert other.isIf();
    assert false : "Not supported";
    return 0;
  }

  public BasicBlock targetFromCondition(long cond) {
    switch (type) {
      case EQ:
        return cond == 0 ? getTrueTarget() : fallthroughBlock();
      case NE:
        return cond != 0 ? getTrueTarget() : fallthroughBlock();
      case GE:
        return cond >= 0 ? getTrueTarget() : fallthroughBlock();
      case GT:
        return cond > 0 ? getTrueTarget() : fallthroughBlock();
      case LE:
        return cond <= 0 ? getTrueTarget() : fallthroughBlock();
      case LT:
        return cond < 0 ? getTrueTarget() : fallthroughBlock();
    }
    throw new Unreachable("Unexpected condition type " + type);
  }

  @Override
  public boolean isIf() {
    return true;
  }

  @Override
  public If asIf() {
    return this;
  }

  @Override
  public void insertLoadAndStores(InstructionListIterator it, LoadStoreHelper helper) {
    helper.loadInValues(this, it);
  }

  @Override
  public void buildCf(CfBuilder builder) {
    if (inValues.size() == 1) {
      builder.add(new CfIf(type, inValues.get(0).type, builder.getLabel(getTrueTarget())));
      return;
    }
    assert inValues.size() == 2;
    assert inValues.get(0).type == inValues.get(1).type;
    builder.add(new CfIfCmp(type, inValues.get(0).type, builder.getLabel(getTrueTarget())));
  }
}
