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

import static com.android.tools.r8.utils.DexVersion.Layout.SINGLE_DEX;
import static com.android.tools.r8.utils.LebUtils.sizeAsUleb128;

import com.android.tools.r8.ByteBufferProvider;
import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.errors.UnsupportedDefaultInterfaceMethodDiagnostic;
import com.android.tools.r8.errors.UnsupportedInvokeCustomDiagnostic;
import com.android.tools.r8.errors.UnsupportedPrivateInterfaceMethodDiagnostic;
import com.android.tools.r8.errors.UnsupportedStaticInterfaceMethodDiagnostic;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexAnnotation;
import com.android.tools.r8.graph.DexAnnotationDirectory;
import com.android.tools.r8.graph.DexAnnotationElement;
import com.android.tools.r8.graph.DexAnnotationSet;
import com.android.tools.r8.graph.DexCallSite;
import com.android.tools.r8.graph.DexCode.Try;
import com.android.tools.r8.graph.DexCode.TryHandler;
import com.android.tools.r8.graph.DexCode.TryHandler.TypeAddrPair;
import com.android.tools.r8.graph.DexDebugInfoForWriting;
import com.android.tools.r8.graph.DexEncodedAnnotation;
import com.android.tools.r8.graph.DexEncodedArray;
import com.android.tools.r8.graph.DexEncodedField;
import com.android.tools.r8.graph.DexEncodedMember;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexItem;
import com.android.tools.r8.graph.DexMember;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexMethodHandle;
import com.android.tools.r8.graph.DexMethodHandle.MethodHandleType;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexProto;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.DexTypeList;
import com.android.tools.r8.graph.DexValue;
import com.android.tools.r8.graph.DexWritableCode;
import com.android.tools.r8.graph.GraphLens;
import com.android.tools.r8.graph.IndexedDexItem;
import com.android.tools.r8.graph.ObjectToOffsetMapping;
import com.android.tools.r8.graph.ParameterAnnotationsList;
import com.android.tools.r8.graph.ProgramClassVisitor;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.position.MethodPosition;
import com.android.tools.r8.position.Position;
import com.android.tools.r8.synthesis.SyntheticNaming;
import com.android.tools.r8.utils.AndroidApiLevel;
import com.android.tools.r8.utils.DexVersion;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.IterableUtils;
import com.android.tools.r8.utils.LebUtils;
import com.google.common.collect.Sets;
import it.unimi.dsi.fastutil.objects.Object2IntLinkedOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Reference2IntLinkedOpenHashMap;
import it.unimi.dsi.fastutil.objects.Reference2IntMap;
import java.security.MessageDigest;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.ToIntFunction;
import java.util.zip.Adler32;

public class FileWriter {

  /** Simple pair of a byte buffer and its written length. */
  public static class ByteBufferResult {

    // Ownership of the buffer is transferred to the receiver of this result structure.
    public final CompatByteBuffer buffer;
    public final int length;

    protected ByteBufferResult(CompatByteBuffer buffer, int length) {
      this.buffer = buffer;
      this.length = length;
    }
  }

  private final AppView<?> appView;
  private final GraphLens graphLens;
  private final ObjectToOffsetMapping mapping;
  private final InternalOptions options;
  private final DexOutputBuffer dest;
  private final MixedSectionOffsets mixedSectionOffsets;
  private final CodeToKeep desugaredLibraryCodeToKeep;
  private final VirtualFile virtualFile;
  private final boolean includeStringData;

  public FileWriter(
      AppView<?> appView,
      ByteBufferProvider provider,
      ObjectToOffsetMapping mapping,
      CodeToKeep desugaredLibraryCodeToKeep,
      VirtualFile virtualFile) {
    this(
        appView,
        new DexOutputBuffer(provider),
        mapping,
        desugaredLibraryCodeToKeep,
        virtualFile,
        true);
  }

  public FileWriter(
      AppView<?> appView,
      DexOutputBuffer dexOutputBuffer,
      ObjectToOffsetMapping mapping,
      CodeToKeep desugaredLibraryCodeToKeep,
      VirtualFile virtualFile,
      boolean includeStringData) {
    this.appView = appView;
    this.graphLens = appView.graphLens();
    this.mapping = mapping;
    this.options = appView.options();
    this.dest = dexOutputBuffer;
    this.mixedSectionOffsets = new MixedSectionOffsets(options);
    this.desugaredLibraryCodeToKeep = desugaredLibraryCodeToKeep;
    this.virtualFile = virtualFile;
    this.includeStringData = includeStringData;
  }

  private NamingLens getNamingLens() {
    return appView.getNamingLens();
  }

  public MixedSectionOffsets getMixedSectionOffsets() {
    return mixedSectionOffsets;
  }

  public static void writeEncodedAnnotation(
      DexEncodedAnnotation annotation, DexOutputBuffer dest, ObjectToOffsetMapping mapping) {
    List<DexAnnotationElement> elements = new ArrayList<>(Arrays.asList(annotation.elements));
    elements.sort((a, b) -> a.name.acceptCompareTo(b.name, mapping.getCompareToVisitor()));
    dest.putUleb128(mapping.getOffsetFor(annotation.type));
    dest.putUleb128(elements.size());
    for (DexAnnotationElement element : elements) {
      dest.putUleb128(mapping.getOffsetFor(element.name));
      element.value.writeTo(dest, mapping);
    }
  }

  public FileWriter collect() {
    // Use the class array from the mapping, as it has a deterministic iteration order.
    new ProgramClassDependencyCollector(appView, mapping.getClasses()).run(mapping.getClasses());

    // Add the static values for all fields now that we have committed to their sorting.
    mixedSectionOffsets.getClassesWithData().forEach(this::addStaticFieldValues);

    // String data is not tracked by the MixedSectionCollection.
    assert mixedSectionOffsets.stringData.size() == 0;
    for (DexString string : mapping.getStrings()) {
      mixedSectionOffsets.add(string);
    }
    // Neither are the typelists in protos...
    for (DexProto proto : mapping.getProtos()) {
      mixedSectionOffsets.add(proto.getParameters());
    }

    DexItem.collectAll(mixedSectionOffsets, mapping.getCallSites());

    DexItem.collectAll(mixedSectionOffsets, mapping.getClasses());

    return this;
  }

  public static class DexContainerSection {
    private final FileWriter writer;
    private final DexOutputBuffer buffer;
    private final Layout layout;

    public DexContainerSection(FileWriter writer, DexOutputBuffer buffer, Layout layout) {
      this.writer = writer;
      this.buffer = buffer;
      this.layout = layout;
    }

    public FileWriter getFileWriter() {
      return writer;
    }

    public DexOutputBuffer getBuffer() {
      return buffer;
    }

    public Layout getLayout() {
      return layout;
    }
  }

  public ByteBufferResult generate() {
    DexContainerSection res = generate(0, SINGLE_DEX);
    return new ByteBufferResult(res.getBuffer().stealByteBuffer(), res.getLayout().getEndOfFile());
  }

