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

import com.android.tools.r8.cf.code.CfArithmeticBinop;
import com.android.tools.r8.cf.code.CfArrayLength;
import com.android.tools.r8.cf.code.CfArrayLoad;
import com.android.tools.r8.cf.code.CfArrayStore;
import com.android.tools.r8.cf.code.CfCheckCast;
import com.android.tools.r8.cf.code.CfCmp;
import com.android.tools.r8.cf.code.CfConstClass;
import com.android.tools.r8.cf.code.CfConstMethodHandle;
import com.android.tools.r8.cf.code.CfConstMethodType;
import com.android.tools.r8.cf.code.CfConstNull;
import com.android.tools.r8.cf.code.CfConstNumber;
import com.android.tools.r8.cf.code.CfConstString;
import com.android.tools.r8.cf.code.CfFieldInstruction;
import com.android.tools.r8.cf.code.CfFrame;
import com.android.tools.r8.cf.code.CfFrame.FrameType;
import com.android.tools.r8.cf.code.CfGoto;
import com.android.tools.r8.cf.code.CfIf;
import com.android.tools.r8.cf.code.CfIfCmp;
import com.android.tools.r8.cf.code.CfIinc;
import com.android.tools.r8.cf.code.CfInstanceOf;
import com.android.tools.r8.cf.code.CfInstruction;
import com.android.tools.r8.cf.code.CfInvoke;
import com.android.tools.r8.cf.code.CfInvokeDynamic;
import com.android.tools.r8.cf.code.CfJsrRet;
import com.android.tools.r8.cf.code.CfLabel;
import com.android.tools.r8.cf.code.CfLoad;
import com.android.tools.r8.cf.code.CfLogicalBinop;
import com.android.tools.r8.cf.code.CfMonitor;
import com.android.tools.r8.cf.code.CfMultiANewArray;
import com.android.tools.r8.cf.code.CfNeg;
import com.android.tools.r8.cf.code.CfNew;
import com.android.tools.r8.cf.code.CfNewArray;
import com.android.tools.r8.cf.code.CfNop;
import com.android.tools.r8.cf.code.CfNumberConversion;
import com.android.tools.r8.cf.code.CfPosition;
import com.android.tools.r8.cf.code.CfReturn;
import com.android.tools.r8.cf.code.CfReturnVoid;
import com.android.tools.r8.cf.code.CfStackInstruction;
import com.android.tools.r8.cf.code.CfStore;
import com.android.tools.r8.cf.code.CfSwitch;
import com.android.tools.r8.cf.code.CfThrow;
import com.android.tools.r8.cf.code.CfTryCatch;
import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.errors.Unimplemented;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.CfCode.LocalVariableInfo;
import com.android.tools.r8.graph.JarClassFileReader.ReparseContext;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.If;
import com.android.tools.r8.ir.code.MemberType;
import com.android.tools.r8.ir.code.Monitor;
import com.android.tools.r8.ir.code.NumberGenerator;
import com.android.tools.r8.ir.code.Position;
import com.android.tools.r8.ir.code.ValueType;
import com.android.tools.r8.ir.conversion.MethodProcessor;
import com.android.tools.r8.naming.ClassNameMapper;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.position.MethodPosition;
import com.android.tools.r8.shaking.ProguardConfiguration;
import com.android.tools.r8.shaking.ProguardKeepAttributes;
import com.android.tools.r8.utils.InternalOptions;
import it.unimi.dsi.fastutil.ints.Int2ReferenceAVLTreeMap;
import it.unimi.dsi.fastutil.ints.Int2ReferenceMap;
import it.unimi.dsi.fastutil.ints.Int2ReferenceSortedMap;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Deque;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.ConstantDynamic;
import org.objectweb.asm.Handle;
import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.JSRInlinerAdapter;

public class LazyCfCode extends Code {

  private static class JsrEncountered extends RuntimeException {
    public JsrEncountered(String s) {
      super(s);
    }
  }

  public LazyCfCode(
      DexMethod method, Origin origin, ReparseContext context, JarApplicationReader application) {
    this.origin = origin;
    this.context = context;
    this.application = application;
    context.codeList.add(this);
  }

  private final Origin origin;
  private JarApplicationReader application;
  private CfCode code;
  protected ReparseContext context;
  private boolean reachabilitySensitive = false;

  public void markReachabilitySensitive() {
    assert code == null;
    reachabilitySensitive = true;
  }

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

  @Override
  public LazyCfCode asLazyCfCode() {
    return this;
  }

