Index: src/wasm/encoder.cc |
diff --git a/src/wasm/encoder.cc b/src/wasm/encoder.cc |
index a9b6c89792ceb5e9ff590587dc1e9d5559a41bb8..6f91793f21bd633b60b7485458db3c4a7b60564b 100644 |
--- a/src/wasm/encoder.cc |
+++ b/src/wasm/encoder.cc |
@@ -30,15 +30,11 @@ namespace v8 { |
namespace internal { |
namespace wasm { |
-// Emit a section name and the size as a padded varint that can be patched |
+// Emit a section code and the size as a padded varint that can be patched |
// later. |
-size_t EmitSection(WasmSection::Code code, ZoneBuffer& buffer) { |
- // Emit the section name. |
- const char* name = WasmSection::getName(code); |
- TRACE("emit section: %s\n", name); |
- size_t length = WasmSection::getNameLength(code); |
- buffer.write_size(length); // Section name string size. |
- buffer.write(reinterpret_cast<const byte*>(name), length); |
+size_t EmitSection(WasmSectionCode code, ZoneBuffer& buffer) { |
+ // Emit the section code. |
+ buffer.write_u8(code); |
// Emit a placeholder for the length. |
return buffer.reserve_u32v(); |
@@ -55,6 +51,8 @@ WasmFunctionBuilder::WasmFunctionBuilder(WasmModuleBuilder* builder) |
locals_(builder->zone()), |
signature_index_(0), |
exported_(0), |
+ func_index_(static_cast<uint32_t>(builder->imports_.size() + |
+ builder->functions_.size())), |
body_(builder->zone()), |
name_(builder->zone()), |
i32_temps_(builder->zone()), |
@@ -90,6 +88,10 @@ void WasmFunctionBuilder::EmitSetLocal(uint32_t local_index) { |
EmitWithVarInt(kExprSetLocal, local_index); |
} |
+void WasmFunctionBuilder::EmitTeeLocal(uint32_t local_index) { |
+ EmitWithVarInt(kExprTeeLocal, local_index); |
+} |
+ |
void WasmFunctionBuilder::EmitCode(const byte* code, uint32_t code_size) { |
for (size_t i = 0; i < code_size; ++i) { |
body_.push_back(code[i]); |
@@ -143,14 +145,14 @@ void WasmFunctionBuilder::WriteSignature(ZoneBuffer& buffer) const { |
buffer.write_u32v(signature_index_); |
} |
-void WasmFunctionBuilder::WriteExport(ZoneBuffer& buffer, |
- uint32_t func_index) const { |
+void WasmFunctionBuilder::WriteExport(ZoneBuffer& buffer) const { |
if (exported_) { |
- buffer.write_u32v(func_index); |
buffer.write_size(name_.size()); |
if (name_.size() > 0) { |
buffer.write(reinterpret_cast<const byte*>(&name_[0]), name_.size()); |
} |
+ buffer.write_u8(kExternalFunction); |
+ buffer.write_u32v(func_index_); |
} |
} |
@@ -175,7 +177,10 @@ WasmDataSegmentEncoder::WasmDataSegmentEncoder(Zone* zone, const byte* data, |
} |
void WasmDataSegmentEncoder::Write(ZoneBuffer& buffer) const { |
+ buffer.write_u8(0); // linear memory zero |
+ buffer.write_u8(kExprI32Const); |
buffer.write_u32v(dest_); |
+ buffer.write_u8(kExprEnd); |
buffer.write_u32v(static_cast<uint32_t>(data_.size())); |
buffer.write(&data_[0], data_.size()); |
} |
@@ -191,17 +196,11 @@ WasmModuleBuilder::WasmModuleBuilder(Zone* zone) |
signature_map_(zone), |
start_function_index_(-1) {} |
-uint32_t WasmModuleBuilder::AddFunction() { |
+WasmFunctionBuilder* WasmModuleBuilder::AddFunction(FunctionSig* sig) { |
functions_.push_back(new (zone_) WasmFunctionBuilder(this)); |
- return static_cast<uint32_t>(functions_.size() - 1); |
-} |
- |
-WasmFunctionBuilder* WasmModuleBuilder::FunctionAt(size_t index) { |
- if (functions_.size() > index) { |
- return functions_.at(index); |
- } else { |
- return nullptr; |
- } |
+ // Add the signature if one was provided here. |
+ if (sig) functions_.back()->SetSignature(sig); |
+ return functions_.back(); |
} |
void WasmModuleBuilder::AddDataSegment(WasmDataSegmentEncoder* data) { |
@@ -243,16 +242,18 @@ void WasmModuleBuilder::AddIndirectFunction(uint32_t index) { |
uint32_t WasmModuleBuilder::AddImport(const char* name, int name_length, |
FunctionSig* sig) { |
+ DCHECK_EQ(0, functions_.size()); // imports must be added before functions! |
imports_.push_back({AddSignature(sig), name, name_length}); |
return static_cast<uint32_t>(imports_.size() - 1); |
} |
-void WasmModuleBuilder::MarkStartFunction(uint32_t index) { |
- start_function_index_ = index; |
+void WasmModuleBuilder::MarkStartFunction(WasmFunctionBuilder* function) { |
+ start_function_index_ = function->func_index(); |
} |
-uint32_t WasmModuleBuilder::AddGlobal(LocalType type, bool exported) { |
- globals_.push_back(std::make_pair(type, exported)); |
+uint32_t WasmModuleBuilder::AddGlobal(LocalType type, bool exported, |
+ bool mutability) { |
+ globals_.push_back(std::make_tuple(type, exported, mutability)); |
return static_cast<uint32_t>(globals_.size() - 1); |
} |
@@ -266,7 +267,7 @@ void WasmModuleBuilder::WriteTo(ZoneBuffer& buffer) const { |
// == Emit signatures ======================================================== |
if (signatures_.size() > 0) { |
- size_t start = EmitSection(WasmSection::Code::Signatures, buffer); |
+ size_t start = EmitSection(kTypeSectionCode, buffer); |
buffer.write_size(signatures_.size()); |
for (FunctionSig* sig : signatures_) { |
@@ -283,86 +284,130 @@ void WasmModuleBuilder::WriteTo(ZoneBuffer& buffer) const { |
FixupSection(buffer, start); |
} |
- // == Emit globals =========================================================== |
- if (globals_.size() > 0) { |
- size_t start = EmitSection(WasmSection::Code::Globals, buffer); |
- buffer.write_size(globals_.size()); |
- |
- for (auto global : globals_) { |
- buffer.write_u32v(0); // Length of the global name. |
- buffer.write_u8(WasmOpcodes::LocalTypeCodeFor(global.first)); |
- buffer.write_u8(global.second); |
- } |
- FixupSection(buffer, start); |
- } |
- |
// == Emit imports =========================================================== |
if (imports_.size() > 0) { |
- size_t start = EmitSection(WasmSection::Code::ImportTable, buffer); |
+ size_t start = EmitSection(kImportSectionCode, buffer); |
buffer.write_size(imports_.size()); |
for (auto import : imports_) { |
- buffer.write_u32v(import.sig_index); |
- buffer.write_u32v(import.name_length); |
- buffer.write(reinterpret_cast<const byte*>(import.name), |
+ buffer.write_u32v(import.name_length); // module name length |
+ buffer.write(reinterpret_cast<const byte*>(import.name), // module name |
import.name_length); |
- buffer.write_u32v(0); |
+ buffer.write_u32v(0); // field name length |
+ buffer.write_u8(kExternalFunction); |
+ buffer.write_u32v(import.sig_index); |
} |
FixupSection(buffer, start); |
} |
// == Emit function signatures =============================================== |
+ bool has_names = false; |
if (functions_.size() > 0) { |
- size_t start = EmitSection(WasmSection::Code::FunctionSignatures, buffer); |
+ size_t start = EmitSection(kFunctionSectionCode, buffer); |
buffer.write_size(functions_.size()); |
for (auto function : functions_) { |
function->WriteSignature(buffer); |
if (function->exported()) exports++; |
+ if (function->name_.size() > 0) has_names = true; |
} |
FixupSection(buffer, start); |
} |
// == emit function table ==================================================== |
if (indirect_functions_.size() > 0) { |
- size_t start = EmitSection(WasmSection::Code::FunctionTable, buffer); |
+ size_t start = EmitSection(kTableSectionCode, buffer); |
+ buffer.write_u8(1); // table count |
+ buffer.write_u8(kWasmAnyFunctionTypeForm); |
+ buffer.write_u8(kResizableMaximumFlag); |
+ buffer.write_size(indirect_functions_.size()); |
buffer.write_size(indirect_functions_.size()); |
- |
- for (auto index : indirect_functions_) { |
- buffer.write_u32v(index); |
- } |
FixupSection(buffer, start); |
} |
// == emit memory declaration ================================================ |
{ |
- size_t start = EmitSection(WasmSection::Code::Memory, buffer); |
+ size_t start = EmitSection(kMemorySectionCode, buffer); |
+ buffer.write_u8(1); // memory count |
+ buffer.write_u32v(kResizableMaximumFlag); |
buffer.write_u32v(16); // min memory size |
buffer.write_u32v(16); // max memory size |
- buffer.write_u8(0); // memory export |
- static_assert(kDeclMemorySize == 3, "memory size must match emit above"); |
+ FixupSection(buffer, start); |
+ } |
+ |
+ // == Emit globals =========================================================== |
+ if (globals_.size() > 0) { |
+ size_t start = EmitSection(kGlobalSectionCode, buffer); |
+ buffer.write_size(globals_.size()); |
+ |
+ for (auto global : globals_) { |
+ static const int kLocalTypeIndex = 0; |
+ static const int kMutabilityIndex = 2; |
+ buffer.write_u8( |
+ WasmOpcodes::LocalTypeCodeFor(std::get<kLocalTypeIndex>(global))); |
+ buffer.write_u8(std::get<kMutabilityIndex>(global)); |
+ switch (std::get<kLocalTypeIndex>(global)) { |
+ case kAstI32: { |
+ static const byte code[] = {WASM_I32V_1(0)}; |
+ buffer.write(code, sizeof(code)); |
+ break; |
+ } |
+ case kAstF32: { |
+ static const byte code[] = {WASM_F32(0)}; |
+ buffer.write(code, sizeof(code)); |
+ break; |
+ } |
+ case kAstI64: { |
+ static const byte code[] = {WASM_I64V_1(0)}; |
+ buffer.write(code, sizeof(code)); |
+ break; |
+ } |
+ case kAstF64: { |
+ static const byte code[] = {WASM_F64(0.0)}; |
+ buffer.write(code, sizeof(code)); |
+ break; |
+ } |
+ default: |
+ UNREACHABLE(); |
+ } |
+ buffer.write_u8(kExprEnd); |
+ } |
FixupSection(buffer, start); |
} |
// == emit exports =========================================================== |
if (exports > 0) { |
- size_t start = EmitSection(WasmSection::Code::ExportTable, buffer); |
+ size_t start = EmitSection(kExportSectionCode, buffer); |
buffer.write_u32v(exports); |
- uint32_t index = 0; |
- for (auto function : functions_) { |
- function->WriteExport(buffer, index++); |
- } |
+ for (auto function : functions_) function->WriteExport(buffer); |
FixupSection(buffer, start); |
} |
// == emit start function index ============================================== |
if (start_function_index_ >= 0) { |
- size_t start = EmitSection(WasmSection::Code::StartFunction, buffer); |
+ size_t start = EmitSection(kStartSectionCode, buffer); |
buffer.write_u32v(start_function_index_); |
FixupSection(buffer, start); |
} |
+ // == emit function table elements =========================================== |
+ if (indirect_functions_.size() > 0) { |
+ size_t start = EmitSection(kElementSectionCode, buffer); |
+ buffer.write_u8(1); // count of entries |
+ buffer.write_u8(0); // table index |
+ buffer.write_u8(kExprI32Const); // offset |
+ buffer.write_u32v(0); |
+ buffer.write_u8(kExprEnd); |
+ buffer.write_size(indirect_functions_.size()); // element count |
+ |
+ for (auto index : indirect_functions_) { |
+ buffer.write_u32v(index); |
+ } |
+ |
+ FixupSection(buffer, start); |
+ } |
+ |
// == emit code ============================================================== |
if (functions_.size() > 0) { |
- size_t start = EmitSection(WasmSection::Code::FunctionBodies, buffer); |
+ size_t start = EmitSection(kCodeSectionCode, buffer); |
buffer.write_size(functions_.size()); |
for (auto function : functions_) { |
function->WriteBody(buffer); |
@@ -372,7 +417,7 @@ void WasmModuleBuilder::WriteTo(ZoneBuffer& buffer) const { |
// == emit data segments ===================================================== |
if (data_segments_.size() > 0) { |
- size_t start = EmitSection(WasmSection::Code::DataSegments, buffer); |
+ size_t start = EmitSection(kDataSectionCode, buffer); |
buffer.write_size(data_segments_.size()); |
for (auto segment : data_segments_) { |
@@ -380,6 +425,28 @@ void WasmModuleBuilder::WriteTo(ZoneBuffer& buffer) const { |
} |
FixupSection(buffer, start); |
} |
+ |
+ // == Emit names ============================================================= |
+ if (has_names) { |
+ // Emit the section code. |
+ buffer.write_u8(kUnknownSectionCode); |
+ // Emit a placeholder for the length. |
+ size_t start = buffer.reserve_u32v(); |
+ // Emit the section string. |
+ buffer.write_size(4); |
+ buffer.write(reinterpret_cast<const byte*>("name"), 4); |
+ // Emit the names. |
+ buffer.write_size(functions_.size()); |
+ for (auto function : functions_) { |
+ buffer.write_size(function->name_.size()); |
+ if (function->name_.size() > 0) { |
+ buffer.write(reinterpret_cast<const byte*>(&function->name_[0]), |
+ function->name_.size()); |
+ } |
+ buffer.write_u8(0); |
+ } |
+ FixupSection(buffer, start); |
+ } |
} |
} // namespace wasm |
} // namespace internal |