// 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.Instruction;
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 java.util.function.Function;

public abstract class ArithmeticBinop extends Binop {

  public ArithmeticBinop(NumericType type, Value dest, Value left, Value right) {
    super(type, dest, left, right);
  }

  public abstract com.android.tools.r8.code.Instruction CreateInt(int dest, int left, int right);

  public abstract Instruction CreateLong(int dest, int left, int right);

  public abstract Instruction CreateFloat(int dest, int left, int right);

  public abstract Instruction CreateDouble(int dest, int left, int right);

  public abstract Instruction CreateInt2Addr(int left, int right);

  public abstract Instruction CreateLong2Addr(int left, int right);

  public abstract Instruction CreateFloat2Addr(int left, int right);

  public abstract Instruction CreateDouble2Addr(int left, int right);

  public abstract Instruction CreateIntLit8(int dest, int left, int constant);

  public abstract Instruction CreateIntLit16(int dest, int left, int constant);

  @Override
  public boolean canBeFolded() {
    return (type == NumericType.INT || type == NumericType.LONG || type == NumericType.FLOAT
            || type == NumericType.DOUBLE)
        && leftValue().isConstant() && rightValue().isConstant();
  }

  @Override
  public boolean needsValueInRegister(Value value) {
    assert !isSub();  // Constants in instructions for sub must be handled in subclass Sub.
    // Always require the left value in a register. If left and right are the same value, then
    // both will use its register.
    if (value == leftValue()) {
      return true;
    }
    assert value == rightValue();
    return !fitsInDexInstruction(value);
  }

  @Override
  public void buildDex(DexBuilder builder) {
    // Method needsValueInRegister ensures that left value has an allocated register.
    int left = builder.allocatedRegister(leftValue(), getNumber());
    int dest = builder.allocatedRegister(outValue, getNumber());
    Instruction instruction = null;
    if (isTwoAddr(builder.getRegisterAllocator())) {
      int right = builder.allocatedRegister(rightValue(), getNumber());
      if (left != dest) {
        assert isCommutative();
        assert right == dest;
        right = left;
      }
      switch (type) {
        case DOUBLE:
          instruction = CreateDouble2Addr(dest, right);
          break;
        case FLOAT:
          instruction = CreateFloat2Addr(dest, right);
          break;
        case INT:
          instruction = CreateInt2Addr(dest, right);
          break;
        case LONG:
          instruction = CreateLong2Addr(dest, right);
          break;
        default:
          throw new Unreachable("Unexpected numeric type " + type.name());
      }
    } else if (!needsValueInRegister(rightValue())) {
      assert !isSub();  // Constants in instructions for sub must be handled in subclass Sub.
      assert fitsInDexInstruction(rightValue());
      ConstNumber right = rightValue().getConstInstruction().asConstNumber();
      if (right.is8Bit()) {
        instruction = CreateIntLit8(dest, left, right.getIntValue());
      } else {
        assert right.is16Bit();
        instruction = CreateIntLit16(dest, left, right.getIntValue());
      }
    } else {
      int right = builder.allocatedRegister(rightValue(), getNumber());
      switch (type) {
        case DOUBLE:
          instruction = CreateDouble(dest, left, right);
          break;
        case FLOAT:
          instruction = CreateFloat(dest, left, right);
          break;
        case INT:
          instruction = CreateInt(dest, left, right);
          break;
        case LONG:
          instruction = CreateLong(dest, left, right);
          break;
        default:
          throw new Unreachable("Unexpected numeric type " + type.name());
      }
    }
    builder.add(this, instruction);
  }

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

  @Override
  public ArithmeticBinop asArithmeticBinop() {
    return this;
  }

  @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();
      ConstNumber newConst;
      if (type == NumericType.INT) {
        int result = foldIntegers(leftConst.getIntValue(), rightConst.getIntValue());
        Value value = code.createValue(ValueType.INT, getLocalInfo());
        newConst = new ConstNumber(value, result);
      } else if (type == NumericType.LONG) {
        long result = foldLongs(leftConst.getLongValue(), rightConst.getLongValue());
        Value value = code.createValue(ValueType.LONG, getLocalInfo());
        newConst = new ConstNumber(value, result);
      } else if (type == NumericType.FLOAT) {
        float result = foldFloat(leftConst.getFloatValue(), rightConst.getFloatValue());
        Value value = code.createValue(ValueType.FLOAT, getLocalInfo());
        newConst = new ConstNumber(value, Float.floatToIntBits(result));
      } else {
        assert type == NumericType.DOUBLE;
        double result = foldDouble(leftConst.getDoubleValue(), rightConst.getDoubleValue());
        Value value = code.createValue(ValueType.DOUBLE, getLocalInfo());
        newConst = new ConstNumber(value, Double.doubleToLongBits(result));
      }
      return new ConstLatticeElement(newConst);
    }
    return Bottom.getInstance();
  }
}