  @Override
  public CfCode asCfCode() {
    if (code == null) {
      ReparseContext context = this.context;
      JarApplicationReader application = this.application;
      assert application != null;
      assert context != null;
      // The ClassCodeVisitor is in charge of setting this.context to null.
      try {
        parseCode(context, false);
      } catch (JsrEncountered e) {
        for (Code code : context.codeList) {
          code.asLazyCfCode().code = null;
          code.asLazyCfCode().context = context;
          code.asLazyCfCode().application = application;
        }
        try {
          parseCode(context, true);
        } catch (JsrEncountered e1) {
          throw new Unreachable(e1);
        }
      }
      assert verifyNoReparseContext(context.owner);
    }
    assert code != null;
    return code;
  }

  public static class DebugParsingOptions {
    public final boolean lineInfo;
    public final boolean localInfo;
    public final int asmReaderOptions;

    public DebugParsingOptions(boolean lineInfo, boolean localInfo, int asmReaderOptions) {
      this.lineInfo = lineInfo;
      this.localInfo = localInfo;
      this.asmReaderOptions = asmReaderOptions;
    }
  }

  public void parseCode(ReparseContext context, boolean useJsrInliner) {
    DebugParsingOptions parsingOptions = getParsingOptions(application, reachabilitySensitive);

    ClassCodeVisitor classVisitor =
        new ClassCodeVisitor(
            context.owner,
            createCodeLocator(context),
            application,
            useJsrInliner,
            origin,
            parsingOptions);
    new ClassReader(context.classCache).accept(classVisitor, parsingOptions.asmReaderOptions);
  }

  private void setCode(CfCode code) {
    assert this.code == null;
    assert this.context != null;
    this.code = code;
    this.context = null;
    this.application = null;
  }

  @Override
  protected int computeHashCode() {
    throw new Unimplemented();
  }

  @Override
  protected boolean computeEquals(Object other) {
    throw new Unimplemented();
  }

  @Override
  public boolean isEmptyVoidMethod() {
    return asCfCode().isEmptyVoidMethod();
  }

  @Override
  public int estimatedSizeForInlining() {
    return asCfCode().estimatedSizeForInlining();
  }

  @Override
  public boolean estimatedSizeForInliningAtMost(int threshold) {
    return asCfCode().estimatedSizeForInliningAtMost(threshold);
  }

  @Override
  public IRCode buildIR(ProgramMethod method, AppView<?> appView, Origin origin) {
    return asCfCode().buildIR(method, appView, origin);
  }

  @Override
  public IRCode buildInliningIR(
      ProgramMethod context,
      ProgramMethod method,
      AppView<?> appView,
      NumberGenerator valueNumberGenerator,
      Position callerPosition,
      Origin origin,
      MethodProcessor methodProcessor) {
    return asCfCode()
        .buildInliningIR(
            context,
            method,
            appView,
            valueNumberGenerator,
            callerPosition,
            origin,
            methodProcessor);
  }

  @Override
  public void registerCodeReferences(ProgramMethod method, UseRegistry registry) {
    asCfCode().registerCodeReferences(method, registry);
  }

  @Override
  public void registerCodeReferencesForDesugaring(ClasspathMethod method, UseRegistry registry) {
    asCfCode().registerCodeReferencesForDesugaring(method, registry);
  }

  @Override
  public void registerArgumentReferences(DexEncodedMethod method, ArgumentUse registry) {
    asCfCode().registerArgumentReferences(method, registry);
  }

  @Override
  public String toString() {
    return asCfCode().toString();
  }

  @Override
  public String toString(DexEncodedMethod method, ClassNameMapper naming) {
    return asCfCode().toString(method, naming);
  }

  protected BiFunction<String, String, LazyCfCode> createCodeLocator(ReparseContext context) {
    return new DefaultCodeLocator(context, application);
  }

  private static class DefaultCodeLocator implements BiFunction<String, String, LazyCfCode> {
    private final ReparseContext context;
    private final JarApplicationReader application;
    private int methodIndex = 0;

    private DefaultCodeLocator(ReparseContext context, JarApplicationReader application) {
      this.context = context;
      this.application = application;
    }

    @Override
    public LazyCfCode apply(String name, String desc) {
      return context.codeList.get(methodIndex++).asLazyCfCode();
    }
  }

  private static class ClassCodeVisitor extends ClassVisitor {

    private final DexClass clazz;
    private final BiFunction<String, String, LazyCfCode> codeLocator;
    private final JarApplicationReader application;
    private boolean usrJsrInliner;
    private final Origin origin;
    private final DebugParsingOptions debugParsingOptions;

