blob: 39a2f5aeb5b47849a63a81e64a5f41f58b406451 [file] [log] [blame]
Ben Murdoch4a90d5f2016-03-22 12:00:34 +00001// 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#include "src/signature.h"
6
7#include "src/handles.h"
8#include "src/v8.h"
9#include "src/zone-containers.h"
10
11#include "src/wasm/ast-decoder.h"
12#include "src/wasm/encoder.h"
Ben Murdochc5610432016-08-08 18:44:38 +010013#include "src/wasm/leb-helper.h"
Ben Murdochda12d292016-06-02 14:46:10 +010014#include "src/wasm/wasm-macro-gen.h"
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000015#include "src/wasm/wasm-module.h"
16#include "src/wasm/wasm-opcodes.h"
17
18#include "src/v8memory.h"
19
Ben Murdochda12d292016-06-02 14:46:10 +010020#if DEBUG
21#define TRACE(...) \
22 do { \
23 if (FLAG_trace_wasm_encoder) PrintF(__VA_ARGS__); \
24 } while (false)
25#else
26#define TRACE(...)
27#endif
28
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000029namespace v8 {
30namespace internal {
31namespace wasm {
32
33/*TODO: add error cases for adding too many locals, too many functions and bad
34 indices in body */
35
36namespace {
37void EmitUint8(byte** b, uint8_t x) {
38 Memory::uint8_at(*b) = x;
39 *b += 1;
40}
41
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000042void EmitUint16(byte** b, uint16_t x) {
Ben Murdoch097c5b22016-05-18 11:27:45 +010043 WriteUnalignedUInt16(*b, x);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000044 *b += 2;
45}
46
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000047void EmitUint32(byte** b, uint32_t x) {
Ben Murdoch097c5b22016-05-18 11:27:45 +010048 WriteUnalignedUInt32(*b, x);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000049 *b += 4;
50}
51
Ben Murdochc5610432016-08-08 18:44:38 +010052void EmitVarInt(byte** b, size_t val) {
53 LEBHelper::write_u32v(b, static_cast<uint32_t>(val));
54}
55
Ben Murdochda12d292016-06-02 14:46:10 +010056// Sections all start with a size, but it's unknown at the start.
57// We generate a large varint which we then fixup later when the size is known.
58//
59// TODO(jfb) Not strictly necessary since sizes are calculated ahead of time.
Ben Murdochc5610432016-08-08 18:44:38 +010060const size_t kPaddedVarintSize = 5;
Ben Murdochda12d292016-06-02 14:46:10 +010061
62void FixupSection(byte* start, byte* end) {
Ben Murdochc5610432016-08-08 18:44:38 +010063 // Same as LEBHelper::write_u32v, but fixed-width with zeroes in the MSBs.
64 size_t val = end - start - kPaddedVarintSize;
Ben Murdochda12d292016-06-02 14:46:10 +010065 TRACE(" fixup %u\n", (unsigned)val);
Ben Murdochc5610432016-08-08 18:44:38 +010066 for (size_t pos = 0; pos != kPaddedVarintSize; ++pos) {
Ben Murdochda12d292016-06-02 14:46:10 +010067 size_t next = val >> 7;
68 byte out = static_cast<byte>(val & 0x7f);
Ben Murdochc5610432016-08-08 18:44:38 +010069 if (pos != kPaddedVarintSize - 1) {
Ben Murdochda12d292016-06-02 14:46:10 +010070 *(start++) = 0x80 | out;
71 val = next;
72 } else {
73 *(start++) = out;
74 // TODO(jfb) check that the pre-allocated fixup size isn't overflowed.
75 }
76 }
77}
78
79// Returns the start of the section, where the section VarInt size is.
80byte* EmitSection(WasmSection::Code code, byte** b) {
Ben Murdochc5610432016-08-08 18:44:38 +010081 // Emit the section name.
Ben Murdochda12d292016-06-02 14:46:10 +010082 const char* name = WasmSection::getName(code);
Ben Murdochda12d292016-06-02 14:46:10 +010083 TRACE("emit section: %s\n", name);
Ben Murdochc5610432016-08-08 18:44:38 +010084 size_t length = WasmSection::getNameLength(code);
Ben Murdochda12d292016-06-02 14:46:10 +010085 EmitVarInt(b, length); // Section name string size.
86 for (size_t i = 0; i != length; ++i) EmitUint8(b, name[i]);
Ben Murdochc5610432016-08-08 18:44:38 +010087
88 // Emit a placeholder for the length.
89 byte* start = *b;
90 for (size_t padding = 0; padding != kPaddedVarintSize; ++padding) {
91 EmitUint8(b, 0xff); // Will get fixed up later.
92 }
93
Ben Murdochda12d292016-06-02 14:46:10 +010094 return start;
95}
96} // namespace
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000097
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000098WasmFunctionBuilder::WasmFunctionBuilder(Zone* zone)
Ben Murdochc5610432016-08-08 18:44:38 +010099 : locals_(zone), exported_(0), body_(zone), name_(zone) {}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000100
Ben Murdochc5610432016-08-08 18:44:38 +0100101void WasmFunctionBuilder::EmitVarInt(uint32_t val) {
102 byte buffer[8];
103 byte* ptr = buffer;
104 LEBHelper::write_u32v(&ptr, val);
105 for (byte* p = buffer; p < ptr; p++) {
106 body_.push_back(*p);
107 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000108}
109
Ben Murdochc5610432016-08-08 18:44:38 +0100110void WasmFunctionBuilder::SetSignature(FunctionSig* sig) {
111 DCHECK(!locals_.has_sig());
112 locals_.set_sig(sig);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000113}
114
Ben Murdochc5610432016-08-08 18:44:38 +0100115uint32_t WasmFunctionBuilder::AddLocal(LocalType type) {
116 DCHECK(locals_.has_sig());
117 return locals_.AddLocals(1, type);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000118}
119
Ben Murdochc5610432016-08-08 18:44:38 +0100120void WasmFunctionBuilder::EmitGetLocal(uint32_t local_index) {
121 EmitWithVarInt(kExprGetLocal, local_index);
122}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000123
Ben Murdochc5610432016-08-08 18:44:38 +0100124void WasmFunctionBuilder::EmitSetLocal(uint32_t local_index) {
125 EmitWithVarInt(kExprSetLocal, local_index);
126}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000127
128void WasmFunctionBuilder::EmitCode(const byte* code, uint32_t code_size) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000129 for (size_t i = 0; i < code_size; i++) {
130 body_.push_back(code[i]);
131 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000132}
133
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000134void WasmFunctionBuilder::Emit(WasmOpcode opcode) {
135 body_.push_back(static_cast<byte>(opcode));
136}
137
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000138void WasmFunctionBuilder::EmitWithU8(WasmOpcode opcode, const byte immediate) {
139 body_.push_back(static_cast<byte>(opcode));
140 body_.push_back(immediate);
141}
142
Ben Murdochda12d292016-06-02 14:46:10 +0100143void WasmFunctionBuilder::EmitWithU8U8(WasmOpcode opcode, const byte imm1,
144 const byte imm2) {
145 body_.push_back(static_cast<byte>(opcode));
146 body_.push_back(imm1);
147 body_.push_back(imm2);
148}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000149
Ben Murdochda12d292016-06-02 14:46:10 +0100150void WasmFunctionBuilder::EmitWithVarInt(WasmOpcode opcode,
151 uint32_t immediate) {
152 body_.push_back(static_cast<byte>(opcode));
Ben Murdochc5610432016-08-08 18:44:38 +0100153 EmitVarInt(immediate);
Ben Murdochda12d292016-06-02 14:46:10 +0100154}
155
Ben Murdochc5610432016-08-08 18:44:38 +0100156void WasmFunctionBuilder::EmitI32Const(int32_t value) {
157 // TODO(titzer): variable-length signed and unsigned i32 constants.
158 if (-128 <= value && value <= 127) {
159 EmitWithU8(kExprI8Const, static_cast<byte>(value));
160 } else {
161 byte code[] = {WASM_I32V_5(value)};
162 EmitCode(code, sizeof(code));
Ben Murdochda12d292016-06-02 14:46:10 +0100163 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000164}
165
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000166void WasmFunctionBuilder::Exported(uint8_t flag) { exported_ = flag; }
167
Ben Murdochc5610432016-08-08 18:44:38 +0100168void WasmFunctionBuilder::SetName(const char* name, int name_length) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000169 name_.clear();
170 if (name_length > 0) {
171 for (int i = 0; i < name_length; i++) {
172 name_.push_back(*(name + i));
173 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000174 }
175}
176
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000177WasmFunctionEncoder* WasmFunctionBuilder::Build(Zone* zone,
178 WasmModuleBuilder* mb) const {
179 WasmFunctionEncoder* e =
Ben Murdochc5610432016-08-08 18:44:38 +0100180 new (zone) WasmFunctionEncoder(zone, locals_, exported_);
181 // TODO(titzer): lame memcpy here.
182 e->body_.insert(e->body_.begin(), body_.begin(), body_.end());
183 e->signature_index_ = mb->AddSignature(locals_.get_sig());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000184 e->name_.insert(e->name_.begin(), name_.begin(), name_.end());
185 return e;
186}
187
Ben Murdochc5610432016-08-08 18:44:38 +0100188WasmFunctionEncoder::WasmFunctionEncoder(Zone* zone, LocalDeclEncoder locals,
189 bool exported)
190 : locals_(locals), exported_(exported), body_(zone), name_(zone) {}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000191
192uint32_t WasmFunctionEncoder::HeaderSize() const {
193 uint32_t size = 3;
Ben Murdochc5610432016-08-08 18:44:38 +0100194 size += 2;
Ben Murdochda12d292016-06-02 14:46:10 +0100195 if (HasName()) {
196 uint32_t name_size = NameSize();
Ben Murdochc5610432016-08-08 18:44:38 +0100197 size +=
198 static_cast<uint32_t>(LEBHelper::sizeof_u32v(name_size)) + name_size;
Ben Murdochda12d292016-06-02 14:46:10 +0100199 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000200 return size;
201}
202
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000203uint32_t WasmFunctionEncoder::BodySize(void) const {
Ben Murdochc5610432016-08-08 18:44:38 +0100204 return static_cast<uint32_t>(body_.size() + locals_.Size());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000205}
206
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000207uint32_t WasmFunctionEncoder::NameSize() const {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100208 return HasName() ? static_cast<uint32_t>(name_.size()) : 0;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000209}
210
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000211void WasmFunctionEncoder::Serialize(byte* buffer, byte** header,
212 byte** body) const {
213 uint8_t decl_bits = (exported_ ? kDeclFunctionExport : 0) |
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000214 (HasName() ? kDeclFunctionName : 0);
215
216 EmitUint8(header, decl_bits);
217 EmitUint16(header, signature_index_);
218
219 if (HasName()) {
Ben Murdochda12d292016-06-02 14:46:10 +0100220 EmitVarInt(header, NameSize());
221 for (size_t i = 0; i < name_.size(); ++i) {
222 EmitUint8(header, name_[i]);
223 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000224 }
225
Ben Murdochc5610432016-08-08 18:44:38 +0100226 EmitUint16(header, static_cast<uint16_t>(body_.size() + locals_.Size()));
227 (*header) += locals_.Emit(*header);
228 if (body_.size() > 0) {
229 std::memcpy(*header, &body_[0], body_.size());
230 (*header) += body_.size();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000231 }
232}
233
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000234WasmDataSegmentEncoder::WasmDataSegmentEncoder(Zone* zone, const byte* data,
235 uint32_t size, uint32_t dest)
236 : data_(zone), dest_(dest) {
237 for (size_t i = 0; i < size; i++) {
238 data_.push_back(data[i]);
239 }
240}
241
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000242uint32_t WasmDataSegmentEncoder::HeaderSize() const {
243 static const int kDataSegmentSize = 13;
244 return kDataSegmentSize;
245}
246
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000247uint32_t WasmDataSegmentEncoder::BodySize() const {
248 return static_cast<uint32_t>(data_.size());
249}
250
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000251void WasmDataSegmentEncoder::Serialize(byte* buffer, byte** header,
252 byte** body) const {
Ben Murdochda12d292016-06-02 14:46:10 +0100253 EmitVarInt(header, dest_);
254 EmitVarInt(header, static_cast<uint32_t>(data_.size()));
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000255
Ben Murdochda12d292016-06-02 14:46:10 +0100256 std::memcpy(*header, &data_[0], data_.size());
257 (*header) += data_.size();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000258}
259
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000260WasmModuleBuilder::WasmModuleBuilder(Zone* zone)
261 : zone_(zone),
262 signatures_(zone),
Ben Murdochc5610432016-08-08 18:44:38 +0100263 imports_(zone),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000264 functions_(zone),
265 data_segments_(zone),
266 indirect_functions_(zone),
267 globals_(zone),
Ben Murdochda12d292016-06-02 14:46:10 +0100268 signature_map_(zone),
269 start_function_index_(-1) {}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000270
Ben Murdochc5610432016-08-08 18:44:38 +0100271uint32_t WasmModuleBuilder::AddFunction() {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000272 functions_.push_back(new (zone_) WasmFunctionBuilder(zone_));
Ben Murdochc5610432016-08-08 18:44:38 +0100273 return static_cast<uint32_t>(functions_.size() - 1);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000274}
275
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000276WasmFunctionBuilder* WasmModuleBuilder::FunctionAt(size_t index) {
277 if (functions_.size() > index) {
278 return functions_.at(index);
279 } else {
280 return nullptr;
281 }
282}
283
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000284void WasmModuleBuilder::AddDataSegment(WasmDataSegmentEncoder* data) {
285 data_segments_.push_back(data);
286}
287
Ben Murdoch097c5b22016-05-18 11:27:45 +0100288bool WasmModuleBuilder::CompareFunctionSigs::operator()(FunctionSig* a,
289 FunctionSig* b) const {
290 if (a->return_count() < b->return_count()) return true;
291 if (a->return_count() > b->return_count()) return false;
292 if (a->parameter_count() < b->parameter_count()) return true;
293 if (a->parameter_count() > b->parameter_count()) return false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000294 for (size_t r = 0; r < a->return_count(); r++) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100295 if (a->GetReturn(r) < b->GetReturn(r)) return true;
296 if (a->GetReturn(r) > b->GetReturn(r)) return false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000297 }
298 for (size_t p = 0; p < a->parameter_count(); p++) {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100299 if (a->GetParam(p) < b->GetParam(p)) return true;
300 if (a->GetParam(p) > b->GetParam(p)) return false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000301 }
Ben Murdoch097c5b22016-05-18 11:27:45 +0100302 return false;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000303}
304
Ben Murdochc5610432016-08-08 18:44:38 +0100305uint32_t WasmModuleBuilder::AddSignature(FunctionSig* sig) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000306 SignatureMap::iterator pos = signature_map_.find(sig);
307 if (pos != signature_map_.end()) {
308 return pos->second;
309 } else {
Ben Murdochc5610432016-08-08 18:44:38 +0100310 uint32_t index = static_cast<uint32_t>(signatures_.size());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000311 signature_map_[sig] = index;
312 signatures_.push_back(sig);
313 return index;
314 }
315}
316
Ben Murdochc5610432016-08-08 18:44:38 +0100317void WasmModuleBuilder::AddIndirectFunction(uint32_t index) {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000318 indirect_functions_.push_back(index);
319}
320
Ben Murdochc5610432016-08-08 18:44:38 +0100321uint32_t WasmModuleBuilder::AddImport(const char* name, int name_length,
322 FunctionSig* sig) {
323 imports_.push_back({AddSignature(sig), name, name_length});
324 return static_cast<uint32_t>(imports_.size() - 1);
325}
326
327void WasmModuleBuilder::MarkStartFunction(uint32_t index) {
Ben Murdochda12d292016-06-02 14:46:10 +0100328 start_function_index_ = index;
329}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000330
331WasmModuleWriter* WasmModuleBuilder::Build(Zone* zone) {
332 WasmModuleWriter* writer = new (zone) WasmModuleWriter(zone);
Ben Murdochc5610432016-08-08 18:44:38 +0100333 for (auto import : imports_) {
334 writer->imports_.push_back(import);
335 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000336 for (auto function : functions_) {
337 writer->functions_.push_back(function->Build(zone, this));
338 }
339 for (auto segment : data_segments_) {
340 writer->data_segments_.push_back(segment);
341 }
342 for (auto sig : signatures_) {
343 writer->signatures_.push_back(sig);
344 }
345 for (auto index : indirect_functions_) {
346 writer->indirect_functions_.push_back(index);
347 }
348 for (auto global : globals_) {
349 writer->globals_.push_back(global);
350 }
Ben Murdochda12d292016-06-02 14:46:10 +0100351 writer->start_function_index_ = start_function_index_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000352 return writer;
353}
354
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000355uint32_t WasmModuleBuilder::AddGlobal(MachineType type, bool exported) {
356 globals_.push_back(std::make_pair(type, exported));
357 return static_cast<uint32_t>(globals_.size() - 1);
358}
359
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000360WasmModuleWriter::WasmModuleWriter(Zone* zone)
Ben Murdochc5610432016-08-08 18:44:38 +0100361 : imports_(zone),
362 functions_(zone),
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000363 data_segments_(zone),
364 signatures_(zone),
365 indirect_functions_(zone),
366 globals_(zone) {}
367
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000368struct Sizes {
369 size_t header_size;
370 size_t body_size;
371
372 size_t total() { return header_size + body_size; }
373
374 void Add(size_t header, size_t body) {
375 header_size += header;
376 body_size += body;
377 }
378
Ben Murdochda12d292016-06-02 14:46:10 +0100379 void AddSection(WasmSection::Code code, size_t other_size) {
Ben Murdochc5610432016-08-08 18:44:38 +0100380 Add(kPaddedVarintSize +
381 LEBHelper::sizeof_u32v(WasmSection::getNameLength(code)) +
Ben Murdochda12d292016-06-02 14:46:10 +0100382 WasmSection::getNameLength(code),
383 0);
Ben Murdochc5610432016-08-08 18:44:38 +0100384 if (other_size) Add(LEBHelper::sizeof_u32v(other_size), 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000385 }
386};
387
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000388WasmModuleIndex* WasmModuleWriter::WriteTo(Zone* zone) const {
389 Sizes sizes = {0, 0};
390
Ben Murdochda12d292016-06-02 14:46:10 +0100391 sizes.Add(2 * sizeof(uint32_t), 0); // header
392
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000393 if (globals_.size() > 0) {
Ben Murdochda12d292016-06-02 14:46:10 +0100394 sizes.AddSection(WasmSection::Code::Globals, globals_.size());
395 /* These globals never have names, so are always 3 bytes. */
396 sizes.Add(3 * globals_.size(), 0);
397 TRACE("Size after globals: %u, %u\n", (unsigned)sizes.header_size,
398 (unsigned)sizes.body_size);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000399 }
400
Ben Murdochda12d292016-06-02 14:46:10 +0100401 if (signatures_.size() > 0) {
402 sizes.AddSection(WasmSection::Code::Signatures, signatures_.size());
403 for (auto sig : signatures_) {
Ben Murdochc5610432016-08-08 18:44:38 +0100404 sizes.Add(1 + LEBHelper::sizeof_u32v(sig->parameter_count()) +
405 sig->parameter_count() +
406 LEBHelper::sizeof_u32v(sig->return_count()) +
407 sig->return_count(),
408 0);
Ben Murdochda12d292016-06-02 14:46:10 +0100409 }
410 TRACE("Size after signatures: %u, %u\n", (unsigned)sizes.header_size,
411 (unsigned)sizes.body_size);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000412 }
413
Ben Murdochda12d292016-06-02 14:46:10 +0100414 if (functions_.size() > 0) {
Ben Murdochc5610432016-08-08 18:44:38 +0100415 sizes.AddSection(WasmSection::Code::OldFunctions, functions_.size());
Ben Murdochda12d292016-06-02 14:46:10 +0100416 for (auto function : functions_) {
417 sizes.Add(function->HeaderSize() + function->BodySize(),
418 function->NameSize());
419 }
420 TRACE("Size after functions: %u, %u\n", (unsigned)sizes.header_size,
421 (unsigned)sizes.body_size);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000422 }
423
Ben Murdochc5610432016-08-08 18:44:38 +0100424 if (imports_.size() > 0) {
425 sizes.AddSection(WasmSection::Code::ImportTable, imports_.size());
426 for (auto import : imports_) {
427 sizes.Add(LEBHelper::sizeof_u32v(import.sig_index), 0);
428 sizes.Add(LEBHelper::sizeof_u32v(import.name_length), 0);
429 sizes.Add(import.name_length, 0);
430 sizes.Add(1, 0);
431 }
432 TRACE("Size after imports: %u, %u\n", (unsigned)sizes.header_size,
433 (unsigned)sizes.body_size);
434 }
435
436 if (indirect_functions_.size() > 0) {
437 sizes.AddSection(WasmSection::Code::FunctionTable,
438 indirect_functions_.size());
439 for (auto function_index : indirect_functions_) {
440 sizes.Add(LEBHelper::sizeof_u32v(function_index), 0);
441 }
442 TRACE("Size after indirect functions: %u, %u\n",
443 (unsigned)sizes.header_size, (unsigned)sizes.body_size);
444 }
445
446 sizes.AddSection(WasmSection::Code::Memory, 0);
447 sizes.Add(kDeclMemorySize, 0);
448 TRACE("Size after memory: %u, %u\n", (unsigned)sizes.header_size,
449 (unsigned)sizes.body_size);
450
Ben Murdochda12d292016-06-02 14:46:10 +0100451 if (start_function_index_ >= 0) {
452 sizes.AddSection(WasmSection::Code::StartFunction, 0);
Ben Murdochc5610432016-08-08 18:44:38 +0100453 sizes.Add(LEBHelper::sizeof_u32v(start_function_index_), 0);
Ben Murdochda12d292016-06-02 14:46:10 +0100454 TRACE("Size after start: %u, %u\n", (unsigned)sizes.header_size,
455 (unsigned)sizes.body_size);
456 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000457
Ben Murdochda12d292016-06-02 14:46:10 +0100458 if (data_segments_.size() > 0) {
459 sizes.AddSection(WasmSection::Code::DataSegments, data_segments_.size());
460 for (auto segment : data_segments_) {
461 sizes.Add(segment->HeaderSize(), segment->BodySize());
462 }
463 TRACE("Size after data segments: %u, %u\n", (unsigned)sizes.header_size,
464 (unsigned)sizes.body_size);
465 }
466
Ben Murdochda12d292016-06-02 14:46:10 +0100467 if (sizes.body_size > 0) {
468 sizes.AddSection(WasmSection::Code::End, 0);
469 TRACE("Size after end: %u, %u\n", (unsigned)sizes.header_size,
470 (unsigned)sizes.body_size);
471 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000472
473 ZoneVector<uint8_t> buffer_vector(sizes.total(), zone);
474 byte* buffer = &buffer_vector[0];
475 byte* header = buffer;
476 byte* body = buffer + sizes.header_size;
477
Ben Murdochda12d292016-06-02 14:46:10 +0100478 // -- emit magic -------------------------------------------------------------
479 TRACE("emit magic\n");
480 EmitUint32(&header, kWasmMagic);
481 EmitUint32(&header, kWasmVersion);
482
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000483 // -- emit globals -----------------------------------------------------------
484 if (globals_.size() > 0) {
Ben Murdochda12d292016-06-02 14:46:10 +0100485 byte* section = EmitSection(WasmSection::Code::Globals, &header);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000486 EmitVarInt(&header, globals_.size());
487
488 for (auto global : globals_) {
Ben Murdochda12d292016-06-02 14:46:10 +0100489 EmitVarInt(&header, 0); // Length of the global name.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000490 EmitUint8(&header, WasmOpcodes::MemTypeCodeFor(global.first));
491 EmitUint8(&header, global.second);
492 }
Ben Murdochda12d292016-06-02 14:46:10 +0100493 FixupSection(section, header);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000494 }
495
496 // -- emit signatures --------------------------------------------------------
497 if (signatures_.size() > 0) {
Ben Murdochda12d292016-06-02 14:46:10 +0100498 byte* section = EmitSection(WasmSection::Code::Signatures, &header);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000499 EmitVarInt(&header, signatures_.size());
500
501 for (FunctionSig* sig : signatures_) {
Ben Murdochc5610432016-08-08 18:44:38 +0100502 EmitUint8(&header, kWasmFunctionTypeForm);
Ben Murdochda12d292016-06-02 14:46:10 +0100503 EmitVarInt(&header, sig->parameter_count());
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000504 for (size_t j = 0; j < sig->parameter_count(); j++) {
505 EmitUint8(&header, WasmOpcodes::LocalTypeCodeFor(sig->GetParam(j)));
506 }
Ben Murdochc5610432016-08-08 18:44:38 +0100507 EmitVarInt(&header, sig->return_count());
508 for (size_t j = 0; j < sig->return_count(); j++) {
509 EmitUint8(&header, WasmOpcodes::LocalTypeCodeFor(sig->GetReturn(j)));
510 }
511 }
512 FixupSection(section, header);
513 }
514
515 // -- emit imports -----------------------------------------------------------
516 if (imports_.size() > 0) {
517 byte* section = EmitSection(WasmSection::Code::ImportTable, &header);
518 EmitVarInt(&header, imports_.size());
519 for (auto import : imports_) {
520 EmitVarInt(&header, import.sig_index);
521 EmitVarInt(&header, import.name_length);
522 std::memcpy(header, import.name, import.name_length);
523 header += import.name_length;
524 EmitVarInt(&header, 0);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000525 }
Ben Murdochda12d292016-06-02 14:46:10 +0100526 FixupSection(section, header);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000527 }
528
529 // -- emit functions ---------------------------------------------------------
530 if (functions_.size() > 0) {
Ben Murdochc5610432016-08-08 18:44:38 +0100531 byte* section = EmitSection(WasmSection::Code::OldFunctions, &header);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000532 EmitVarInt(&header, functions_.size());
533
534 for (auto func : functions_) {
535 func->Serialize(buffer, &header, &body);
536 }
Ben Murdochda12d292016-06-02 14:46:10 +0100537 FixupSection(section, header);
538 }
539
Ben Murdochc5610432016-08-08 18:44:38 +0100540 // -- emit function table ----------------------------------------------------
541 if (indirect_functions_.size() > 0) {
542 byte* section = EmitSection(WasmSection::Code::FunctionTable, &header);
543 EmitVarInt(&header, indirect_functions_.size());
544
545 for (auto index : indirect_functions_) {
546 EmitVarInt(&header, index);
547 }
548 FixupSection(section, header);
549 }
550
551 // -- emit memory declaration ------------------------------------------------
552 {
553 byte* section = EmitSection(WasmSection::Code::Memory, &header);
554 EmitVarInt(&header, 16); // min memory size
555 EmitVarInt(&header, 16); // max memory size
556 EmitUint8(&header, 0); // memory export
557 static_assert(kDeclMemorySize == 3, "memory size must match emit above");
558 FixupSection(section, header);
559 }
560
Ben Murdochda12d292016-06-02 14:46:10 +0100561 // -- emit start function index ----------------------------------------------
562 if (start_function_index_ >= 0) {
563 byte* section = EmitSection(WasmSection::Code::StartFunction, &header);
564 EmitVarInt(&header, start_function_index_);
565 FixupSection(section, header);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000566 }
567
568 // -- emit data segments -----------------------------------------------------
569 if (data_segments_.size() > 0) {
Ben Murdochda12d292016-06-02 14:46:10 +0100570 byte* section = EmitSection(WasmSection::Code::DataSegments, &header);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000571 EmitVarInt(&header, data_segments_.size());
572
573 for (auto segment : data_segments_) {
574 segment->Serialize(buffer, &header, &body);
575 }
Ben Murdochda12d292016-06-02 14:46:10 +0100576 FixupSection(section, header);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000577 }
578
Ben Murdochda12d292016-06-02 14:46:10 +0100579 if (sizes.body_size > 0) {
580 byte* section = EmitSection(WasmSection::Code::End, &header);
581 FixupSection(section, header);
582 }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000583
584 return new (zone) WasmModuleIndex(buffer, buffer + sizes.total());
585}
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000586} // namespace wasm
587} // namespace internal
588} // namespace v8