// Copyright 2015 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_WASM_WASM_MODULE_H_
#define V8_WASM_WASM_MODULE_H_

#include <memory>

#include "src/base/optional.h"
#include "src/common/globals.h"
#include "src/handles/handles.h"
#include "src/utils/vector.h"
#include "src/wasm/signature-map.h"
#include "src/wasm/struct-types.h"
#include "src/wasm/wasm-constants.h"
#include "src/wasm/wasm-opcodes.h"

namespace v8 {

namespace internal {

class WasmModuleObject;

namespace wasm {

using WasmName = Vector<const char>;

struct AsmJsOffsets;
class ErrorThrower;

// Reference to a string in the wire bytes.
class WireBytesRef {
 public:
  WireBytesRef() : WireBytesRef(0, 0) {}
  WireBytesRef(uint32_t offset, uint32_t length)
      : offset_(offset), length_(length) {
    DCHECK_IMPLIES(offset_ == 0, length_ == 0);
    DCHECK_LE(offset_, offset_ + length_);  // no uint32_t overflow.
  }

  uint32_t offset() const { return offset_; }
  uint32_t length() const { return length_; }
  uint32_t end_offset() const { return offset_ + length_; }
  bool is_empty() const { return length_ == 0; }
  bool is_set() const { return offset_ != 0; }

 private:
  uint32_t offset_;
  uint32_t length_;
};

// Static representation of a wasm function.
struct WasmFunction {
  const FunctionSig* sig;  // signature of the function.
  uint32_t func_index;     // index into the function table.
  uint32_t sig_index;      // index into the signature table.
  WireBytesRef code;       // code of this function.
  bool imported;
  bool exported;
  bool declared;
};

// Static representation of a wasm global variable.
struct WasmGlobal {
  ValueType type;     // type of the global.
  bool mutability;    // {true} if mutable.
  WasmInitExpr init;  // the initialization expression of the global.
  union {
    uint32_t index;   // index of imported mutable global.
    uint32_t offset;  // offset into global memory (if not imported & mutable).
  };
  bool imported;  // true if imported.
  bool exported;  // true if exported.
};

// Note: An exception signature only uses the params portion of a
// function signature.
using WasmExceptionSig = FunctionSig;

// Static representation of a wasm exception type.
struct WasmException {
  explicit WasmException(const WasmExceptionSig* sig) : sig(sig) {}
  const FunctionSig* ToFunctionSig() const { return sig; }

  const WasmExceptionSig* sig;  // type signature of the exception.
};

// Static representation of a wasm data segment.
struct WasmDataSegment {
  // Construct an active segment.
  explicit WasmDataSegment(WasmInitExpr dest_addr)
      : dest_addr(std::move(dest_addr)), active(true) {}

  // Construct a passive segment, which has no dest_addr.
  WasmDataSegment() : active(false) {}

  WasmInitExpr dest_addr;  // destination memory address of the data.
  WireBytesRef source;     // start offset in the module bytes.
  bool active = true;      // true if copied automatically during instantiation.
};

// Static representation of wasm element segment (table initializer).
struct WasmElemSegment {
  MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(WasmElemSegment);

  // Construct an active segment.
  WasmElemSegment(uint32_t table_index, WasmInitExpr offset)
      : type(kWasmFuncRef),
        table_index(table_index),
        offset(std::move(offset)),
        status(kStatusActive) {}

  // Construct a passive or declarative segment, which has no table index or
  // offset.
  explicit WasmElemSegment(bool declarative)
      : type(kWasmFuncRef),
        table_index(0),
        status(declarative ? kStatusDeclarative : kStatusPassive) {}

  // Used in the {entries} vector to represent a `ref.null` entry in a passive
  // segment.
  V8_EXPORT_PRIVATE static const uint32_t kNullIndex = ~0u;

