// Copyright (c) 2017, 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 stringconcat;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.invoke.CallSite;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.List;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Handle;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

public class TestGenerator {
  private static final String RECIPE_PREFIX = "RECIPE:";

  private static final String STRING_CONCAT_FACTORY = "java/lang/invoke/StringConcatFactory";

  private static final Handle MAKE_CONCAT_WITH_CONSTANTS =
      new Handle(
          Opcodes.H_INVOKESTATIC,
          STRING_CONCAT_FACTORY,
          "makeConcatWithConstants",
          MethodType.methodType(
                  CallSite.class,
                  MethodHandles.Lookup.class,
                  String.class,
                  MethodType.class,
                  String.class,
                  Object[].class)
              .toMethodDescriptorString(),
          false);

  private static final Handle MAKE_CONCAT =
      new Handle(
          Opcodes.H_INVOKESTATIC,
          STRING_CONCAT_FACTORY,
          "makeConcat",
          MethodType.methodType(
                  CallSite.class, MethodHandles.Lookup.class, String.class, MethodType.class)
              .toMethodDescriptorString(),
          false);

  public static void main(String[] args) throws IOException {
    assert args.length == 2;
    String fileName = StringConcat.class.getSimpleName() + ".class";
    Path inputFile = Paths.get(args[0], TestGenerator.class.getPackage().getName(), fileName);
    Path outputFile = Paths.get(args[1], fileName);
    generateTests(inputFile, outputFile);
  }

  private static void generateTests(Path classNamePath, Path outputClassNamePath)
      throws IOException {
    Files.createDirectories(outputClassNamePath.getParent());
    try (InputStream input = Files.newInputStream(classNamePath)) {
      ClassReader cr = new ClassReader(input);
      ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
      cr.accept(
          new ClassVisitor(Opcodes.ASM7, cw) {
            @Override
            public MethodVisitor visitMethod(
                int access,
                final String methodName,
                String desc,
                String signature,
                String[] exceptions) {
              MethodVisitor mv = super.visitMethod(access, methodName, desc, signature, exceptions);
              return new MethodVisitor(Opcodes.ASM7, mv) {
                private List<Object> recentConstants = new ArrayList<>();

                @Override
                public void visitLdcInsn(Object cst) {
                  if (!recentConstants.isEmpty()
                      || (cst instanceof String && ((String) cst).startsWith(RECIPE_PREFIX))) {
                    // Add the constant, don't push anything on stack.
                    recentConstants.add(cst);
                    return;
                  }
                  super.visitLdcInsn(cst);
                }

                @Override
                public void visitMethodInsn(
                    int opcode, String owner, String name, String desc, boolean itf) {
                  // Replace calls to 'makeConcat(...)' with appropriate `invokedynamic`.
                  if (opcode == Opcodes.INVOKESTATIC && name.equals("makeConcat")) {
                    mv.visitInvokeDynamicInsn(MAKE_CONCAT.getName(), desc, MAKE_CONCAT);
                    recentConstants.clear();
                    return;
                  }

                  // Replace calls to 'makeConcat(...)' with appropriate `invokedynamic`.
                  if (opcode == Opcodes.INVOKESTATIC && name.equals("makeConcatWithConstants")) {
                    if (recentConstants.isEmpty()) {
                      throw new AssertionError(
                          "No constants detected in `" + methodName + "`: call to " + name + desc);
                    }
                    recentConstants.set(
                        0, ((String) recentConstants.get(0)).substring(RECIPE_PREFIX.length()));

                    mv.visitInvokeDynamicInsn(
                        MAKE_CONCAT_WITH_CONSTANTS.getName(),
                        removeLastParams(desc, recentConstants.size()),
                        MAKE_CONCAT_WITH_CONSTANTS,
                        recentConstants.toArray());
                    recentConstants.clear();
                    return;
                  }

                  // Otherwise fall back to default implementation.
                  super.visitMethodInsn(opcode, owner, name, desc, itf);
                }

                private String removeLastParams(String descr, int paramsToRemove) {
                  MethodType methodType =
                      MethodType.fromMethodDescriptorString(
                          descr, this.getClass().getClassLoader());
                  return methodType
                      .dropParameterTypes(
                          methodType.parameterCount() - paramsToRemove, methodType.parameterCount())
                      .toMethodDescriptorString();
                }

                @Override
                public void visitInsn(int opcode) {
                  switch (opcode) {
                    case Opcodes.ICONST_0:
                      if (!recentConstants.isEmpty()) {
                        recentConstants.add(0);
                        return;
                      }
                      break;
                    case Opcodes.ICONST_1:
                      if (!recentConstants.isEmpty()) {
                        recentConstants.add(1);
                        return;
                      }
                      break;
                    case Opcodes.ICONST_2:
                      if (!recentConstants.isEmpty()) {
                        recentConstants.add(2);
                        return;
                      }
                      break;
                    case Opcodes.ICONST_3:
                      if (!recentConstants.isEmpty()) {
                        recentConstants.add(3);
                        return;
                      }
                      break;
                    case Opcodes.ICONST_4:
                      if (!recentConstants.isEmpty()) {
                        recentConstants.add(4);
                        return;
                      }
                      break;
                    case Opcodes.ICONST_5:
                      if (!recentConstants.isEmpty()) {
                        recentConstants.add(5);
                        return;
                      }
                      break;
                    case Opcodes.ICONST_M1:
                      if (!recentConstants.isEmpty()) {
                        recentConstants.add(-1);
                        return;
                      }
                      break;
                    default:
                      recentConstants.clear();
                      break;
                  }
                  super.visitInsn(opcode);
                }

                @Override
                public void visitIntInsn(int opcode, int operand) {
                  recentConstants.clear();
                  super.visitIntInsn(opcode, operand);
                }

                @Override
                public void visitVarInsn(int opcode, int var) {
                  recentConstants.clear();
                  super.visitVarInsn(opcode, var);
                }

                @Override
                public void visitTypeInsn(int opcode, String type) {
                  recentConstants.clear();
                  super.visitTypeInsn(opcode, type);
                }

                @Override
                public void visitFieldInsn(int opcode, String owner, String name, String desc) {
                  recentConstants.clear();
                  super.visitFieldInsn(opcode, owner, name, desc);
                }

                @Override
                public void visitJumpInsn(int opcode, Label label) {
                  recentConstants.clear();
                  super.visitJumpInsn(opcode, label);
                }

                @Override
                public void visitIincInsn(int var, int increment) {
                  recentConstants.clear();
                  super.visitIincInsn(var, increment);
                }

                @Override
                public void visitTableSwitchInsn(int min, int max, Label dflt, Label... labels) {
                  recentConstants.clear();
                  super.visitTableSwitchInsn(min, max, dflt, labels);
                }

                @Override
                public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
                  recentConstants.clear();
                  super.visitLookupSwitchInsn(dflt, keys, labels);
                }

                @Override
                public void visitMultiANewArrayInsn(String desc, int dims) {
                  recentConstants.clear();
                  super.visitMultiANewArrayInsn(desc, dims);
                }
              };
            }
          },
          0);
      try (OutputStream output =
          Files.newOutputStream(outputClassNamePath, StandardOpenOption.CREATE)) {
        output.write(cw.toByteArray());
      }
    }
  }
}
