• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)
zone_(zone)27       : zone_(zone), buffer_(reinterpret_cast<byte*>(zone->New(initial))) {
28     pos_ = buffer_;
29     end_ = buffer_ + initial;
30   }
31 
write_u8(uint8_t x)32   void write_u8(uint8_t x) {
33     EnsureSpace(1);
34     *(pos_++) = x;
35   }
36 
write_u16(uint16_t x)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 
write_u32(uint32_t x)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 
write_u32v(uint32_t val)61   void write_u32v(uint32_t val) {
62     EnsureSpace(kMaxVarInt32Size);
63     LEBHelper::write_u32v(&pos_, val);
64   }
65 
write_size(size_t val)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 
write(const byte * data,size_t size)72   void write(const byte* data, size_t size) {
73     EnsureSpace(size);
74     memcpy(pos_, data, size);
75     pos_ += size;
76   }
77 
reserve_u32v()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.
patch_u32v(size_t offset,uint32_t val)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 
offset()100   size_t offset() { return static_cast<size_t>(pos_ - buffer_); }
size()101   size_t size() { return static_cast<size_t>(pos_ - buffer_); }
begin()102   const byte* begin() { return buffer_; }
end()103   const byte* end() { return pos_; }
104 
EnsureSpace(size_t size)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 
pos_ptr()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);
exported()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 
zone()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