/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "dex_writer.h"

#include <stdint.h>

#include <vector>

#include "compact_dex_writer.h"
#include "dex/compact_dex_file.h"
#include "dex/dex_file_layout.h"
#include "dex/dex_file_types.h"
#include "dex/standard_dex_file.h"
#include "dex/utf.h"
#include "dexlayout.h"

namespace art {

constexpr uint32_t DexWriter::kDataSectionAlignment;

static size_t EncodeIntValue(int32_t value, uint8_t* buffer) {
  size_t length = 0;
  if (value >= 0) {
    while (value > 0x7f) {
      buffer[length++] = static_cast<uint8_t>(value);
      value >>= 8;
    }
  } else {
    while (value < -0x80) {
      buffer[length++] = static_cast<uint8_t>(value);
      value >>= 8;
    }
  }
  buffer[length++] = static_cast<uint8_t>(value);
  return length;
}

static size_t EncodeUIntValue(uint32_t value, uint8_t* buffer) {
  size_t length = 0;
  do {
    buffer[length++] = static_cast<uint8_t>(value);
    value >>= 8;
  } while (value != 0);
  return length;
}

static size_t EncodeLongValue(int64_t value, uint8_t* buffer) {
  size_t length = 0;
  if (value >= 0) {
    while (value > 0x7f) {
      buffer[length++] = static_cast<uint8_t>(value);
      value >>= 8;
    }
  } else {
    while (value < -0x80) {
      buffer[length++] = static_cast<uint8_t>(value);
      value >>= 8;
    }
  }
  buffer[length++] = static_cast<uint8_t>(value);
  return length;
}

union FloatUnion {
  float f_;
  uint32_t i_;
};

static size_t EncodeFloatValue(float value, uint8_t* buffer) {
  FloatUnion float_union;
  float_union.f_ = value;
  uint32_t int_value = float_union.i_;
  size_t index = 3;
  do {
    buffer[index--] = int_value >> 24;
    int_value <<= 8;
  } while (int_value != 0);
  return 3 - index;
}

union DoubleUnion {
  double d_;
  uint64_t l_;
};

static size_t EncodeDoubleValue(double value, uint8_t* buffer) {
  DoubleUnion double_union;
  double_union.d_ = value;
  uint64_t long_value = double_union.l_;
  size_t index = 7;
  do {
    buffer[index--] = long_value >> 56;
    long_value <<= 8;
  } while (long_value != 0);
  return 7 - index;
}

DexWriter::DexWriter(DexLayout* dex_layout, bool compute_offsets)
    : header_(dex_layout->GetHeader()),
      dex_layout_(dex_layout),
      compute_offsets_(compute_offsets) {}

void DexWriter::WriteEncodedValue(Stream* stream, dex_ir::EncodedValue* encoded_value) {
  size_t start = 0;
  size_t length;
  uint8_t buffer[8];
  int8_t type = encoded_value->Type();
  switch (type) {
    case DexFile::kDexAnnotationByte:
      length = EncodeIntValue(encoded_value->GetByte(), buffer);
      break;
    case DexFile::kDexAnnotationShort:
      length = EncodeIntValue(encoded_value->GetShort(), buffer);
      break;
    case DexFile::kDexAnnotationChar:
      length = EncodeUIntValue(encoded_value->GetChar(), buffer);
      break;
    case DexFile::kDexAnnotationInt:
      length = EncodeIntValue(encoded_value->GetInt(), buffer);
      break;
    case DexFile::kDexAnnotationLong:
      length = EncodeLongValue(encoded_value->GetLong(), buffer);
      break;
    case DexFile::kDexAnnotationFloat:
      length = EncodeFloatValue(encoded_value->GetFloat(), buffer);
      start = 4 - length;
      break;
    case DexFile::kDexAnnotationDouble:
      length = EncodeDoubleValue(encoded_value->GetDouble(), buffer);
      start = 8 - length;
      break;
    case DexFile::kDexAnnotationMethodType:
      length = EncodeUIntValue(encoded_value->GetProtoId()->GetIndex(), buffer);
      break;
    case DexFile::kDexAnnotationMethodHandle:
      length = EncodeUIntValue(encoded_value->GetMethodHandle()->GetIndex(), buffer);
      break;
    case DexFile::kDexAnnotationString:
      length = EncodeUIntValue(encoded_value->GetStringId()->GetIndex(), buffer);
      break;
    case DexFile::kDexAnnotationType:
      length = EncodeUIntValue(encoded_value->GetTypeId()->GetIndex(), buffer);
      break;
    case DexFile::kDexAnnotationField:
    case DexFile::kDexAnnotationEnum:
      length = EncodeUIntValue(encoded_value->GetFieldId()->GetIndex(), buffer);
      break;
    case DexFile::kDexAnnotationMethod:
      length = EncodeUIntValue(encoded_value->GetMethodId()->GetIndex(), buffer);
      break;
    case DexFile::kDexAnnotationArray:
      WriteEncodedValueHeader(stream, type, 0);
      WriteEncodedArray(stream, encoded_value->GetEncodedArray()->GetEncodedValues());
      return;
    case DexFile::kDexAnnotationAnnotation:
      WriteEncodedValueHeader(stream, type, 0);
      WriteEncodedAnnotation(stream, encoded_value->GetEncodedAnnotation());
      return;
    case DexFile::kDexAnnotationNull:
      WriteEncodedValueHeader(stream, type, 0);
      return;
    case DexFile::kDexAnnotationBoolean:
      WriteEncodedValueHeader(stream, type, encoded_value->GetBoolean() ? 1 : 0);
      return;
    default:
      return;
  }
  WriteEncodedValueHeader(stream, type, length - 1);
  stream->Write(buffer + start, length);
}

void DexWriter::WriteEncodedValueHeader(Stream* stream, int8_t value_type, size_t value_arg) {
  uint8_t buffer[1] = { static_cast<uint8_t>((value_arg << 5) | value_type) };
  stream->Write(buffer, sizeof(uint8_t));
}

void DexWriter::WriteEncodedArray(Stream* stream, dex_ir::EncodedValueVector* values) {
  stream->WriteUleb128(values->size());
  for (std::unique_ptr<dex_ir::EncodedValue>& value : *values) {
    WriteEncodedValue(stream, value.get());
  }
}

void DexWriter::WriteEncodedAnnotation(Stream* stream, dex_ir::EncodedAnnotation* annotation) {
  stream->WriteUleb128(annotation->GetType()->GetIndex());
  stream->WriteUleb128(annotation->GetAnnotationElements()->size());
  for (std::unique_ptr<dex_ir::AnnotationElement>& annotation_element :
      *annotation->GetAnnotationElements()) {
    stream->WriteUleb128(annotation_element->GetName()->GetIndex());
    WriteEncodedValue(stream, annotation_element->GetValue());
  }
}

void DexWriter::WriteEncodedFields(Stream* stream, dex_ir::FieldItemVector* fields) {
  uint32_t prev_index = 0;
  for (auto& field : *fields) {
    uint32_t index = field.GetFieldId()->GetIndex();
    stream->WriteUleb128(index - prev_index);
    stream->WriteUleb128(field.GetAccessFlags());
    prev_index = index;
  }
}

void DexWriter::WriteEncodedMethods(Stream* stream, dex_ir::MethodItemVector* methods) {
  uint32_t prev_index = 0;
  for (auto& method : *methods) {
    uint32_t index = method.GetMethodId()->GetIndex();
    uint32_t code_off = method.GetCodeItem() == nullptr ? 0 : method.GetCodeItem()->GetOffset();
    stream->WriteUleb128(index - prev_index);
    stream->WriteUleb128(method.GetAccessFlags());
    stream->WriteUleb128(code_off);
    prev_index = index;
  }
}

// TODO: Refactor this to remove duplicated boiler plate. One way to do this is adding
// function that takes a CollectionVector<T> and uses overloading.
void DexWriter::WriteStringIds(Stream* stream, bool reserve_only) {
  const uint32_t start = stream->Tell();
  for (auto& string_id : header_->StringIds()) {
    stream->AlignTo(SectionAlignment(DexFile::kDexTypeStringIdItem));
    if (reserve_only) {
      stream->Skip(string_id->GetSize());
    } else {
      uint32_t string_data_off = string_id->DataItem()->GetOffset();
      stream->Write(&string_data_off, string_id->GetSize());
    }
  }
  if (compute_offsets_ && start != stream->Tell()) {
    header_->StringIds().SetOffset(start);
  }
}

void DexWriter::WriteStringData(Stream* stream, dex_ir::StringData* string_data) {
  ProcessOffset(stream, string_data);
  stream->AlignTo(SectionAlignment(DexFile::kDexTypeStringDataItem));
  stream->WriteUleb128(CountModifiedUtf8Chars(string_data->Data()));
  stream->Write(string_data->Data(), strlen(string_data->Data()));
  // Skip null terminator (already zeroed out, no need to write).
  stream->Skip(1);
}

void DexWriter::WriteStringDatas(Stream* stream) {
  const uint32_t start = stream->Tell();
  for (auto& string_data : header_->StringDatas()) {
    WriteStringData(stream, string_data.get());
  }
  if (compute_offsets_ && start != stream->Tell()) {
    header_->StringDatas().SetOffset(start);
  }
}

void DexWriter::WriteTypeIds(Stream* stream) {
  uint32_t descriptor_idx[1];
  const uint32_t start = stream->Tell();
  for (auto& type_id : header_->TypeIds()) {
    stream->AlignTo(SectionAlignment(DexFile::kDexTypeTypeIdItem));
    ProcessOffset(stream, type_id.get());
    descriptor_idx[0] = type_id->GetStringId()->GetIndex();
    stream->Write(descriptor_idx, type_id->GetSize());
  }
  if (compute_offsets_ && start != stream->Tell()) {
    header_->TypeIds().SetOffset(start);
  }
}

void DexWriter::WriteTypeLists(Stream* stream) {
  uint32_t size[1];
  uint16_t list[1];
  const uint32_t start = stream->Tell();
  for (auto& type_list : header_->TypeLists()) {
    stream->AlignTo(SectionAlignment(DexFile::kDexTypeTypeList));
    size[0] = type_list->GetTypeList()->size();
    ProcessOffset(stream, type_list.get());
    stream->Write(size, sizeof(uint32_t));
    for (const dex_ir::TypeId* type_id : *type_list->GetTypeList()) {
      list[0] = type_id->GetIndex();
      stream->Write(list, sizeof(uint16_t));
    }
  }
  if (compute_offsets_ && start != stream->Tell()) {
    header_->TypeLists().SetOffset(start);
  }
}

void DexWriter::WriteProtoIds(Stream* stream, bool reserve_only) {
  uint32_t buffer[3];
  const uint32_t start = stream->Tell();
  for (auto& proto_id : header_->ProtoIds()) {
    stream->AlignTo(SectionAlignment(DexFile::kDexTypeProtoIdItem));
    ProcessOffset(stream, proto_id.get());
    if (reserve_only) {
      stream->Skip(proto_id->GetSize());
    } else {
      buffer[0] = proto_id->Shorty()->GetIndex();
      buffer[1] = proto_id->ReturnType()->GetIndex();
      buffer[2] = proto_id->Parameters() == nullptr ? 0 : proto_id->Parameters()->GetOffset();
      stream->Write(buffer, proto_id->GetSize());
    }
  }
  if (compute_offsets_ && start != stream->Tell()) {
    header_->ProtoIds().SetOffset(start);
  }
}

void DexWriter::WriteFieldIds(Stream* stream) {
  uint16_t buffer[4];
  const uint32_t start = stream->Tell();
  for (auto& field_id : header_->FieldIds()) {
    stream->AlignTo(SectionAlignment(DexFile::kDexTypeFieldIdItem));
    ProcessOffset(stream, field_id.get());
    buffer[0] = field_id->Class()->GetIndex();
    buffer[1] = field_id->Type()->GetIndex();
    buffer[2] = field_id->Name()->GetIndex();
    buffer[3] = field_id->Name()->GetIndex() >> 16;
    stream->Write(buffer, field_id->GetSize());
  }
  if (compute_offsets_ && start != stream->Tell()) {
    header_->FieldIds().SetOffset(start);
  }
}

void DexWriter::WriteMethodIds(Stream* stream) {
  uint16_t buffer[4];
  const uint32_t start = stream->Tell();
  for (auto& method_id : header_->MethodIds()) {
    stream->AlignTo(SectionAlignment(DexFile::kDexTypeMethodIdItem));
    ProcessOffset(stream, method_id.get());
    buffer[0] = method_id->Class()->GetIndex();
    buffer[1] = method_id->Proto()->GetIndex();
    buffer[2] = method_id->Name()->GetIndex();
    buffer[3] = method_id->Name()->GetIndex() >> 16;
    stream->Write(buffer, method_id->GetSize());
  }
  if (compute_offsets_ && start != stream->Tell()) {
    header_->MethodIds().SetOffset(start);
  }
}

void DexWriter::WriteEncodedArrays(Stream* stream) {
  const uint32_t start = stream->Tell();
  for (auto& encoded_array : header_->EncodedArrayItems()) {
    stream->AlignTo(SectionAlignment(DexFile::kDexTypeEncodedArrayItem));
    ProcessOffset(stream, encoded_array.get());
    WriteEncodedArray(stream, encoded_array->GetEncodedValues());
  }
  if (compute_offsets_ && start != stream->Tell()) {
    header_->EncodedArrayItems().SetOffset(start);
  }
}

void DexWriter::WriteAnnotations(Stream* stream) {
  uint8_t visibility[1];
  const uint32_t start = stream->Tell();
  for (auto& annotation : header_->AnnotationItems()) {
    stream->AlignTo(SectionAlignment(DexFile::kDexTypeAnnotationItem));
    visibility[0] = annotation->GetVisibility();
    ProcessOffset(stream, annotation.get());
    stream->Write(visibility, sizeof(uint8_t));
    WriteEncodedAnnotation(stream, annotation->GetAnnotation());
  }
  if (compute_offsets_ && start != stream->Tell()) {
    header_->AnnotationItems().SetOffset(start);
  }
}

void DexWriter::WriteAnnotationSets(Stream* stream) {
  uint32_t size[1];
  uint32_t annotation_off[1];
  const uint32_t start = stream->Tell();
  for (auto& annotation_set : header_->AnnotationSetItems()) {
    stream->AlignTo(SectionAlignment(DexFile::kDexTypeAnnotationSetItem));
    size[0] = annotation_set->GetItems()->size();
    ProcessOffset(stream, annotation_set.get());
    stream->Write(size, sizeof(uint32_t));
    for (dex_ir::AnnotationItem* annotation : *annotation_set->GetItems()) {
      annotation_off[0] = annotation->GetOffset();
      stream->Write(annotation_off, sizeof(uint32_t));
    }
  }
  if (compute_offsets_ && start != stream->Tell()) {
    header_->AnnotationSetItems().SetOffset(start);
  }
}

void DexWriter::WriteAnnotationSetRefs(Stream* stream) {
  uint32_t size[1];
  uint32_t annotations_off[1];
  const uint32_t start = stream->Tell();
  for (auto& annotation_set_ref : header_->AnnotationSetRefLists()) {
    stream->AlignTo(SectionAlignment(DexFile::kDexTypeAnnotationSetRefList));
    size[0] = annotation_set_ref->GetItems()->size();
    ProcessOffset(stream, annotation_set_ref.get());
    stream->Write(size, sizeof(uint32_t));
    for (dex_ir::AnnotationSetItem* annotation_set : *annotation_set_ref->GetItems()) {
      annotations_off[0] = annotation_set == nullptr ? 0 : annotation_set->GetOffset();
      stream->Write(annotations_off, sizeof(uint32_t));
    }
  }
  if (compute_offsets_ && start != stream->Tell()) {
    header_->AnnotationSetRefLists().SetOffset(start);
  }
}

void DexWriter::WriteAnnotationsDirectories(Stream* stream) {
  uint32_t directory_buffer[4];
  uint32_t annotation_buffer[2];
  const uint32_t start = stream->Tell();
  for (auto& annotations_directory : header_->AnnotationsDirectoryItems()) {
    stream->AlignTo(SectionAlignment(DexFile::kDexTypeAnnotationsDirectoryItem));
    ProcessOffset(stream, annotations_directory.get());
    directory_buffer[0] = annotations_directory->GetClassAnnotation() == nullptr ? 0 :
        annotations_directory->GetClassAnnotation()->GetOffset();
    directory_buffer[1] = annotations_directory->GetFieldAnnotations() == nullptr ? 0 :
        annotations_directory->GetFieldAnnotations()->size();
    directory_buffer[2] = annotations_directory->GetMethodAnnotations() == nullptr ? 0 :
        annotations_directory->GetMethodAnnotations()->size();
    directory_buffer[3] = annotations_directory->GetParameterAnnotations() == nullptr ? 0 :
        annotations_directory->GetParameterAnnotations()->size();
    stream->Write(directory_buffer, 4 * sizeof(uint32_t));
    if (annotations_directory->GetFieldAnnotations() != nullptr) {
      for (std::unique_ptr<dex_ir::FieldAnnotation>& field :
          *annotations_directory->GetFieldAnnotations()) {
        annotation_buffer[0] = field->GetFieldId()->GetIndex();
        annotation_buffer[1] = field->GetAnnotationSetItem()->GetOffset();
        stream->Write(annotation_buffer, 2 * sizeof(uint32_t));
      }
    }
    if (annotations_directory->GetMethodAnnotations() != nullptr) {
      for (std::unique_ptr<dex_ir::MethodAnnotation>& method :
          *annotations_directory->GetMethodAnnotations()) {
        annotation_buffer[0] = method->GetMethodId()->GetIndex();
        annotation_buffer[1] = method->GetAnnotationSetItem()->GetOffset();
        stream->Write(annotation_buffer, 2 * sizeof(uint32_t));
      }
    }
    if (annotations_directory->GetParameterAnnotations() != nullptr) {
      for (std::unique_ptr<dex_ir::ParameterAnnotation>& parameter :
          *annotations_directory->GetParameterAnnotations()) {
        annotation_buffer[0] = parameter->GetMethodId()->GetIndex();
        annotation_buffer[1] = parameter->GetAnnotations()->GetOffset();
        stream->Write(annotation_buffer, 2 * sizeof(uint32_t));
      }
    }
  }
  if (compute_offsets_ && start != stream->Tell()) {
    header_->AnnotationsDirectoryItems().SetOffset(start);
  }
}

void DexWriter::WriteHiddenapiClassData(Stream* stream) {
  if (header_->HiddenapiClassDatas().Empty()) {
    return;
  }
  DCHECK_EQ(header_->HiddenapiClassDatas().Size(), header_->ClassDefs().Size());

  stream->AlignTo(SectionAlignment(DexFile::kDexTypeHiddenapiClassData));
  const uint32_t start = stream->Tell();

  // Compute offsets for each class def and write the header.
  // data_header[0]: total size of the section
  // data_header[i + 1]: offset of class def[i] from the beginning of the section,
  //                     or zero if no data
  std::vector<uint32_t> data_header(header_->ClassDefs().Size() + 1, 0);
  data_header[0] = sizeof(uint32_t) * (header_->ClassDefs().Size() + 1);
  for (uint32_t i = 0; i < header_->ClassDefs().Size(); ++i) {
    uint32_t item_size = header_->HiddenapiClassDatas()[i]->ItemSize();
    data_header[i + 1] = item_size == 0u ? 0 : data_header[0];
    data_header[0] += item_size;
  }
  stream->Write(data_header.data(), sizeof(uint32_t) * data_header.size());

  // Write class data streams.
  for (uint32_t i = 0; i < header_->ClassDefs().Size(); ++i) {
    dex_ir::ClassDef* class_def = header_->ClassDefs()[i];
    const auto& item = header_->HiddenapiClassDatas()[i];
    DCHECK(item->GetClassDef() == class_def);

    if (data_header[i + 1] != 0u) {
      dex_ir::ClassData* class_data = class_def->GetClassData();
      DCHECK(class_data != nullptr);
      DCHECK_EQ(data_header[i + 1], stream->Tell() - start);
      for (const dex_ir::FieldItem& field : *class_data->StaticFields()) {
        stream->WriteUleb128(item->GetFlags(&field));
      }
      for (const dex_ir::FieldItem& field : *class_data->InstanceFields()) {
        stream->WriteUleb128(item->GetFlags(&field));
      }
      for (const dex_ir::MethodItem& method : *class_data->DirectMethods()) {
        stream->WriteUleb128(item->GetFlags(&method));
      }
      for (const dex_ir::MethodItem& method : *class_data->VirtualMethods()) {
        stream->WriteUleb128(item->GetFlags(&method));
      }
    }
  }
  DCHECK_EQ(stream->Tell() - start, data_header[0]);

  if (compute_offsets_ && start != stream->Tell()) {
    header_->HiddenapiClassDatas().SetOffset(start);
  }
}

void DexWriter::WriteDebugInfoItem(Stream* stream, dex_ir::DebugInfoItem* debug_info) {
  stream->AlignTo(SectionAlignment(DexFile::kDexTypeDebugInfoItem));
  ProcessOffset(stream, debug_info);
  stream->Write(debug_info->GetDebugInfo(), debug_info->GetDebugInfoSize());
}

void DexWriter::WriteDebugInfoItems(Stream* stream) {
  const uint32_t start = stream->Tell();
  for (auto& debug_info : header_->DebugInfoItems()) {
    WriteDebugInfoItem(stream, debug_info.get());
  }
  if (compute_offsets_ && start != stream->Tell()) {
    header_->DebugInfoItems().SetOffset(start);
  }
}

void DexWriter::WriteCodeItemPostInstructionData(Stream* stream,
                                                 dex_ir::CodeItem* code_item,
                                                 bool reserve_only) {
  if (code_item->TriesSize() != 0) {
    stream->AlignTo(dex::TryItem::kAlignment);
    // Write try items.
    for (std::unique_ptr<const dex_ir::TryItem>& try_item : *code_item->Tries()) {
      dex::TryItem disk_try_item;
      if (!reserve_only) {
        disk_try_item.start_addr_ = try_item->StartAddr();
        disk_try_item.insn_count_ = try_item->InsnCount();
        disk_try_item.handler_off_ = try_item->GetHandlers()->GetListOffset();
      }
      stream->Write(&disk_try_item, sizeof(disk_try_item));
    }
    // Leave offset pointing to the end of the try items.
    const size_t offset = stream->Tell();
    size_t max_offset = offset + stream->WriteUleb128(code_item->Handlers()->size());
    for (std::unique_ptr<const dex_ir::CatchHandler>& handlers : *code_item->Handlers()) {
      stream->Seek(offset + handlers->GetListOffset());
      uint32_t size = handlers->HasCatchAll() ? (handlers->GetHandlers()->size() - 1) * -1 :
          handlers->GetHandlers()->size();
      stream->WriteSleb128(size);
      for (std::unique_ptr<const dex_ir::TypeAddrPair>& handler : *handlers->GetHandlers()) {
        if (handler->GetTypeId() != nullptr) {
          stream->WriteUleb128(handler->GetTypeId()->GetIndex());
        }
        stream->WriteUleb128(handler->GetAddress());
      }
      // TODO: Clean this up to write the handlers in address order.
      max_offset = std::max(max_offset, stream->Tell());
    }
    stream->Seek(max_offset);
  }
}

void DexWriter::WriteCodeItem(Stream* stream,
                              dex_ir::CodeItem* code_item,
                              bool reserve_only) {
  DCHECK(code_item != nullptr);
  const uint32_t start_offset = stream->Tell();
  stream->AlignTo(SectionAlignment(DexFile::kDexTypeCodeItem));
  ProcessOffset(stream, code_item);

  StandardDexFile::CodeItem disk_code_item;
  if (!reserve_only) {
    disk_code_item.registers_size_ = code_item->RegistersSize();
    disk_code_item.ins_size_ = code_item->InsSize();
    disk_code_item.outs_size_ = code_item->OutsSize();
    disk_code_item.tries_size_ = code_item->TriesSize();
    disk_code_item.debug_info_off_ = code_item->DebugInfo() == nullptr
        ? 0
        : code_item->DebugInfo()->GetOffset();
    disk_code_item.insns_size_in_code_units_ = code_item->InsnsSize();
  }
  // Avoid using sizeof so that we don't write the fake instruction array at the end of the code
  // item.
  stream->Write(&disk_code_item, OFFSETOF_MEMBER(StandardDexFile::CodeItem, insns_));
  // Write the instructions.
  stream->Write(code_item->Insns(), code_item->InsnsSize() * sizeof(uint16_t));
  // Write the post instruction data.
  WriteCodeItemPostInstructionData(stream, code_item, reserve_only);
  if (reserve_only) {
    stream->Clear(start_offset, stream->Tell() - start_offset);
  }
}

void DexWriter::WriteCodeItems(Stream* stream, bool reserve_only) {
  DexLayoutSection* code_section = nullptr;
  if (!reserve_only && dex_layout_ != nullptr) {
    code_section = &dex_layout_->GetSections().sections_[static_cast<size_t>(
        DexLayoutSections::SectionType::kSectionTypeCode)];
  }
  const uint32_t start = stream->Tell();
  for (auto& code_item : header_->CodeItems()) {
    uint32_t start_offset = stream->Tell();
    WriteCodeItem(stream, code_item.get(), reserve_only);
    // Only add the section hotness info once.
    if (!reserve_only && code_section != nullptr) {
      auto it = dex_layout_->LayoutHotnessInfo().code_item_layout_.find(code_item.get());
      if (it != dex_layout_->LayoutHotnessInfo().code_item_layout_.end()) {
        code_section->parts_[static_cast<size_t>(it->second)].CombineSection(
            start_offset,
            stream->Tell());
      }
    }
  }

  if (compute_offsets_ && start != stream->Tell()) {
    header_->CodeItems().SetOffset(start);
  }
}

void DexWriter::WriteClassDefs(Stream* stream, bool reserve_only) {
  const uint32_t start = stream->Tell();
  uint32_t class_def_buffer[8];
  for (auto& class_def : header_->ClassDefs()) {
    stream->AlignTo(SectionAlignment(DexFile::kDexTypeClassDefItem));
    if (reserve_only) {
      stream->Skip(class_def->GetSize());
    } else {
      class_def_buffer[0] = class_def->ClassType()->GetIndex();
      class_def_buffer[1] = class_def->GetAccessFlags();
      class_def_buffer[2] = class_def->Superclass() == nullptr ? dex::kDexNoIndex :
          class_def->Superclass()->GetIndex();
      class_def_buffer[3] = class_def->InterfacesOffset();
      class_def_buffer[4] = class_def->SourceFile() == nullptr ? dex::kDexNoIndex :
          class_def->SourceFile()->GetIndex();
      class_def_buffer[5] = class_def->Annotations() == nullptr ? 0 :
          class_def->Annotations()->GetOffset();
      class_def_buffer[6] = class_def->GetClassData() == nullptr ? 0 :
          class_def->GetClassData()->GetOffset();
      class_def_buffer[7] = class_def->StaticValues() == nullptr ? 0 :
          class_def->StaticValues()->GetOffset();
      stream->Write(class_def_buffer, class_def->GetSize());
    }
  }
  if (compute_offsets_ && start != stream->Tell()) {
    header_->ClassDefs().SetOffset(start);
  }
}

void DexWriter::WriteClassDatas(Stream* stream) {
  const uint32_t start = stream->Tell();
  for (const std::unique_ptr<dex_ir::ClassData>& class_data :
      header_->ClassDatas()) {
    stream->AlignTo(SectionAlignment(DexFile::kDexTypeClassDataItem));
    ProcessOffset(stream, class_data.get());
    stream->WriteUleb128(class_data->StaticFields()->size());
    stream->WriteUleb128(class_data->InstanceFields()->size());
    stream->WriteUleb128(class_data->DirectMethods()->size());
    stream->WriteUleb128(class_data->VirtualMethods()->size());
    WriteEncodedFields(stream, class_data->StaticFields());
    WriteEncodedFields(stream, class_data->InstanceFields());
    WriteEncodedMethods(stream, class_data->DirectMethods());
    WriteEncodedMethods(stream, class_data->VirtualMethods());
  }
  if (compute_offsets_ && start != stream->Tell()) {
    header_->ClassDatas().SetOffset(start);
  }
}

void DexWriter::WriteCallSiteIds(Stream* stream, bool reserve_only) {
  const uint32_t start = stream->Tell();
  uint32_t call_site_off[1];
  for (auto& call_site_id : header_->CallSiteIds()) {
    stream->AlignTo(SectionAlignment(DexFile::kDexTypeCallSiteIdItem));
    if (reserve_only) {
      stream->Skip(call_site_id->GetSize());
    } else {
      call_site_off[0] = call_site_id->CallSiteItem()->GetOffset();
      stream->Write(call_site_off, call_site_id->GetSize());
    }
  }
  if (compute_offsets_ && start != stream->Tell()) {
    header_->CallSiteIds().SetOffset(start);
  }
}

void DexWriter::WriteMethodHandles(Stream* stream) {
  const uint32_t start = stream->Tell();
  uint16_t method_handle_buff[4];
  for (auto& method_handle : header_->MethodHandleItems()) {
    stream->AlignTo(SectionAlignment(DexFile::kDexTypeMethodHandleItem));
    method_handle_buff[0] = static_cast<uint16_t>(method_handle->GetMethodHandleType());
    method_handle_buff[1] = 0;  // unused.
    method_handle_buff[2] = method_handle->GetFieldOrMethodId()->GetIndex();
    method_handle_buff[3] = 0;  // unused.
    stream->Write(method_handle_buff, method_handle->GetSize());
  }
  if (compute_offsets_ && start != stream->Tell()) {
    header_->MethodHandleItems().SetOffset(start);
  }
}

void DexWriter::WriteMapItems(Stream* stream, MapItemQueue* queue) {
  // All the sections should already have been added.
  const uint32_t map_list_size = queue->size();
  stream->Write(&map_list_size, sizeof(map_list_size));
  while (!queue->empty()) {
    const MapItem& item = queue->top();
    dex::MapItem map_item;
    map_item.type_ = item.type_;
    map_item.size_ = item.size_;
    map_item.offset_ = item.offset_;
    map_item.unused_ = 0u;
    stream->Write(&map_item, sizeof(map_item));
    queue->pop();
  }
}

void DexWriter::GenerateAndWriteMapItems(Stream* stream) {
  MapItemQueue queue;

  // Header and index section.
  queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeHeaderItem, 1, 0));
  queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeStringIdItem,
                              header_->StringIds().Size(),
                              header_->StringIds().GetOffset()));
  queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeTypeIdItem,
                              header_->TypeIds().Size(),
                              header_->TypeIds().GetOffset()));
  queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeProtoIdItem,
                              header_->ProtoIds().Size(),
                              header_->ProtoIds().GetOffset()));
  queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeFieldIdItem,
                              header_->FieldIds().Size(),
                              header_->FieldIds().GetOffset()));
  queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeMethodIdItem,
                              header_->MethodIds().Size(),
                              header_->MethodIds().GetOffset()));
  queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeClassDefItem,
                              header_->ClassDefs().Size(),
                              header_->ClassDefs().GetOffset()));
  queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeCallSiteIdItem,
                              header_->CallSiteIds().Size(),
                              header_->CallSiteIds().GetOffset()));
  queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeMethodHandleItem,
                              header_->MethodHandleItems().Size(),
                              header_->MethodHandleItems().GetOffset()));
  // Data section.
  queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeMapList, 1, header_->MapListOffset()));
  queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeTypeList,
                              header_->TypeLists().Size(),
                              header_->TypeLists().GetOffset()));
  queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeAnnotationSetRefList,
                              header_->AnnotationSetRefLists().Size(),
                              header_->AnnotationSetRefLists().GetOffset()));
  queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeAnnotationSetItem,
                              header_->AnnotationSetItems().Size(),
                              header_->AnnotationSetItems().GetOffset()));
  queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeClassDataItem,
                              header_->ClassDatas().Size(),
                              header_->ClassDatas().GetOffset()));
  queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeCodeItem,
                              header_->CodeItems().Size(),
                              header_->CodeItems().GetOffset()));
  queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeStringDataItem,
                              header_->StringDatas().Size(),
                              header_->StringDatas().GetOffset()));
  queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeDebugInfoItem,
                              header_->DebugInfoItems().Size(),
                              header_->DebugInfoItems().GetOffset()));
  queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeAnnotationItem,
                              header_->AnnotationItems().Size(),
                              header_->AnnotationItems().GetOffset()));
  queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeEncodedArrayItem,
                              header_->EncodedArrayItems().Size(),
                              header_->EncodedArrayItems().GetOffset()));
  queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeAnnotationsDirectoryItem,
                              header_->AnnotationsDirectoryItems().Size(),
                              header_->AnnotationsDirectoryItems().GetOffset()));
  queue.AddIfNotEmpty(MapItem(DexFile::kDexTypeHiddenapiClassData,
                              header_->HiddenapiClassDatas().Empty() ? 0u : 1u,
                              header_->HiddenapiClassDatas().GetOffset()));
  WriteMapItems(stream, &queue);
}

