11cb0ef41Sopenharmony_ci// Copyright 2015 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#if !V8_ENABLE_WEBASSEMBLY
61cb0ef41Sopenharmony_ci#error This header should only be included if WebAssembly is enabled.
71cb0ef41Sopenharmony_ci#endif  // !V8_ENABLE_WEBASSEMBLY
81cb0ef41Sopenharmony_ci
91cb0ef41Sopenharmony_ci#ifndef V8_WASM_WASM_MODULE_BUILDER_H_
101cb0ef41Sopenharmony_ci#define V8_WASM_WASM_MODULE_BUILDER_H_
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_ci#include "src/base/memory.h"
131cb0ef41Sopenharmony_ci#include "src/base/platform/wrappers.h"
141cb0ef41Sopenharmony_ci#include "src/base/vector.h"
151cb0ef41Sopenharmony_ci#include "src/codegen/signature.h"
161cb0ef41Sopenharmony_ci#include "src/wasm/leb-helper.h"
171cb0ef41Sopenharmony_ci#include "src/wasm/local-decl-encoder.h"
181cb0ef41Sopenharmony_ci#include "src/wasm/value-type.h"
191cb0ef41Sopenharmony_ci#include "src/wasm/wasm-module.h"
201cb0ef41Sopenharmony_ci#include "src/wasm/wasm-opcodes.h"
211cb0ef41Sopenharmony_ci#include "src/wasm/wasm-result.h"
221cb0ef41Sopenharmony_ci#include "src/zone/zone-containers.h"
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_cinamespace v8 {
251cb0ef41Sopenharmony_cinamespace internal {
261cb0ef41Sopenharmony_cinamespace wasm {
271cb0ef41Sopenharmony_ci
281cb0ef41Sopenharmony_ciclass ZoneBuffer : public ZoneObject {
291cb0ef41Sopenharmony_ci public:
301cb0ef41Sopenharmony_ci  // This struct is just a type tag for Zone::NewArray<T>(size_t) call.
311cb0ef41Sopenharmony_ci  struct Buffer {};
321cb0ef41Sopenharmony_ci
331cb0ef41Sopenharmony_ci  static constexpr size_t kInitialSize = 1024;
341cb0ef41Sopenharmony_ci  explicit ZoneBuffer(Zone* zone, size_t initial = kInitialSize)
351cb0ef41Sopenharmony_ci      : zone_(zone), buffer_(zone->NewArray<byte, Buffer>(initial)) {
361cb0ef41Sopenharmony_ci    pos_ = buffer_;
371cb0ef41Sopenharmony_ci    end_ = buffer_ + initial;
381cb0ef41Sopenharmony_ci  }
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_ci  void write_u8(uint8_t x) {
411cb0ef41Sopenharmony_ci    EnsureSpace(1);
421cb0ef41Sopenharmony_ci    *(pos_++) = x;
431cb0ef41Sopenharmony_ci  }
441cb0ef41Sopenharmony_ci
451cb0ef41Sopenharmony_ci  void write_u16(uint16_t x) {
461cb0ef41Sopenharmony_ci    EnsureSpace(2);
471cb0ef41Sopenharmony_ci    base::WriteLittleEndianValue<uint16_t>(reinterpret_cast<Address>(pos_), x);
481cb0ef41Sopenharmony_ci    pos_ += 2;
491cb0ef41Sopenharmony_ci  }
501cb0ef41Sopenharmony_ci
511cb0ef41Sopenharmony_ci  void write_u32(uint32_t x) {
521cb0ef41Sopenharmony_ci    EnsureSpace(4);
531cb0ef41Sopenharmony_ci    base::WriteLittleEndianValue<uint32_t>(reinterpret_cast<Address>(pos_), x);
541cb0ef41Sopenharmony_ci    pos_ += 4;
551cb0ef41Sopenharmony_ci  }
561cb0ef41Sopenharmony_ci
571cb0ef41Sopenharmony_ci  void write_u64(uint64_t x) {
581cb0ef41Sopenharmony_ci    EnsureSpace(8);
591cb0ef41Sopenharmony_ci    base::WriteLittleEndianValue<uint64_t>(reinterpret_cast<Address>(pos_), x);
601cb0ef41Sopenharmony_ci    pos_ += 8;
611cb0ef41Sopenharmony_ci  }
621cb0ef41Sopenharmony_ci
631cb0ef41Sopenharmony_ci  void write_u32v(uint32_t val) {
641cb0ef41Sopenharmony_ci    EnsureSpace(kMaxVarInt32Size);
651cb0ef41Sopenharmony_ci    LEBHelper::write_u32v(&pos_, val);
661cb0ef41Sopenharmony_ci  }
671cb0ef41Sopenharmony_ci
681cb0ef41Sopenharmony_ci  void write_i32v(int32_t val) {
691cb0ef41Sopenharmony_ci    EnsureSpace(kMaxVarInt32Size);
701cb0ef41Sopenharmony_ci    LEBHelper::write_i32v(&pos_, val);
711cb0ef41Sopenharmony_ci  }
721cb0ef41Sopenharmony_ci
731cb0ef41Sopenharmony_ci  void write_u64v(uint64_t val) {
741cb0ef41Sopenharmony_ci    EnsureSpace(kMaxVarInt64Size);
751cb0ef41Sopenharmony_ci    LEBHelper::write_u64v(&pos_, val);
761cb0ef41Sopenharmony_ci  }
771cb0ef41Sopenharmony_ci
781cb0ef41Sopenharmony_ci  void write_i64v(int64_t val) {
791cb0ef41Sopenharmony_ci    EnsureSpace(kMaxVarInt64Size);
801cb0ef41Sopenharmony_ci    LEBHelper::write_i64v(&pos_, val);
811cb0ef41Sopenharmony_ci  }
821cb0ef41Sopenharmony_ci
831cb0ef41Sopenharmony_ci  void write_size(size_t val) {
841cb0ef41Sopenharmony_ci    EnsureSpace(kMaxVarInt32Size);
851cb0ef41Sopenharmony_ci    DCHECK_EQ(val, static_cast<uint32_t>(val));
861cb0ef41Sopenharmony_ci    LEBHelper::write_u32v(&pos_, static_cast<uint32_t>(val));
871cb0ef41Sopenharmony_ci  }
881cb0ef41Sopenharmony_ci
891cb0ef41Sopenharmony_ci  void write_f32(float val) { write_u32(bit_cast<uint32_t>(val)); }
901cb0ef41Sopenharmony_ci
911cb0ef41Sopenharmony_ci  void write_f64(double val) { write_u64(bit_cast<uint64_t>(val)); }
921cb0ef41Sopenharmony_ci
931cb0ef41Sopenharmony_ci  void write(const byte* data, size_t size) {
941cb0ef41Sopenharmony_ci    if (size == 0) return;
951cb0ef41Sopenharmony_ci    EnsureSpace(size);
961cb0ef41Sopenharmony_ci    memcpy(pos_, data, size);
971cb0ef41Sopenharmony_ci    pos_ += size;
981cb0ef41Sopenharmony_ci  }
991cb0ef41Sopenharmony_ci
1001cb0ef41Sopenharmony_ci  void write_string(base::Vector<const char> name) {
1011cb0ef41Sopenharmony_ci    write_size(name.length());
1021cb0ef41Sopenharmony_ci    write(reinterpret_cast<const byte*>(name.begin()), name.length());
1031cb0ef41Sopenharmony_ci  }
1041cb0ef41Sopenharmony_ci
1051cb0ef41Sopenharmony_ci  size_t reserve_u32v() {
1061cb0ef41Sopenharmony_ci    size_t off = offset();
1071cb0ef41Sopenharmony_ci    EnsureSpace(kMaxVarInt32Size);
1081cb0ef41Sopenharmony_ci    pos_ += kMaxVarInt32Size;
1091cb0ef41Sopenharmony_ci    return off;
1101cb0ef41Sopenharmony_ci  }
1111cb0ef41Sopenharmony_ci
1121cb0ef41Sopenharmony_ci  // Patch a (padded) u32v at the given offset to be the given value.
1131cb0ef41Sopenharmony_ci  void patch_u32v(size_t offset, uint32_t val) {
1141cb0ef41Sopenharmony_ci    byte* ptr = buffer_ + offset;
1151cb0ef41Sopenharmony_ci    for (size_t pos = 0; pos != kPaddedVarInt32Size; ++pos) {
1161cb0ef41Sopenharmony_ci      uint32_t next = val >> 7;
1171cb0ef41Sopenharmony_ci      byte out = static_cast<byte>(val & 0x7f);
1181cb0ef41Sopenharmony_ci      if (pos != kPaddedVarInt32Size - 1) {
1191cb0ef41Sopenharmony_ci        *(ptr++) = 0x80 | out;
1201cb0ef41Sopenharmony_ci        val = next;
1211cb0ef41Sopenharmony_ci      } else {
1221cb0ef41Sopenharmony_ci        *(ptr++) = out;
1231cb0ef41Sopenharmony_ci      }
1241cb0ef41Sopenharmony_ci    }
1251cb0ef41Sopenharmony_ci  }
1261cb0ef41Sopenharmony_ci
1271cb0ef41Sopenharmony_ci  void patch_u8(size_t offset, byte val) {
1281cb0ef41Sopenharmony_ci    DCHECK_GE(size(), offset);
1291cb0ef41Sopenharmony_ci    buffer_[offset] = val;
1301cb0ef41Sopenharmony_ci  }
1311cb0ef41Sopenharmony_ci
1321cb0ef41Sopenharmony_ci  size_t offset() const { return static_cast<size_t>(pos_ - buffer_); }
1331cb0ef41Sopenharmony_ci  size_t size() const { return static_cast<size_t>(pos_ - buffer_); }
1341cb0ef41Sopenharmony_ci  const byte* data() const { return buffer_; }
1351cb0ef41Sopenharmony_ci  const byte* begin() const { return buffer_; }
1361cb0ef41Sopenharmony_ci  const byte* end() const { return pos_; }
1371cb0ef41Sopenharmony_ci
1381cb0ef41Sopenharmony_ci  void EnsureSpace(size_t size) {
1391cb0ef41Sopenharmony_ci    if ((pos_ + size) > end_) {
1401cb0ef41Sopenharmony_ci      size_t new_size = size + (end_ - buffer_) * 2;
1411cb0ef41Sopenharmony_ci      byte* new_buffer = zone_->NewArray<byte, Buffer>(new_size);
1421cb0ef41Sopenharmony_ci      memcpy(new_buffer, buffer_, (pos_ - buffer_));
1431cb0ef41Sopenharmony_ci      pos_ = new_buffer + (pos_ - buffer_);
1441cb0ef41Sopenharmony_ci      buffer_ = new_buffer;
1451cb0ef41Sopenharmony_ci      end_ = new_buffer + new_size;
1461cb0ef41Sopenharmony_ci    }
1471cb0ef41Sopenharmony_ci    DCHECK(pos_ + size <= end_);
1481cb0ef41Sopenharmony_ci  }
1491cb0ef41Sopenharmony_ci
1501cb0ef41Sopenharmony_ci  void Truncate(size_t size) {
1511cb0ef41Sopenharmony_ci    DCHECK_GE(offset(), size);
1521cb0ef41Sopenharmony_ci    pos_ = buffer_ + size;
1531cb0ef41Sopenharmony_ci  }
1541cb0ef41Sopenharmony_ci
1551cb0ef41Sopenharmony_ci  byte** pos_ptr() { return &pos_; }
1561cb0ef41Sopenharmony_ci
1571cb0ef41Sopenharmony_ci private:
1581cb0ef41Sopenharmony_ci  Zone* zone_;
1591cb0ef41Sopenharmony_ci  byte* buffer_;
1601cb0ef41Sopenharmony_ci  byte* pos_;
1611cb0ef41Sopenharmony_ci  byte* end_;
1621cb0ef41Sopenharmony_ci};
1631cb0ef41Sopenharmony_ci
1641cb0ef41Sopenharmony_ciclass WasmModuleBuilder;
1651cb0ef41Sopenharmony_ci
1661cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE WasmFunctionBuilder : public ZoneObject {
1671cb0ef41Sopenharmony_ci public:
1681cb0ef41Sopenharmony_ci  // Building methods.
1691cb0ef41Sopenharmony_ci  void SetSignature(const FunctionSig* sig);
1701cb0ef41Sopenharmony_ci  void SetSignature(uint32_t sig_index);
1711cb0ef41Sopenharmony_ci  uint32_t AddLocal(ValueType type);
1721cb0ef41Sopenharmony_ci  void EmitByte(byte b);
1731cb0ef41Sopenharmony_ci  void EmitI32V(int32_t val);
1741cb0ef41Sopenharmony_ci  void EmitU32V(uint32_t val);
1751cb0ef41Sopenharmony_ci  void EmitCode(const byte* code, uint32_t code_size);
1761cb0ef41Sopenharmony_ci  void Emit(WasmOpcode opcode);
1771cb0ef41Sopenharmony_ci  void EmitWithPrefix(WasmOpcode opcode);
1781cb0ef41Sopenharmony_ci  void EmitGetLocal(uint32_t index);
1791cb0ef41Sopenharmony_ci  void EmitSetLocal(uint32_t index);
1801cb0ef41Sopenharmony_ci  void EmitTeeLocal(uint32_t index);
1811cb0ef41Sopenharmony_ci  void EmitI32Const(int32_t val);
1821cb0ef41Sopenharmony_ci  void EmitI64Const(int64_t val);
1831cb0ef41Sopenharmony_ci  void EmitF32Const(float val);
1841cb0ef41Sopenharmony_ci  void EmitF64Const(double val);
1851cb0ef41Sopenharmony_ci  void EmitS128Const(Simd128 val);
1861cb0ef41Sopenharmony_ci  void EmitWithU8(WasmOpcode opcode, const byte immediate);
1871cb0ef41Sopenharmony_ci  void EmitWithU8U8(WasmOpcode opcode, const byte imm1, const byte imm2);
1881cb0ef41Sopenharmony_ci  void EmitWithI32V(WasmOpcode opcode, int32_t immediate);
1891cb0ef41Sopenharmony_ci  void EmitWithU32V(WasmOpcode opcode, uint32_t immediate);
1901cb0ef41Sopenharmony_ci  void EmitValueType(ValueType type);
1911cb0ef41Sopenharmony_ci  void EmitDirectCallIndex(uint32_t index);
1921cb0ef41Sopenharmony_ci  void SetName(base::Vector<const char> name);
1931cb0ef41Sopenharmony_ci  void AddAsmWasmOffset(size_t call_position, size_t to_number_position);
1941cb0ef41Sopenharmony_ci  void SetAsmFunctionStartPosition(size_t function_position);
1951cb0ef41Sopenharmony_ci  void SetCompilationHint(WasmCompilationHintStrategy strategy,
1961cb0ef41Sopenharmony_ci                          WasmCompilationHintTier baseline,
1971cb0ef41Sopenharmony_ci                          WasmCompilationHintTier top_tier);
1981cb0ef41Sopenharmony_ci
1991cb0ef41Sopenharmony_ci  size_t GetPosition() const { return body_.size(); }
2001cb0ef41Sopenharmony_ci  void FixupByte(size_t position, byte value) {
2011cb0ef41Sopenharmony_ci    body_.patch_u8(position, value);
2021cb0ef41Sopenharmony_ci  }
2031cb0ef41Sopenharmony_ci  void DeleteCodeAfter(size_t position);
2041cb0ef41Sopenharmony_ci
2051cb0ef41Sopenharmony_ci  void WriteSignature(ZoneBuffer* buffer) const;
2061cb0ef41Sopenharmony_ci  void WriteBody(ZoneBuffer* buffer) const;
2071cb0ef41Sopenharmony_ci  void WriteAsmWasmOffsetTable(ZoneBuffer* buffer) const;
2081cb0ef41Sopenharmony_ci
2091cb0ef41Sopenharmony_ci  WasmModuleBuilder* builder() const { return builder_; }
2101cb0ef41Sopenharmony_ci  uint32_t func_index() { return func_index_; }
2111cb0ef41Sopenharmony_ci  uint32_t sig_index() { return signature_index_; }
2121cb0ef41Sopenharmony_ci  inline const FunctionSig* signature();
2131cb0ef41Sopenharmony_ci
2141cb0ef41Sopenharmony_ci private:
2151cb0ef41Sopenharmony_ci  explicit WasmFunctionBuilder(WasmModuleBuilder* builder);
2161cb0ef41Sopenharmony_ci  friend class WasmModuleBuilder;
2171cb0ef41Sopenharmony_ci  friend Zone;
2181cb0ef41Sopenharmony_ci
2191cb0ef41Sopenharmony_ci  struct DirectCallIndex {
2201cb0ef41Sopenharmony_ci    size_t offset;
2211cb0ef41Sopenharmony_ci    uint32_t direct_index;
2221cb0ef41Sopenharmony_ci  };
2231cb0ef41Sopenharmony_ci
2241cb0ef41Sopenharmony_ci  WasmModuleBuilder* builder_;
2251cb0ef41Sopenharmony_ci  LocalDeclEncoder locals_;
2261cb0ef41Sopenharmony_ci  uint32_t signature_index_;
2271cb0ef41Sopenharmony_ci  uint32_t func_index_;
2281cb0ef41Sopenharmony_ci  ZoneBuffer body_;
2291cb0ef41Sopenharmony_ci  base::Vector<const char> name_;
2301cb0ef41Sopenharmony_ci  ZoneVector<uint32_t> i32_temps_;
2311cb0ef41Sopenharmony_ci  ZoneVector<uint32_t> i64_temps_;
2321cb0ef41Sopenharmony_ci  ZoneVector<uint32_t> f32_temps_;
2331cb0ef41Sopenharmony_ci  ZoneVector<uint32_t> f64_temps_;
2341cb0ef41Sopenharmony_ci  ZoneVector<DirectCallIndex> direct_calls_;
2351cb0ef41Sopenharmony_ci
2361cb0ef41Sopenharmony_ci  // Delta-encoded mapping from wasm bytes to asm.js source positions.
2371cb0ef41Sopenharmony_ci  ZoneBuffer asm_offsets_;
2381cb0ef41Sopenharmony_ci  uint32_t last_asm_byte_offset_ = 0;
2391cb0ef41Sopenharmony_ci  uint32_t last_asm_source_position_ = 0;
2401cb0ef41Sopenharmony_ci  uint32_t asm_func_start_source_position_ = 0;
2411cb0ef41Sopenharmony_ci  uint8_t hint_ = kNoCompilationHint;
2421cb0ef41Sopenharmony_ci};
2431cb0ef41Sopenharmony_ci
2441cb0ef41Sopenharmony_ciclass V8_EXPORT_PRIVATE WasmModuleBuilder : public ZoneObject {
2451cb0ef41Sopenharmony_ci public:
2461cb0ef41Sopenharmony_ci  explicit WasmModuleBuilder(Zone* zone);
2471cb0ef41Sopenharmony_ci  WasmModuleBuilder(const WasmModuleBuilder&) = delete;
2481cb0ef41Sopenharmony_ci  WasmModuleBuilder& operator=(const WasmModuleBuilder&) = delete;
2491cb0ef41Sopenharmony_ci
2501cb0ef41Sopenharmony_ci  // Static representation of wasm element segment (table initializer). This is
2511cb0ef41Sopenharmony_ci  // different than the version in wasm-module.h.
2521cb0ef41Sopenharmony_ci  class WasmElemSegment {
2531cb0ef41Sopenharmony_ci   public:
2541cb0ef41Sopenharmony_ci    // asm.js gives function indices starting with the first non-imported
2551cb0ef41Sopenharmony_ci    // function.
2561cb0ef41Sopenharmony_ci    enum FunctionIndexingMode {
2571cb0ef41Sopenharmony_ci      kRelativeToImports,
2581cb0ef41Sopenharmony_ci      kRelativeToDeclaredFunctions
2591cb0ef41Sopenharmony_ci    };
2601cb0ef41Sopenharmony_ci    enum Status {
2611cb0ef41Sopenharmony_ci      kStatusActive,      // copied automatically during instantiation.
2621cb0ef41Sopenharmony_ci      kStatusPassive,     // copied explicitly after instantiation.
2631cb0ef41Sopenharmony_ci      kStatusDeclarative  // purely declarative and never copied.
2641cb0ef41Sopenharmony_ci    };
2651cb0ef41Sopenharmony_ci    struct Entry {
2661cb0ef41Sopenharmony_ci      enum Kind { kGlobalGetEntry, kRefFuncEntry, kRefNullEntry } kind;
2671cb0ef41Sopenharmony_ci      uint32_t index;
2681cb0ef41Sopenharmony_ci      Entry(Kind kind, uint32_t index) : kind(kind), index(index) {}
2691cb0ef41Sopenharmony_ci      Entry() : kind(kRefNullEntry), index(0) {}
2701cb0ef41Sopenharmony_ci    };
2711cb0ef41Sopenharmony_ci
2721cb0ef41Sopenharmony_ci    // Construct an active segment.
2731cb0ef41Sopenharmony_ci    WasmElemSegment(Zone* zone, ValueType type, uint32_t table_index,
2741cb0ef41Sopenharmony_ci                    WasmInitExpr offset)
2751cb0ef41Sopenharmony_ci        : type(type),
2761cb0ef41Sopenharmony_ci          table_index(table_index),
2771cb0ef41Sopenharmony_ci          offset(offset),
2781cb0ef41Sopenharmony_ci          entries(zone),
2791cb0ef41Sopenharmony_ci          status(kStatusActive) {
2801cb0ef41Sopenharmony_ci      DCHECK(IsValidOffsetKind(offset.kind()));
2811cb0ef41Sopenharmony_ci    }
2821cb0ef41Sopenharmony_ci
2831cb0ef41Sopenharmony_ci    // Construct a passive or declarative segment, which has no table
2841cb0ef41Sopenharmony_ci    // index or offset.
2851cb0ef41Sopenharmony_ci    WasmElemSegment(Zone* zone, ValueType type, bool declarative)
2861cb0ef41Sopenharmony_ci        : type(type),
2871cb0ef41Sopenharmony_ci          table_index(0),
2881cb0ef41Sopenharmony_ci          entries(zone),
2891cb0ef41Sopenharmony_ci          status(declarative ? kStatusDeclarative : kStatusPassive) {
2901cb0ef41Sopenharmony_ci      DCHECK(IsValidOffsetKind(offset.kind()));
2911cb0ef41Sopenharmony_ci    }
2921cb0ef41Sopenharmony_ci
2931cb0ef41Sopenharmony_ci    MOVE_ONLY_NO_DEFAULT_CONSTRUCTOR(WasmElemSegment);
2941cb0ef41Sopenharmony_ci
2951cb0ef41Sopenharmony_ci    ValueType type;
2961cb0ef41Sopenharmony_ci    uint32_t table_index;
2971cb0ef41Sopenharmony_ci    WasmInitExpr offset;
2981cb0ef41Sopenharmony_ci    FunctionIndexingMode indexing_mode = kRelativeToImports;
2991cb0ef41Sopenharmony_ci    ZoneVector<Entry> entries;
3001cb0ef41Sopenharmony_ci    Status status;
3011cb0ef41Sopenharmony_ci
3021cb0ef41Sopenharmony_ci   private:
3031cb0ef41Sopenharmony_ci    // This ensures no {WasmInitExpr} with subexpressions is used, which would
3041cb0ef41Sopenharmony_ci    // cause a memory leak because those are stored in an std::vector. Such
3051cb0ef41Sopenharmony_ci    // offset would also be mistyped.
3061cb0ef41Sopenharmony_ci    bool IsValidOffsetKind(WasmInitExpr::Operator kind) {
3071cb0ef41Sopenharmony_ci      return kind == WasmInitExpr::kI32Const ||
3081cb0ef41Sopenharmony_ci             kind == WasmInitExpr::kGlobalGet;
3091cb0ef41Sopenharmony_ci    }
3101cb0ef41Sopenharmony_ci  };
3111cb0ef41Sopenharmony_ci
3121cb0ef41Sopenharmony_ci  // Building methods.
3131cb0ef41Sopenharmony_ci  uint32_t AddImport(base::Vector<const char> name, FunctionSig* sig,
3141cb0ef41Sopenharmony_ci                     base::Vector<const char> module = {});
3151cb0ef41Sopenharmony_ci  WasmFunctionBuilder* AddFunction(const FunctionSig* sig = nullptr);
3161cb0ef41Sopenharmony_ci  WasmFunctionBuilder* AddFunction(uint32_t sig_index);
3171cb0ef41Sopenharmony_ci  uint32_t AddGlobal(ValueType type, bool mutability = true,
3181cb0ef41Sopenharmony_ci                     WasmInitExpr init = WasmInitExpr());
3191cb0ef41Sopenharmony_ci  uint32_t AddGlobalImport(base::Vector<const char> name, ValueType type,
3201cb0ef41Sopenharmony_ci                           bool mutability,
3211cb0ef41Sopenharmony_ci                           base::Vector<const char> module = {});
3221cb0ef41Sopenharmony_ci  void AddDataSegment(const byte* data, uint32_t size, uint32_t dest);
3231cb0ef41Sopenharmony_ci  // Add an element segment to this {WasmModuleBuilder}. {segment}'s enties
3241cb0ef41Sopenharmony_ci  // have to be initialized.
3251cb0ef41Sopenharmony_ci  void AddElementSegment(WasmElemSegment segment);
3261cb0ef41Sopenharmony_ci  // Helper method to create an active segment with one function. Assumes that
3271cb0ef41Sopenharmony_ci  // table segment at {table_index} is typed as funcref.
3281cb0ef41Sopenharmony_ci  void SetIndirectFunction(uint32_t table_index, uint32_t index_in_table,
3291cb0ef41Sopenharmony_ci                           uint32_t direct_function_index,
3301cb0ef41Sopenharmony_ci                           WasmElemSegment::FunctionIndexingMode indexing_mode);
3311cb0ef41Sopenharmony_ci  // Increase the starting size of the table at {table_index} by {count}. Also
3321cb0ef41Sopenharmony_ci  // increases the maximum table size if needed. Returns the former starting
3331cb0ef41Sopenharmony_ci  // size, or the maximum uint32_t value if the maximum table size has been
3341cb0ef41Sopenharmony_ci  // exceeded.
3351cb0ef41Sopenharmony_ci  uint32_t IncreaseTableMinSize(uint32_t table_index, uint32_t count);
3361cb0ef41Sopenharmony_ci  // Adds the signature to the module if it does not already exist.
3371cb0ef41Sopenharmony_ci  uint32_t AddSignature(const FunctionSig* sig,
3381cb0ef41Sopenharmony_ci                        uint32_t supertype = kNoSuperType);
3391cb0ef41Sopenharmony_ci  // Does not deduplicate function signatures.
3401cb0ef41Sopenharmony_ci  uint32_t ForceAddSignature(const FunctionSig* sig,
3411cb0ef41Sopenharmony_ci                             uint32_t supertype = kNoSuperType);
3421cb0ef41Sopenharmony_ci  uint32_t AddException(const FunctionSig* type);
3431cb0ef41Sopenharmony_ci  uint32_t AddStructType(StructType* type, uint32_t supertype = kNoSuperType);
3441cb0ef41Sopenharmony_ci  uint32_t AddArrayType(ArrayType* type, uint32_t supertype = kNoSuperType);
3451cb0ef41Sopenharmony_ci  uint32_t AddTable(ValueType type, uint32_t min_size);
3461cb0ef41Sopenharmony_ci  uint32_t AddTable(ValueType type, uint32_t min_size, uint32_t max_size);
3471cb0ef41Sopenharmony_ci  uint32_t AddTable(ValueType type, uint32_t min_size, uint32_t max_size,
3481cb0ef41Sopenharmony_ci                    WasmInitExpr init);
3491cb0ef41Sopenharmony_ci  void MarkStartFunction(WasmFunctionBuilder* builder);
3501cb0ef41Sopenharmony_ci  void AddExport(base::Vector<const char> name, ImportExportKindCode kind,
3511cb0ef41Sopenharmony_ci                 uint32_t index);
3521cb0ef41Sopenharmony_ci  void AddExport(base::Vector<const char> name, WasmFunctionBuilder* builder) {
3531cb0ef41Sopenharmony_ci    AddExport(name, kExternalFunction, builder->func_index());
3541cb0ef41Sopenharmony_ci  }
3551cb0ef41Sopenharmony_ci  uint32_t AddExportedGlobal(ValueType type, bool mutability, WasmInitExpr init,
3561cb0ef41Sopenharmony_ci                             base::Vector<const char> name);
3571cb0ef41Sopenharmony_ci  void ExportImportedFunction(base::Vector<const char> name, int import_index);
3581cb0ef41Sopenharmony_ci  void SetMinMemorySize(uint32_t value);
3591cb0ef41Sopenharmony_ci  void SetMaxMemorySize(uint32_t value);
3601cb0ef41Sopenharmony_ci  void SetHasSharedMemory();
3611cb0ef41Sopenharmony_ci
3621cb0ef41Sopenharmony_ci  void StartRecursiveTypeGroup() {
3631cb0ef41Sopenharmony_ci    DCHECK_EQ(current_recursive_group_start_, -1);
3641cb0ef41Sopenharmony_ci    current_recursive_group_start_ = static_cast<int>(types_.size());
3651cb0ef41Sopenharmony_ci  }
3661cb0ef41Sopenharmony_ci
3671cb0ef41Sopenharmony_ci  void EndRecursiveTypeGroup() {
3681cb0ef41Sopenharmony_ci    // Make sure we are in a recursive group.
3691cb0ef41Sopenharmony_ci    DCHECK_NE(current_recursive_group_start_, -1);
3701cb0ef41Sopenharmony_ci    // Make sure the current recursive group has at least one element.
3711cb0ef41Sopenharmony_ci    DCHECK_GT(static_cast<int>(types_.size()), current_recursive_group_start_);
3721cb0ef41Sopenharmony_ci    recursive_groups_.emplace(
3731cb0ef41Sopenharmony_ci        current_recursive_group_start_,
3741cb0ef41Sopenharmony_ci        static_cast<uint32_t>(types_.size()) - current_recursive_group_start_);
3751cb0ef41Sopenharmony_ci    current_recursive_group_start_ = -1;
3761cb0ef41Sopenharmony_ci  }
3771cb0ef41Sopenharmony_ci
3781cb0ef41Sopenharmony_ci  // Writing methods.
3791cb0ef41Sopenharmony_ci  void WriteTo(ZoneBuffer* buffer) const;
3801cb0ef41Sopenharmony_ci  void WriteAsmJsOffsetTable(ZoneBuffer* buffer) const;
3811cb0ef41Sopenharmony_ci
3821cb0ef41Sopenharmony_ci  Zone* zone() { return zone_; }
3831cb0ef41Sopenharmony_ci
3841cb0ef41Sopenharmony_ci  ValueType GetTableType(uint32_t index) { return tables_[index].type; }
3851cb0ef41Sopenharmony_ci
3861cb0ef41Sopenharmony_ci  bool IsSignature(uint32_t index) {
3871cb0ef41Sopenharmony_ci    return types_[index].kind == TypeDefinition::kFunction;
3881cb0ef41Sopenharmony_ci  }
3891cb0ef41Sopenharmony_ci
3901cb0ef41Sopenharmony_ci  const FunctionSig* GetSignature(uint32_t index) {
3911cb0ef41Sopenharmony_ci    DCHECK(types_[index].kind == TypeDefinition::kFunction);
3921cb0ef41Sopenharmony_ci    return types_[index].function_sig;
3931cb0ef41Sopenharmony_ci  }
3941cb0ef41Sopenharmony_ci
3951cb0ef41Sopenharmony_ci  bool IsStructType(uint32_t index) {
3961cb0ef41Sopenharmony_ci    return types_[index].kind == TypeDefinition::kStruct;
3971cb0ef41Sopenharmony_ci  }
3981cb0ef41Sopenharmony_ci  const StructType* GetStructType(uint32_t index) {
3991cb0ef41Sopenharmony_ci    return types_[index].struct_type;
4001cb0ef41Sopenharmony_ci  }
4011cb0ef41Sopenharmony_ci
4021cb0ef41Sopenharmony_ci  bool IsArrayType(uint32_t index) {
4031cb0ef41Sopenharmony_ci    return types_[index].kind == TypeDefinition::kArray;
4041cb0ef41Sopenharmony_ci  }
4051cb0ef41Sopenharmony_ci  const ArrayType* GetArrayType(uint32_t index) {
4061cb0ef41Sopenharmony_ci    return types_[index].array_type;
4071cb0ef41Sopenharmony_ci  }
4081cb0ef41Sopenharmony_ci
4091cb0ef41Sopenharmony_ci  WasmFunctionBuilder* GetFunction(uint32_t index) { return functions_[index]; }
4101cb0ef41Sopenharmony_ci  int NumExceptions() { return static_cast<int>(exceptions_.size()); }
4111cb0ef41Sopenharmony_ci
4121cb0ef41Sopenharmony_ci  int NumTypes() { return static_cast<int>(types_.size()); }
4131cb0ef41Sopenharmony_ci
4141cb0ef41Sopenharmony_ci  int NumTables() { return static_cast<int>(tables_.size()); }
4151cb0ef41Sopenharmony_ci
4161cb0ef41Sopenharmony_ci  int NumFunctions() { return static_cast<int>(functions_.size()); }
4171cb0ef41Sopenharmony_ci
4181cb0ef41Sopenharmony_ci  const FunctionSig* GetExceptionType(int index) {
4191cb0ef41Sopenharmony_ci    return types_[exceptions_[index]].function_sig;
4201cb0ef41Sopenharmony_ci  }
4211cb0ef41Sopenharmony_ci
4221cb0ef41Sopenharmony_ci private:
4231cb0ef41Sopenharmony_ci  struct WasmFunctionImport {
4241cb0ef41Sopenharmony_ci    base::Vector<const char> module;
4251cb0ef41Sopenharmony_ci    base::Vector<const char> name;
4261cb0ef41Sopenharmony_ci    uint32_t sig_index;
4271cb0ef41Sopenharmony_ci  };
4281cb0ef41Sopenharmony_ci
4291cb0ef41Sopenharmony_ci  struct WasmGlobalImport {
4301cb0ef41Sopenharmony_ci    base::Vector<const char> module;
4311cb0ef41Sopenharmony_ci    base::Vector<const char> name;
4321cb0ef41Sopenharmony_ci    ValueTypeCode type_code;
4331cb0ef41Sopenharmony_ci    bool mutability;
4341cb0ef41Sopenharmony_ci  };
4351cb0ef41Sopenharmony_ci
4361cb0ef41Sopenharmony_ci  struct WasmExport {
4371cb0ef41Sopenharmony_ci    base::Vector<const char> name;
4381cb0ef41Sopenharmony_ci    ImportExportKindCode kind;
4391cb0ef41Sopenharmony_ci    int index;  // Can be negative for re-exported imports.
4401cb0ef41Sopenharmony_ci  };
4411cb0ef41Sopenharmony_ci
4421cb0ef41Sopenharmony_ci  struct WasmGlobal {
4431cb0ef41Sopenharmony_ci    ValueType type;
4441cb0ef41Sopenharmony_ci    bool mutability;
4451cb0ef41Sopenharmony_ci    WasmInitExpr init;
4461cb0ef41Sopenharmony_ci  };
4471cb0ef41Sopenharmony_ci
4481cb0ef41Sopenharmony_ci  struct WasmTable {
4491cb0ef41Sopenharmony_ci    ValueType type;
4501cb0ef41Sopenharmony_ci    uint32_t min_size;
4511cb0ef41Sopenharmony_ci    uint32_t max_size;
4521cb0ef41Sopenharmony_ci    bool has_maximum;
4531cb0ef41Sopenharmony_ci    WasmInitExpr init;
4541cb0ef41Sopenharmony_ci  };
4551cb0ef41Sopenharmony_ci
4561cb0ef41Sopenharmony_ci  struct WasmDataSegment {
4571cb0ef41Sopenharmony_ci    ZoneVector<byte> data;
4581cb0ef41Sopenharmony_ci    uint32_t dest;
4591cb0ef41Sopenharmony_ci  };
4601cb0ef41Sopenharmony_ci
4611cb0ef41Sopenharmony_ci  friend class WasmFunctionBuilder;
4621cb0ef41Sopenharmony_ci  Zone* zone_;
4631cb0ef41Sopenharmony_ci  ZoneVector<TypeDefinition> types_;
4641cb0ef41Sopenharmony_ci  ZoneVector<WasmFunctionImport> function_imports_;
4651cb0ef41Sopenharmony_ci  ZoneVector<WasmGlobalImport> global_imports_;
4661cb0ef41Sopenharmony_ci  ZoneVector<WasmExport> exports_;
4671cb0ef41Sopenharmony_ci  ZoneVector<WasmFunctionBuilder*> functions_;
4681cb0ef41Sopenharmony_ci  ZoneVector<WasmTable> tables_;
4691cb0ef41Sopenharmony_ci  ZoneVector<WasmDataSegment> data_segments_;
4701cb0ef41Sopenharmony_ci  ZoneVector<WasmElemSegment> element_segments_;
4711cb0ef41Sopenharmony_ci  ZoneVector<WasmGlobal> globals_;
4721cb0ef41Sopenharmony_ci  ZoneVector<int> exceptions_;
4731cb0ef41Sopenharmony_ci  ZoneUnorderedMap<FunctionSig, uint32_t> signature_map_;
4741cb0ef41Sopenharmony_ci  int current_recursive_group_start_;
4751cb0ef41Sopenharmony_ci  // first index -> size
4761cb0ef41Sopenharmony_ci  ZoneUnorderedMap<uint32_t, uint32_t> recursive_groups_;
4771cb0ef41Sopenharmony_ci  int start_function_index_;
4781cb0ef41Sopenharmony_ci  uint32_t min_memory_size_;
4791cb0ef41Sopenharmony_ci  uint32_t max_memory_size_;
4801cb0ef41Sopenharmony_ci  bool has_max_memory_size_;
4811cb0ef41Sopenharmony_ci  bool has_shared_memory_;
4821cb0ef41Sopenharmony_ci#if DEBUG
4831cb0ef41Sopenharmony_ci  // Once AddExportedImport is called, no more imports can be added.
4841cb0ef41Sopenharmony_ci  bool adding_imports_allowed_ = true;
4851cb0ef41Sopenharmony_ci#endif
4861cb0ef41Sopenharmony_ci};
4871cb0ef41Sopenharmony_ci
4881cb0ef41Sopenharmony_ciconst FunctionSig* WasmFunctionBuilder::signature() {
4891cb0ef41Sopenharmony_ci  return builder_->types_[signature_index_].function_sig;
4901cb0ef41Sopenharmony_ci}
4911cb0ef41Sopenharmony_ci
4921cb0ef41Sopenharmony_ci}  // namespace wasm
4931cb0ef41Sopenharmony_ci}  // namespace internal
4941cb0ef41Sopenharmony_ci}  // namespace v8
4951cb0ef41Sopenharmony_ci
4961cb0ef41Sopenharmony_ci#endif  // V8_WASM_WASM_MODULE_BUILDER_H_
497