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