    ClassCodeVisitor(
        DexClass clazz,
        BiFunction<String, String, LazyCfCode> codeLocator,
        JarApplicationReader application,
        boolean useJsrInliner,
        Origin origin,
        DebugParsingOptions debugParsingOptions) {
      super(InternalOptions.ASM_VERSION);
      this.clazz = clazz;
      this.codeLocator = codeLocator;
      this.application = application;
      this.usrJsrInliner = useJsrInliner;
      this.origin = origin;
      this.debugParsingOptions = debugParsingOptions;
    }

    @Override
    public MethodVisitor visitMethod(
        int access, String name, String desc, String signature, String[] exceptions) {
      MethodAccessFlags flags = JarClassFileReader.createMethodAccessFlags(name, access);
      if (!flags.isAbstract() && !flags.isNative()) {
        LazyCfCode code = codeLocator.apply(name, desc);
        if (code != null) {
          DexMethod method = application.getMethod(clazz.type, name, desc);
          MethodCodeVisitor methodVisitor =
              new MethodCodeVisitor(application, method, code, origin, debugParsingOptions);
          if (!usrJsrInliner) {
            return methodVisitor;
          }
          return new JSRInlinerAdapter(methodVisitor, access, name, desc, signature, exceptions);
        }
      }
      return null;
    }
  }

  private static class MethodCodeVisitor extends MethodVisitor {
    private final JarApplicationReader application;
    private final DexItemFactory factory;
    private final DebugParsingOptions debugParsingOptions;
    private int maxStack;
    private int maxLocals;
    private List<CfInstruction> instructions;
    private List<CfTryCatch> tryCatchRanges;
    private List<LocalVariableInfo> localVariables;
    private final Map<DebugLocalInfo, DebugLocalInfo> canonicalDebugLocalInfo = new HashMap<>();
    private Map<Label, CfLabel> labelMap;
    private final LazyCfCode code;
    private final DexMethod method;
    private final Origin origin;

    MethodCodeVisitor(
        JarApplicationReader application,
        DexMethod method,
        LazyCfCode code,
        Origin origin,
        DebugParsingOptions debugParsingOptions) {
      super(InternalOptions.ASM_VERSION);
      this.debugParsingOptions = debugParsingOptions;
      assert code != null;
      this.application = application;
      this.factory = application.getFactory();
      this.code = code;
      this.method = method;
      this.origin = origin;
    }

    @Override
    public void visitCode() {
      maxStack = 0;
      maxLocals = 0;
      instructions = new ArrayList<>();
      tryCatchRanges = new ArrayList<>();
      localVariables = new ArrayList<>();
      labelMap = new IdentityHashMap<>();
    }

    @Override
    public void visitEnd() {
      if (instructions == null) {
        // Everything that is initialized at `visitCode` should be null too.
        assert tryCatchRanges == null && localVariables == null && labelMap == null;
        // This code visitor is used only if the method is neither abstract nor native, hence it
        // should have exactly one Code attribute:
        // https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7.3
        throw new CompilationError(
            "Absent Code attribute in method that is not native or abstract",
            origin,
            new MethodPosition(method.asMethodReference()));
      }
      code.setCode(
          new CfCode(
              method.holder, maxStack, maxLocals, instructions, tryCatchRanges, localVariables));
    }

    @Override
    public void visitFrame(
        int frameType, int nLocals, Object[] localTypes, int nStack, Object[] stackTypes) {
      assert frameType == Opcodes.F_NEW;
      Int2ReferenceSortedMap<FrameType> parsedLocals = parseLocals(nLocals, localTypes);
      Deque<FrameType> parsedStack = parseStack(nStack, stackTypes);
      instructions.add(new CfFrame(parsedLocals, parsedStack));
    }

    private Int2ReferenceSortedMap<FrameType> parseLocals(int typeCount, Object[] asmTypes) {
      Int2ReferenceSortedMap<FrameType> types = new Int2ReferenceAVLTreeMap<>();
      int i = 0;
      for (int j = 0; j < typeCount; j++) {
        Object localType = asmTypes[j];
        FrameType value = getFrameType(localType);
        types.put(i++, value);
        if (value.isWide()) {
          i++;
        }
      }
      return types;
    }

    private Deque<FrameType> parseStack(int nStack, Object[] stackTypes) {
      Deque<FrameType> dexStack = new ArrayDeque<>(nStack);
      for (int i = 0; i < nStack; i++) {
        dexStack.add(getFrameType(stackTypes[i]));
      }
      return dexStack;
    }

