// 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 com.android.tools.r8.code.CmpLong;
import com.android.tools.r8.code.CmpgDouble;
import com.android.tools.r8.code.CmpgFloat;
import com.android.tools.r8.code.CmplDouble;
import com.android.tools.r8.code.CmplFloat;
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.ir.analysis.constant.Bottom;
import com.android.tools.r8.ir.analysis.constant.ConstLatticeElement;
import com.android.tools.r8.ir.analysis.constant.LatticeElement;
import com.android.tools.r8.ir.conversion.DexBuilder;
import com.android.tools.r8.utils.LongInterval;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.StringUtils.BraceType;
import java.util.function.Function;
import org.objectweb.asm.Opcodes;

public class Cmp extends Binop {

  public enum Bias {
    NONE, GT, LT
  }

  private final Bias bias;

  public Cmp(NumericType type, Bias bias, Value dest, Value left, Value right) {
    super(type, dest, left, right);
    this.bias = bias;
  }

  @Override
  public boolean isCommutative() {
    return false;
  }

  @Override
  public void buildDex(DexBuilder builder) {
    com.android.tools.r8.code.Instruction instruction;
    int dest = builder.allocatedRegister(outValue, getNumber());
    int left = builder.allocatedRegister(leftValue(), getNumber());
    int right = builder.allocatedRegister(rightValue(), getNumber());
    switch (type) {
      case DOUBLE:
        assert bias != Bias.NONE;
        if (bias == Bias.GT) {
          instruction = new CmpgDouble(dest, left, right);
        } else {
          assert bias == Bias.LT;
          instruction = new CmplDouble(dest, left, right);
        }
        break;
      case FLOAT:
        assert bias != Bias.NONE;
        if (bias == Bias.GT) {
          instruction = new CmpgFloat(dest, left, right);
        } else {
          assert bias == Bias.LT;
          instruction = new CmplFloat(dest, left, right);
        }
        break;
      case LONG:
        assert bias == Bias.NONE;
        instruction = new CmpLong(dest, left, right);
        break;
      default:
        throw new Unreachable("Unexpected type " + type);
    }
    builder.add(this, instruction);
  }

  private String biasToString(Bias bias) {
    switch (bias) {
      case NONE:
        return "none";
      case GT:
        return "gt";
      case LT:
        return "lt";
      default:
        throw new Unreachable("Unexpected bias " + bias);
    }
  }

  @Override
  public String toString() {
    StringBuilder builder = new StringBuilder();
    builder.append(getClass().getSimpleName());
    builder.append(" (");
    switch (type) {
      case DOUBLE:
        builder.append("double, ");
        builder.append(biasToString(bias));
        break;
      case FLOAT:
        builder.append("float, ");
        builder.append(biasToString(bias));
        break;
      case LONG:
        builder.append("long");
        break;
      default:
        throw new Unreachable("Unexpected type " + type);
    }
    builder.append(")");
    for (int i = builder.length(); i < 20; i++) {
      builder.append(" ");
    }
    if (outValue != null) {
      builder.append(outValue);
      builder.append(" <- ");
    }
    StringUtils.append(builder, inValues, ", ", BraceType.NONE);
    return builder.toString();
  }

  @Override
  public boolean identicalNonValueNonPositionParts(Instruction other) {
    return other.asCmp().bias == bias;
  }

  @Override
  public int compareNonValueParts(Instruction other) {
    return bias.ordinal() - other.asCmp().bias.ordinal();
  }

  @Override
  public int maxInValueRegister() {
    return Constants.U8BIT_MAX;
  }

  @Override
  public int maxOutValueRegister() {
    return Constants.U8BIT_MAX;
  }

  private boolean nonOverlapingRanges() {
    return type == NumericType.LONG
        && leftValue().hasValueRange()
        && rightValue().hasValueRange()
        && leftValue().getValueRange().doesntOverlapWith(rightValue().getValueRange());
  }

  @Override
  public boolean canBeFolded() {
    return (leftValue().isConstNumber() && rightValue().isConstNumber()) || nonOverlapingRanges();
  }

  @Override
  public LatticeElement evaluate(IRCode code, Function<Value, LatticeElement> getLatticeElement) {
    LatticeElement leftLattice = getLatticeElement.apply(leftValue());
    LatticeElement rightLattice = getLatticeElement.apply(rightValue());
    if (leftLattice.isConst() && rightLattice.isConst()) {
      ConstNumber leftConst = leftLattice.asConst().getConstNumber();
      ConstNumber rightConst = rightLattice.asConst().getConstNumber();
      int result;
      if (type == NumericType.LONG) {
        result = Integer.signum(Long.compare(leftConst.getLongValue(), rightConst.getLongValue()));
      } else if (type == NumericType.FLOAT) {
        float left = leftConst.getFloatValue();
        float right = rightConst.getFloatValue();
        if (Float.isNaN(left) || Float.isNaN(right)) {
          result = bias == Bias.GT ? 1 : -1;
        } else {
          result = (int) Math.signum(left - right);
        }
      } else {
        assert type == NumericType.DOUBLE;
        double left = leftConst.getDoubleValue();
        double right = rightConst.getDoubleValue();
        if (Double.isNaN(left) || Double.isNaN(right)) {
          result = bias == Bias.GT ? 1 : -1;
        } else {
          result = (int) Math.signum(left - right);
        }
      }
      Value value = code.createValue(ValueType.INT, getLocalInfo());
      ConstNumber newConst = new ConstNumber(value, result);
      return new ConstLatticeElement(newConst);
    } else if (leftLattice.isValueRange() && rightLattice.isConst()) {
      Value leftValueRange = leftLattice.asConstRange().getConstRange();
      ConstNumber rightConst = rightLattice.asConst().getConstNumber();
      return buildLatticeResult(code, leftValueRange.getValueRange(),
          rightConst.outValue().getValueRange());
    } else if (leftLattice.isConst() && rightLattice.isValueRange()) {
      Value rigthValueRange = rightLattice.asConstRange().getConstRange();
      ConstNumber leftConst = leftLattice.asConst().getConstNumber();
      return buildLatticeResult(code, leftConst.outValue().getValueRange(),
          rigthValueRange.getValueRange());
    } else if (leftLattice.isValueRange() && rightLattice.isValueRange()) {
      Value rigthValueRange = rightLattice.asConstRange().getConstRange();
      Value leftValueRange = leftLattice.asConstRange().getConstRange();
      return buildLatticeResult(code, leftValueRange.getValueRange(),
          rigthValueRange.getValueRange());
    }
    return Bottom.getInstance();
  }

  private LatticeElement buildLatticeResult(IRCode code, LongInterval leftRange,
      LongInterval rightRange) {
    if (leftRange.overlapsWith(rightRange)) {
      return Bottom.getInstance();
    }
    int result = Integer.signum(Long.compare(leftRange.getMin(), rightRange.getMin()));
    Value value = code.createValue(ValueType.INT, getLocalInfo());
    ConstNumber newConst = new ConstNumber(value, result);
    return new ConstLatticeElement(newConst);
  }

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

  @Override
  public Cmp asCmp() {
    return this;
  }

  @Override
  int getCfOpcode() {
    switch (type) {
      case LONG:
        assert bias == Bias.NONE;
        return Opcodes.LCMP;
      case FLOAT:
        return bias == Bias.GT ? Opcodes.FCMPG : Opcodes.FCMPL;
      case DOUBLE:
        return bias == Bias.GT ? Opcodes.DCMPG : Opcodes.DCMPL;
      default:
        throw new Unreachable("Unexpected cmp type: " + type);
    }
  }
}
