/*
 * 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 "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) { }

  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_;
  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_
