| 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 |