/*
 * Copyright (C) 2014 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.
 */

#ifndef ART_COMPILER_DWARF_DEBUG_INFO_ENTRY_WRITER_H_
#define ART_COMPILER_DWARF_DEBUG_INFO_ENTRY_WRITER_H_

#include <cstdint>
#include <unordered_map>

#include "dwarf.h"
#include "leb128.h"
#include "writer.h"

namespace art {
namespace dwarf {

// 32-bit FNV-1a hash function which we use to find duplicate abbreviations.
// See http://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
template< typename Allocator >
struct FNVHash {
  size_t operator()(const std::vector<uint8_t, Allocator>& v) const {
    uint32_t hash = 2166136261u;
    for (size_t i = 0; i < v.size(); i++) {
      hash = (hash ^ v[i]) * 16777619u;
    }
    return hash;
  }
};

/*
 * Writer for debug information entries (DIE).
 * It also handles generation of abbreviations.
 *
 * Usage:
 *   StartTag(DW_TAG_compile_unit, DW_CHILDREN_yes);
 *     WriteStrp(DW_AT_producer, "Compiler name", debug_str);
 *     StartTag(DW_TAG_subprogram, DW_CHILDREN_no);
 *       WriteStrp(DW_AT_name, "Foo", debug_str);
 *     EndTag();
 *   EndTag();
 */
template< typename Allocator = std::allocator<uint8_t> >
class DebugInfoEntryWriter FINAL : private Writer<Allocator> {
 public:
  // Start debugging information entry.
  void StartTag(Tag tag, Children children) {
    DCHECK(has_children) << "This tag can not have nested tags";
    if (inside_entry_) {
      // Write abbrev code for the previous entry.
      this->UpdateUleb128(abbrev_code_offset_, EndAbbrev());
      inside_entry_ = false;
    }
    StartAbbrev(tag, children);
    // Abbrev code placeholder of sufficient size.
    abbrev_code_offset_ = this->data()->size();
    this->PushUleb128(NextAbbrevCode());
    depth_++;
    inside_entry_ = true;
    has_children = (children == DW_CHILDREN_yes);
  }

  // End debugging information entry.
  void EndTag() {
    DCHECK_GT(depth_, 0);
    if (inside_entry_) {
      // Write abbrev code for this tag.
      this->UpdateUleb128(abbrev_code_offset_, EndAbbrev());
      inside_entry_ = false;
    }
    if (has_children) {
      this->PushUint8(0);  // End of children.
    }
    depth_--;
    has_children = true;  // Parent tag obviously has children.
  }

  void WriteAddr(Attribute attrib, uint64_t value) {
    AddAbbrevAttribute(attrib, DW_FORM_addr);
    patch_locations_.push_back(this->data()->size());
    if (is64bit_) {
      this->PushUint64(value);
    } else {
      this->PushUint32(value);
    }
  }

  void WriteBlock(Attribute attrib, const void* ptr, int size) {
    AddAbbrevAttribute(attrib, DW_FORM_block);
    this->PushUleb128(size);
    this->PushData(ptr, size);
  }

  void WriteData1(Attribute attrib, uint8_t value) {
    AddAbbrevAttribute(attrib, DW_FORM_data1);
    this->PushUint8(value);
  }

  void WriteData2(Attribute attrib, uint16_t value) {
    AddAbbrevAttribute(attrib, DW_FORM_data2);
    this->PushUint16(value);
  }

  void WriteData4(Attribute attrib, uint32_t value) {
    AddAbbrevAttribute(attrib, DW_FORM_data4);
    this->PushUint32(value);
  }

  void WriteData8(Attribute attrib, uint64_t value) {
    AddAbbrevAttribute(attrib, DW_FORM_data8);
    this->PushUint64(value);
  }

  void WriteSdata(Attribute attrib, int value) {
    AddAbbrevAttribute(attrib, DW_FORM_sdata);
    this->PushSleb128(value);
  }

  void WriteUdata(Attribute attrib, int value) {
    AddAbbrevAttribute(attrib, DW_FORM_udata);
    this->PushUleb128(value);
  }

  void WriteUdata(Attribute attrib, uint32_t value) {
    AddAbbrevAttribute(attrib, DW_FORM_udata);
    this->PushUleb128(value);
  }

