// Copyright (c) 2021, 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.desugar.records;

import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.FieldResolutionResult;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.code.ArrayPut;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.ConstNumber;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
import com.android.tools.r8.ir.code.InstructionListIterator;
import com.android.tools.r8.ir.code.MemberType;
import com.android.tools.r8.ir.code.NewArrayEmpty;
import com.android.tools.r8.ir.code.Position;
import com.android.tools.r8.ir.code.RecordFieldValues;
import com.android.tools.r8.ir.code.Value;
import com.android.tools.r8.ir.conversion.IRConverter;
import com.android.tools.r8.ir.optimize.info.OptimizationFeedbackIgnore;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.utils.Timing;
import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;

/** Used to shrink record field arrays in dex compilations */
public class RecordFieldValuesRewriter {

  private final AppView<AppInfoWithLiveness> appView;
  private final IRConverter irConverter;

  public static RecordFieldValuesRewriter create(AppView<AppInfoWithLiveness> appView) {
    if (appView.enableWholeProgramOptimizations()
        && appView.options().isGeneratingDex()
        && appView.options().testing.enableRecordModeling) {
      return new RecordFieldValuesRewriter(appView);
    }
    return null;
  }

  private RecordFieldValuesRewriter(AppView<AppInfoWithLiveness> appView) {
    this.appView = appView;
    irConverter = new IRConverter(appView, Timing.empty());
  }

  // Called after final tree shaking, prune and minify field names and field values.
  // At least one instruction is a newRecordFieldArray.
  public void rewriteRecordFieldValues() {
    for (DexMethod recordFieldValuesReference : appView.appInfo().recordFieldValuesReferences) {
      DexClass dexClass =
          appView.contextIndependentDefinitionFor(recordFieldValuesReference.getHolderType());
      assert dexClass.isProgramClass();
      ProgramMethod programMethod =
          dexClass.asProgramClass().lookupProgramMethod(recordFieldValuesReference);
      assert programMethod != null;
      rewriteRecordFieldValues(programMethod);
    }
  }

  public void rewriteRecordFieldValues(ProgramMethod programMethod) {
    IRCode irCode =
        programMethod
            .getDefinition()
            .getCode()
            .buildIR(programMethod, appView, programMethod.getOrigin());
    boolean done = false;
    ListIterator<BasicBlock> blockIterator = irCode.listIterator();
    while (blockIterator.hasNext()) {
      BasicBlock block = blockIterator.next();
      InstructionListIterator iterator = block.listIterator(irCode);
      while (iterator.hasNext()) {
        Instruction instruction = iterator.next();
        if (instruction.isRecordFieldValues()) {
          rewriteRecordFieldArray(
              instruction.asRecordFieldValues(), irCode, blockIterator, iterator);
          done = true;
        }
      }
    }
    assert done;
    irConverter.removeDeadCodeAndFinalizeIR(
        irCode, OptimizationFeedbackIgnore.getInstance(), Timing.empty());
  }

  public void rewriteRecordFieldArray(
      RecordFieldValues recordFieldArray,
      IRCode code,
      ListIterator<BasicBlock> blockIterator,
      InstructionListIterator iterator) {
    List<Value> newInValues = computePresentFields(recordFieldArray, code.context());
    ConstNumber arrayLengthIntConstant = code.createIntConstant(newInValues.size());
    Position constantPosition =
        appView.options().debug ? Position.none() : recordFieldArray.getPosition();
    arrayLengthIntConstant.setPosition(constantPosition);
    iterator.previous();
    iterator.add(arrayLengthIntConstant);
    iterator.next();
    NewArrayEmpty newArrayEmpty =
        new NewArrayEmpty(
            recordFieldArray.outValue(),
            arrayLengthIntConstant.outValue(),
            appView.dexItemFactory().objectArrayType);
    newArrayEmpty.setPosition(recordFieldArray.getPosition());
    iterator.replaceCurrentInstruction(newArrayEmpty);
    for (int i = 0; i < newInValues.size(); i++) {
      ConstNumber intConstantI = code.createIntConstant(i);
      intConstantI.setPosition(constantPosition);
      iterator.add(intConstantI);
      ArrayPut arrayPut =
          new ArrayPut(
              MemberType.OBJECT,
              newArrayEmpty.outValue(),
              intConstantI.outValue(),
              newInValues.get(i));
      iterator.add(arrayPut);
      arrayPut.setPosition(recordFieldArray.getPosition());
    }
    if (newArrayEmpty.getBlock().hasCatchHandlers()) {
      splitIfCatchHandlers(code, newArrayEmpty.getBlock(), blockIterator);
    }
  }

  private void splitIfCatchHandlers(
      IRCode code,
      BasicBlock blockWithIncorrectThrowingInstructions,
      ListIterator<BasicBlock> blockIterator) {
    InstructionListIterator instructionsIterator =
        blockWithIncorrectThrowingInstructions.listIterator(code);
    BasicBlock currentBlock = blockWithIncorrectThrowingInstructions;
    while (currentBlock != null && instructionsIterator.hasNext()) {
      Instruction throwingInstruction =
          instructionsIterator.nextUntil(Instruction::instructionTypeCanThrow);
      BasicBlock nextBlock;
      if (throwingInstruction != null) {
        nextBlock = instructionsIterator.split(code, blockIterator);
        // Back up to before the split before inserting catch handlers.
        blockIterator.previous();
        nextBlock.copyCatchHandlers(code, blockIterator, currentBlock, appView.options());
        BasicBlock b = blockIterator.next();
        assert b == nextBlock;
        // Switch iteration to the split block.
        instructionsIterator = nextBlock.listIterator(code);
        currentBlock = nextBlock;
      } else {
        assert !instructionsIterator.hasNext();
        instructionsIterator = null;
        currentBlock = null;
      }
    }
  }

  private List<Value> computePresentFields(
      RecordFieldValues recordFieldValues, ProgramMethod context) {
    List<Value> inValues = recordFieldValues.inValues();
    DexField[] fields = recordFieldValues.getFields();
    assert inValues.size() == fields.length;
    List<Value> newInValues = new ArrayList<>();
    for (int index = 0; index < fields.length; index++) {
      FieldResolutionResult resolution =
          appView
              .appInfo()
              .resolveField(appView.graphLens().getRenamedFieldSignature(fields[index]), context);
      if (resolution.isSingleFieldResolutionResult()) {
        newInValues.add(inValues.get(index));
      }
    }
    return newInValues;
  }
}
