/*
 * 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.
 *
 * Header file of the dexlayout utility.
 *
 * This is a tool to read dex files into an internal representation,
 * reorganize the representation, and emit dex files with a better
 * file layout.
 */

#ifndef ART_DEXLAYOUT_DEXLAYOUT_H_
#define ART_DEXLAYOUT_DEXLAYOUT_H_

#include <stdint.h>
#include <stdio.h>

#include <set>
#include <unordered_map>

#include "base/mem_map.h"
#include "dex/compact_dex_level.h"
#include "dex_container.h"
#include "dex/dex_file_layout.h"
#include "dex_ir.h"

namespace art {

class DexFile;
class Instruction;
class ProfileCompilationInfo;

/* Supported output formats. */
enum OutputFormat {
  kOutputPlain = 0,  // default
  kOutputXml,        // XML-style
};

/* Command-line options. */
class Options {
 public:
  Options() = default;

  bool dump_ = false;
  bool build_dex_ir_ = false;
  bool checksum_only_ = false;
  bool disassemble_ = false;
  bool exports_only_ = false;
  bool ignore_bad_checksum_ = false;
  bool output_to_container_ = false;
  bool show_annotations_ = false;
  bool show_file_headers_ = false;
  bool show_section_headers_ = false;
  bool show_section_statistics_ = false;
  bool verbose_ = false;
  bool verify_output_ = kIsDebugBuild;
  bool visualize_pattern_ = false;
  bool update_checksum_ = false;
  CompactDexLevel compact_dex_level_ = CompactDexLevel::kCompactDexLevelNone;
  OutputFormat output_format_ = kOutputPlain;
  const char* output_dex_directory_ = nullptr;
  const char* output_file_name_ = nullptr;
  const char* profile_file_name_ = nullptr;
  // Filter that removes classes that don't have a matching descriptor (during IR creation).
  // This speeds up cases when the output only requires a single class.
  std::set<std::string> class_filter_;
};

// Hotness info
class DexLayoutHotnessInfo {
 public:
  // Store layout information so that the offset calculation can specify the section sizes.
  std::unordered_map<dex_ir::CodeItem*, LayoutType> code_item_layout_;
};

class DexLayout {
 public:
  class VectorOutputContainer {
   public:
    // Begin is not necessarily aligned (for now).
    uint8_t* Begin() {
      return &data_[0];
    }

   private:
    std::vector<uint8_t> data_;
  };


  // Setting this to false disables class def layout entirely, which is stronger than strictly
  // necessary to ensure the partial order w.r.t. class derivation. TODO: Re-enable (b/68317550).
  // This should never be set for a device build, as changing class defs ids
  // conflict with profiles and verification passed by Play.
  static constexpr bool kChangeClassDefOrder = false;
  static_assert(!(kIsTargetBuild && kChangeClassDefOrder), "Never set class reordering on target");

  DexLayout(Options& options,
            ProfileCompilationInfo* info,
            FILE* out_file,
            dex_ir::Header* header)
      : options_(options),
        info_(info),
        out_file_(out_file),
        header_(header),
        page_size_(MemMap::GetPageSize()) { }

  int ProcessFile(const char* file_name);
  bool ProcessDexFile(const char* file_name,
                      const DexFile* dex_file,
                      size_t dex_file_index,
                      std::unique_ptr<DexContainer>* dex_container,
                      std::string* error_msg);

  dex_ir::Header* GetHeader() const { return header_; }
  void SetHeader(dex_ir::Header* header) { header_ = header; }

  DexLayoutSections& GetSections() {
    return dex_sections_;
  }

  const DexLayoutHotnessInfo& LayoutHotnessInfo() const {
    return layout_hotness_info_;
  }

  const Options& GetOptions() const {
    return options_;
  }

 private:
  void DumpAnnotationSetItem(dex_ir::AnnotationSetItem* set_item);
  void DumpBytecodes(uint32_t idx, const dex_ir::CodeItem* code, uint32_t code_offset);
  void DumpCatches(const dex_ir::CodeItem* code);
  void DumpClass(int idx, char** last_package);
  void DumpMethodHandle(int idx);
  void DumpCallSite(int idx);
  void DumpClassAnnotations(int idx);
  void DumpClassDef(int idx);
  void DumpCode(uint32_t idx,
                const dex_ir::CodeItem* code,
                uint32_t code_offset,
                const char* declaring_class_descriptor,
                const char* method_name,
                bool is_static,
                const dex_ir::ProtoId* proto);
  void DumpEncodedAnnotation(dex_ir::EncodedAnnotation* annotation);
  void DumpEncodedValue(const dex_ir::EncodedValue* data);
  void DumpFileHeader();
  void DumpIField(uint32_t idx, uint32_t flags, uint32_t hiddenapi_flags, int i);
  void DumpInstruction(const dex_ir::CodeItem* code,
                       uint32_t code_offset,
                       uint32_t insn_idx,
                       uint32_t insn_width,
                       const Instruction* dec_insn);
  void DumpInterface(const dex_ir::TypeId* type_item, int i);
  void DumpLocalInfo(const dex_ir::CodeItem* code);
  void DumpMethod(uint32_t idx,
                  uint32_t flags,
                  uint32_t hiddenapi_flags,
                  const dex_ir::CodeItem* code,
                  int i);
  void DumpPositionInfo(const dex_ir::CodeItem* code);
  void DumpSField(uint32_t idx,
                  uint32_t flags,
                  uint32_t hiddenapi_flags,
                  int i,
                  dex_ir::EncodedValue* init);
  void DumpDexFile();

  void LayoutClassDefsAndClassData(const DexFile* dex_file);
  void LayoutCodeItems(const DexFile* dex_file);
  void LayoutStringData(const DexFile* dex_file);

  // Creates a new layout for the dex file based on profile info.
  // Currently reorders ClassDefs, ClassDataItems, and CodeItems.
  void LayoutOutputFile(const DexFile* dex_file);
  bool OutputDexFile(const DexFile* input_dex_file,
                     bool compute_offsets,
                     std::unique_ptr<DexContainer>* dex_container,
                     std::string* error_msg);

  void DumpCFG(const DexFile* dex_file, int idx);
  void DumpCFG(const DexFile* dex_file, uint32_t dex_method_idx, const dex::CodeItem* code);

  Options& options_;
  ProfileCompilationInfo* info_;
  FILE* out_file_;
  dex_ir::Header* header_;
  const size_t page_size_;
  DexLayoutSections dex_sections_;
  // Layout hotness information is only calculated when dexlayout is enabled.
  DexLayoutHotnessInfo layout_hotness_info_;

  DISALLOW_COPY_AND_ASSIGN(DexLayout);
};

class DexLoaderContainer : public MemoryDexFileContainer {
 public:
  DexLoaderContainer(const uint8_t* begin,
                     const uint8_t* end,
                     const uint8_t* data_begin,
                     const uint8_t* data_end)
      : MemoryDexFileContainer(begin, end), data_(data_begin, data_end - data_begin) {}
  ArrayRef<const uint8_t> Data() const override { return data_; }

 private:
  ArrayRef<const uint8_t> data_;
};

}  // namespace art

#endif  // ART_DEXLAYOUT_DEXLAYOUT_H_