    private FrameType getFrameType(Object localType) {
      if (localType instanceof Label) {
        return FrameType.uninitializedNew(getLabel((Label) localType), null);
      } else if (localType == Opcodes.UNINITIALIZED_THIS) {
        return FrameType.uninitializedThis();
      } else if (localType == null || localType == Opcodes.TOP) {
        return FrameType.top();
      } else {
        return FrameType.initialized(parseAsmType(localType));
      }
    }

    private CfLabel getLabel(Label label) {
      return labelMap.computeIfAbsent(label, l -> new CfLabel());
    }

    private DexType parseAsmType(Object local) {
      assert local != null && local != Opcodes.TOP;
      if (local == Opcodes.INTEGER) {
        return factory.intType;
      } else if (local == Opcodes.FLOAT) {
        return factory.floatType;
      } else if (local == Opcodes.LONG) {
        return factory.longType;
      } else if (local == Opcodes.DOUBLE) {
        return factory.doubleType;
      } else if (local == Opcodes.NULL) {
        return DexItemFactory.nullValueType;
      } else if (local instanceof String) {
        return createTypeFromInternalType((String) local);
      } else {
        throw new Unreachable("Unexpected ASM type: " + local);
      }
    }

    private DexType createTypeFromInternalType(String local) {
      assert local.indexOf('.') == -1;
      return factory.createType(Type.getObjectType(local).getDescriptor());
    }

    @Override
    public void visitInsn(int opcode) {
      switch (opcode) {
        case Opcodes.NOP:
          instructions.add(new CfNop());
          break;
        case Opcodes.ACONST_NULL:
          instructions.add(new CfConstNull());
          break;
        case Opcodes.ICONST_M1:
        case Opcodes.ICONST_0:
        case Opcodes.ICONST_1:
        case Opcodes.ICONST_2:
        case Opcodes.ICONST_3:
        case Opcodes.ICONST_4:
        case Opcodes.ICONST_5:
          instructions.add(new CfConstNumber(opcode - Opcodes.ICONST_0, ValueType.INT));
          break;
        case Opcodes.LCONST_0:
        case Opcodes.LCONST_1:
          instructions.add(new CfConstNumber(opcode - Opcodes.LCONST_0, ValueType.LONG));
          break;
        case Opcodes.FCONST_0:
        case Opcodes.FCONST_1:
        case Opcodes.FCONST_2:
          instructions.add(
              new CfConstNumber(
                  Float.floatToRawIntBits(opcode - Opcodes.FCONST_0), ValueType.FLOAT));
          break;
        case Opcodes.DCONST_0:
        case Opcodes.DCONST_1:
          instructions.add(
              new CfConstNumber(
                  Double.doubleToRawLongBits(opcode - Opcodes.DCONST_0), ValueType.DOUBLE));
          break;
        case Opcodes.IALOAD:
        case Opcodes.LALOAD:
        case Opcodes.FALOAD:
        case Opcodes.DALOAD:
        case Opcodes.AALOAD:
        case Opcodes.BALOAD:
        case Opcodes.CALOAD:
        case Opcodes.SALOAD:
          instructions.add(new CfArrayLoad(getMemberTypeForOpcode(opcode)));
          break;
        case Opcodes.IASTORE:
        case Opcodes.LASTORE:
        case Opcodes.FASTORE:
        case Opcodes.DASTORE:
        case Opcodes.AASTORE:
        case Opcodes.BASTORE:
        case Opcodes.CASTORE:
        case Opcodes.SASTORE:
          instructions.add(new CfArrayStore(getMemberTypeForOpcode(opcode)));
          break;
        case Opcodes.POP:
        case Opcodes.POP2:
        case Opcodes.DUP:
        case Opcodes.DUP_X1:
        case Opcodes.DUP_X2:
        case Opcodes.DUP2:
        case Opcodes.DUP2_X1:
        case Opcodes.DUP2_X2:
        case Opcodes.SWAP:
          instructions.add(CfStackInstruction.fromAsm(opcode));
          break;
        case Opcodes.IADD:
        case Opcodes.LADD:
        case Opcodes.FADD:
        case Opcodes.DADD:
        case Opcodes.ISUB:
        case Opcodes.LSUB:
        case Opcodes.FSUB:
        case Opcodes.DSUB:
        case Opcodes.IMUL:
        case Opcodes.LMUL:
        case Opcodes.FMUL:
        case Opcodes.DMUL:
        case Opcodes.IDIV:
        case Opcodes.LDIV:
        case Opcodes.FDIV:
        case Opcodes.DDIV:
        case Opcodes.IREM:
        case Opcodes.LREM:
        case Opcodes.FREM:
        case Opcodes.DREM:
          instructions.add(CfArithmeticBinop.fromAsm(opcode));
          break;
        case Opcodes.INEG:
        case Opcodes.LNEG:
        case Opcodes.FNEG:
        case Opcodes.DNEG:
          instructions.add(CfNeg.fromAsm(opcode));
          break;
        case Opcodes.ISHL:
        case Opcodes.LSHL:
        case Opcodes.ISHR:
        case Opcodes.LSHR:
        case Opcodes.IUSHR:
        case Opcodes.LUSHR:
        case Opcodes.IAND:
        case Opcodes.LAND:
        case Opcodes.IOR:
        case Opcodes.LOR:
        case Opcodes.IXOR:
        case Opcodes.LXOR:
          instructions.add(CfLogicalBinop.fromAsm(opcode));
          break;
        case Opcodes.I2L:
        case Opcodes.I2F:
        case Opcodes.I2D:
        case Opcodes.L2I:
        case Opcodes.L2F:
        case Opcodes.L2D:
        case Opcodes.F2I:
        case Opcodes.F2L:
        case Opcodes.F2D:
        case Opcodes.D2I:
        case Opcodes.D2L:
        case Opcodes.D2F:
        case Opcodes.I2B:
        case Opcodes.I2C:
        case Opcodes.I2S:
          instructions.add(CfNumberConversion.fromAsm(opcode));
          break;
        case Opcodes.LCMP:
        case Opcodes.FCMPL:
        case Opcodes.FCMPG:
        case Opcodes.DCMPL:
        case Opcodes.DCMPG:
          instructions.add(CfCmp.fromAsm(opcode));
          break;
        case Opcodes.IRETURN:
          instructions.add(new CfReturn(ValueType.INT));
          break;
        case Opcodes.LRETURN:
          instructions.add(new CfReturn(ValueType.LONG));
          break;
        case Opcodes.FRETURN:
          instructions.add(new CfReturn(ValueType.FLOAT));
          break;
        case Opcodes.DRETURN:
          instructions.add(new CfReturn(ValueType.DOUBLE));
          break;
        case Opcodes.ARETURN:
          instructions.add(new CfReturn(ValueType.OBJECT));
          break;
        case Opcodes.RETURN:
          instructions.add(new CfReturnVoid());
          break;
        case Opcodes.ARRAYLENGTH:
          instructions.add(new CfArrayLength());
          break;
        case Opcodes.ATHROW:
          instructions.add(new CfThrow());
          break;
        case Opcodes.MONITORENTER:
          instructions.add(new CfMonitor(Monitor.Type.ENTER));
          break;
        case Opcodes.MONITOREXIT:
          instructions.add(new CfMonitor(Monitor.Type.EXIT));
          break;
        default:
          throw new Unreachable("Unknown instruction");
      }
    }

