// Copyright (c) 2023, 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.lightir;

import com.android.tools.r8.graph.DebugLocalInfo;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.Phi;
import com.android.tools.r8.ir.code.Phi.RegisterReadType;
import com.android.tools.r8.ir.code.Value;
import it.unimi.dsi.fastutil.objects.Reference2IntMap;
import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap;
import java.util.function.Function;
import java.util.function.IntFunction;

/** Strategy encoding phi values as instructions in the LIR instruction stream. */
public class PhiInInstructionsStrategy extends LirStrategy<Value, Integer> {

  @Override
  public LirEncodingStrategy<Value, Integer> getEncodingStrategy() {
    return new EncodingStrategy();
  }

  @Override
  public LirDecodingStrategy<Value, Integer> getDecodingStrategy(LirCode<Integer> code) {
    return new DecodingStrategy(code);
  }

  private static class EncodingStrategy extends LirEncodingStrategy<Value, Integer> {

    // EV == Integer and its definition is equal to its shifted instruction index.
    // The conversion for EV to its int-valued reference is determined by the 'valueStrategy'.

    private final LirSsaValueStrategy<Integer> referenceStrategy = LirSsaValueStrategy.get();
    private final Reference2IntMap<Value> values = new Reference2IntOpenHashMap<>();
    private final Reference2IntMap<BasicBlock> blocks = new Reference2IntOpenHashMap<>();

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

    @Override
    public void defineBlock(BasicBlock block, int index) {
      assert !blocks.containsKey(block);
      blocks.put(block, index);
    }

    @Override
    public Integer defineValue(Value value, int index) {
      values.put(value, index);
      return index;
    }

    @Override
    public boolean verifyValueIndex(Value value, int expectedIndex) {
      assert expectedIndex == values.getInt(value);
      return true;
    }

    @Override
    public Integer getEncodedValue(Value value) {
      return values.getInt(value);
    }

    @Override
    public int getBlockIndex(BasicBlock block) {
      assert blocks.containsKey(block);
      return blocks.getInt(block);
    }

    @Override
    public LirStrategyInfo<Integer> getStrategyInfo() {
      return new LirStrategyInfo<Integer>() {
        @Override
        public LirSsaValueStrategy<Integer> getReferenceStrategy() {
          return referenceStrategy;
        }
      };
    }
  }

  private static class DecodingStrategy extends LirDecodingStrategy<Value, Integer> {

    private final Value[] values;

    DecodingStrategy(LirCode<Integer> code) {
      values = new Value[code.getArgumentCount() + code.getInstructionCount()];
    }

    @Override
    public Value getValue(Integer encodedValue, LirStrategyInfo<Integer> strategyInfo) {
      int index = encodedValue;
      Value value = values[index];
      if (value == null) {
        value = new Value(index, TypeElement.getBottom(), null);
        values[index] = value;
      }
      return value;
    }

    @Override
    public Value getValueDefinitionForInstructionIndex(
        int index, TypeElement type, Function<Integer, DebugLocalInfo> getLocalInfo) {
      DebugLocalInfo localInfo = getLocalInfo.apply(index);
      Value value = values[index];
      if (value == null) {
        value = new Value(index, type, localInfo);
        values[index] = value;
      } else {
        value.setType(type);
        if (localInfo != null) {
          if (!value.hasLocalInfo()) {
            value.setLocalInfo(localInfo);
          }
          assert localInfo == value.getLocalInfo();
        }
      }
      return value;
    }

    @Override
    public Phi getPhiDefinitionForInstructionIndex(
        int valueIndex,
        IntFunction<BasicBlock> getBlock,
        TypeElement type,
        Function<Integer, DebugLocalInfo> getLocalInfo,
        LirStrategyInfo<Integer> strategyInfo) {
      BasicBlock block = getBlock.apply(valueIndex);
      DebugLocalInfo localInfo = getLocalInfo.apply(valueIndex);
      Phi phi = new Phi(valueIndex, block, type, localInfo, RegisterReadType.NORMAL);
      Value value = values[valueIndex];
      if (value != null) {
        // A fake ssa value has already been created, replace the users by the actual phi.
        // TODO(b/225838009): We could consider encoding the value type as a bit in the value index
        //  and avoid the overhead of replacing users at phi-definition time.
        assert !value.isPhi();
        value.replaceUsers(phi);
      }
      values[valueIndex] = phi;
      return phi;
    }
  }
}
