blob: 19fc39703d63ef1f8add9036f4e42b9a001e4a41 [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#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
Ben Murdoch61f157c2016-09-16 13:49:30 +010013#include "src/wasm/leb-helper.h"
Ben Murdochc5610432016-08-08 18:44:38 +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#include "src/wasm/wasm-result.h"
18
19namespace v8 {
20namespace internal {
21namespace wasm {
22
Ben Murdoch61f157c2016-09-16 13:49:30 +010023class ZoneBuffer : public ZoneObject {
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000024 public:
Ben Murdoch61f157c2016-09-16 13:49:30 +010025 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_; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000117
118 private:
Ben Murdoch61f157c2016-09-16 13:49:30 +0100119 Zone* zone_;
120 byte* buffer_;
121 byte* pos_;
122 byte* end_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000123};
124
Ben Murdoch61f157c2016-09-16 13:49:30 +0100125class WasmModuleBuilder;
126
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000127class WasmFunctionBuilder : public ZoneObject {
128 public:
Ben Murdoch61f157c2016-09-16 13:49:30 +0100129 // Building methods.
Ben Murdochc5610432016-08-08 18:44:38 +0100130 void SetSignature(FunctionSig* sig);
131 uint32_t AddLocal(LocalType type);
132 void EmitVarInt(uint32_t val);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000133 void EmitCode(const byte* code, uint32_t code_size);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000134 void Emit(WasmOpcode opcode);
Ben Murdochc5610432016-08-08 18:44:38 +0100135 void EmitGetLocal(uint32_t index);
136 void EmitSetLocal(uint32_t index);
137 void EmitI32Const(int32_t val);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000138 void EmitWithU8(WasmOpcode opcode, const byte immediate);
Ben Murdochda12d292016-06-02 14:46:10 +0100139 void EmitWithU8U8(WasmOpcode opcode, const byte imm1, const byte imm2);
140 void EmitWithVarInt(WasmOpcode opcode, uint32_t immediate);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100141 void SetExported();
Ben Murdochc5610432016-08-08 18:44:38 +0100142 void SetName(const char* name, int name_length);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100143 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;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000149
150 private:
Ben Murdoch61f157c2016-09-16 13:49:30 +0100151 explicit WasmFunctionBuilder(WasmModuleBuilder* builder);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000152 friend class WasmModuleBuilder;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100153 WasmModuleBuilder* builder_;
Ben Murdochc5610432016-08-08 18:44:38 +0100154 LocalDeclEncoder locals_;
Ben Murdoch61f157c2016-09-16 13:49:30 +0100155 uint32_t signature_index_;
156 bool exported_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000157 ZoneVector<uint8_t> body_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000158 ZoneVector<char> name_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000159};
160
Ben Murdoch61f157c2016-09-16 13:49:30 +0100161// TODO(titzer): kill!
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000162class WasmDataSegmentEncoder : public ZoneObject {
163 public:
164 WasmDataSegmentEncoder(Zone* zone, const byte* data, uint32_t size,
165 uint32_t dest);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100166 void Write(ZoneBuffer& buffer) const;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000167
168 private:
169 ZoneVector<byte> data_;
170 uint32_t dest_;
171};
172
Ben Murdochc5610432016-08-08 18:44:38 +0100173struct WasmFunctionImport {
174 uint32_t sig_index;
175 const char* name;
176 int name_length;
177};
178
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000179class WasmModuleBuilder : public ZoneObject {
180 public:
181 explicit WasmModuleBuilder(Zone* zone);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100182
183 // Building methods.
Ben Murdochc5610432016-08-08 18:44:38 +0100184 uint32_t AddFunction();
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000185 uint32_t AddGlobal(MachineType type, bool exported);
186 WasmFunctionBuilder* FunctionAt(size_t index);
187 void AddDataSegment(WasmDataSegmentEncoder* data);
Ben Murdochc5610432016-08-08 18:44:38 +0100188 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);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100192
193 // Writing methods.
194 void WriteTo(ZoneBuffer& buffer) const;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000195
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000196 struct CompareFunctionSigs {
Ben Murdoch097c5b22016-05-18 11:27:45 +0100197 bool operator()(FunctionSig* a, FunctionSig* b) const;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000198 };
Ben Murdochc5610432016-08-08 18:44:38 +0100199 typedef ZoneMap<FunctionSig*, uint32_t, CompareFunctionSigs> SignatureMap;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000200
Ben Murdoch61f157c2016-09-16 13:49:30 +0100201 Zone* zone() { return zone_; }
202
Ben Murdoch097c5b22016-05-18 11:27:45 +0100203 private:
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000204 Zone* zone_;
205 ZoneVector<FunctionSig*> signatures_;
Ben Murdochc5610432016-08-08 18:44:38 +0100206 ZoneVector<WasmFunctionImport> imports_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000207 ZoneVector<WasmFunctionBuilder*> functions_;
208 ZoneVector<WasmDataSegmentEncoder*> data_segments_;
Ben Murdochc5610432016-08-08 18:44:38 +0100209 ZoneVector<uint32_t> indirect_functions_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000210 ZoneVector<std::pair<MachineType, bool>> globals_;
211 SignatureMap signature_map_;
Ben Murdochda12d292016-06-02 14:46:10 +0100212 int start_function_index_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000213};
214
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000215} // namespace wasm
216} // namespace internal
217} // namespace v8
218
219#endif // V8_WASM_ENCODER_H_