    private static MemberType getMemberTypeForOpcode(int opcode) {
      switch (opcode) {
        case Opcodes.IALOAD:
        case Opcodes.IASTORE:
          return MemberType.INT;
        case Opcodes.FALOAD:
        case Opcodes.FASTORE:
          return MemberType.FLOAT;
        case Opcodes.LALOAD:
        case Opcodes.LASTORE:
          return MemberType.LONG;
        case Opcodes.DALOAD:
        case Opcodes.DASTORE:
          return MemberType.DOUBLE;
        case Opcodes.AALOAD:
        case Opcodes.AASTORE:
          return MemberType.OBJECT;
        case Opcodes.BALOAD:
        case Opcodes.BASTORE:
          return MemberType.BOOLEAN_OR_BYTE;
        case Opcodes.CALOAD:
        case Opcodes.CASTORE:
          return MemberType.CHAR;
        case Opcodes.SALOAD:
        case Opcodes.SASTORE:
          return MemberType.SHORT;
        default:
          throw new Unreachable("Unexpected array opcode " + opcode);
      }
    }

    @Override
    public void visitIntInsn(int opcode, int operand) {
      switch (opcode) {
        case Opcodes.SIPUSH:
        case Opcodes.BIPUSH:
          instructions.add(new CfConstNumber(operand, ValueType.INT));
          break;
        case Opcodes.NEWARRAY:
          instructions.add(
              new CfNewArray(factory.createArrayType(1, arrayTypeDesc(operand, factory))));
          break;
        default:
          throw new Unreachable("Unexpected int opcode " + opcode);
      }
    }