  ValueType type;
  uint32_t table_index;
  WasmInitExpr offset;
  std::vector<uint32_t> entries;
  enum Status {
    kStatusActive,      // copied automatically during instantiation.
    kStatusPassive,     // copied explicitly after instantiation.
    kStatusDeclarative  // purely declarative and never copied.
  } status;
};

// Static representation of a wasm import.
struct WasmImport {
  WireBytesRef module_name;   // module name.
  WireBytesRef field_name;    // import name.
  ImportExportKindCode kind;  // kind of the import.
  uint32_t index;             // index into the respective space.
};

// Static representation of a wasm export.
struct WasmExport {
  WireBytesRef name;          // exported name.
  ImportExportKindCode kind;  // kind of the export.
  uint32_t index;             // index into the respective space.
};

enum class WasmCompilationHintStrategy : uint8_t {
  kDefault = 0,
  kLazy = 1,
  kEager = 2,
  kLazyBaselineEagerTopTier = 3,
};

enum class WasmCompilationHintTier : uint8_t {
  kDefault = 0,
  kBaseline = 1,
  kOptimized = 2,
};

// Static representation of a wasm compilation hint
struct WasmCompilationHint {
  WasmCompilationHintStrategy strategy;
  WasmCompilationHintTier baseline_tier;
  WasmCompilationHintTier top_tier;
};

enum ModuleOrigin : uint8_t {
  kWasmOrigin,
  kAsmJsSloppyOrigin,
  kAsmJsStrictOrigin
};

#define SELECT_WASM_COUNTER(counters, origin, prefix, suffix)     \
  ((origin) == kWasmOrigin ? (counters)->prefix##_wasm_##suffix() \
                           : (counters)->prefix##_asm_##suffix())

struct ModuleWireBytes;

class V8_EXPORT_PRIVATE LazilyGeneratedNames {
 public:
  WireBytesRef LookupFunctionName(const ModuleWireBytes& wire_bytes,
                                  uint32_t function_index,
                                  Vector<const WasmExport> export_table) const;

  // For memory and global.
  std::pair<WireBytesRef, WireBytesRef> LookupNameFromImportsAndExports(
      ImportExportKindCode kind, uint32_t index,
      const Vector<const WasmImport> import_table,
      const Vector<const WasmExport> export_table) const;

  void AddForTesting(int function_index, WireBytesRef name);

 private:
  // {function_names_}, {global_names_}, {memory_names_} and {table_names_} are
  // populated lazily after decoding, and therefore need a mutex to protect
  // concurrent modifications from multiple {WasmModuleObject}.
  mutable base::Mutex mutex_;
  mutable std::unique_ptr<std::unordered_map<uint32_t, WireBytesRef>>
      function_names_;
  mutable std::unique_ptr<
      std::unordered_map<uint32_t, std::pair<WireBytesRef, WireBytesRef>>>
      global_names_;
  mutable std::unique_ptr<
      std::unordered_map<uint32_t, std::pair<WireBytesRef, WireBytesRef>>>
      memory_names_;
  mutable std::unique_ptr<
      std::unordered_map<uint32_t, std::pair<WireBytesRef, WireBytesRef>>>
      table_names_;
};

class V8_EXPORT_PRIVATE AsmJsOffsetInformation {
 public:
  explicit AsmJsOffsetInformation(Vector<const byte> encoded_offsets);

  // Destructor defined in wasm-module.cc, where the definition of
  // {AsmJsOffsets} is available.
  ~AsmJsOffsetInformation();

  int GetSourcePosition(int func_index, int byte_offset,
                        bool is_at_number_conversion);

  std::pair<int, int> GetFunctionOffsets(int func_index);

 private:
  void EnsureDecodedOffsets();

  // The offset information table is decoded lazily, hence needs to be
  // protected against concurrent accesses.
  // Exactly one of the two fields below will be set at a time.
  mutable base::Mutex mutex_;

  // Holds the encoded offset table bytes.
  OwnedVector<const uint8_t> encoded_offsets_;

  // Holds the decoded offset table.
  std::unique_ptr<AsmJsOffsets> decoded_offsets_;
};

struct TypeDefinition {
  explicit TypeDefinition(const FunctionSig* sig) : function_sig(sig) {}
  explicit TypeDefinition(const StructType* type) : struct_type(type) {}
  explicit TypeDefinition(const ArrayType* type) : array_type(type) {}
  union {
    const FunctionSig* function_sig;
    const StructType* struct_type;
    const ArrayType* array_type;
  };
};

struct V8_EXPORT_PRIVATE WasmDebugSymbols {
  enum class Type { None, SourceMap, EmbeddedDWARF, ExternalDWARF };
  Type type = Type::None;
  WireBytesRef external_url;
};

struct WasmTable;

// Static representation of a module.
struct V8_EXPORT_PRIVATE WasmModule {
  std::unique_ptr<Zone> signature_zone;
  uint32_t initial_pages = 0;      // initial size of the memory in 64k pages
  uint32_t maximum_pages = 0;      // maximum size of the memory in 64k pages
  bool has_shared_memory = false;  // true if memory is a SharedArrayBuffer
  bool has_maximum_pages = false;  // true if there is a maximum memory size
  bool is_memory64 = false;        // true if the memory is 64 bit
  bool has_memory = false;         // true if the memory was defined or imported
  bool mem_export = false;         // true if the memory is exported
  int start_function_index = -1;   // start function, >= 0 if any

  std::vector<WasmGlobal> globals;
  // Size of the buffer required for all globals that are not imported and
  // mutable.
  uint32_t untagged_globals_buffer_size = 0;
  uint32_t tagged_globals_buffer_size = 0;
  uint32_t num_imported_mutable_globals = 0;
  uint32_t num_imported_functions = 0;
  uint32_t num_imported_tables = 0;
  uint32_t num_declared_functions = 0;  // excluding imported
  uint32_t num_exported_functions = 0;
  uint32_t num_declared_data_segments = 0;  // From the DataCount section.
  WireBytesRef code = {0, 0};
  WireBytesRef name = {0, 0};
  std::vector<TypeDefinition> types;  // by type index
  std::vector<uint8_t> type_kinds;    // by type index
  // Map from each type index to the index of its corresponding canonical type.
  // Note: right now, only functions are canonicalized, and arrays and structs
  // map to themselves.
  std::vector<uint32_t> canonicalized_type_ids;

  bool has_type(uint32_t index) const { return index < types.size(); }

  void add_signature(const FunctionSig* sig) {
    types.push_back(TypeDefinition(sig));
    type_kinds.push_back(kWasmFunctionTypeCode);
    uint32_t canonical_id = sig ? signature_map.FindOrInsert(*sig) : 0;
    canonicalized_type_ids.push_back(canonical_id);
  }
  bool has_signature(uint32_t index) const {
    return index < types.size() && type_kinds[index] == kWasmFunctionTypeCode;
  }
  const FunctionSig* signature(uint32_t index) const {
    DCHECK(has_signature(index));
    return types[index].function_sig;
  }

  void add_struct_type(const StructType* type) {
    types.push_back(TypeDefinition(type));
    type_kinds.push_back(kWasmStructTypeCode);
    // No canonicalization for structs.
    canonicalized_type_ids.push_back(0);
  }
  bool has_struct(uint32_t index) const {
    return index < types.size() && type_kinds[index] == kWasmStructTypeCode;
  }
  const StructType* struct_type(uint32_t index) const {
    DCHECK(has_struct(index));
    return types[index].struct_type;
  }

  void add_array_type(const ArrayType* type) {
    types.push_back(TypeDefinition(type));
    type_kinds.push_back(kWasmArrayTypeCode);
    // No canonicalization for arrays.
    canonicalized_type_ids.push_back(0);
  }
  bool has_array(uint32_t index) const {
    return index < types.size() && type_kinds[index] == kWasmArrayTypeCode;
  }
  const ArrayType* array_type(uint32_t index) const {
    DCHECK(has_array(index));
    return types[index].array_type;
  }

  std::vector<WasmFunction> functions;
  std::vector<WasmDataSegment> data_segments;
  std::vector<WasmTable> tables;
  std::vector<WasmImport> import_table;
  std::vector<WasmExport> export_table;
  std::vector<WasmException> exceptions;
  std::vector<WasmElemSegment> elem_segments;
  std::vector<WasmCompilationHint> compilation_hints;
  SignatureMap signature_map;  // canonicalizing map for signature indexes.

  ModuleOrigin origin = kWasmOrigin;  // origin of the module
  LazilyGeneratedNames lazily_generated_names;
  WasmDebugSymbols debug_symbols;

  // Asm.js source position information. Only available for modules compiled
  // from asm.js.
  std::unique_ptr<AsmJsOffsetInformation> asm_js_offset_information;

  explicit WasmModule(std::unique_ptr<Zone> signature_zone = nullptr);
  WasmModule(const WasmModule&) = delete;
  WasmModule& operator=(const WasmModule&) = delete;
};

// Static representation of a wasm indirect call table.
struct WasmTable {
  MOVE_ONLY_WITH_DEFAULT_CONSTRUCTORS(WasmTable);

  // 'module' can be nullptr
  // TODO(9495): Update this function as more table types are supported, or
  // remove it completely when all reference types are allowed.
  static bool IsValidTableType(ValueType type, const WasmModule* module) {
    if (!type.is_nullable()) return false;
    HeapType heap_type = type.heap_type();
    return heap_type == HeapType::kFunc || heap_type == HeapType::kExtern ||
           heap_type == HeapType::kExn ||
           (module != nullptr && heap_type.is_index() &&
            module->has_signature(heap_type.ref_index()));
  }

  ValueType type = kWasmStmt;     // table type.
  uint32_t initial_size = 0;      // initial table size.
  uint32_t maximum_size = 0;      // maximum table size.
  bool has_maximum_size = false;  // true if there is a maximum size.
  bool imported = false;          // true if imported.
  bool exported = false;          // true if exported.
};

inline bool is_asmjs_module(const WasmModule* module) {
  return module->origin != kWasmOrigin;
}

size_t EstimateStoredSize(const WasmModule* module);

// Returns the number of possible export wrappers for a given module.
V8_EXPORT_PRIVATE int MaxNumExportWrappers(const WasmModule* module);

// Returns the wrapper index for a function in {module} with signature {sig}
// and origin defined by {is_import}.
int GetExportWrapperIndex(const WasmModule* module, const FunctionSig* sig,
                          bool is_import);

// Return the byte offset of the function identified by the given index.
// The offset will be relative to the start of the module bytes.
// Returns -1 if the function index is invalid.
int GetWasmFunctionOffset(const WasmModule* module, uint32_t func_index);

// Returns the function containing the given byte offset.
// Returns -1 if the byte offset is not contained in any
// function of this module.
int GetContainingWasmFunction(const WasmModule* module, uint32_t byte_offset);

// Returns the function containing the given byte offset.
// Will return preceding function if the byte offset is not
// contained within a function.
int GetNearestWasmFunction(const WasmModule* module, uint32_t byte_offset);

// Interface to the storage (wire bytes) of a wasm module.
// It is illegal for anyone receiving a ModuleWireBytes to store pointers based
// on module_bytes, as this storage is only guaranteed to be alive as long as
// this struct is alive.
struct V8_EXPORT_PRIVATE ModuleWireBytes {
  explicit ModuleWireBytes(Vector<const byte> module_bytes)
      : module_bytes_(module_bytes) {}
  ModuleWireBytes(const byte* start, const byte* end)
      : module_bytes_(start, static_cast<int>(end - start)) {
    DCHECK_GE(kMaxInt, end - start);
  }

  // Get a string stored in the module bytes representing a name.
  WasmName GetNameOrNull(WireBytesRef ref) const;

  // Get a string stored in the module bytes representing a function name.
  WasmName GetNameOrNull(const WasmFunction* function,
                         const WasmModule* module) const;

  // Checks the given reference is contained within the module bytes.
  bool BoundsCheck(WireBytesRef ref) const {
    uint32_t size = static_cast<uint32_t>(module_bytes_.length());
    return ref.offset() <= size && ref.length() <= size - ref.offset();
  }

  Vector<const byte> GetFunctionBytes(const WasmFunction* function) const {
    return module_bytes_.SubVector(function->code.offset(),
                                   function->code.end_offset());
  }

  Vector<const byte> module_bytes() const { return module_bytes_; }
  const byte* start() const { return module_bytes_.begin(); }
  const byte* end() const { return module_bytes_.end(); }
  size_t length() const { return module_bytes_.length(); }

 private:
  Vector<const byte> module_bytes_;
};

// A helper for printing out the names of functions.
struct WasmFunctionName {
  WasmFunctionName(const WasmFunction* function, WasmName name)
      : function_(function), name_(name) {}

  const WasmFunction* function_;
  const WasmName name_;
};

std::ostream& operator<<(std::ostream& os, const WasmFunctionName& name);

V8_EXPORT_PRIVATE bool IsWasmCodegenAllowed(Isolate* isolate,
                                            Handle<Context> context);

Handle<JSObject> GetTypeForFunction(Isolate* isolate, const FunctionSig* sig);
Handle<JSObject> GetTypeForGlobal(Isolate* isolate, bool is_mutable,
                                  ValueType type);
Handle<JSObject> GetTypeForMemory(Isolate* isolate, uint32_t min_size,
                                  base::Optional<uint32_t> max_size);
Handle<JSObject> GetTypeForTable(Isolate* isolate, ValueType type,
                                 uint32_t min_size,
                                 base::Optional<uint32_t> max_size);
Handle<JSArray> GetImports(Isolate* isolate, Handle<WasmModuleObject> module);
Handle<JSArray> GetExports(Isolate* isolate, Handle<WasmModuleObject> module);
Handle<JSArray> GetCustomSections(Isolate* isolate,
                                  Handle<WasmModuleObject> module,
                                  Handle<String> name, ErrorThrower* thrower);

// Get the source position from a given function index and byte offset,
// for either asm.js or pure Wasm modules.
int GetSourcePosition(const WasmModule*, uint32_t func_index,
                      uint32_t byte_offset, bool is_at_number_conversion);

// Translate function index to the index relative to the first declared (i.e.
// non-imported) function.
inline int declared_function_index(const WasmModule* module, int func_index) {
  DCHECK_LE(module->num_imported_functions, func_index);
  int declared_idx = func_index - module->num_imported_functions;
  DCHECK_GT(module->num_declared_functions, declared_idx);
  return declared_idx;
}

// TruncatedUserString makes it easy to output names up to a certain length, and
// output a truncation followed by '...' if they exceed a limit.
// Use like this:
//   TruncatedUserString<> name (pc, len);
//   printf("... %.*s ...", name.length(), name.start())
template <int kMaxLen = 50>
class TruncatedUserString {
  static_assert(kMaxLen >= 4, "minimum length is 4 (length of '...' plus one)");

 public:
  template <typename T>
  explicit TruncatedUserString(Vector<T> name)
      : TruncatedUserString(name.begin(), name.length()) {}

  TruncatedUserString(const byte* start, size_t len)
      : TruncatedUserString(reinterpret_cast<const char*>(start), len) {}

  TruncatedUserString(const char* start, size_t len)
      : start_(start), length_(std::min(kMaxLen, static_cast<int>(len))) {
    if (len > static_cast<size_t>(kMaxLen)) {
      memcpy(buffer_, start, kMaxLen - 3);
      memset(buffer_ + kMaxLen - 3, '.', 3);
      start_ = buffer_;
    }
  }

  const char* start() const { return start_; }

  int length() const { return length_; }

 private:
  const char* start_;
  const int length_;
  char buffer_[kMaxLen];
};

// Print the signature into the given {buffer}, using {delimiter} as separator
// between parameter types and return types. If {buffer} is non-empty, it will
// be null-terminated, even if the signature is cut off. Returns the number of
// characters written, excluding the terminating null-byte.
size_t PrintSignature(Vector<char> buffer, const wasm::FunctionSig*,
                      char delimiter = ':');

}  // namespace wasm
}  // namespace internal
}  // namespace v8

#endif  // V8_WASM_WASM_MODULE_H_