void DexWriter::WriteHeader(Stream* stream) {
  StandardDexFile::Header header;
  if (CompactDexFile::IsMagicValid(header_->Magic())) {
    StandardDexFile::WriteMagic(header.magic_);
    // TODO: Should we write older versions based on the feature flags?
    StandardDexFile::WriteCurrentVersion(header.magic_);
  } else {
    // Standard dex -> standard dex, just reuse the same header.
    static constexpr size_t kMagicAndVersionLen =
        StandardDexFile::kDexMagicSize + StandardDexFile::kDexVersionLen;
    std::copy_n(header_->Magic(), kMagicAndVersionLen, header.magic_);
  }
  header.checksum_ = header_->Checksum();
  std::copy_n(header_->Signature(), DexFile::kSha1DigestSize, header.signature_);
  header.file_size_ = header_->FileSize();
  header.header_size_ = GetHeaderSize();
  header.endian_tag_ = header_->EndianTag();
  header.link_size_ = header_->LinkSize();
  header.link_off_ = header_->LinkOffset();
  header.map_off_ = header_->MapListOffset();
  header.string_ids_size_ = header_->StringIds().Size();
  header.string_ids_off_ = header_->StringIds().GetOffset();
  header.type_ids_size_ = header_->TypeIds().Size();
  header.type_ids_off_ = header_->TypeIds().GetOffset();
  header.proto_ids_size_ = header_->ProtoIds().Size();
  header.proto_ids_off_ = header_->ProtoIds().GetOffset();
  header.field_ids_size_ = header_->FieldIds().Size();
  header.field_ids_off_ = header_->FieldIds().GetOffset();
  header.method_ids_size_ = header_->MethodIds().Size();
  header.method_ids_off_ = header_->MethodIds().GetOffset();
  header.class_defs_size_ = header_->ClassDefs().Size();
  header.class_defs_off_ = header_->ClassDefs().GetOffset();
  header.data_size_ = header_->DataSize();
  header.data_off_ = header_->DataOffset();

  CHECK_EQ(sizeof(header), GetHeaderSize());
  static_assert(sizeof(header) == 0x70, "Size doesn't match dex spec");
  stream->Seek(0);
  stream->Overwrite(reinterpret_cast<uint8_t*>(&header), sizeof(header));
}

