| // Copyright 2015 the V8 project authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef V8_WASM_ENCODER_H_ |
| #define V8_WASM_ENCODER_H_ |
| |
| #include "src/signature.h" |
| #include "src/zone-containers.h" |
| |
| #include "src/base/smart-pointers.h" |
| |
| #include "src/wasm/leb-helper.h" |
| #include "src/wasm/wasm-macro-gen.h" |
| #include "src/wasm/wasm-module.h" |
| #include "src/wasm/wasm-opcodes.h" |
| #include "src/wasm/wasm-result.h" |
| |
| namespace v8 { |
| namespace internal { |
| namespace wasm { |
| |
| class ZoneBuffer : public ZoneObject { |
| public: |
| static const uint32_t kInitialSize = 4096; |
| explicit ZoneBuffer(Zone* zone, size_t initial = kInitialSize) |
| : zone_(zone), buffer_(reinterpret_cast<byte*>(zone->New(initial))) { |
| pos_ = buffer_; |
| end_ = buffer_ + initial; |
| } |
| |
| void write_u8(uint8_t x) { |
| EnsureSpace(1); |
| *(pos_++) = x; |
| } |
| |
| void write_u16(uint16_t x) { |
| EnsureSpace(2); |
| #if V8_TARGET_LITTLE_ENDIAN |
| WriteUnalignedUInt16(pos_, x); |
| #else |
| pos_[0] = x & 0xff; |
| pos_[1] = (x >> 8) & 0xff; |
| #endif |
| pos_ += 2; |
| } |
| |
| void write_u32(uint32_t x) { |
| EnsureSpace(4); |
| #if V8_TARGET_LITTLE_ENDIAN |
| WriteUnalignedUInt32(pos_, x); |
| #else |
| pos_[0] = x & 0xff; |
| pos_[1] = (x >> 8) & 0xff; |
| pos_[2] = (x >> 16) & 0xff; |
| pos_[3] = (x >> 24) & 0xff; |
| #endif |
| pos_ += 4; |
| } |
| |
| void write_u32v(uint32_t val) { |
| EnsureSpace(kMaxVarInt32Size); |
| LEBHelper::write_u32v(&pos_, val); |
| } |
| |
| void write_size(size_t val) { |
| EnsureSpace(kMaxVarInt32Size); |
| DCHECK_EQ(val, static_cast<uint32_t>(val)); |
| LEBHelper::write_u32v(&pos_, static_cast<uint32_t>(val)); |
| } |
| |
| void write(const byte* data, size_t size) { |
| EnsureSpace(size); |
| memcpy(pos_, data, size); |
| pos_ += size; |
| } |
| |
| size_t reserve_u32v() { |
| size_t off = offset(); |
| EnsureSpace(kMaxVarInt32Size); |
| pos_ += kMaxVarInt32Size; |
| return off; |
| } |
| |
| // Patch a (padded) u32v at the given offset to be the given value. |
| void patch_u32v(size_t offset, uint32_t val) { |
| byte* ptr = buffer_ + offset; |
| for (size_t pos = 0; pos != kPaddedVarInt32Size; ++pos) { |
| uint32_t next = val >> 7; |
| byte out = static_cast<byte>(val & 0x7f); |
| if (pos != kPaddedVarInt32Size - 1) { |
| *(ptr++) = 0x80 | out; |
| val = next; |
| } else { |
| *(ptr++) = out; |
| } |
| } |
| } |
| |
| size_t offset() { return static_cast<size_t>(pos_ - buffer_); } |
| size_t size() { return static_cast<size_t>(pos_ - buffer_); } |
| const byte* begin() { return buffer_; } |
| const byte* end() { return pos_; } |
| |
| void EnsureSpace(size_t size) { |
| if ((pos_ + size) > end_) { |
| size_t new_size = 4096 + (end_ - buffer_) * 3; |
| byte* new_buffer = reinterpret_cast<byte*>(zone_->New(new_size)); |
| memcpy(new_buffer, buffer_, (pos_ - buffer_)); |
| pos_ = new_buffer + (pos_ - buffer_); |
| buffer_ = new_buffer; |
| end_ = new_buffer + new_size; |
| } |
| } |
| |
| byte** pos_ptr() { return &pos_; } |
| |
| private: |
| Zone* zone_; |
| byte* buffer_; |
| byte* pos_; |
| byte* end_; |
| }; |
| |
| class WasmModuleBuilder; |
| |
| class WasmFunctionBuilder : public ZoneObject { |
| public: |
| // Building methods. |
| void SetSignature(FunctionSig* sig); |
| uint32_t AddLocal(LocalType type); |
| void EmitVarInt(uint32_t val); |
| void EmitCode(const byte* code, uint32_t code_size); |
| void Emit(WasmOpcode opcode); |
| void EmitGetLocal(uint32_t index); |
| void EmitSetLocal(uint32_t index); |
| void EmitI32Const(int32_t val); |
| void EmitWithU8(WasmOpcode opcode, const byte immediate); |
| void EmitWithU8U8(WasmOpcode opcode, const byte imm1, const byte imm2); |
| void EmitWithVarInt(WasmOpcode opcode, uint32_t immediate); |
| void SetExported(); |
| void SetName(const char* name, int name_length); |
| bool exported() { return exported_; } |
| |
| // Writing methods. |
| void WriteSignature(ZoneBuffer& buffer) const; |
| void WriteExport(ZoneBuffer& buffer, uint32_t func_index) const; |
| void WriteBody(ZoneBuffer& buffer) const; |
| |
| private: |
| explicit WasmFunctionBuilder(WasmModuleBuilder* builder); |
| friend class WasmModuleBuilder; |
| WasmModuleBuilder* builder_; |
| LocalDeclEncoder locals_; |
| uint32_t signature_index_; |
| bool exported_; |
| ZoneVector<uint8_t> body_; |
| ZoneVector<char> name_; |
| }; |
| |
| // TODO(titzer): kill! |
| class WasmDataSegmentEncoder : public ZoneObject { |
| public: |
| WasmDataSegmentEncoder(Zone* zone, const byte* data, uint32_t size, |
| uint32_t dest); |
| void Write(ZoneBuffer& buffer) const; |
| |
| private: |
| ZoneVector<byte> data_; |
| uint32_t dest_; |
| }; |
| |
| struct WasmFunctionImport { |
| uint32_t sig_index; |
| const char* name; |
| int name_length; |
| }; |
| |
| class WasmModuleBuilder : public ZoneObject { |
| public: |
| explicit WasmModuleBuilder(Zone* zone); |
| |
| // Building methods. |
| uint32_t AddFunction(); |
| uint32_t AddGlobal(MachineType type, bool exported); |
| WasmFunctionBuilder* FunctionAt(size_t index); |
| void AddDataSegment(WasmDataSegmentEncoder* data); |
| uint32_t AddSignature(FunctionSig* sig); |
| void AddIndirectFunction(uint32_t index); |
| void MarkStartFunction(uint32_t index); |
| uint32_t AddImport(const char* name, int name_length, FunctionSig* sig); |
| |
| // Writing methods. |
| void WriteTo(ZoneBuffer& buffer) const; |
| |
| struct CompareFunctionSigs { |
| bool operator()(FunctionSig* a, FunctionSig* b) const; |
| }; |
| typedef ZoneMap<FunctionSig*, uint32_t, CompareFunctionSigs> SignatureMap; |
| |
| Zone* zone() { return zone_; } |
| |
| private: |
| Zone* zone_; |
| ZoneVector<FunctionSig*> signatures_; |
| ZoneVector<WasmFunctionImport> imports_; |
| ZoneVector<WasmFunctionBuilder*> functions_; |
| ZoneVector<WasmDataSegmentEncoder*> data_segments_; |
| ZoneVector<uint32_t> indirect_functions_; |
| ZoneVector<std::pair<MachineType, bool>> globals_; |
| SignatureMap signature_map_; |
| int start_function_index_; |
| }; |
| |
| } // namespace wasm |
| } // namespace internal |
| } // namespace v8 |
| |
| #endif // V8_WASM_ENCODER_H_ |