encoder.h 5.51 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12
// 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_ENCODER_H_
#define V8_WASM_ENCODER_H_

#include "src/signature.h"
#include "src/zone-containers.h"

#include "src/base/smart-pointers.h"

13
#include "src/wasm/leb-helper.h"
14
#include "src/wasm/wasm-macro-gen.h"
15 16 17 18 19 20 21 22
#include "src/wasm/wasm-module.h"
#include "src/wasm/wasm-opcodes.h"
#include "src/wasm/wasm-result.h"

namespace v8 {
namespace internal {
namespace wasm {

23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
class ZoneBuffer : public ZoneObject {
 public:
  static const uint32_t kInitialSize = 4096;
  explicit ZoneBuffer(Zone* zone, size_t initial = kInitialSize)
      : zone_(zone), buffer_(reinterpret_cast<byte*>(zone->New(initial))) {
    pos_ = buffer_;
    end_ = buffer_ + initial;
  }

  void write_u8(uint8_t x) {
    EnsureSpace(1);
    *(pos_++) = x;
  }

  void write_u16(uint16_t x) {
    EnsureSpace(2);
39
    WriteLittleEndianValue<uint16_t>(pos_, x);
40 41 42 43 44
    pos_ += 2;
  }

  void write_u32(uint32_t x) {
    EnsureSpace(4);
45
    WriteLittleEndianValue<uint32_t>(pos_, x);
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
    pos_ += 4;
  }

  void write_u32v(uint32_t val) {
    EnsureSpace(kMaxVarInt32Size);
    LEBHelper::write_u32v(&pos_, val);
  }

  void write_size(size_t val) {
    EnsureSpace(kMaxVarInt32Size);
    DCHECK_EQ(val, static_cast<uint32_t>(val));
    LEBHelper::write_u32v(&pos_, static_cast<uint32_t>(val));
  }

  void write(const byte* data, size_t size) {
    EnsureSpace(size);
    memcpy(pos_, data, size);
    pos_ += size;
  }

  size_t reserve_u32v() {
    size_t off = offset();
    EnsureSpace(kMaxVarInt32Size);
    pos_ += kMaxVarInt32Size;
    return off;
  }

  // Patch a (padded) u32v at the given offset to be the given value.
  void patch_u32v(size_t offset, uint32_t val) {
    byte* ptr = buffer_ + offset;
    for (size_t pos = 0; pos != kPaddedVarInt32Size; ++pos) {
      uint32_t next = val >> 7;
      byte out = static_cast<byte>(val & 0x7f);
      if (pos != kPaddedVarInt32Size - 1) {
        *(ptr++) = 0x80 | out;
        val = next;
      } else {
        *(ptr++) = out;
      }
    }
  }

  size_t offset() { return static_cast<size_t>(pos_ - buffer_); }
  size_t size() { return static_cast<size_t>(pos_ - buffer_); }
  const byte* begin() { return buffer_; }
  const byte* end() { return pos_; }

  void EnsureSpace(size_t size) {
    if ((pos_ + size) > end_) {
      size_t new_size = 4096 + (end_ - buffer_) * 3;
      byte* new_buffer = reinterpret_cast<byte*>(zone_->New(new_size));
      memcpy(new_buffer, buffer_, (pos_ - buffer_));
      pos_ = new_buffer + (pos_ - buffer_);
      buffer_ = new_buffer;
      end_ = new_buffer + new_size;
    }
  }

  byte** pos_ptr() { return &pos_; }

 private:
  Zone* zone_;
  byte* buffer_;
  byte* pos_;
  byte* end_;
};

113 114 115 116
class WasmModuleBuilder;

class WasmFunctionBuilder : public ZoneObject {
 public:
117
  // Building methods.
118 119
  void SetSignature(FunctionSig* sig);
  uint32_t AddLocal(LocalType type);
120
  void EmitVarInt(uint32_t val);
121 122
  void EmitCode(const byte* code, uint32_t code_size);
  void Emit(WasmOpcode opcode);
123 124
  void EmitGetLocal(uint32_t index);
  void EmitSetLocal(uint32_t index);
125
  void EmitI32Const(int32_t val);
126
  void EmitWithU8(WasmOpcode opcode, const byte immediate);
127
  void EmitWithU8U8(WasmOpcode opcode, const byte imm1, const byte imm2);
128
  void EmitWithVarInt(WasmOpcode opcode, uint32_t immediate);
129
  void SetExported();
130
  void SetName(const char* name, int name_length);
131 132 133 134 135 136
  bool exported() { return exported_; }

  // Writing methods.
  void WriteSignature(ZoneBuffer& buffer) const;
  void WriteExport(ZoneBuffer& buffer, uint32_t func_index) const;
  void WriteBody(ZoneBuffer& buffer) const;
137 138

 private:
139
  explicit WasmFunctionBuilder(WasmModuleBuilder* builder);
140
  friend class WasmModuleBuilder;
141
  WasmModuleBuilder* builder_;
142
  LocalDeclEncoder locals_;
143 144
  uint32_t signature_index_;
  bool exported_;
145 146 147 148
  ZoneVector<uint8_t> body_;
  ZoneVector<char> name_;
};

149
// TODO(titzer): kill!
150 151 152 153
class WasmDataSegmentEncoder : public ZoneObject {
 public:
  WasmDataSegmentEncoder(Zone* zone, const byte* data, uint32_t size,
                         uint32_t dest);
154
  void Write(ZoneBuffer& buffer) const;
155 156 157 158 159 160

 private:
  ZoneVector<byte> data_;
  uint32_t dest_;
};

161 162 163 164 165 166
struct WasmFunctionImport {
  uint32_t sig_index;
  const char* name;
  int name_length;
};

167 168 169
class WasmModuleBuilder : public ZoneObject {
 public:
  explicit WasmModuleBuilder(Zone* zone);
170 171

  // Building methods.
172
  uint32_t AddFunction();
173
  uint32_t AddGlobal(LocalType type, bool exported);
174 175
  WasmFunctionBuilder* FunctionAt(size_t index);
  void AddDataSegment(WasmDataSegmentEncoder* data);
176
  uint32_t AddSignature(FunctionSig* sig);
177 178
  void AddIndirectFunction(uint32_t index);
  void MarkStartFunction(uint32_t index);
179
  uint32_t AddImport(const char* name, int name_length, FunctionSig* sig);
180 181 182

  // Writing methods.
  void WriteTo(ZoneBuffer& buffer) const;
183 184

  struct CompareFunctionSigs {
185
    bool operator()(FunctionSig* a, FunctionSig* b) const;
186
  };
187
  typedef ZoneMap<FunctionSig*, uint32_t, CompareFunctionSigs> SignatureMap;
188

189 190
  Zone* zone() { return zone_; }

191
 private:
192 193
  Zone* zone_;
  ZoneVector<FunctionSig*> signatures_;
194
  ZoneVector<WasmFunctionImport> imports_;
195 196
  ZoneVector<WasmFunctionBuilder*> functions_;
  ZoneVector<WasmDataSegmentEncoder*> data_segments_;
197
  ZoneVector<uint32_t> indirect_functions_;
198
  ZoneVector<std::pair<LocalType, bool>> globals_;
199
  SignatureMap signature_map_;
200
  int start_function_index_;
201 202 203 204 205 206 207
};

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

#endif  // V8_WASM_ENCODER_H_