  public DexContainerSection generate(int offset, DexVersion.Layout layoutType) {
    // Check restrictions on interface methods.
    checkInterfaceMethods();

    // Check restriction on the names of fields, methods and classes
    assert verifyNames();

    Layout layout = Layout.from(mapping, offset, layoutType, includeStringData);
    layout.setCodesOffset(layout.dataSectionOffset);

    // Sort the codes first, as their order might impact size due to alignment constraints.
    MixedSectionLayoutStrategy mixedSectionLayoutStrategy =
        MixedSectionLayoutStrategy.create(appView, mixedSectionOffsets, virtualFile);
    Collection<ProgramMethod> codes = mixedSectionLayoutStrategy.getCodeLayout();

    // Output the debug_info_items first, as they have no dependencies.
    dest.moveTo(layout.getCodesOffset() + sizeOfCodeItems(codes));
    if (mixedSectionOffsets.getDebugInfos().isEmpty()) {
      layout.setDebugInfosOffset(0);
    } else {
      // Ensure deterministic ordering of debug info by sorting consistent with the code objects.
      layout.setDebugInfosOffset(dest.align(1));
      Set<DexDebugInfoForWriting> seen = new HashSet<>(mixedSectionOffsets.getDebugInfos().size());
      for (ProgramMethod method : codes) {
        DexDebugInfoForWriting info =
            method.getDefinition().getCode().asDexWritableCode().getDebugInfoForWriting();
        if (info != null && seen.add(info)) {
          writeDebugItem(info);
        }
      }
    }

    // Remember the typelist offset for later.
    layout.setTypeListsOffset(dest.align(4)); // type_list are aligned.

    // Now output the code.
    dest.moveTo(layout.getCodesOffset());
    assert dest.isAligned(4);
    writeItems(codes, layout::alreadySetOffset, this::writeCodeItem, 4);
    assert layout.getDebugInfosOffset() == 0 || dest.position() == layout.getDebugInfosOffset();

    // Now the type lists and rest.
    dest.moveTo(layout.getTypeListsOffset());
    writeItems(
        mixedSectionLayoutStrategy.getTypeListLayout(),
        layout::alreadySetOffset,
        this::writeTypeList);
    if (includeStringData) {
      writeItems(
          mixedSectionLayoutStrategy.getStringDataLayout(),
          layout::setStringDataOffsets,
          this::writeStringData);
    } else {
      layout.stringDataOffsets = 0; // Empty string data section.
    }
    writeItems(
        mixedSectionLayoutStrategy.getAnnotationLayout(),
        layout::setAnnotationsOffset,
        this::writeAnnotation);
    writeItems(
        mixedSectionLayoutStrategy.getClassDataLayout(),
        layout::setClassDataOffset,
        this::writeClassData);
    writeItems(
        mixedSectionLayoutStrategy.getEncodedArrayLayout(),
        layout::setEncodedArraysOffset,
        this::writeEncodedArray);
    writeItems(
        mixedSectionLayoutStrategy.getAnnotationSetLayout(),
        layout::setAnnotationSetsOffset,
        this::writeAnnotationSet,
        4);
    writeItems(
        mixedSectionLayoutStrategy.getAnnotationSetRefListLayout(),
        layout::setAnnotationSetRefListsOffset,
        this::writeAnnotationSetRefList,
        4);
    writeItems(
        mixedSectionLayoutStrategy.getAnnotationDirectoryLayout(),
        layout::setAnnotationDirectoriesOffset,
        this::writeAnnotationDirectory,
        4);

    // Add the map at the end.
    writeMap(layout);
    layout.setEndOfFile(dest.position());

    // Now that we have all mixedSectionOffsets, lets write the indexed items.
    dest.moveTo(layout.headerOffset + layout.getHeaderSize());
    if (includeStringData) {
      writeFixedSectionItems(mapping.getStrings(), layout.stringIdsOffset, this::writeStringItem);
    } else {
      assert layout.stringIdsOffset == layout.typeIdsOffset;
    }
    writeFixedSectionItems(mapping.getTypes(), layout.typeIdsOffset, this::writeTypeItem);
    writeFixedSectionItems(mapping.getProtos(), layout.protoIdsOffset, this::writeProtoItem);
    writeFixedSectionItems(mapping.getFields(), layout.fieldIdsOffset, this::writeFieldItem);
    writeFixedSectionItems(mapping.getMethods(), layout.methodIdsOffset, this::writeMethodItem);
    writeFixedSectionItems(mapping.getClasses(), layout.classDefsOffset, this::writeClassDefItem);
    writeFixedSectionItems(mapping.getCallSites(), layout.callSiteIdsOffset, this::writeCallSite);
    writeFixedSectionItems(
        mapping.getMethodHandles(), layout.methodHandleIdsOffset, this::writeMethodHandle);

    // Fill in the header information.
    writeHeader(layout);
    if (includeStringData) {
      writeSignature(layout);
      writeChecksum(layout);
    }

    // Wrap backing buffer with actual length.
    return new DexContainerSection(this, dest, layout);
  }

  private void checkInterfaceMethods() {
    for (DexProgramClass clazz : mapping.getClasses()) {
      if (clazz.isInterface()) {
        for (DexEncodedMethod method : clazz.directMethods()) {
          checkInterfaceMethod(clazz, method);
        }
        for (DexEncodedMethod method : clazz.virtualMethods()) {
          checkInterfaceMethod(clazz, method);
        }
      }
    }
  }

  // Ensures interface method comply with requirements imposed by Android runtime:
  //  -- in pre-N Android versions interfaces may only have class
  //     initializer and public abstract methods.
  //  -- starting with N interfaces may also have public or private
  //     static methods, as well as public non-abstract (default)
  //     and private instance methods.
  private void checkInterfaceMethod(DexProgramClass holder, DexEncodedMethod method) {
    if (appView.dexItemFactory().isClassConstructor(method.getReference())) {
      return; // Class constructor is always OK.
    }
    if (method.accessFlags.isStatic()) {
      if (!options.canUseDefaultAndStaticInterfaceMethods()
          && !options.testing.allowStaticInterfaceMethodsForPreNApiLevel) {
        throw options.reporter.fatalError(
            new UnsupportedStaticInterfaceMethodDiagnostic(
                holder.getOrigin(), MethodPosition.create(method)));
      }
    } else {
      if (method.isInstanceInitializer()) {
        throw new CompilationError(
            "Interface must not have constructors: " + method.getReference().toSourceString());
      }
      if (!method.accessFlags.isAbstract() && !method.accessFlags.isPrivate() &&
          !options.canUseDefaultAndStaticInterfaceMethods()) {
        throw options.reporter.fatalError(
            new UnsupportedDefaultInterfaceMethodDiagnostic(
                holder.getOrigin(), MethodPosition.create(method)));
      }
    }

    if (method.accessFlags.isPrivate()) {
      if (options.canUsePrivateInterfaceMethods()) {
        return;
      }
      throw options.reporter.fatalError(
          new UnsupportedPrivateInterfaceMethodDiagnostic(
              holder.getOrigin(), MethodPosition.create(method)));
    }

    if (!method.accessFlags.isPublic()) {
      throw new CompilationError(
          "Interface methods must not be "
              + "protected or package private: "
              + method.getReference().toSourceString());
    }
  }

  private boolean verifyNames() {
    if (appView.dexItemFactory().getSkipNameValidationForTesting()) {
      return true;
    }

    AndroidApiLevel apiLevel = options.getMinApiLevel();
    for (DexField field : mapping.getFields()) {
      assert field.name.isValidSimpleName(apiLevel);
    }
    for (DexMethod method : mapping.getMethods()) {
      assert method.name.isValidSimpleName(apiLevel);
    }
    for (DexType type : mapping.getTypes()) {
      if (type.isClassType()) {
        assert DexString.isValidSimpleName(apiLevel, type.getName());
        assert SyntheticNaming.verifyNotInternalSynthetic(type);
      }
    }

    return true;
  }

  private <T extends IndexedDexItem> void writeFixedSectionItems(
      Collection<T> items, int offset, Consumer<T> writer) {
    assert dest.position() == offset;
    for (T item : items) {
      writer.accept(item);
    }
  }

  private void writeFixedSectionItems(
      DexProgramClass[] items, int offset, Consumer<DexProgramClass> writer) {
    assert dest.position() == offset;
    for (DexProgramClass item : items) {
      writer.accept(item);
    }
  }

  private <T extends DexItem> void writeItems(Collection<T> items, Consumer<Integer> offsetSetter,
      Consumer<T> writer) {
    writeItems(items, offsetSetter, writer, 1);
  }

  private <T> void writeItems(
      Collection<T> items, Consumer<Integer> offsetSetter, Consumer<T> writer, int alignment) {
    if (items.isEmpty()) {
      offsetSetter.accept(0);
    } else {
      offsetSetter.accept(dest.align(alignment));
      items.forEach(writer);
    }
  }

  private int sizeOfCodeItems(Iterable<ProgramMethod> methods) {
    int size = 0;
    for (ProgramMethod method : methods) {
      size = alignSize(4, size);
      size += sizeOfCodeItem(method.getDefinition().getCode().asDexWritableCode());
    }
    return size;
  }