size_t DexWriter::GetHeaderSize() const {
  return sizeof(StandardDexFile::Header);
}

bool DexWriter::Write(DexContainer* output, std::string* error_msg) {
  DCHECK(error_msg != nullptr);

  Stream stream_storage(output->GetMainSection());
  Stream* stream = &stream_storage;

  // Starting offset is right after the header.
  stream->Seek(GetHeaderSize());

  // Based on: https://source.android.com/devices/tech/dalvik/dex-format
  // Since the offsets may not be calculated already, the writing must be done in the correct order.
  const uint32_t string_ids_offset = stream->Tell();
  WriteStringIds(stream, /*reserve_only=*/ true);
  WriteTypeIds(stream);
  const uint32_t proto_ids_offset = stream->Tell();
  WriteProtoIds(stream, /*reserve_only=*/ true);
  WriteFieldIds(stream);
  WriteMethodIds(stream);
  const uint32_t class_defs_offset = stream->Tell();
  WriteClassDefs(stream, /*reserve_only=*/ true);
  const uint32_t call_site_ids_offset = stream->Tell();
  WriteCallSiteIds(stream, /*reserve_only=*/ true);
  WriteMethodHandles(stream);

  uint32_t data_offset_ = 0u;
  if (compute_offsets_) {
    // Data section.
    stream->AlignTo(kDataSectionAlignment);
    data_offset_ = stream->Tell();
  }

  // Write code item first to minimize the space required for encoded methods.
  // Reserve code item space since we need the debug offsets to actually write them.
  const uint32_t code_items_offset = stream->Tell();
  WriteCodeItems(stream, /*reserve_only=*/ true);
  // Write debug info section.
  WriteDebugInfoItems(stream);
  {
    // Actually write code items since debug info offsets are calculated now.
    Stream::ScopedSeek seek(stream, code_items_offset);
    WriteCodeItems(stream, /*reserve_only=*/ false);
  }

  WriteEncodedArrays(stream);
  WriteAnnotations(stream);
  WriteAnnotationSets(stream);
  WriteAnnotationSetRefs(stream);
  WriteAnnotationsDirectories(stream);
  WriteTypeLists(stream);
  WriteClassDatas(stream);
  WriteStringDatas(stream);
  WriteHiddenapiClassData(stream);

  // Write delayed id sections that depend on data sections.
  {
    Stream::ScopedSeek seek(stream, string_ids_offset);
    WriteStringIds(stream, /*reserve_only=*/ false);
  }
  {
    Stream::ScopedSeek seek(stream, proto_ids_offset);
    WriteProtoIds(stream, /*reserve_only=*/ false);
  }
  {
    Stream::ScopedSeek seek(stream, class_defs_offset);
    WriteClassDefs(stream, /*reserve_only=*/ false);
  }
  {
    Stream::ScopedSeek seek(stream, call_site_ids_offset);
    WriteCallSiteIds(stream, /*reserve_only=*/ false);
  }

  // Write the map list.
  if (compute_offsets_) {
    stream->AlignTo(SectionAlignment(DexFile::kDexTypeMapList));
    header_->SetMapListOffset(stream->Tell());
  } else {
    stream->Seek(header_->MapListOffset());
  }
  GenerateAndWriteMapItems(stream);
  stream->AlignTo(kDataSectionAlignment);

  // Map items are included in the data section.
  if (compute_offsets_) {
    header_->SetDataSize(stream->Tell() - data_offset_);
    if (header_->DataSize() != 0) {
      // Offset must be zero when the size is zero.
      header_->SetDataOffset(data_offset_);
    } else {
      header_->SetDataOffset(0u);
    }
  }

  // Write link data if it exists.
  const std::vector<uint8_t>& link_data = header_->LinkData();
  if (link_data.size() > 0) {
    CHECK_EQ(header_->LinkSize(), static_cast<uint32_t>(link_data.size()));
    if (compute_offsets_) {
      header_->SetLinkOffset(stream->Tell());
    } else {
      stream->Seek(header_->LinkOffset());
    }
    stream->Write(&link_data[0], link_data.size());
  }

  // Write header last.
  if (compute_offsets_) {
    header_->SetFileSize(stream->Tell());
  }
  WriteHeader(stream);

  if (dex_layout_->GetOptions().update_checksum_) {
    header_->SetChecksum(DexFile::CalculateChecksum(stream->Begin(), header_->FileSize()));
    // Rewrite the header with the calculated checksum.
    WriteHeader(stream);
  }

  // Trim the map to make it sized as large as the dex file.
  output->GetMainSection()->Resize(header_->FileSize());
  return true;
}

