OLD | NEW |
| (Empty) |
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/zone-containers.h" | |
10 | |
11 #include "src/wasm/leb-helper.h" | |
12 #include "src/wasm/wasm-macro-gen.h" | |
13 #include "src/wasm/wasm-module.h" | |
14 #include "src/wasm/wasm-opcodes.h" | |
15 #include "src/wasm/wasm-result.h" | |
16 | |
17 namespace v8 { | |
18 namespace internal { | |
19 namespace wasm { | |
20 | |
21 class ZoneBuffer : public ZoneObject { | |
22 public: | |
23 static const uint32_t kInitialSize = 4096; | |
24 explicit ZoneBuffer(Zone* zone, size_t initial = kInitialSize) | |
25 : zone_(zone), buffer_(reinterpret_cast<byte*>(zone->New(initial))) { | |
26 pos_ = buffer_; | |
27 end_ = buffer_ + initial; | |
28 } | |
29 | |
30 void write_u8(uint8_t x) { | |
31 EnsureSpace(1); | |
32 *(pos_++) = x; | |
33 } | |
34 | |
35 void write_u16(uint16_t x) { | |
36 EnsureSpace(2); | |
37 WriteLittleEndianValue<uint16_t>(pos_, x); | |
38 pos_ += 2; | |
39 } | |
40 | |
41 void write_u32(uint32_t x) { | |
42 EnsureSpace(4); | |
43 WriteLittleEndianValue<uint32_t>(pos_, x); | |
44 pos_ += 4; | |
45 } | |
46 | |
47 void write_u32v(uint32_t val) { | |
48 EnsureSpace(kMaxVarInt32Size); | |
49 LEBHelper::write_u32v(&pos_, val); | |
50 } | |
51 | |
52 void write_size(size_t val) { | |
53 EnsureSpace(kMaxVarInt32Size); | |
54 DCHECK_EQ(val, static_cast<uint32_t>(val)); | |
55 LEBHelper::write_u32v(&pos_, static_cast<uint32_t>(val)); | |
56 } | |
57 | |
58 void write(const byte* data, size_t size) { | |
59 EnsureSpace(size); | |
60 memcpy(pos_, data, size); | |
61 pos_ += size; | |
62 } | |
63 | |
64 size_t reserve_u32v() { | |
65 size_t off = offset(); | |
66 EnsureSpace(kMaxVarInt32Size); | |
67 pos_ += kMaxVarInt32Size; | |
68 return off; | |
69 } | |
70 | |
71 // Patch a (padded) u32v at the given offset to be the given value. | |
72 void patch_u32v(size_t offset, uint32_t val) { | |
73 byte* ptr = buffer_ + offset; | |
74 for (size_t pos = 0; pos != kPaddedVarInt32Size; ++pos) { | |
75 uint32_t next = val >> 7; | |
76 byte out = static_cast<byte>(val & 0x7f); | |
77 if (pos != kPaddedVarInt32Size - 1) { | |
78 *(ptr++) = 0x80 | out; | |
79 val = next; | |
80 } else { | |
81 *(ptr++) = out; | |
82 } | |
83 } | |
84 } | |
85 | |
86 size_t offset() { return static_cast<size_t>(pos_ - buffer_); } | |
87 size_t size() { return static_cast<size_t>(pos_ - buffer_); } | |
88 const byte* begin() { return buffer_; } | |
89 const byte* end() { return pos_; } | |
90 | |
91 void EnsureSpace(size_t size) { | |
92 if ((pos_ + size) > end_) { | |
93 size_t new_size = 4096 + size + (end_ - buffer_) * 3; | |
94 byte* new_buffer = reinterpret_cast<byte*>(zone_->New(new_size)); | |
95 memcpy(new_buffer, buffer_, (pos_ - buffer_)); | |
96 pos_ = new_buffer + (pos_ - buffer_); | |
97 buffer_ = new_buffer; | |
98 end_ = new_buffer + new_size; | |
99 } | |
100 DCHECK(pos_ + size <= end_); | |
101 } | |
102 | |
103 byte** pos_ptr() { return &pos_; } | |
104 | |
105 private: | |
106 Zone* zone_; | |
107 byte* buffer_; | |
108 byte* pos_; | |
109 byte* end_; | |
110 }; | |
111 | |
112 class WasmModuleBuilder; | |
113 | |
114 class V8_EXPORT_PRIVATE WasmFunctionBuilder : public ZoneObject { | |
115 public: | |
116 // Building methods. | |
117 void SetSignature(FunctionSig* sig); | |
118 uint32_t AddLocal(LocalType type); | |
119 void EmitVarInt(uint32_t val); | |
120 void EmitCode(const byte* code, uint32_t code_size); | |
121 void Emit(WasmOpcode opcode); | |
122 void EmitGetLocal(uint32_t index); | |
123 void EmitSetLocal(uint32_t index); | |
124 void EmitTeeLocal(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 void WriteSignature(ZoneBuffer& buffer) const; | |
133 void WriteExport(ZoneBuffer& buffer) const; | |
134 void WriteBody(ZoneBuffer& buffer) const; | |
135 | |
136 bool exported() { return exported_; } | |
137 uint32_t func_index() { return func_index_; } | |
138 FunctionSig* signature(); | |
139 | |
140 private: | |
141 explicit WasmFunctionBuilder(WasmModuleBuilder* builder); | |
142 friend class WasmModuleBuilder; | |
143 friend class WasmTemporary; | |
144 WasmModuleBuilder* builder_; | |
145 LocalDeclEncoder locals_; | |
146 uint32_t signature_index_; | |
147 bool exported_; | |
148 uint32_t func_index_; | |
149 ZoneVector<uint8_t> body_; | |
150 ZoneVector<char> name_; | |
151 ZoneVector<uint32_t> i32_temps_; | |
152 ZoneVector<uint32_t> i64_temps_; | |
153 ZoneVector<uint32_t> f32_temps_; | |
154 ZoneVector<uint32_t> f64_temps_; | |
155 }; | |
156 | |
157 class WasmTemporary { | |
158 public: | |
159 WasmTemporary(WasmFunctionBuilder* builder, LocalType type) { | |
160 switch (type) { | |
161 case kAstI32: | |
162 temporary_ = &builder->i32_temps_; | |
163 break; | |
164 case kAstI64: | |
165 temporary_ = &builder->i64_temps_; | |
166 break; | |
167 case kAstF32: | |
168 temporary_ = &builder->f32_temps_; | |
169 break; | |
170 case kAstF64: | |
171 temporary_ = &builder->f64_temps_; | |
172 break; | |
173 default: | |
174 UNREACHABLE(); | |
175 temporary_ = nullptr; | |
176 } | |
177 if (temporary_->size() == 0) { | |
178 // Allocate a new temporary. | |
179 index_ = builder->AddLocal(type); | |
180 } else { | |
181 // Reuse a previous temporary. | |
182 index_ = temporary_->back(); | |
183 temporary_->pop_back(); | |
184 } | |
185 } | |
186 ~WasmTemporary() { | |
187 temporary_->push_back(index_); // return the temporary to the list. | |
188 } | |
189 uint32_t index() { return index_; } | |
190 | |
191 private: | |
192 ZoneVector<uint32_t>* temporary_; | |
193 uint32_t index_; | |
194 }; | |
195 | |
196 // TODO(titzer): kill! | |
197 class WasmDataSegmentEncoder : public ZoneObject { | |
198 public: | |
199 WasmDataSegmentEncoder(Zone* zone, const byte* data, uint32_t size, | |
200 uint32_t dest); | |
201 void Write(ZoneBuffer& buffer) const; | |
202 | |
203 private: | |
204 ZoneVector<byte> data_; | |
205 uint32_t dest_; | |
206 }; | |
207 | |
208 struct WasmFunctionImport { | |
209 uint32_t sig_index; | |
210 const char* name; | |
211 int name_length; | |
212 }; | |
213 | |
214 class V8_EXPORT_PRIVATE WasmModuleBuilder : public ZoneObject { | |
215 public: | |
216 explicit WasmModuleBuilder(Zone* zone); | |
217 | |
218 // Building methods. | |
219 uint32_t AddImport(const char* name, int name_length, FunctionSig* sig); | |
220 void SetImportName(uint32_t index, const char* name, int name_length) { | |
221 imports_[index].name = name; | |
222 imports_[index].name_length = name_length; | |
223 } | |
224 WasmFunctionBuilder* AddFunction(FunctionSig* sig = nullptr); | |
225 uint32_t AddGlobal(LocalType type, bool exported, bool mutability = true); | |
226 void AddDataSegment(WasmDataSegmentEncoder* data); | |
227 uint32_t AddSignature(FunctionSig* sig); | |
228 void AddIndirectFunction(uint32_t index); | |
229 void MarkStartFunction(WasmFunctionBuilder* builder); | |
230 | |
231 // Writing methods. | |
232 void WriteTo(ZoneBuffer& buffer) const; | |
233 | |
234 struct CompareFunctionSigs { | |
235 bool operator()(FunctionSig* a, FunctionSig* b) const; | |
236 }; | |
237 typedef ZoneMap<FunctionSig*, uint32_t, CompareFunctionSigs> SignatureMap; | |
238 | |
239 Zone* zone() { return zone_; } | |
240 | |
241 FunctionSig* GetSignature(uint32_t index) { return signatures_[index]; } | |
242 | |
243 private: | |
244 friend class WasmFunctionBuilder; | |
245 Zone* zone_; | |
246 ZoneVector<FunctionSig*> signatures_; | |
247 ZoneVector<WasmFunctionImport> imports_; | |
248 ZoneVector<WasmFunctionBuilder*> functions_; | |
249 ZoneVector<WasmDataSegmentEncoder*> data_segments_; | |
250 ZoneVector<uint32_t> indirect_functions_; | |
251 ZoneVector<std::tuple<LocalType, bool, bool>> globals_; | |
252 SignatureMap signature_map_; | |
253 int start_function_index_; | |
254 }; | |
255 | |
256 inline FunctionSig* WasmFunctionBuilder::signature() { | |
257 return builder_->signatures_[signature_index_]; | |
258 } | |
259 | |
260 } // namespace wasm | |
261 } // namespace internal | |
262 } // namespace v8 | |
263 | |
264 #endif // V8_WASM_ENCODER_H_ | |
OLD | NEW |