// 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.

#ifndef V8_SNAPSHOT_EMBEDDED_FILE_WRITER_H_
#define V8_SNAPSHOT_EMBEDDED_FILE_WRITER_H_

#include <cinttypes>
#include <cstdio>
#include <cstring>

#include "src/globals.h"
#include "src/snapshot/embedded-data.h"
#include "src/snapshot/embedded/platform-embedded-file-writer-base.h"

#if defined(V8_OS_WIN_X64)
#include "src/diagnostics/unwinding-info-win64.h"
#endif

namespace v8 {
namespace internal {

static constexpr char kDefaultEmbeddedVariant[] = "Default";

// Detailed source-code information about builtins can only be obtained by
// registration on the isolate during compilation.
class EmbeddedFileWriterInterface {
 public:
  // We maintain a database of filenames to synthetic IDs.
  virtual int LookupOrAddExternallyCompiledFilename(const char* filename) = 0;
  virtual const char* GetExternallyCompiledFilename(int index) const = 0;
  virtual int GetExternallyCompiledFilenameCount() const = 0;

  // The isolate will call the method below just prior to replacing the
  // compiled builtin Code objects with trampolines.
  virtual void PrepareBuiltinSourcePositionMap(Builtins* builtins) = 0;

#if defined(V8_OS_WIN_X64)
  virtual void SetBuiltinUnwindData(
      int builtin_index,
      const win64_unwindinfo::BuiltinUnwindInfo& unwinding_info) = 0;
#endif
};

// Generates the embedded.S file which is later compiled into the final v8
// binary. Its contents are exported through two symbols:
//
// v8_<variant>_embedded_blob_ (intptr_t):
//     a pointer to the start of the embedded blob.
// v8_<variant>_embedded_blob_size_ (uint32_t):
//     size of the embedded blob in bytes.
//
// The variant is usually "Default" but can be modified in multisnapshot builds.
class EmbeddedFileWriter : public EmbeddedFileWriterInterface {
 public:
  int LookupOrAddExternallyCompiledFilename(const char* filename) override;
  const char* GetExternallyCompiledFilename(int fileid) const override;
  int GetExternallyCompiledFilenameCount() const override;

  void PrepareBuiltinSourcePositionMap(Builtins* builtins) override;

#if defined(V8_OS_WIN_X64)
  void SetBuiltinUnwindData(
      int builtin_index,
      const win64_unwindinfo::BuiltinUnwindInfo& unwinding_info) override;
#endif

  void SetEmbeddedFile(const char* embedded_src_path) {
    embedded_src_path_ = embedded_src_path;
  }

  void SetEmbeddedVariant(const char* embedded_variant) {
    if (embedded_variant == nullptr) return;
    embedded_variant_ = embedded_variant;
  }

  void SetTargetArch(const char* target_arch) { target_arch_ = target_arch; }

  void SetTargetOs(const char* target_os) { target_os_ = target_os; }

  void WriteEmbedded(const i::EmbeddedData* blob) const {
    MaybeWriteEmbeddedFile(blob);
  }

 private:
  void MaybeWriteEmbeddedFile(const i::EmbeddedData* blob) const {
    if (embedded_src_path_ == nullptr) return;

    FILE* fp = GetFileDescriptorOrDie(embedded_src_path_);

    std::unique_ptr<PlatformEmbeddedFileWriterBase> writer =
        NewPlatformEmbeddedFileWriter(target_arch_, target_os_);
    writer->SetFile(fp);

    WriteFilePrologue(writer.get());
    WriteExternalFilenames(writer.get());
    WriteMetadataSection(writer.get(), blob);
    WriteInstructionStreams(writer.get(), blob);
    WriteFileEpilogue(writer.get(), blob);

    fclose(fp);
  }

  static FILE* GetFileDescriptorOrDie(const char* filename) {
    FILE* fp = v8::base::OS::FOpen(filename, "wb");
    if (fp == nullptr) {
      i::PrintF("Unable to open file \"%s\" for writing.\n", filename);
      exit(1);
    }
    return fp;
  }

  void WriteFilePrologue(PlatformEmbeddedFileWriterBase* w) const {
    w->Comment("Autogenerated file. Do not edit.");
    w->Newline();
    w->FilePrologue();
  }

