/*
 * 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_LIBELFFILE_DWARF_DEBUG_INFO_ENTRY_WRITER_H_
#define ART_LIBELFFILE_DWARF_DEBUG_INFO_ENTRY_WRITER_H_

#include <cstdint>
#include <unordered_map>

#include "base/casts.h"
#include "base/leb128.h"
#include "dwarf/debug_abbrev_writer.h"
#include "dwarf/dwarf_constants.h"
#include "dwarf/expression.h"
#include "dwarf/writer.h"

namespace art {
namespace dwarf {

/*
 * Writer for debug information entries (DIE).
 *
 * Usage:
 *   StartTag(DW_TAG_compile_unit);
 *     WriteStrp(DW_AT_producer, "Compiler name", debug_str);
 *     StartTag(DW_TAG_subprogram);
 *       WriteStrp(DW_AT_name, "Foo", debug_str);
 *     EndTag();
 *   EndTag();
 */
template <typename Vector = std::vector<uint8_t>>
class DebugInfoEntryWriter final : private Writer<Vector> {
  static_assert(std::is_same<typename Vector::value_type, uint8_t>::value, "Invalid value type");

 public:
  static constexpr size_t kCompilationUnitHeaderSize = 11;

  // Start debugging information entry.
  // Returns offset of the entry in compilation unit.
  size_t StartTag(Tag tag) {
    if (inside_entry_) {
      // Write abbrev code for the previous entry.
      // Parent entry is finalized before any children are written.
      this->UpdateUleb128(abbrev_code_offset_, debug_abbrev_->EndAbbrev(DW_CHILDREN_yes));
      inside_entry_ = false;
    }
    debug_abbrev_->StartAbbrev(tag);
    // Abbrev code placeholder of sufficient size.
    abbrev_code_offset_ = this->data()->size();
    this->PushUleb128(debug_abbrev_->NextAbbrevCode());
    depth_++;
    inside_entry_ = true;
    return abbrev_code_offset_ + kCompilationUnitHeaderSize;
  }

  // End debugging information entry.
  void EndTag() {
    DCHECK_GT(depth_, 0);
    if (inside_entry_) {
      // Write abbrev code for this entry.
      this->UpdateUleb128(abbrev_code_offset_, debug_abbrev_->EndAbbrev(DW_CHILDREN_no));
      inside_entry_ = false;
      // This entry has no children and so there is no terminator.
    } else {
      // The entry has been already finalized so it must be parent entry
      // and we need to write the terminator required by DW_CHILDREN_yes.
      this->PushUint8(0);
    }
    depth_--;
  }

  void WriteAddr(Attribute attrib, uint64_t value) {
    debug_abbrev_->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 uint8_t* ptr, size_t num_bytes) {
    debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_block);
    this->PushUleb128(num_bytes);
    this->PushData(ptr, num_bytes);
  }

  void WriteExprLoc(Attribute attrib, const Expression& expr) {
    debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_exprloc);
    this->PushUleb128(dchecked_integral_cast<uint32_t>(expr.size()));
    this->PushData(expr.data());
  }

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

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

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

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

  void WriteSecOffset(Attribute attrib, uint32_t offset) {
    debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_sec_offset);
    this->PushUint32(offset);
  }

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

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

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

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

  void WriteFlagPresent(Attribute attrib) {
    debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_flag_present);
  }

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

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

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

  void WriteStrp(Attribute attrib, size_t debug_str_offset) {
    debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_strp);
    this->PushUint32(dchecked_integral_cast<uint32_t>(debug_str_offset));
  }

  void WriteStrp(Attribute attrib, const char* str, size_t len,
                 std::vector<uint8_t>* debug_str) {
    debug_abbrev_->AddAbbrevAttribute(attrib, DW_FORM_strp);
    this->PushUint32(debug_str->size());
    debug_str->insert(debug_str->end(), str, str + len);
    debug_str->push_back(0);
  }

  void WriteStrp(Attribute attrib, const char* str, std::vector<uint8_t>* debug_str) {
    WriteStrp(attrib, str, strlen(str), debug_str);
  }

  bool Is64bit() const { return is64bit_; }

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

  int Depth() const { return depth_; }

  using Writer<Vector>::data;
  using Writer<Vector>::size;
  using Writer<Vector>::UpdateUint32;

  DebugInfoEntryWriter(bool is64bitArch,
                       DebugAbbrevWriter<Vector>* debug_abbrev,
                       const typename Vector::allocator_type& alloc =
                           typename Vector::allocator_type())
      : Writer<Vector>(&entries_),
        debug_abbrev_(debug_abbrev),
        entries_(alloc),
        is64bit_(is64bitArch) {
  }

  ~DebugInfoEntryWriter() {
    DCHECK(!inside_entry_);
    DCHECK_EQ(depth_, 0);
  }

 private:
  DebugAbbrevWriter<Vector>* debug_abbrev_;
  Vector 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).
  std::vector<uintptr_t> patch_locations_;
};

}  // namespace dwarf
}  // namespace art

#endif  // ART_LIBELFFILE_DWARF_DEBUG_INFO_ENTRY_WRITER_H_