bool DexWriter::Output(DexLayout* dex_layout,
                       std::unique_ptr<DexContainer>* container,
                       bool compute_offsets,
                       std::string* error_msg) {
  CHECK(dex_layout != nullptr);
  std::unique_ptr<DexWriter> writer;
  if (dex_layout->GetOptions().compact_dex_level_ != CompactDexLevel::kCompactDexLevelNone) {
    CHECK(compute_offsets) << "Compact dex requires computing offsets";
    writer.reset(new CompactDexWriter(dex_layout));
  } else {
    writer.reset(new DexWriter(dex_layout, compute_offsets));
  }
  DCHECK(container != nullptr);
  if (*container == nullptr) {
    *container = writer->CreateDexContainer();
  }
  return writer->Write(container->get(), error_msg);
}

void MapItemQueue::AddIfNotEmpty(const MapItem& item) {
  if (item.size_ != 0) {
    push(item);
  }
}

void DexWriter::ProcessOffset(Stream* stream, dex_ir::Item* item) {
  if (compute_offsets_) {
    item->SetOffset(stream->Tell());
  } else {
    // Not computing offsets, just use the one in the item.
    stream->Seek(item->GetOffset());
  }
}

std::unique_ptr<DexContainer> DexWriter::CreateDexContainer() const {
  return std::unique_ptr<DexContainer>(new DexWriter::Container);
}

}  // namespace art