  private int sizeOfCodeItem(DexWritableCode code) {
    int result = 16;
    int insnSize = code.codeSizeInBytes();
    result += insnSize * 2;
    result += code.getTries().length * 8;
    if (code.getHandlers().length > 0) {
      result = alignSize(4, result);
      result += LebUtils.sizeAsUleb128(code.getHandlers().length);
      for (TryHandler handler : code.getHandlers()) {
        boolean hasCatchAll = handler.catchAllAddr != TryHandler.NO_HANDLER;
        result += LebUtils
            .sizeAsSleb128(hasCatchAll ? -handler.pairs.length : handler.pairs.length);
        for (TypeAddrPair pair : handler.pairs) {
          result += sizeAsUleb128(mapping.getOffsetFor(pair.getType(graphLens)));
          result += sizeAsUleb128(pair.addr);
        }
        if (hasCatchAll) {
          result += sizeAsUleb128(handler.catchAllAddr);
        }
      }
    }
    return result;
  }

  private void writeStringItem(DexString string) {
    dest.putInt(mixedSectionOffsets.getOffsetFor(string));
  }

  private void writeTypeItem(DexType type) {
    DexString descriptor = getNamingLens().lookupDescriptor(type);
    dest.putInt(mapping.getOffsetFor(descriptor));
  }

  private void writeProtoItem(DexProto proto) {
    dest.putInt(mapping.getOffsetFor(proto.shorty));
    dest.putInt(mapping.getOffsetFor(proto.returnType));
    dest.putInt(mixedSectionOffsets.getOffsetFor(proto.parameters));
  }

  private void writeFieldItem(DexField field) {
    int classIdx = mapping.getOffsetFor(field.holder);
    assert (classIdx & 0xFFFF) == classIdx;
    dest.putShort((short) classIdx);
    int typeIdx = mapping.getOffsetFor(field.type);
    assert (typeIdx & 0xFFFF) == typeIdx;
    dest.putShort((short) typeIdx);
    DexString name = getNamingLens().lookupName(field);
    dest.putInt(mapping.getOffsetFor(name));
  }

  private void writeMethodItem(DexMethod method) {
    int classIdx = mapping.getOffsetFor(method.holder);
    assert (classIdx & 0xFFFF) == classIdx;
    dest.putShort((short) classIdx);
    int protoIdx = mapping.getOffsetFor(method.proto);
    assert (protoIdx & 0xFFFF) == protoIdx;
    dest.putShort((short) protoIdx);
    DexString name = getNamingLens().lookupName(method);
    dest.putInt(mapping.getOffsetFor(name));
  }

  private void writeClassDefItem(DexProgramClass clazz) {
    desugaredLibraryCodeToKeep.recordHierarchyOf(clazz);
    dest.putInt(mapping.getOffsetFor(clazz.type));
    dest.putInt(clazz.accessFlags.getAsDexAccessFlags());
    dest.putInt(
        clazz.superType == null ? Constants.NO_INDEX : mapping.getOffsetFor(clazz.superType));
    dest.putInt(mixedSectionOffsets.getOffsetFor(clazz.interfaces));
    dest.putInt(
        clazz.sourceFile == null ? Constants.NO_INDEX : mapping.getOffsetFor(clazz.sourceFile));
    dest.putInt(mixedSectionOffsets.getOffsetForAnnotationsDirectory(clazz));
    dest.putInt(
        clazz.hasMethodsOrFields() ? mixedSectionOffsets.getOffsetFor(clazz) : Constants.NO_OFFSET);
    dest.putInt(
        mixedSectionOffsets.getOffsetFor(mixedSectionOffsets.getStaticFieldValuesForClass(clazz)));
  }

  private void writeDebugItem(DexDebugInfoForWriting debugInfo) {
    mixedSectionOffsets.setOffsetFor(debugInfo, dest.position());
    dest.putBytes(new DebugBytecodeWriter(debugInfo, mapping, graphLens).generate());
  }

  private void writeCodeItem(ProgramMethod method) {
    writeCodeItem(method, method.getDefinition().getCode().asDexWritableCode());
  }

  private void writeCodeItem(ProgramMethod method, DexWritableCode code) {
    mixedSectionOffsets.setOffsetFor(method.getDefinition(), code, dest.align(4));
    // Fixed size header information.
    dest.putShort((short) code.getRegisterSize(method));
    dest.putShort((short) code.getIncomingRegisterSize(method));
    dest.putShort((short) code.getOutgoingRegisterSize());
    dest.putShort((short) code.getTries().length);
    dest.putInt(mixedSectionOffsets.getOffsetFor(code.getDebugInfoForWriting()));
    // Jump over the size.
    int insnSizeOffset = dest.position();
    dest.forward(4);
    // Write instruction stream.
    dest.putInstructions(appView, code, method, mapping, desugaredLibraryCodeToKeep);
    // Compute size and do the backward/forward dance to write the size at the beginning.
    int insnSize = dest.position() - insnSizeOffset - 4;
    dest.rewind(insnSize + 4);
    dest.putInt(insnSize / 2);
    dest.forward(insnSize);
    if (code.getTries().length > 0) {
      // The tries need to be 4 byte aligned.
      int beginOfTriesOffset = dest.align(4);
      // First write the handlers, so that we know their mixedSectionOffsets.
      dest.forward(code.getTries().length * 8);
      int beginOfHandlersOffset = dest.position();
      dest.putUleb128(code.getHandlers().length);
      short[] offsets = new short[code.getHandlers().length];
      int i = 0;
      for (TryHandler handler : code.getHandlers()) {
        offsets[i++] = (short) (dest.position() - beginOfHandlersOffset);
        boolean hasCatchAll = handler.catchAllAddr != TryHandler.NO_HANDLER;
        dest.putSleb128(hasCatchAll ? -handler.pairs.length : handler.pairs.length);
        for (TypeAddrPair pair : handler.pairs) {
          dest.putUleb128(mapping.getOffsetFor(pair.getType(graphLens)));
          dest.putUleb128(pair.addr);
          desugaredLibraryCodeToKeep.recordClass(pair.getType(graphLens));
        }
        if (hasCatchAll) {
          dest.putUleb128(handler.catchAllAddr);
        }
      }
      int endOfCodeOffset = dest.position();
      // Now write the tries.
      dest.moveTo(beginOfTriesOffset);
      for (Try aTry : code.getTries()) {
        dest.putInt(aTry.startAddress);
        dest.putShort((short) aTry.instructionCount);
        dest.putShort(offsets[aTry.handlerIndex]);
      }
      // And move to the end.
      dest.moveTo(endOfCodeOffset);
    }
  }

  private void writeTypeList(DexTypeList list) {
    assert !list.isEmpty();
    mixedSectionOffsets.setOffsetFor(list, dest.align(4));
    DexType[] values = list.values;
    dest.putInt(values.length);
    for (DexType type : values) {
      dest.putShort((short) mapping.getOffsetFor(type));
    }
  }

  private void writeStringData(DexString string) {
    mixedSectionOffsets.setOffsetFor(string, dest.position());
    dest.putUleb128(string.size);
    dest.putBytes(string.content);
  }

  private void writeAnnotation(DexAnnotation annotation) {
    mixedSectionOffsets.setOffsetFor(annotation, dest.position());
    dest.putByte((byte) annotation.visibility);
    writeEncodedAnnotation(annotation.annotation, dest, mapping);
  }

  private void writeAnnotationSet(DexAnnotationSet set) {
    mixedSectionOffsets.setOffsetFor(set, dest.align(4));
    List<DexAnnotation> annotations = new ArrayList<>(Arrays.asList(set.annotations));
    annotations.sort(
        (a, b) ->
            a.annotation.type.acceptCompareTo(b.annotation.type, mapping.getCompareToVisitor()));
    dest.putInt(annotations.size());
    for (DexAnnotation annotation : annotations) {
      dest.putInt(mixedSectionOffsets.getOffsetFor(annotation));
    }
  }

