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

import static org.junit.Assert.assertTrue;

import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.cf.code.CfInstruction;
import com.android.tools.r8.cf.code.CfInvoke;
import com.android.tools.r8.cf.code.CfLabel;
import com.android.tools.r8.cf.code.CfLoad;
import com.android.tools.r8.cf.code.CfStackInstruction;
import com.android.tools.r8.graph.CfCode;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Instruction;
import com.android.tools.r8.utils.StringUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
import java.util.List;
import java.util.ListIterator;
import org.junit.Test;

/**
 * This tests that we produce valid code when having normal-flow with exceptional edges in blocks.
 * We might perform optimizations that add operations (dup, swap, etc.) before and after
 * instructions that lie on the boundary of the exception table that is generated for a basic block.
 * If live-ranges are minimized this could produce VerifyErrors.
 */
public class TryRangeTestRunner extends TestBase {

  @Test
  public void testRegisterAllocationLimitTrailingRange() throws Exception {
    testForR8(Backend.CF)
        .addProgramClasses(TryRangeTest.class)
        .addKeepMainRule(TryRangeTest.class)
        .setMode(CompilationMode.RELEASE)
        .minification(false)
        .noTreeShaking()
        .enableInliningAnnotations()
        .addOptionsModification(
            o -> {
              o.testing.disallowLoadStoreOptimization = true;
            })
        .run(TryRangeTest.class)
        .assertSuccessWithOutput(StringUtils.lines("10", "7.0"));
  }

  @Test
  public void testRegisterAllocationLimitLeadingRange() throws Exception {
    CodeInspector inspector =
        testForR8(Backend.CF)
            .addProgramClasses(TryRangeTestLimitRange.class)
            .addKeepMainRule(TryRangeTestLimitRange.class)
            .setMode(CompilationMode.RELEASE)
            .minification(false)
            .noTreeShaking()
            .enableInliningAnnotations()
            .addOptionsModification(
                o -> {
                  o.testing.disallowLoadStoreOptimization = true;
                  o.testing.irModifier = this::processIR;
                })
            .run(TryRangeTestLimitRange.class)
            .assertSuccessWithOutput("")
            .inspector();
    // Assert that we do not have any register-modifying instructions in the throwing block:
    // L0: ; locals:
    // iload 1;
    // invokestatic com.android.tools.r8.cf.TryRangeTestLimitRange.doSomething(I)F
    // L1: ; locals:
    // 11:   pop
    ClassSubject clazz = inspector.clazz("com.android.tools.r8.cf.TryRangeTestLimitRange");
    CfCode cfCode = clazz.uniqueMethodWithName("main").getMethod().getCode().asCfCode();
    List<CfInstruction> instructions = cfCode.getInstructions();
    CfLabel startLabel = cfCode.getTryCatchRanges().get(0).start;
    int index = 0;
    while (instructions.get(index) != startLabel) {
      index++;
    }
    assert instructions.get(index + 1) instanceof CfLoad;
    assert instructions.get(index + 2) instanceof CfInvoke;
    assert instructions.get(index + 3) == cfCode.getTryCatchRanges().get(0).end;
    assert instructions.get(index + 4) instanceof CfStackInstruction;
  }

  private void processIR(IRCode code) {
    if (!code.method.qualifiedName().equals(TryRangeTestLimitRange.class.getName() + ".main")) {
      return;
    }
    BasicBlock entryBlock = code.blocks.get(0);
    BasicBlock tryBlock = code.blocks.get(1);
    assertTrue(tryBlock.hasCatchHandlers());
    ListIterator<Instruction> it = entryBlock.getInstructions().listIterator();
    Instruction constNumber = it.next();
    while (!constNumber.isConstNumber()) {
      constNumber = it.next();
    }
    it.remove();
    Instruction add = it.next();
    while (!add.isAdd()) {
      add = it.next();
    }
    it.remove();
    constNumber.setBlock(tryBlock);
    add.setBlock(tryBlock);
    tryBlock.getInstructions().add(0, add);
    tryBlock.getInstructions().add(0, constNumber);
  }
}
