// Copyright (c) 2026, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#ifndef RUNTIME_VM_DEBUG_INFO_STREAM_H_
#define RUNTIME_VM_DEBUG_INFO_STREAM_H_

#include "platform/globals.h"

#if defined(DART_PRECOMPILER)

#include "vm/datastream.h"
#include "vm/debug_info.h"
#include "vm/so_writer.h"

namespace dart {

class DebugInfoStream : public DebugInfoWriteStream {
 public:
  DebugInfoStream(Zone* zone, NonStreamingWriteStream* stream)
      : zone_(ASSERT_NOTNULL(zone)),
        stream_(ASSERT_NOTNULL(stream)),
        relocations_(new (zone) SharedObjectWriter::RelocationArray()) {}

  static constexpr intptr_t kInitialBufferSize = 64 * KB;

  uint8_t* buffer() { return stream_->buffer(); }
  const uint8_t* buffer() const { return stream_->buffer(); }
  intptr_t bytes_written() const { return stream_->bytes_written(); }
  intptr_t Position() const { return stream_->Position(); }
  void SetPosition(intptr_t value) { stream_->SetPosition(value); }

  void sleb128(intptr_t value) override { stream_->WriteSLEB128(value); }
  void uleb128(uintptr_t value) override { stream_->WriteLEB128(value); }
  void u1(uint8_t value) override { stream_->WriteByte(value); }
  void u2(uint16_t value) override { stream_->WriteFixed(value); }
  void u4(uint32_t value) override { stream_->WriteFixed(value); }
  void u8(uint64_t value) override { stream_->WriteFixed(value); }
  void bytes(const void* addr, intptr_t len) { stream_->WriteBytes(addr, len); }
  void string(const char* cstr) override {  // NOLINT
    // Unlike stream_->WriteString(), we want the null terminator written.
    stream_->WriteBytes(cstr, strlen(cstr) + 1);
  }
  // The prefix is ignored for binary debug-info streams.
  void WritePrefixedLength(const char* unused,
                           std::function<void()> body) override {
    const intptr_t fixup = stream_->Position();
    // DWARF v2 sizes and CodeView subsection sizes are both 32-bit here.
    u4(0);
    const intptr_t start = stream_->Position();
    body();
    const intptr_t end = stream_->Position();
    stream_->SetPosition(fixup);
    u4(end - start);
    stream_->SetPosition(end);
  }
  // Shorthand for when working directly with DebugInfoStreams.
  void WritePrefixedLength(std::function<void()> body) {
    WritePrefixedLength(nullptr, body);
  }
  void WritePrefixedLengthU16(std::function<void()> body) {
    const intptr_t fixup = stream_->Position();
    u2(0);
    const intptr_t start = stream_->Position();
    body();
    const intptr_t end = stream_->Position();
    const intptr_t length = end - start;
    ASSERT(length <= kMaxUint16);
    stream_->SetPosition(fixup);
    u2(static_cast<uint16_t>(length));
    stream_->SetPosition(end);
  }

  uint8_t LoadU1(intptr_t offset) const {
    ASSERT(offset >= 0);
    ASSERT(offset < bytes_written());
    return stream_->buffer()[offset];
  }

  void StoreU1(intptr_t offset, uint8_t value) {
    ASSERT(offset >= 0);
    ASSERT(offset < bytes_written());
    stream_->buffer()[offset] = value;
  }

  void OffsetFromSymbol(intptr_t label,
                        intptr_t offset,
                        size_t size = kAddressSize) override {
    ASSERT(size > 0);
    ASSERT(size <= static_cast<size_t>(kInt64Size));
    relocations_->Add({size, stream_->Position(),
                       SharedObjectWriter::Relocation::kSnapshotRelative, 0,
                       label, offset});
    const uint64_t placeholder = 0;  // Resolved later.
    stream_->WriteBytes(&placeholder, size);
  }
  void InitializeAbstractOrigins(intptr_t size) override {
    abstract_origins_size_ = size;
    abstract_origins_ = zone_->Alloc<uint32_t>(abstract_origins_size_);
  }
  void RegisterAbstractOrigin(intptr_t index) override {
    ASSERT(abstract_origins_ != nullptr);
    ASSERT(index < abstract_origins_size_);
    abstract_origins_[index] = stream_->Position();
  }
  void AbstractOrigin(intptr_t index) override { u4(abstract_origins_[index]); }

  // Generates the offset of the virtual address corresponding to the given
  // symbol label from the current position in the output. That is, if
  //   X = the virtual address of the current position
  //   Y = the virtual address of the symbol
  // then the value at the current position in the output is Y - X.
  //
  // If no size is provided, the size of the offset in the stream is
  // the native word size.
  void RelativeSymbolOffset(intptr_t label, size_t size = kAddressSize) {
    relocations_->Add({size, stream_->Position(),
                       SharedObjectWriter::Relocation::kSelfRelative, 0, label,
                       0});
    const uint64_t placeholder = 0;  // Resolved later.
    stream_->WriteBytes(&placeholder, size);
  }

  intptr_t Align(intptr_t alignment,
                 intptr_t offset = 0,
                 uint8_t fill_byte = 0) {
    return stream_->Align(alignment, offset, fill_byte);
  }

  const SharedObjectWriter::RelocationArray* relocations() const {
    return relocations_;
  }

 protected:
  Zone* const zone_;
  NonStreamingWriteStream* const stream_;
  SharedObjectWriter::RelocationArray* const relocations_ = nullptr;
  uint32_t* abstract_origins_ = nullptr;
  intptr_t abstract_origins_size_ = -1;

 private:
  DISALLOW_COPY_AND_ASSIGN(DebugInfoStream);
};

}  // namespace dart

#endif  // DART_PRECOMPILER

#endif  // RUNTIME_VM_DEBUG_INFO_STREAM_H_
