Home | History | Annotate | Download | only in wasm
      1 // Copyright 2015 the V8 project authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef V8_WASM_ENCODER_H_
      6 #define V8_WASM_ENCODER_H_
      7 
      8 #include "src/signature.h"
      9 #include "src/zone-containers.h"
     10 
     11 #include "src/base/smart-pointers.h"
     12 
     13 #include "src/wasm/leb-helper.h"
     14 #include "src/wasm/wasm-macro-gen.h"
     15 #include "src/wasm/wasm-module.h"
     16 #include "src/wasm/wasm-opcodes.h"
     17 #include "src/wasm/wasm-result.h"
     18 
     19 namespace v8 {
     20 namespace internal {
     21 namespace wasm {
     22 
     23 class ZoneBuffer : public ZoneObject {
     24  public:
     25   static const uint32_t kInitialSize = 4096;
     26   explicit ZoneBuffer(Zone* zone, size_t initial = kInitialSize)
     27       : zone_(zone), buffer_(reinterpret_cast<byte*>(zone->New(initial))) {
     28     pos_ = buffer_;
     29     end_ = buffer_ + initial;
     30   }
     31 
     32   void write_u8(uint8_t x) {
     33     EnsureSpace(1);
     34     *(pos_++) = x;
     35   }
     36 
     37   void write_u16(uint16_t x) {
     38     EnsureSpace(2);
     39 #if V8_TARGET_LITTLE_ENDIAN
     40     WriteUnalignedUInt16(pos_, x);
     41 #else
     42     pos_[0] = x & 0xff;
     43     pos_[1] = (x >> 8) & 0xff;
     44 #endif
     45     pos_ += 2;
     46   }
     47 
     48   void write_u32(uint32_t x) {
     49     EnsureSpace(4);
     50 #if V8_TARGET_LITTLE_ENDIAN
     51     WriteUnalignedUInt32(pos_, x);
     52 #else
     53     pos_[0] = x & 0xff;
     54     pos_[1] = (x >> 8) & 0xff;
     55     pos_[2] = (x >> 16) & 0xff;
     56     pos_[3] = (x >> 24) & 0xff;
     57 #endif
     58     pos_ += 4;
     59   }
     60 
     61   void write_u32v(uint32_t val) {
     62     EnsureSpace(kMaxVarInt32Size);
     63     LEBHelper::write_u32v(&pos_, val);
     64   }
     65 
     66   void write_size(size_t val) {
     67     EnsureSpace(kMaxVarInt32Size);
     68     DCHECK_EQ(val, static_cast<uint32_t>(val));
     69     LEBHelper::write_u32v(&pos_, static_cast<uint32_t>(val));
     70   }
     71 
     72   void write(const byte* data, size_t size) {
     73     EnsureSpace(size);
     74     memcpy(pos_, data, size);
     75     pos_ += size;
     76   }
     77 
     78   size_t reserve_u32v() {
     79     size_t off = offset();
     80     EnsureSpace(kMaxVarInt32Size);
     81     pos_ += kMaxVarInt32Size;
     82     return off;
     83   }
     84 
     85   // Patch a (padded) u32v at the given offset to be the given value.
     86   void patch_u32v(size_t offset, uint32_t val) {
     87     byte* ptr = buffer_ + offset;
     88     for (size_t pos = 0; pos != kPaddedVarInt32Size; ++pos) {
     89       uint32_t next = val >> 7;
     90       byte out = static_cast<byte>(val & 0x7f);
     91       if (pos != kPaddedVarInt32Size - 1) {
     92         *(ptr++) = 0x80 | out;
     93         val = next;
     94       } else {
     95         *(ptr++) = out;
     96       }
     97     }
     98   }
     99 
    100   size_t offset() { return static_cast<size_t>(pos_ - buffer_); }
    101   size_t size() { return static_cast<size_t>(pos_ - buffer_); }
    102   const byte* begin() { return buffer_; }
    103   const byte* end() { return pos_; }
    104 
    105   void EnsureSpace(size_t size) {
    106     if ((pos_ + size) > end_) {
    107       size_t new_size = 4096 + (end_ - buffer_) * 3;
    108       byte* new_buffer = reinterpret_cast<byte*>(zone_->New(new_size));
    109       memcpy(new_buffer, buffer_, (pos_ - buffer_));
    110       pos_ = new_buffer + (pos_ - buffer_);
    111       buffer_ = new_buffer;
    112       end_ = new_buffer + new_size;
    113     }
    114   }
    115 
    116   byte** pos_ptr() { return &pos_; }
    117 
    118  private:
    119   Zone* zone_;
    120   byte* buffer_;
    121   byte* pos_;
    122   byte* end_;
    123 };
    124 
    125 class WasmModuleBuilder;
    126 
    127 class WasmFunctionBuilder : public ZoneObject {
    128  public:
    129   // Building methods.
    130   void SetSignature(FunctionSig* sig);
    131   uint32_t AddLocal(LocalType type);
    132   void EmitVarInt(uint32_t val);
    133   void EmitCode(const byte* code, uint32_t code_size);
    134   void Emit(WasmOpcode opcode);
    135   void EmitGetLocal(uint32_t index);
    136   void EmitSetLocal(uint32_t index);
    137   void EmitI32Const(int32_t val);
    138   void EmitWithU8(WasmOpcode opcode, const byte immediate);
    139   void EmitWithU8U8(WasmOpcode opcode, const byte imm1, const byte imm2);
    140   void EmitWithVarInt(WasmOpcode opcode, uint32_t immediate);
    141   void SetExported();
    142   void SetName(const char* name, int name_length);
    143   bool exported() { return exported_; }
    144 
    145   // Writing methods.
    146   void WriteSignature(ZoneBuffer& buffer) const;
    147   void WriteExport(ZoneBuffer& buffer, uint32_t func_index) const;
    148   void WriteBody(ZoneBuffer& buffer) const;
    149 
    150  private:
    151   explicit WasmFunctionBuilder(WasmModuleBuilder* builder);
    152   friend class WasmModuleBuilder;
    153   WasmModuleBuilder* builder_;
    154   LocalDeclEncoder locals_;
    155   uint32_t signature_index_;
    156   bool exported_;
    157   ZoneVector<uint8_t> body_;
    158   ZoneVector<char> name_;
    159 };
    160 
    161 // TODO(titzer): kill!
    162 class WasmDataSegmentEncoder : public ZoneObject {
    163  public:
    164   WasmDataSegmentEncoder(Zone* zone, const byte* data, uint32_t size,
    165                          uint32_t dest);
    166   void Write(ZoneBuffer& buffer) const;
    167 
    168  private:
    169   ZoneVector<byte> data_;
    170   uint32_t dest_;
    171 };
    172 
    173 struct WasmFunctionImport {
    174   uint32_t sig_index;
    175   const char* name;
    176   int name_length;
    177 };
    178 
    179 class WasmModuleBuilder : public ZoneObject {
    180  public:
    181   explicit WasmModuleBuilder(Zone* zone);
    182 
    183   // Building methods.
    184   uint32_t AddFunction();
    185   uint32_t AddGlobal(MachineType type, bool exported);
    186   WasmFunctionBuilder* FunctionAt(size_t index);
    187   void AddDataSegment(WasmDataSegmentEncoder* data);
    188   uint32_t AddSignature(FunctionSig* sig);
    189   void AddIndirectFunction(uint32_t index);
    190   void MarkStartFunction(uint32_t index);
    191   uint32_t AddImport(const char* name, int name_length, FunctionSig* sig);
    192 
    193   // Writing methods.
    194   void WriteTo(ZoneBuffer& buffer) const;
    195 
    196   struct CompareFunctionSigs {
    197     bool operator()(FunctionSig* a, FunctionSig* b) const;
    198   };
    199   typedef ZoneMap<FunctionSig*, uint32_t, CompareFunctionSigs> SignatureMap;
    200 
    201   Zone* zone() { return zone_; }
    202 
    203  private:
    204   Zone* zone_;
    205   ZoneVector<FunctionSig*> signatures_;
    206   ZoneVector<WasmFunctionImport> imports_;
    207   ZoneVector<WasmFunctionBuilder*> functions_;
    208   ZoneVector<WasmDataSegmentEncoder*> data_segments_;
    209   ZoneVector<uint32_t> indirect_functions_;
    210   ZoneVector<std::pair<MachineType, bool>> globals_;
    211   SignatureMap signature_map_;
    212   int start_function_index_;
    213 };
    214 
    215 }  // namespace wasm
    216 }  // namespace internal
    217 }  // namespace v8
    218 
    219 #endif  // V8_WASM_ENCODER_H_
    220