    private static DexType arrayTypeDesc(int arrayTypeCode, DexItemFactory factory) {
      switch (arrayTypeCode) {
        case Opcodes.T_BOOLEAN:
          return factory.booleanType;
        case Opcodes.T_CHAR:
          return factory.charType;
        case Opcodes.T_FLOAT:
          return factory.floatType;
        case Opcodes.T_DOUBLE:
          return factory.doubleType;
        case Opcodes.T_BYTE:
          return factory.byteType;
        case Opcodes.T_SHORT:
          return factory.shortType;
        case Opcodes.T_INT:
          return factory.intType;
        case Opcodes.T_LONG:
          return factory.longType;
        default:
          throw new Unreachable("Unexpected array-type code " + arrayTypeCode);
      }
    }

    @Override
    public void visitVarInsn(int opcode, int var) {
      ValueType type;
      switch (opcode) {
        case Opcodes.ILOAD:
        case Opcodes.ISTORE:
          type = ValueType.INT;
          break;
        case Opcodes.FLOAD:
        case Opcodes.FSTORE:
          type = ValueType.FLOAT;
          break;
        case Opcodes.LLOAD:
        case Opcodes.LSTORE:
          type = ValueType.LONG;
          break;
        case Opcodes.DLOAD:
        case Opcodes.DSTORE:
          type = ValueType.DOUBLE;
          break;
        case Opcodes.ALOAD:
        case Opcodes.ASTORE:
          type = ValueType.OBJECT;
          break;
        case Opcodes.RET:
          {
            instructions.add(new CfJsrRet(var));
            return;
          }
        default:
          throw new Unreachable("Unexpected VarInsn opcode: " + opcode);
      }
      if (Opcodes.ILOAD <= opcode && opcode <= Opcodes.ALOAD) {
        instructions.add(new CfLoad(type, var));
      } else {
        instructions.add(new CfStore(type, var));
      }
    }

    @Override
    public void visitTypeInsn(int opcode, String typeName) {
      DexType type = factory.createType(Type.getObjectType(typeName).getDescriptor());
      switch (opcode) {
        case Opcodes.NEW:
          instructions.add(new CfNew(type));
          break;
        case Opcodes.ANEWARRAY:
          instructions.add(new CfNewArray(factory.createArrayType(1, type)));
          break;
        case Opcodes.CHECKCAST:
          instructions.add(new CfCheckCast(type));
          break;
        case Opcodes.INSTANCEOF:
          instructions.add(new CfInstanceOf(type));
          break;
        default:
          throw new Unreachable("Unexpected TypeInsn opcode: " + opcode);
      }
    }

    @Override
    public void visitFieldInsn(int opcode, String owner, String name, String desc) {
      DexField field =
          factory.createField(createTypeFromInternalType(owner), factory.createType(desc), name);
      // TODO(mathiasr): Don't require CfFieldInstruction::declaringField. It is needed for proper
      // renaming in the backend, but it is not available here in the frontend.
      instructions.add(new CfFieldInstruction(opcode, field, field));
    }

    @Override
    public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
      DexMethod method = application.getMethod(owner, name, desc);
      instructions.add(new CfInvoke(opcode, method, itf));
    }