  private void writeAnnotationSetRefList(ParameterAnnotationsList parameterAnnotationsList) {
    assert !parameterAnnotationsList.isEmpty();
    mixedSectionOffsets.setOffsetFor(parameterAnnotationsList, dest.align(4));
    dest.putInt(parameterAnnotationsList.countNonMissing());
    for (int i = 0; i < parameterAnnotationsList.size(); i++) {
      if (parameterAnnotationsList.isMissing(i)) {
        // b/62300145: Maintain broken ParameterAnnotations attribute by only outputting the
        // non-missing annotation lists.
        continue;
      }
      dest.putInt(mixedSectionOffsets.getOffsetFor(parameterAnnotationsList.get(i)));
    }
  }

  private <D extends DexEncodedMember<D, R>, R extends DexMember<D, R>> void writeMemberAnnotations(
      List<D> items, ToIntFunction<D> getter) {
    for (D item : items) {
      dest.putInt(item.getReference().getOffset(mapping));
      dest.putInt(getter.applyAsInt(item));
    }
  }

  private void writeAnnotationDirectory(DexAnnotationDirectory annotationDirectory) {
    mixedSectionOffsets.setOffsetForAnnotationsDirectory(annotationDirectory, dest.align(4));
    dest.putInt(mixedSectionOffsets.getOffsetFor(annotationDirectory.getClazzAnnotations()));
    List<DexEncodedMethod> methodAnnotations =
        annotationDirectory.sortMethodAnnotations(mapping.getCompareToVisitor());
    List<DexEncodedMethod> parameterAnnotations =
        annotationDirectory.sortParameterAnnotations(mapping.getCompareToVisitor());
    List<DexEncodedField> fieldAnnotations =
        annotationDirectory.sortFieldAnnotations(mapping.getCompareToVisitor());
    dest.putInt(fieldAnnotations.size());
    dest.putInt(methodAnnotations.size());
    dest.putInt(parameterAnnotations.size());
    writeMemberAnnotations(
        fieldAnnotations, item -> mixedSectionOffsets.getOffsetFor(item.annotations()));
    writeMemberAnnotations(
        methodAnnotations, item -> mixedSectionOffsets.getOffsetFor(item.annotations()));
    writeMemberAnnotations(parameterAnnotations,
        item -> mixedSectionOffsets.getOffsetFor(item.parameterAnnotationsList));
  }

  private void writeEncodedFields(List<DexEncodedField> unsortedFields) {
    List<DexEncodedField> fields = new ArrayList<>(unsortedFields);
    fields.sort(
        (a, b) ->
            a.getReference().acceptCompareTo(b.getReference(), mapping.getCompareToVisitor()));
    int currentOffset = 0;
    for (DexEncodedField field : fields) {
      assert field.validateDexValue(appView.dexItemFactory());
      int nextOffset = mapping.getOffsetFor(field.getReference());
      assert nextOffset - currentOffset >= 0;
      dest.putUleb128(nextOffset - currentOffset);
      currentOffset = nextOffset;
      dest.putUleb128(field.accessFlags.getAsDexAccessFlags());
      desugaredLibraryCodeToKeep.recordField(field.getReference());
    }
  }

  private void writeEncodedMethods(Iterable<DexEncodedMethod> unsortedMethods) {
    List<DexEncodedMethod> methods = IterableUtils.toNewArrayList(unsortedMethods);
    methods.sort(
        (a, b) ->
            a.getReference().acceptCompareTo(b.getReference(), mapping.getCompareToVisitor()));
    int currentOffset = 0;
    for (DexEncodedMethod method : methods) {
      int nextOffset = mapping.getOffsetFor(method.getReference());
      assert nextOffset - currentOffset >= 0;
      dest.putUleb128(nextOffset - currentOffset);
      currentOffset = nextOffset;
      dest.putUleb128(method.accessFlags.getAsDexAccessFlags());
      DexWritableCode code = method.getDexWritableCodeOrNull();
      desugaredLibraryCodeToKeep.recordMethod(method.getReference());
      if (code == null) {
        assert method.shouldNotHaveCode();
        dest.putUleb128(0);
      } else {
        dest.putUleb128(mixedSectionOffsets.getOffsetFor(method, code));
        // Writing the methods starts to take up memory so we are going to flush the
        // code objects since they are no longer necessary after this.
        method.unsetCode();
      }
    }
  }

  private void writeClassData(DexProgramClass clazz) {
    assert clazz.hasMethodsOrFields();
    mixedSectionOffsets.setOffsetFor(clazz, dest.position());
    dest.putUleb128(clazz.staticFields().size());
    dest.putUleb128(clazz.instanceFields().size());
    dest.putUleb128(clazz.getMethodCollection().numberOfDirectMethods());
    dest.putUleb128(clazz.getMethodCollection().numberOfVirtualMethods());
    writeEncodedFields(clazz.staticFields());
    writeEncodedFields(clazz.instanceFields());
    writeEncodedMethods(clazz.directMethods());
    writeEncodedMethods(clazz.virtualMethods());
  }

  private void addStaticFieldValues(DexProgramClass clazz) {
    // We have collected the individual components of this array due to the data stored in
    // DexEncodedField#staticValues. However, we have to collect the DexEncodedArray itself
    // here.
    DexEncodedArray staticValues = clazz.computeStaticValuesArray(getNamingLens());
    if (staticValues != null) {
      mixedSectionOffsets.setStaticFieldValuesForClass(clazz, staticValues);
    }
  }

  private void writeMethodHandle(DexMethodHandle methodHandle) {
    checkThatInvokeCustomIsAllowed();
    MethodHandleType methodHandleDexType;
    switch (methodHandle.type) {
      case INVOKE_SUPER:
        methodHandleDexType = MethodHandleType.INVOKE_DIRECT;
        break;
      default:
        methodHandleDexType = methodHandle.type;
        break;
    }
    assert dest.isAligned(4);
    dest.putShort(methodHandleDexType.getValue());
    dest.putShort((short) 0); // unused
    int fieldOrMethodIdx;
    if (methodHandle.isMethodHandle()) {
      fieldOrMethodIdx = mapping.getOffsetFor(methodHandle.asMethod());
    } else {
      assert methodHandle.isFieldHandle();
      fieldOrMethodIdx = mapping.getOffsetFor(methodHandle.asField());
    }
    assert (fieldOrMethodIdx & 0xFFFF) == fieldOrMethodIdx;
    dest.putShort((short) fieldOrMethodIdx);
    dest.putShort((short) 0); // unused
  }

  private void writeCallSite(DexCallSite callSite) {
    checkThatInvokeCustomIsAllowed();
    assert dest.isAligned(4);
    dest.putInt(mixedSectionOffsets.getOffsetFor(callSite.getEncodedArray()));
  }

  private void writeEncodedArray(DexEncodedArray array) {
    mixedSectionOffsets.setOffsetFor(array, dest.position());
    dest.putUleb128(array.values.length);
    for (DexValue value : array.values) {
      value.writeTo(dest, mapping);
    }
  }

  public void writeMap(Layout layout) {
    int startOfMap = dest.align(4);
    layout.setMapOffset(startOfMap);
    dest.forward(4); // Leave space for size;
    List<MapItem> mapItems = layout.generateMapInfo(this);
    int size = 0;
    for (MapItem mapItem : mapItems) {
      size += includeStringData ? mapItem.write(dest) : mapItem.size();
    }
    dest.moveTo(startOfMap);
    dest.putInt(size);
    dest.forward(size * Constants.TYPE_MAP_LIST_ITEM_SIZE);
  }