  void WriteExternalFilenames(PlatformEmbeddedFileWriterBase* w) const {
    w->Comment(
        "Source positions in the embedded blob refer to filenames by id.");
    w->Comment("Assembly directives here map the id to a filename.");
    w->Newline();

    // Write external filenames.
    int size = static_cast<int>(external_filenames_by_index_.size());
    for (int i = 0; i < size; i++) {
      w->DeclareExternalFilename(ExternalFilenameIndexToId(i),
                                 external_filenames_by_index_[i]);
    }
  }

  // Fairly arbitrary but should fit all symbol names.
  static constexpr int kTemporaryStringLength = 256;

  std::string EmbeddedBlobDataSymbol() const {
    i::EmbeddedVector<char, kTemporaryStringLength> embedded_blob_data_symbol;
    i::SNPrintF(embedded_blob_data_symbol, "v8_%s_embedded_blob_data_",
                embedded_variant_);
    return std::string{embedded_blob_data_symbol.begin()};
  }

  void WriteMetadataSection(PlatformEmbeddedFileWriterBase* w,
                            const i::EmbeddedData* blob) const {
    w->Comment("The embedded blob starts here. Metadata comes first, followed");
    w->Comment("by builtin instruction streams.");
    w->SectionText();
    w->AlignToCodeAlignment();
    w->DeclareLabel(EmbeddedBlobDataSymbol().c_str());

    WriteBinaryContentsAsInlineAssembly(w, blob->data(),
                                        i::EmbeddedData::RawDataOffset());
  }

  void WriteBuiltin(PlatformEmbeddedFileWriterBase* w,
                    const i::EmbeddedData* blob, const int builtin_id) const;

  void WriteInstructionStreams(PlatformEmbeddedFileWriterBase* w,
                               const i::EmbeddedData* blob) const {
    for (int i = 0; i < i::Builtins::builtin_count; i++) {
      if (!blob->ContainsBuiltin(i)) continue;

      WriteBuiltin(w, blob, i);
    }
    w->Newline();
  }

  void WriteFileEpilogue(PlatformEmbeddedFileWriterBase* w,
                         const i::EmbeddedData* blob) const;

#if defined(V8_OS_WIN_X64)
  std::string BuiltinsUnwindInfoLabel() const;
  void WriteUnwindInfo(PlatformEmbeddedFileWriterBase* w,
                       const i::EmbeddedData* blob) const;
  void WriteUnwindInfoEntry(PlatformEmbeddedFileWriterBase* w,
                            uint64_t rva_start, uint64_t rva_end) const;
#endif

  static void WriteBinaryContentsAsInlineAssembly(
      PlatformEmbeddedFileWriterBase* w, const uint8_t* data, uint32_t size);

  // In assembly directives, filename ids need to begin with 1.
  static constexpr int kFirstExternalFilenameId = 1;
  static int ExternalFilenameIndexToId(int index) {
    return kFirstExternalFilenameId + index;
  }
  static int ExternalFilenameIdToIndex(int id) {
    return id - kFirstExternalFilenameId;
  }

 private:
  std::vector<byte> source_positions_[Builtins::builtin_count];

#if defined(V8_OS_WIN_X64)
  win64_unwindinfo::BuiltinUnwindInfo unwind_infos_[Builtins::builtin_count];
#endif

  std::map<const char*, int> external_filenames_;
  std::vector<const char*> external_filenames_by_index_;

  // The file to generate or nullptr.
  const char* embedded_src_path_ = nullptr;

  // The variant is only used in multi-snapshot builds and otherwise set to
  // "Default".
  const char* embedded_variant_ = kDefaultEmbeddedVariant;

  // {target_arch} and {target_os} control the generated assembly format. Note
  // these may differ from both host- and target-platforms specified through
  // e.g. V8_OS_* and V8_TARGET_ARCH_* defines.
  const char* target_arch_ = nullptr;
  const char* target_os_ = nullptr;
};

}  // namespace internal
}  // namespace v8

#endif  // V8_SNAPSHOT_EMBEDDED_FILE_WRITER_H_