    @Override
    public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) {
      DexCallSite callSite =
          DexCallSite.fromAsmInvokeDynamic(application, method.holder, name, desc, bsm, bsmArgs);
      instructions.add(new CfInvokeDynamic(callSite));
    }

    @Override
    public void visitJumpInsn(int opcode, Label label) {
      CfLabel target = getLabel(label);
      if (Opcodes.IFEQ <= opcode && opcode <= Opcodes.IF_ACMPNE) {
        if (opcode <= Opcodes.IFLE) {
          // IFEQ, IFNE, IFLT, IFGE, IFGT, or IFLE.
          instructions.add(new CfIf(ifType(opcode), ValueType.INT, target));
        } else {
          // IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ, or
          // IF_ACMPNE.
          ValueType valueType;
          if (opcode <= Opcodes.IF_ICMPLE) {
            valueType = ValueType.INT;
          } else {
            valueType = ValueType.OBJECT;
          }
          instructions.add(new CfIfCmp(ifType(opcode), valueType, target));
        }
      } else {
        // GOTO, JSR, IFNULL or IFNONNULL.
        switch (opcode) {
          case Opcodes.GOTO:
            instructions.add(new CfGoto(target));
            break;
          case Opcodes.IFNULL:
          case Opcodes.IFNONNULL:
            If.Type type = opcode == Opcodes.IFNULL ? If.Type.EQ : If.Type.NE;
            instructions.add(new CfIf(type, ValueType.OBJECT, target));
            break;
          case Opcodes.JSR:
            throw new JsrEncountered("JSR should be handled by the ASM jsr inliner");
          default:
            throw new Unreachable("Unexpected JumpInsn opcode: " + opcode);
        }
      }
    }

    private static If.Type ifType(int opcode) {
      switch (opcode) {
        case Opcodes.IFEQ:
        case Opcodes.IF_ICMPEQ:
        case Opcodes.IF_ACMPEQ:
          return If.Type.EQ;
        case Opcodes.IFNE:
        case Opcodes.IF_ICMPNE:
        case Opcodes.IF_ACMPNE:
          return If.Type.NE;
        case Opcodes.IFLT:
        case Opcodes.IF_ICMPLT:
          return If.Type.LT;
        case Opcodes.IFGE:
        case Opcodes.IF_ICMPGE:
          return If.Type.GE;
        case Opcodes.IFGT:
        case Opcodes.IF_ICMPGT:
          return If.Type.GT;
        case Opcodes.IFLE:
        case Opcodes.IF_ICMPLE:
          return If.Type.LE;
        default:
          throw new Unreachable("Unexpected If instruction opcode: " + opcode);
      }
    }

    @Override
    public void visitLabel(Label label) {
      instructions.add(getLabel(label));
    }

    @Override
    public void visitLdcInsn(Object cst) {
      if (cst instanceof Type) {
        Type type = (Type) cst;
        if (type.getSort() == Type.METHOD) {
          DexProto proto = application.getProto(type.getDescriptor());
          instructions.add(new CfConstMethodType(proto));
        } else {
          instructions.add(new CfConstClass(factory.createType(type.getDescriptor())));
        }
      } else if (cst instanceof String) {
        instructions.add(new CfConstString(factory.createString((String) cst)));
      } else if (cst instanceof Long) {
        instructions.add(new CfConstNumber((Long) cst, ValueType.LONG));
      } else if (cst instanceof Double) {
        long l = Double.doubleToRawLongBits((Double) cst);
        instructions.add(new CfConstNumber(l, ValueType.DOUBLE));
      } else if (cst instanceof Integer) {
        instructions.add(new CfConstNumber((Integer) cst, ValueType.INT));
      } else if (cst instanceof Float) {
        long i = Float.floatToRawIntBits((Float) cst);
        instructions.add(new CfConstNumber(i, ValueType.FLOAT));
      } else if (cst instanceof Handle) {
        instructions.add(
            new CfConstMethodHandle(
                DexMethodHandle.fromAsmHandle((Handle) cst, application, method.holder)));
      } else if (cst instanceof ConstantDynamic) {
        throw new CompilationError("Unsupported dynamic constant: " + cst.toString());
      } else {
        throw new CompilationError("Unsupported constant: " + cst.toString());
      }
    }

    @Override
    public void visitIincInsn(int var, int increment) {
      instructions.add(new CfIinc(var, increment));
    }

    @Override
    public void visitTableSwitchInsn(int min, int max, Label dflt, Label... labels) {
      assert max == min + labels.length - 1;
      ArrayList<CfLabel> targets = new ArrayList<>(labels.length);
      for (Label label : labels) {
        targets.add(getLabel(label));
      }
      instructions.add(new CfSwitch(CfSwitch.Kind.TABLE, getLabel(dflt), new int[] {min}, targets));
    }

    @Override
    public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {
      ArrayList<CfLabel> targets = new ArrayList<>(labels.length);
      for (Label label : labels) {
        targets.add(getLabel(label));
      }
      instructions.add(new CfSwitch(CfSwitch.Kind.LOOKUP, getLabel(dflt), keys, targets));
    }

    @Override
    public void visitMultiANewArrayInsn(String desc, int dims) {
      if (!application.options.isGeneratingDex()) {
        instructions.add(new CfMultiANewArray(factory.createType(desc), dims));
        return;
      }
      // When generating DEX code a multianewarray is desugared to a reflective creation.
      // The stack transformation is:
      //   ..., count1, ..., countN (where N = dims)
      //   ->
      //   ..., arrayref(of type : desc)
      //
      // This is unfolded to a call to java.lang.reflect.Array.newInstance to the same effect:
      // ..., count1, ..., countN
      visitLdcInsn(dims);
      // ..., count1, ..., countN, dims
      visitIntInsn(Opcodes.NEWARRAY, Opcodes.T_INT);
      // ..., count1, ..., countN, dim-array
      for (int i = dims - 1; i >= 0; i--) {
        visitInsn(Opcodes.DUP_X1);
        // ..., count1, ..., dim-array, countN, dim-array
        visitInsn(Opcodes.SWAP);
        // ..., count1, ..., dim-array, dim-array, countN
        visitLdcInsn(i);
        // ..., count1, ..., dim-array, dim-array, countN, index
        visitInsn(Opcodes.SWAP);
        // ..., count1, ..., dim-array, dim-array, index, countN
        visitInsn(Opcodes.IASTORE);
        // ..., count1, ..., dim-array
      }
      visitLdcInsn(Type.getType(desc.substring(dims)));
      // ..., dim-array, dim-member-type
      visitInsn(Opcodes.SWAP);
      // ..., dim-member-type, dim-array
      visitMethodInsn(
          Opcodes.INVOKESTATIC,
          "java/lang/reflect/Array",
          "newInstance",
          "(Ljava/lang/Class;[I)Ljava/lang/Object;",
          false);
      // ..., ref
      visitTypeInsn(Opcodes.CHECKCAST, desc);
      // ..., arrayref(of type : desc)
    }

    @Override
    public void visitTryCatchBlock(Label start, Label end, Label handler, String type) {
      List<DexType> guards =
          Collections.singletonList(
              type == null ? factory.throwableType : createTypeFromInternalType(type));
      List<CfLabel> targets = Collections.singletonList(getLabel(handler));
      tryCatchRanges.add(new CfTryCatch(getLabel(start), getLabel(end), guards, targets));
    }

    @Override
    public void visitLocalVariable(
        String name, String desc, String signature, Label start, Label end, int index) {
      if (debugParsingOptions.localInfo) {
        DebugLocalInfo debugLocalInfo =
            canonicalize(
                new DebugLocalInfo(
                    factory.createString(name),
                    factory.createType(desc),
                    signature == null ? null : factory.createString(signature)));
        localVariables.add(
            new LocalVariableInfo(index, debugLocalInfo, getLabel(start), getLabel(end)));
      }
    }

    private DebugLocalInfo canonicalize(DebugLocalInfo debugLocalInfo) {
      return canonicalDebugLocalInfo.computeIfAbsent(debugLocalInfo, o -> debugLocalInfo);
    }

    @Override
    public void visitLineNumber(int line, Label start) {
      if (debugParsingOptions.lineInfo) {
        instructions.add(new CfPosition(getLabel(start), new Position(line, null, method, null)));
      }
    }

    @Override
    public void visitMaxs(int maxStack, int maxLocals) {
      assert maxStack >= 0;
      assert maxLocals >= 0;
      this.maxStack = maxStack;
      this.maxLocals = maxLocals;
    }
  }

  private static DebugParsingOptions getParsingOptions(
      JarApplicationReader application, boolean reachabilitySensitive) {
    // TODO(b/166841731): We should compute our own from the compressed format.
    int parsingOptions =
        application.options.testing.readInputStackMaps
            ? ClassReader.EXPAND_FRAMES
            : ClassReader.SKIP_FRAMES;
    ProguardConfiguration configuration = application.options.getProguardConfiguration();
    if (configuration == null) {
      return new DebugParsingOptions(true, true, parsingOptions);
    }
    ProguardKeepAttributes keep =
        application.options.getProguardConfiguration().getKeepAttributes();

    boolean localsInfo =
        configuration.isKeepParameterNames()
            || keep.localVariableTable
            || keep.localVariableTypeTable
            || reachabilitySensitive;
    boolean lineInfo = keep.lineNumberTable;
    boolean methodParaeters = keep.methodParameters;

    if (!localsInfo && !lineInfo && !methodParaeters) {
      parsingOptions |= ClassReader.SKIP_DEBUG;
    }

    return new DebugParsingOptions(lineInfo, localsInfo, parsingOptions);
  }

  @Override
  public boolean verifyNoInputReaders() {
    assert context == null && application == null;
    return true;
  }

  private static boolean verifyNoReparseContext(DexClass owner) {
    for (DexEncodedMethod method : owner.virtualMethods()) {
      Code code = method.getCode();
      assert code == null || code.verifyNoInputReaders();
    }
    for (DexEncodedMethod method : owner.directMethods()) {
      Code code = method.getCode();
      assert code == null || code.verifyNoInputReaders();
    }
    return true;
  }

  @Override
  public Int2ReferenceMap<DebugLocalInfo> collectParameterInfo(
      DexEncodedMethod encodedMethod, AppView<?> appView) {
    return asCfCode().collectParameterInfo(encodedMethod, appView);
  }
}