  void WriteFlag(Attribute attrib, bool value) {
    AddAbbrevAttribute(attrib, DW_FORM_flag);
    this->PushUint8(value ? 1 : 0);
  }

  void WriteRef4(Attribute attrib, int cu_offset) {
    AddAbbrevAttribute(attrib, DW_FORM_ref4);
    this->PushUint32(cu_offset);
  }

  void WriteRef(Attribute attrib, int cu_offset) {
    AddAbbrevAttribute(attrib, DW_FORM_ref_udata);
    this->PushUleb128(cu_offset);
  }

  void WriteString(Attribute attrib, const char* value) {
    AddAbbrevAttribute(attrib, DW_FORM_string);
    this->PushString(value);
  }

  void WriteStrp(Attribute attrib, int address) {
    AddAbbrevAttribute(attrib, DW_FORM_strp);
    this->PushUint32(address);
  }

  void WriteStrp(Attribute attrib, const char* value, std::vector<uint8_t>* debug_str) {
    AddAbbrevAttribute(attrib, DW_FORM_strp);
    int address = debug_str->size();
    debug_str->insert(debug_str->end(), value, value + strlen(value) + 1);
    this->PushUint32(address);
  }

  bool Is64bit() const { return is64bit_; }

  const std::vector<uintptr_t>& GetPatchLocations() const {
    return patch_locations_;
  }

  using Writer<Allocator>::data;

  DebugInfoEntryWriter(bool is64bitArch,
                       std::vector<uint8_t, Allocator>* debug_abbrev,
                       const Allocator& alloc = Allocator())
      : Writer<Allocator>(&entries_),
        debug_abbrev_(debug_abbrev),
        current_abbrev_(alloc),
        abbrev_codes_(alloc),
        entries_(alloc),
        is64bit_(is64bitArch) {
    debug_abbrev_.PushUint8(0);  // Add abbrev table terminator.
  }

  ~DebugInfoEntryWriter() {
    DCHECK_EQ(depth_, 0);
  }

 private:
  // Start abbreviation declaration.
  void StartAbbrev(Tag tag, Children children) {
    DCHECK(!inside_entry_);
    current_abbrev_.clear();
    EncodeUnsignedLeb128(&current_abbrev_, tag);
    current_abbrev_.push_back(children);
  }

  // Add attribute specification.
  void AddAbbrevAttribute(Attribute name, Form type) {
    DCHECK(inside_entry_) << "Call StartTag before adding attributes.";
    EncodeUnsignedLeb128(&current_abbrev_, name);
    EncodeUnsignedLeb128(&current_abbrev_, type);
  }

  int NextAbbrevCode() {
    return 1 + abbrev_codes_.size();
  }

  // End abbreviation declaration and return its code.
  int EndAbbrev() {
    DCHECK(inside_entry_);
    auto it = abbrev_codes_.insert(std::make_pair(std::move(current_abbrev_),
                                                  NextAbbrevCode()));
    int abbrev_code = it.first->second;
    if (UNLIKELY(it.second)) {  // Inserted new entry.
      const std::vector<uint8_t, Allocator>& abbrev = it.first->first;
      debug_abbrev_.Pop();  // Remove abbrev table terminator.
      debug_abbrev_.PushUleb128(abbrev_code);
      debug_abbrev_.PushData(abbrev.data(), abbrev.size());
      debug_abbrev_.PushUint8(0);  // Attribute list end.
      debug_abbrev_.PushUint8(0);  // Attribute list end.
      debug_abbrev_.PushUint8(0);  // Add abbrev table terminator.
    }
    return abbrev_code;
  }

 private:
  // Fields for writing and deduplication of abbrevs.
  Writer<Allocator> debug_abbrev_;
  std::vector<uint8_t, Allocator> current_abbrev_;
  std::unordered_map<std::vector<uint8_t, Allocator>, int,
                     FNVHash<Allocator> > abbrev_codes_;

  // Fields for writing of debugging information entries.
  std::vector<uint8_t, Allocator> entries_;
  bool is64bit_;
  int depth_ = 0;
  size_t abbrev_code_offset_ = 0;  // Location to patch once we know the code.
  bool inside_entry_ = false;  // Entry ends at first child (if any).
  bool has_children = true;
  std::vector<uintptr_t> patch_locations_;
};

}  // namespace dwarf
}  // namespace art

#endif  // ART_COMPILER_DWARF_DEBUG_INFO_ENTRY_WRITER_H_
