// Copyright 2018 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <cstring>
#include <iomanip>

#include "src/assembler-inl.h"
#include "src/code-comments.h"

namespace v8 {
namespace internal {

namespace {
static constexpr uint8_t kOffsetToFirstCommentEntry = kUInt32Size;
static constexpr uint8_t kOffsetToPCOffset = 0;
static constexpr uint8_t kOffsetToCommentSize = kOffsetToPCOffset + kUInt32Size;
static constexpr uint8_t kOffsetToCommentString =
    kOffsetToCommentSize + kUInt32Size;
}  // namespace

uint32_t CodeCommentEntry::comment_length() const {
  return static_cast<uint32_t>(comment.size() + 1);
}

uint32_t CodeCommentEntry::size() const {
  return kOffsetToCommentString + comment_length();
}

CodeCommentsIterator::CodeCommentsIterator(Address code_comments_start)
    : code_comments_start_(code_comments_start),
      current_entry_(code_comments_start + kOffsetToFirstCommentEntry) {}

uint32_t CodeCommentsIterator::size() const {
  return code_comments_start_ != kNullAddress
             ? *reinterpret_cast<uint32_t*>(code_comments_start_)
             : 0;
}

const char* CodeCommentsIterator::GetComment() const {
  const char* comment_string =
      reinterpret_cast<const char*>(current_entry_ + kOffsetToCommentString);
  CHECK_EQ(GetCommentSize(), strlen(comment_string) + 1);
  return comment_string;
}

uint32_t CodeCommentsIterator::GetCommentSize() const {
  return *reinterpret_cast<uint32_t*>(current_entry_ + kOffsetToCommentSize);
}

uint32_t CodeCommentsIterator::GetPCOffset() const {
  return *reinterpret_cast<uint32_t*>(current_entry_ + kOffsetToPCOffset);
}

void CodeCommentsIterator::Next() {
  current_entry_ += kOffsetToCommentString + GetCommentSize();
}

bool CodeCommentsIterator::HasCurrent() const {
  return current_entry_ < code_comments_start_ + size();
}

void CodeCommentsWriter::Emit(Assembler* assm) {
  assm->dd(section_size());
  for (auto i = comments_.begin(); i != comments_.end(); ++i) {
    assm->dd(i->pc_offset);
    assm->dd(i->comment_length());
    for (char c : i->comment) {
      EnsureSpace ensure_space(assm);
      assm->db(c);
    }
    assm->db('\0');
  }
}

void CodeCommentsWriter::Add(uint32_t pc_offset, std::string comment) {
  CodeCommentEntry entry = {pc_offset, std::move(comment)};
  byte_count_ += entry.size();
  comments_.push_back(std::move(entry));
}

size_t CodeCommentsWriter::entry_count() const { return comments_.size(); }
uint32_t CodeCommentsWriter::section_size() const {
  return kOffsetToFirstCommentEntry + static_cast<uint32_t>(byte_count_);
}

void PrintCodeCommentsSection(std::ostream& out, Address code_comments_start) {
  CodeCommentsIterator it(code_comments_start);
  out << "CodeComments (size = " << it.size() << ")\n";
  if (it.HasCurrent()) {
    out << std::setw(6) << "pc" << std::setw(6) << "len"
        << " comment\n";
  }
  for (; it.HasCurrent(); it.Next()) {
    out << std::hex << std::setw(6) << it.GetPCOffset() << std::dec
        << std::setw(6) << it.GetCommentSize() << " (" << it.GetComment()
        << ")\n";
  }
}

}  // namespace internal
}  // namespace v8