  private byte[] dexVersionBytes() {
    if (options.testing.dexContainerExperiment) {
      return DexVersion.V41.getBytes();
    }
    // TODO(b/269089718): Remove this testing option and always emit DEX version 040 if DEX contains
    //  identifiers with whitespace.
    if (options.testing.dexVersion40FromApiLevel30
        && options.getMinApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.R)) {
      return DexVersion.V40.getBytes();
    }
    return options.testing.forceDexVersionBytes != null
        ? options.testing.forceDexVersionBytes
        : DexVersion.getDexVersion(options.getMinApiLevel()).getBytes();
  }

  private void writeHeader(Layout layout) {
    dest.moveTo(layout.headerOffset);
    dest.putBytes(Constants.DEX_FILE_MAGIC_PREFIX);
    dest.putBytes(dexVersionBytes());
    dest.putByte(Constants.DEX_FILE_MAGIC_SUFFIX);
    // Leave out checksum and signature for now.
    dest.moveTo(layout.headerOffset + Constants.FILE_SIZE_OFFSET);
    dest.putInt(layout.getEndOfFile() - layout.headerOffset);
    dest.putInt(layout.getHeaderSize());
    dest.putInt(Constants.ENDIAN_CONSTANT);
    dest.putInt(0);
    dest.putInt(0);
    dest.putInt(layout.getMapOffset());
    int numberOfStrings = mapping.getStrings().size();
    dest.putInt(numberOfStrings);
    dest.putInt(numberOfStrings == 0 ? 0 : layout.stringIdsOffset);
    int numberOfTypes = mapping.getTypes().size();
    dest.putInt(numberOfTypes);
    dest.putInt(numberOfTypes == 0 ? 0 : layout.typeIdsOffset);
    int numberOfProtos = mapping.getProtos().size();
    dest.putInt(numberOfProtos);
    dest.putInt(numberOfProtos == 0 ? 0 : layout.protoIdsOffset);
    int numberOfFields = mapping.getFields().size();
    dest.putInt(numberOfFields);
    dest.putInt(numberOfFields == 0 ? 0 : layout.fieldIdsOffset);
    int numberOfMethods = mapping.getMethods().size();
    dest.putInt(numberOfMethods);
    dest.putInt(numberOfMethods == 0 ? 0 : layout.methodIdsOffset);
    int numberOfClasses = mapping.getClasses().length;
    dest.putInt(numberOfClasses);
    dest.putInt(numberOfClasses == 0 ? 0 : layout.classDefsOffset);
    if (layout.isContainerSection()) {
      dest.putInt(0);
      dest.putInt(0);
      dest.putInt(layout.headerOffset);
    } else {
      dest.putInt(layout.getDataSectionSize());
      dest.putInt(layout.dataSectionOffset);
    }
    assert dest.position() == layout.stringIdsOffset;
  }

  private void writeSignature(Layout layout) {
    writeSignature(layout, dest);
  }

  public void writeSignature(Layout layout, DexOutputBuffer dexOutputBuffer) {
    try {
      MessageDigest md = MessageDigest.getInstance("SHA-1");
      md.update(
          dexOutputBuffer.asArray(),
          layout.headerOffset + Constants.FILE_SIZE_OFFSET,
          layout.getEndOfFile() - layout.headerOffset - Constants.FILE_SIZE_OFFSET);
      md.digest(dexOutputBuffer.asArray(), layout.headerOffset + Constants.SIGNATURE_OFFSET, 20);
    } catch (Exception e) {
      throw new RuntimeException(e);
    }
  }

  private void writeChecksum(Layout layout) {
    writeChecksum(layout, dest);
  }

  public void writeChecksum(Layout layout, DexOutputBuffer dexOutputBuffer) {
    Adler32 adler = new Adler32();
    adler.update(
        dexOutputBuffer.asArray(),
        layout.headerOffset + Constants.SIGNATURE_OFFSET,
        layout.getEndOfFile() - layout.headerOffset - Constants.SIGNATURE_OFFSET);
    dexOutputBuffer.moveTo(layout.headerOffset + Constants.CHECKSUM_OFFSET);
    dexOutputBuffer.putInt((int) adler.getValue());
  }

  private static int alignSize(int bytes, int value) {
    int mask = bytes - 1;
    return (value + mask) & ~mask;
  }

  public static class MapItem {
    final int type;
    final int offset;
    final int length;

    public MapItem(int type, int offset, int size) {
      this.type = type;
      this.offset = offset;
      this.length = size;
    }

    public int getType() {
      return type;
    }

    public int getOffset() {
      return offset;
    }

    public int getLength() {
      return length;
    }

    public int write(DexOutputBuffer dest) {
      if (length == 0) {
        return 0;
      }
      dest.putShort((short) type);
      dest.putShort((short) 0);
      dest.putInt(length);
      dest.putInt(offset);
      return 1;
    }

    public int size() {
      return length == 0 && type != Constants.TYPE_STRING_DATA_ITEM ? 0 : 1;
    }
  }

  public static class Layout {

    private static final int NOT_SET = -1;

    // Fixed size constant pool sections
    final int headerOffset;
    final int stringIdsOffset;
    final int typeIdsOffset;
    final int protoIdsOffset;
    final int fieldIdsOffset;
    final int methodIdsOffset;
    final int classDefsOffset;
    final int callSiteIdsOffset;
    final int methodHandleIdsOffset;
    final int dataSectionOffset;
    final DexVersion.Layout layoutType;

    // Mixed size sections
    private int codesOffset = NOT_SET; // aligned
    private int debugInfosOffset = NOT_SET;

    private int typeListsOffset = NOT_SET; // aligned
    private int stringDataOffsets = NOT_SET;
    private int annotationsOffset = NOT_SET;
    private int annotationSetsOffset = NOT_SET; // aligned
    private int annotationSetRefListsOffset = NOT_SET; // aligned
    private int annotationDirectoriesOffset = NOT_SET; // aligned
    private int classDataOffset = NOT_SET;
    private int encodedArraysOffset = NOT_SET;
    private int mapOffset = NOT_SET;
    private int endOfFile = NOT_SET;

    private Layout(
        int headerOffset,
        int stringIdsOffset,
        int typeIdsOffset,
        int protoIdsOffset,
        int fieldIdsOffset,
        int methodIdsOffset,
        int classDefsOffset,
        int callSiteIdsOffset,
        int methodHandleIdsOffset,
        int dataSectionOffset,
        DexVersion.Layout layoutType) {
      this.headerOffset = headerOffset;
      this.stringIdsOffset = stringIdsOffset;
      this.typeIdsOffset = typeIdsOffset;
      this.protoIdsOffset = protoIdsOffset;
      this.fieldIdsOffset = fieldIdsOffset;
      this.methodIdsOffset = methodIdsOffset;
      this.classDefsOffset = classDefsOffset;
      this.callSiteIdsOffset = callSiteIdsOffset;
      this.methodHandleIdsOffset = methodHandleIdsOffset;
      this.dataSectionOffset = dataSectionOffset;
      this.layoutType = layoutType;
      assert stringIdsOffset <= typeIdsOffset;
      assert typeIdsOffset <= protoIdsOffset;
      assert protoIdsOffset <= fieldIdsOffset;
      assert fieldIdsOffset <= methodIdsOffset;
      assert methodIdsOffset <= classDefsOffset;
      assert classDefsOffset <= dataSectionOffset;
      assert callSiteIdsOffset <= dataSectionOffset;
      assert methodHandleIdsOffset <= dataSectionOffset;
    }

    static Layout from(ObjectToOffsetMapping mapping) {
      return from(mapping, 0, SINGLE_DEX, true);
    }

    static Layout from(
        ObjectToOffsetMapping mapping,
        int offset,
        DexVersion.Layout layoutType,
        boolean includeStringData) {
      assert offset == 0 || layoutType.isContainer();
      return new Layout(
          offset,
          offset += layoutType.getHeaderSize(),
          offset +=
              includeStringData
                  ? mapping.getStrings().size() * Constants.TYPE_STRING_ID_ITEM_SIZE
                  : 0,
          offset += mapping.getTypes().size() * Constants.TYPE_TYPE_ID_ITEM_SIZE,
          offset += mapping.getProtos().size() * Constants.TYPE_PROTO_ID_ITEM_SIZE,
          offset += mapping.getFields().size() * Constants.TYPE_FIELD_ID_ITEM_SIZE,
          offset += mapping.getMethods().size() * Constants.TYPE_METHOD_ID_ITEM_SIZE,
          offset += mapping.getClasses().length * Constants.TYPE_CLASS_DEF_ITEM_SIZE,
          offset += mapping.getCallSites().size() * Constants.TYPE_CALL_SITE_ID_ITEM_SIZE,
          offset += mapping.getMethodHandles().size() * Constants.TYPE_METHOD_HANDLE_ITEM_SIZE,
          layoutType);
    }

    int getDataSectionSize() {
      int size = getEndOfFile() - dataSectionOffset;
      assert size % 4 == 0;
      return size;
    }

    private boolean isValidOffset(int value, boolean isAligned) {
      return value != NOT_SET && (!isAligned || value % 4 == 0);
    }

    public int getCodesOffset() {
      assert isValidOffset(codesOffset, true);
      return codesOffset;
    }

    public void setCodesOffset(int codesOffset) {
      assert this.codesOffset == NOT_SET;
      this.codesOffset = codesOffset;
    }

    public int getDebugInfosOffset() {
      assert isValidOffset(debugInfosOffset, false);
      return debugInfosOffset;
    }

    public void setDebugInfosOffset(int debugInfosOffset) {
      assert this.debugInfosOffset == NOT_SET;
      this.debugInfosOffset = debugInfosOffset;
    }

    public int getTypeListsOffset() {
      assert isValidOffset(typeListsOffset, true);
      return typeListsOffset;
    }

    public void setTypeListsOffset(int typeListsOffset) {
      assert this.typeListsOffset == NOT_SET;
      this.typeListsOffset = typeListsOffset;
    }

    public int getStringDataOffsets() {
      assert isValidOffset(stringDataOffsets, false);
      return stringDataOffsets;
    }

    public void setStringDataOffsets(int stringDataOffsets) {
      assert this.stringDataOffsets == NOT_SET;
      this.stringDataOffsets = stringDataOffsets;
    }

    public int getAnnotationsOffset() {
      assert isValidOffset(annotationsOffset, false);
      return annotationsOffset;
    }

    public void setAnnotationsOffset(int annotationsOffset) {
      assert this.annotationsOffset == NOT_SET;
      this.annotationsOffset = annotationsOffset;
    }

    public int getAnnotationSetsOffset() {
      assert isValidOffset(annotationSetsOffset, true);
      return annotationSetsOffset;
    }

    public void alreadySetOffset(int ignored) {
      // Intentionally empty.
    }

    public void setAnnotationSetsOffset(int annotationSetsOffset) {
      assert this.annotationSetsOffset == NOT_SET;
      this.annotationSetsOffset = annotationSetsOffset;
    }

    public int getAnnotationSetRefListsOffset() {
      assert isValidOffset(annotationSetRefListsOffset, true);
      return annotationSetRefListsOffset;
    }

    public void setAnnotationSetRefListsOffset(int annotationSetRefListsOffset) {
      assert this.annotationSetRefListsOffset == NOT_SET;
      this.annotationSetRefListsOffset = annotationSetRefListsOffset;
    }

    public int getAnnotationDirectoriesOffset() {
      assert isValidOffset(annotationDirectoriesOffset, true);
      return annotationDirectoriesOffset;
    }

    public void setAnnotationDirectoriesOffset(int annotationDirectoriesOffset) {
      assert this.annotationDirectoriesOffset == NOT_SET;
      this.annotationDirectoriesOffset = annotationDirectoriesOffset;
    }

    public int getClassDataOffset() {
      assert isValidOffset(classDataOffset, false);
      return classDataOffset;
    }

    public void setClassDataOffset(int classDataOffset) {
      assert this.classDataOffset == NOT_SET;
      this.classDataOffset = classDataOffset;
    }

    public int getEncodedArraysOffset() {
      assert isValidOffset(encodedArraysOffset, false);
      return encodedArraysOffset;
    }

    public void setEncodedArraysOffset(int encodedArraysOffset) {
      assert this.encodedArraysOffset == NOT_SET;
      this.encodedArraysOffset = encodedArraysOffset;
    }

    public int getMapOffset() {
      return mapOffset;
    }

    public void setMapOffset(int mapOffset) {
      this.mapOffset = mapOffset;
    }

    public boolean isContainerSection() {
      return layoutType.isContainer();
    }

    public int getHeaderSize() {
      return layoutType.getHeaderSize();
    }

    public List<MapItem> generateMapInfo(FileWriter fileWriter) {
      return generateMapInfo(
          fileWriter,
          0,
          fileWriter.mixedSectionOffsets.getStringData().size(),
          stringIdsOffset,
          getStringDataOffsets());
    }

    public List<MapItem> generateMapInfo(
        FileWriter fileWriter,
        int headerOffset,
        int stringIdsSize,
        int stringIdsOffset,
        int stringDataOffsets) {
      List<MapItem> mapItems = new ArrayList<>();
      mapItems.add(new MapItem(Constants.TYPE_HEADER_ITEM, headerOffset, 1));
      mapItems.add(
          new MapItem(
              Constants.TYPE_STRING_ID_ITEM,
              stringIdsOffset,
              fileWriter.mapping.getStrings().size()));
      mapItems.add(
          new MapItem(
              Constants.TYPE_TYPE_ID_ITEM, typeIdsOffset, fileWriter.mapping.getTypes().size()));
      mapItems.add(
          new MapItem(
              Constants.TYPE_PROTO_ID_ITEM, protoIdsOffset, fileWriter.mapping.getProtos().size()));
      mapItems.add(
          new MapItem(
              Constants.TYPE_FIELD_ID_ITEM, fieldIdsOffset, fileWriter.mapping.getFields().size()));
      mapItems.add(
          new MapItem(
              Constants.TYPE_METHOD_ID_ITEM,
              methodIdsOffset,
              fileWriter.mapping.getMethods().size()));
      mapItems.add(
          new MapItem(
              Constants.TYPE_CLASS_DEF_ITEM,
              classDefsOffset,
              fileWriter.mapping.getClasses().length));
      mapItems.add(
          new MapItem(
              Constants.TYPE_CALL_SITE_ID_ITEM,
              callSiteIdsOffset,
              fileWriter.mapping.getCallSites().size()));
      mapItems.add(
          new MapItem(
              Constants.TYPE_METHOD_HANDLE_ITEM,
              methodHandleIdsOffset,
              fileWriter.mapping.getMethodHandles().size()));
      mapItems.add(
          new MapItem(
              Constants.TYPE_CODE_ITEM,
              getCodesOffset(),
              fileWriter.mixedSectionOffsets.getCodes().size()));
      mapItems.add(
          new MapItem(
              Constants.TYPE_DEBUG_INFO_ITEM,
              getDebugInfosOffset(),
              fileWriter.mixedSectionOffsets.getDebugInfos().size()));
      mapItems.add(
          new MapItem(
              Constants.TYPE_TYPE_LIST,
              getTypeListsOffset(),
              fileWriter.mixedSectionOffsets.getTypeLists().size()));
      mapItems.add(
          new MapItem(
              Constants.TYPE_STRING_DATA_ITEM,
              stringDataOffsets,
              stringDataOffsets == 0 ? 0 : stringIdsSize));
      mapItems.add(
          new MapItem(
              Constants.TYPE_ANNOTATION_ITEM,
              getAnnotationsOffset(),
              fileWriter.mixedSectionOffsets.getAnnotations().size()));
      mapItems.add(
          new MapItem(
              Constants.TYPE_CLASS_DATA_ITEM,
              getClassDataOffset(),
              fileWriter.mixedSectionOffsets.getClassesWithData().size()));
      mapItems.add(
          new MapItem(
              Constants.TYPE_ENCODED_ARRAY_ITEM,
              getEncodedArraysOffset(),
              fileWriter.mixedSectionOffsets.getEncodedArrays().size()));
      mapItems.add(
          new MapItem(
              Constants.TYPE_ANNOTATION_SET_ITEM,
              getAnnotationSetsOffset(),
              fileWriter.mixedSectionOffsets.getAnnotationSets().size()));
      mapItems.add(
          new MapItem(
              Constants.TYPE_ANNOTATION_SET_REF_LIST,
              getAnnotationSetRefListsOffset(),
              fileWriter.mixedSectionOffsets.getAnnotationSetRefLists().size()));
      mapItems.add(
          new MapItem(
              Constants.TYPE_ANNOTATIONS_DIRECTORY_ITEM,
              getAnnotationDirectoriesOffset(),
              fileWriter.mixedSectionOffsets.getAnnotationDirectories().size()));
      mapItems.add(new MapItem(Constants.TYPE_MAP_LIST, getMapOffset(), 1));
      mapItems.sort(Comparator.comparingInt(MapItem::getOffset));
      return mapItems;
    }

    public int getEndOfFile() {
      return endOfFile;
    }

    public void setEndOfFile(int endOfFile) {
      this.endOfFile = endOfFile;
    }

    @Override
    public String toString() {
      StringBuilder builder = new StringBuilder();
      if (false) {
        builder.append("headerOffset: ").append(headerOffset).append("\n");
        builder.append("stringIdsOffset: ").append(stringIdsOffset).append("\n");
        builder.append("typeIdsOffset: ").append(typeIdsOffset).append("\n");
        builder.append("protoIdsOffset: ").append(protoIdsOffset).append("\n");
        builder.append("fieldIdsOffset: ").append(fieldIdsOffset).append("\n");
        builder.append("methodIdsOffset: ").append(methodIdsOffset).append("\n");
        builder.append("classDefsOffset: ").append(classDefsOffset).append("\n");
        builder.append("callSiteIdsOffset: ").append(callSiteIdsOffset).append("\n");
        builder.append("methodHandleIdsOffset: ").append(methodHandleIdsOffset).append("\n");
        builder.append("dataSectionOffset: ").append(dataSectionOffset).append("\n");

        // Mixed size sections
        builder.append("codesOffset: ").append(codesOffset).append("\n");
        builder.append("debugInfosOffset: ").append(debugInfosOffset).append("\n");

        builder.append("typeListsOffset: ").append(typeListsOffset).append("\n");
        builder.append("stringDataOffsets: ").append(stringDataOffsets).append("\n");
        builder.append("annotationsOffset: ").append(annotationsOffset).append("\n");
        builder.append("annotationSetsOffset: ").append(annotationSetsOffset).append("\n");
        builder
            .append("annotationSetRefListsOffset: ")
            .append(annotationSetRefListsOffset)
            .append("\n");
        builder
            .append("annotationDirectoriesOffset: ")
            .append(annotationDirectoriesOffset)
            .append("\n");
        builder.append("classDataOffset: ").append(classDataOffset).append("\n");
        builder.append("encodedArraysOffset: ").append(encodedArraysOffset).append("\n");
        builder.append("mapOffset: ").append(mapOffset).append("\n");
        builder.append("endOfFile: ").append(endOfFile).append("\n");
      } else {
        builder.append("Header: ").append(stringIdsOffset - headerOffset).append("\n");
        builder.append("StringIds: ").append(typeIdsOffset - stringIdsOffset).append("\n");
        builder.append("typeIds: ").append(protoIdsOffset - typeIdsOffset).append("\n");
        builder.append("protoIds: ").append(fieldIdsOffset - protoIdsOffset).append("\n");
        builder.append("fieldIds: ").append(methodIdsOffset - fieldIdsOffset).append("\n");
        builder.append("methodIds: ").append(classDefsOffset - methodIdsOffset).append("\n");
        builder.append("classDefs: ").append(callSiteIdsOffset - classDefsOffset).append("\n");
        builder
            .append("callSiteIds: ")
            .append(methodHandleIdsOffset - callSiteIdsOffset)
            .append("\n");
        builder
            .append("methodHandleIds: ")
            .append(dataSectionOffset - methodHandleIdsOffset)
            .append("\n");

        // Mixed size sections
        builder.append("code: ").append(debugInfosOffset - codesOffset).append("\n");
        builder.append("debugInfo: ").append(typeListsOffset - debugInfosOffset).append("\n");

        builder
            .append("typeList: ")
            .append(
                (stringDataOffsets > 0 ? stringDataOffsets : annotationsOffset) - typeListsOffset)
            .append("\n");
        builder
            .append("stringData: ")
            .append(stringDataOffsets > 0 ? annotationsOffset - stringDataOffsets : 0)
            .append("\n");
        builder.append("annotations: ").append(classDataOffset - annotationsOffset).append("\n");
        builder.append("classData: ").append(encodedArraysOffset - classDataOffset).append("\n");
        builder
            .append("encodedArrays: ")
            .append(mapOffset - annotationSetRefListsOffset)
            .append("\n");
        builder
            .append("annotationSets: ")
            .append(annotationSetRefListsOffset - annotationSetsOffset)
            .append("\n");
        builder
            .append("annotationSetRefLists: ")
            .append(annotationDirectoriesOffset - annotationSetRefListsOffset)
            .append("\n");
        builder
            .append("annotationDirectories: ")
            .append(mapOffset - annotationDirectoriesOffset)
            .append("\n");
        builder.append("map: ").append(endOfFile - mapOffset).append("\n");
        builder.append("endOfFile: ").append(endOfFile).append("\n");
      }
      return builder.toString();
    }
  }

  /**
   * Encapsulates information on the offsets of items in the sections of the mixed data part of the
   * DEX file. Initially, items are collected using the {@link MixedSectionCollection} traversal and
   * all offsets are unset. When writing a section, the offsets of the written items are stored.
   * These offsets are then used to resolve cross-references between items from different sections
   * into a file offset.
   */
  static class MixedSectionOffsets extends MixedSectionCollection {

    private static final int NOT_SET = -1;
    private static final int NOT_KNOWN = -2;

    private final Reference2IntMap<DexEncodedMethod> codes = createReference2IntMap();
    private final Object2IntMap<DexDebugInfoForWriting> debugInfos = createObject2IntMap();
    private final Object2IntMap<DexTypeList> typeLists = createObject2IntMap();
    private final Reference2IntMap<DexString> stringData = createReference2IntMap();
    private final Object2IntMap<DexAnnotation> annotations = createObject2IntMap();
    private final Object2IntMap<DexAnnotationSet> annotationSets = createObject2IntMap();
    private final Object2IntMap<ParameterAnnotationsList> annotationSetRefLists
        = createObject2IntMap();
    private final Object2IntMap<DexAnnotationDirectory> annotationDirectories
        = createObject2IntMap();
    private final Reference2IntMap<DexProgramClass> classesWithData = createReference2IntMap();
    private final Object2IntMap<DexEncodedArray> encodedArrays = createObject2IntMap();
    private final Map<DexProgramClass, DexAnnotationDirectory> classToAnnotationDirectory =
        new IdentityHashMap<>();
    private final Map<DexProgramClass, DexEncodedArray> classToStaticFieldValues =
        new IdentityHashMap<>();

    private final InternalOptions options;

    private static <T> Object2IntMap<T> createObject2IntMap() {
      Object2IntMap<T> result = new Object2IntLinkedOpenHashMap<>();
      result.defaultReturnValue(NOT_KNOWN);
      return result;
    }

    private static <T> Reference2IntMap<T> createReference2IntMap() {
      Reference2IntMap<T> result = new Reference2IntLinkedOpenHashMap<>();
      result.defaultReturnValue(NOT_KNOWN);
      return result;
    }

    private MixedSectionOffsets(InternalOptions options) {
      this.options = options;
    }

    private <T> boolean add(Object2IntMap<T> map, T item) {
      if (!map.containsKey(item)) {
        map.put(item, NOT_SET);
        return true;
      }
      return false;
    }

    private <T> boolean add(Reference2IntMap<T> map, T item) {
      if (!map.containsKey(item)) {
        map.put(item, NOT_SET);
        return true;
      }
      return false;
    }

    @Override
    public boolean add(DexProgramClass aClassWithData) {
      return add(classesWithData, aClassWithData);
    }

    @Override
    public boolean add(DexEncodedArray encodedArray) {
      return add(encodedArrays, encodedArray);
    }

    @Override
    public boolean add(DexAnnotationSet annotationSet) {
      if (!options.canHaveDalvikEmptyAnnotationSetBug() && annotationSet.isEmpty()) {
        return false;
      }
      return add(annotationSets, annotationSet);
    }

    @Override
    public void visit(DexEncodedMethod method) {
      method.collectMixedSectionItemsWithCodeMapping(this);
    }

    @Override
    public boolean add(DexEncodedMethod method, DexWritableCode code) {
      return add(codes, method);
    }

    @Override
    public boolean add(DexDebugInfoForWriting debugInfo) {
      return add(debugInfos, debugInfo);
    }

    @Override
    public boolean add(DexTypeList typeList) {
      if (typeList.isEmpty()) {
        return false;
      }
      return add(typeLists, typeList);
    }

    @Override
    public boolean add(ParameterAnnotationsList annotationSetRefList) {
      if (annotationSetRefList.isEmpty()) {
        return false;
      }
      return add(annotationSetRefLists, annotationSetRefList);
    }

    @Override
    public boolean add(DexAnnotation annotation) {
      return add(annotations, annotation);
    }

    @Override
    public void setAnnotationsDirectoryForClass(
        DexProgramClass clazz, DexAnnotationDirectory annotationDirectory) {
      DexAnnotationDirectory previous = classToAnnotationDirectory.put(clazz, annotationDirectory);
      assert previous == null;
      add(annotationDirectories, annotationDirectory);
    }

    @Override
    public void setStaticFieldValuesForClass(
        DexProgramClass clazz, DexEncodedArray staticFieldValues) {
      DexEncodedArray previous = classToStaticFieldValues.put(clazz, staticFieldValues);
      assert previous == null;
      add(staticFieldValues);
    }

    public boolean add(DexString string) {
      return add(stringData, string);
    }

    public Collection<DexEncodedMethod> getCodes() {
      return codes.keySet();
    }

    public Collection<DexDebugInfoForWriting> getDebugInfos() {
      return debugInfos.keySet();
    }

    public Collection<DexTypeList> getTypeLists() {
      return typeLists.keySet();
    }

    public Collection<DexString> getStringData() {
      return stringData.keySet();
    }

    public Collection<DexAnnotation> getAnnotations() {
      return annotations.keySet();
    }

    public Collection<DexAnnotationSet> getAnnotationSets() {
      return annotationSets.keySet();
    }

    public Collection<ParameterAnnotationsList> getAnnotationSetRefLists() {
      return annotationSetRefLists.keySet();
    }

    public Collection<DexProgramClass> getClassesWithData() {
      return classesWithData.keySet();
    }

    public Collection<DexAnnotationDirectory> getAnnotationDirectories() {
      return annotationDirectories.keySet();
    }

    public Collection<DexEncodedArray> getEncodedArrays() {
      return encodedArrays.keySet();
    }

    private <T> int lookup(T item, Object2IntMap<T> table) {
      if (item == null) {
        return Constants.NO_OFFSET;
      }
      int offset = table.getInt(item);
      assert offset != NOT_SET && offset != NOT_KNOWN;
      return offset;
    }

    private <T> int lookup(T item, Reference2IntMap<T> table) {
      if (item == null) {
        return Constants.NO_OFFSET;
      }
      int offset = table.getInt(item);
      assert offset != NOT_SET && offset != NOT_KNOWN;
      return offset;
    }

    public int getOffsetFor(DexString item) {
      return lookup(item, stringData);
    }

    public int getOffsetFor(DexTypeList parameters) {
      if (parameters.isEmpty()) {
        return 0;
      }
      return lookup(parameters, typeLists);
    }

    public int getOffsetFor(DexProgramClass aClassWithData) {
      return lookup(aClassWithData, classesWithData);
    }

    public int getOffsetFor(DexEncodedArray encodedArray) {
      return lookup(encodedArray, encodedArrays);
    }

    public int getOffsetFor(DexDebugInfoForWriting debugInfo) {
      return lookup(debugInfo, debugInfos);
    }

    public int getOffsetForAnnotationsDirectory(DexProgramClass clazz) {
      if (!clazz.hasClassOrMemberAnnotations()) {
        return Constants.NO_OFFSET;
      }
      int offset = annotationDirectories.getInt(getAnnotationDirectoryForClass(clazz));
      assert offset != NOT_KNOWN;
      return offset;
    }

    public int getOffsetFor(DexAnnotation annotation) {
      return lookup(annotation, annotations);
    }

    public int getOffsetFor(DexAnnotationSet annotationSet) {
      if (!options.canHaveDalvikEmptyAnnotationSetBug() && annotationSet.isEmpty()) {
        return 0;
      }
      return lookup(annotationSet, annotationSets);
    }

    public int getOffsetFor(ParameterAnnotationsList annotationSetRefList) {
      if (annotationSetRefList.isEmpty()) {
        return 0;
      }
      return lookup(annotationSetRefList, annotationSetRefLists);
    }

    public int getOffsetFor(DexEncodedMethod method, DexWritableCode code) {
      return lookup(method, codes);
    }

    private <T> void setOffsetFor(T item, int offset, Object2IntMap<T> map) {
      int old = map.put(item, offset);
      assert old <= NOT_SET;
    }

    private <T> void setOffsetFor(T item, int offset, Reference2IntMap<T> map) {
      int old = map.put(item, offset);
      assert old <= NOT_SET;
    }

    void setOffsetFor(DexDebugInfoForWriting debugInfo, int offset) {
      setOffsetFor(debugInfo, offset, debugInfos);
    }

    void setOffsetFor(DexEncodedMethod method, DexWritableCode code, int offset) {
      setOffsetFor(method, offset, codes);
    }

    void setOffsetFor(DexTypeList typeList, int offset) {
      assert offset != 0 && !typeLists.isEmpty();
      setOffsetFor(typeList, offset, typeLists);
    }

    void setOffsetFor(DexString string, int offset) {
      setOffsetFor(string, offset, stringData);
    }

    void setOffsetFor(DexAnnotation annotation, int offset) {
      setOffsetFor(annotation, offset, annotations);
    }

    void setOffsetFor(DexAnnotationSet annotationSet, int offset) {
      assert options.canHaveDalvikEmptyAnnotationSetBug() || !annotationSet.isEmpty();
      setOffsetFor(annotationSet, offset, annotationSets);
    }

    void setOffsetForAnnotationsDirectory(DexAnnotationDirectory annotationDirectory, int offset) {
      setOffsetFor(annotationDirectory, offset, annotationDirectories);
    }

    void setOffsetFor(DexProgramClass aClassWithData, int offset) {
      setOffsetFor(aClassWithData, offset, classesWithData);
    }

    void setOffsetFor(DexEncodedArray encodedArray, int offset) {
      setOffsetFor(encodedArray, offset, encodedArrays);
    }

    void setOffsetFor(ParameterAnnotationsList annotationSetRefList, int offset) {
      assert offset != 0 && !annotationSetRefList.isEmpty();
      setOffsetFor(annotationSetRefList, offset, annotationSetRefLists);
    }

    DexAnnotationDirectory getAnnotationDirectoryForClass(DexProgramClass clazz) {
      return classToAnnotationDirectory.get(clazz);
    }

    DexEncodedArray getStaticFieldValuesForClass(DexProgramClass clazz) {
      return classToStaticFieldValues.get(clazz);
    }
  }

  private class ProgramClassDependencyCollector extends ProgramClassVisitor {

    private final Set<DexProgramClass> includedClasses = Sets.newIdentityHashSet();

    ProgramClassDependencyCollector(AppView<?> appView, DexProgramClass[] includedClasses) {
      super(appView);
      Collections.addAll(this.includedClasses, includedClasses);
    }

    @Override
    public void visit(DexProgramClass clazz) {
      // Only visit classes that are part of the current file.
      if (includedClasses.contains(clazz)) {
        clazz.addDependencies(mixedSectionOffsets);
      }
    }
  }

  private void checkThatInvokeCustomIsAllowed() {
    if (!options.canUseInvokeCustom()) {
      throw options.reporter.fatalError(
          new UnsupportedInvokeCustomDiagnostic(Origin.unknown(), Position.UNKNOWN));
    }
  }
}
