From 9bf8e9b7872ffcbdfc4f0dd40fd50b3a81242c76 Mon Sep 17 00:00:00 2001 From: Pip Cet Date: Mon, 6 Mar 2017 22:05:30 +0000 Subject: [PATCH 1/4] extensible name section support See https://github.com/WebAssembly/binaryen/issues/914. --- src/wasm-binary.h | 7 +++++++ src/wasm/wasm-binary.cpp | 17 +++++++++++++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/wasm-binary.h b/src/wasm-binary.h index f57d351c374..264baefb115 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -304,6 +304,11 @@ enum EncodedType { namespace UserSections { extern const char* Name; + +enum Subsection { + NameFunction = 1, + NameLocal = 2, +}; } enum ASTNodes { @@ -546,6 +551,8 @@ class WasmBinaryWriter : public Visitor { void writeResizableLimits(Address initial, Address maximum, bool hasMaximum); int32_t startSection(BinaryConsts::Section code); void finishSection(int32_t start); + int32_t startSubsection(BinaryConsts::UserSections::Subsection code); + void finishSubsection(int32_t start); void writeStart(); void writeMemory(); void writeTypes(); diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 095a0942f6d..a69bc64ab67 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -80,6 +80,16 @@ void WasmBinaryWriter::finishSection(int32_t start) { o.writeAt(start, U32LEB(size)); } +int32_t WasmBinaryWriter::startSubsection(BinaryConsts::UserSections::Subsection code) { + o << U32LEB(code); + return writeU32LEBPlaceholder(); // section size to be filled in later +} + +void WasmBinaryWriter::finishSubsection(int32_t start) { + int32_t size = o.size() - start - 5; // section size does not include the 5 bytes of the size field itself + o.writeAt(start, U32LEB(size)); +} + void WasmBinaryWriter::writeStart() { if (!wasm->start.is()) return; if (debug) std::cerr << "== writeStart" << std::endl; @@ -386,21 +396,24 @@ void WasmBinaryWriter::writeNames() { if (debug) std::cerr << "== writeNames" << std::endl; auto start = startSection(BinaryConsts::Section::User); writeInlineString(BinaryConsts::UserSections::Name); + auto substart = startSubsection(BinaryConsts::UserSections::Subsection::NameFunction); o << U32LEB(mappedFunctions.size()); Index emitted = 0; for (auto& import : wasm->imports) { if (import->kind == ExternalKind::Function) { + o << U32LEB(emitted); writeInlineString(import->name.str); - o << U32LEB(0); // TODO: locals emitted++; } } for (auto& curr : wasm->functions) { + o << U32LEB(emitted); writeInlineString(curr->name.str); - o << U32LEB(0); // TODO: locals emitted++; } assert(emitted == mappedFunctions.size()); + finishSubsection(substart); + /* TODO: locals */ finishSection(start); } From e0834ad5ae82a2af91a44f1f7bd34d17b3e0402c Mon Sep 17 00:00:00 2001 From: Pip Cet Date: Mon, 6 Mar 2017 22:33:15 +0000 Subject: [PATCH 2/4] extensible name section support: read function names, too --- src/wasm/wasm-binary.cpp | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index a69bc64ab67..6e1299eb726 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -1524,23 +1524,27 @@ void WasmBinaryBuilder::readTableElements() { void WasmBinaryBuilder::readNames() { if (debug) std::cerr << "== readNames" << std::endl; + auto name_type = getU32LEB(); + auto subsection_size = getU32LEB(); + WASM_UNUSED(subsection_size); + assert(name_type == BinaryConsts::UserSections::Subsection::NameFunction); + auto num = getU32LEB(); if (num == 0) return; + uint32_t imported_functions = 0; for (auto& import : wasm.imports) { - if (import->kind == ExternalKind::Function) { - getInlineString(); // TODO: use this - auto numLocals = getU32LEB(); - WASM_UNUSED(numLocals); - assert(numLocals == 0); // TODO - if (--num == 0) return; - } + if (import->kind != ExternalKind::Function) continue; + imported_functions++; } for (size_t i = 0; i < num; i++) { - functions[i]->name = getInlineString(); - auto numLocals = getU32LEB(); - WASM_UNUSED(numLocals); - assert(numLocals == 0); // TODO + auto index = getU32LEB(); + if (index < imported_functions) { + getInlineString(); // TODO: use this + } else if (index - imported_functions < functions.size()) { + functions[index - imported_functions]->name = getInlineString(); + } } + // TODO: locals } BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) { From e527d3abee4d84de39d809ee8500745912ea281b Mon Sep 17 00:00:00 2001 From: Pip Cet Date: Tue, 7 Mar 2017 09:02:05 +0000 Subject: [PATCH 3/4] c-api-unused-mem.txt: change expected size to match new name section --- test/example/c-api-unused-mem.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/example/c-api-unused-mem.txt b/test/example/c-api-unused-mem.txt index 52742f47619..0da1be97713 100644 --- a/test/example/c-api-unused-mem.txt +++ b/test/example/c-api-unused-mem.txt @@ -46,7 +46,7 @@ (call $main) ) ) -207 +213 (module (type $0 (func)) (type $1 (func)) From 136525fd5854aa28730e86cd45978ba2350e7626 Mon Sep 17 00:00:00 2001 From: Pip Cet Date: Tue, 7 Mar 2017 20:10:58 +0000 Subject: [PATCH 4/4] * check subsection size matches * print warning for unknown name subsections (including the local section) * name variables properly --- src/wasm-binary.h | 2 +- src/wasm/wasm-binary.cpp | 49 +++++++++++++++++++++++----------------- 2 files changed, 29 insertions(+), 22 deletions(-) diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 264baefb115..b1274fb3abd 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -729,7 +729,7 @@ class WasmBinaryBuilder { void readFunctionTableDeclaration(); void readTableElements(); - void readNames(); + void readNames(size_t); // AST reading int depth = 0; // only for debugging diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 6e1299eb726..a266a4307e1 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -981,7 +981,7 @@ void WasmBinaryBuilder::readUserSection(size_t payloadLen) { auto oldPos = pos; Name sectionName = getInlineString(); if (sectionName.equals(BinaryConsts::UserSections::Name)) { - readNames(); + readNames(payloadLen - (pos - oldPos)); } else { // an unfamiliar custom section wasm.userSections.resize(wasm.userSections.size() + 1); @@ -1522,29 +1522,36 @@ void WasmBinaryBuilder::readTableElements() { } } -void WasmBinaryBuilder::readNames() { +void WasmBinaryBuilder::readNames(size_t payloadLen) { if (debug) std::cerr << "== readNames" << std::endl; - auto name_type = getU32LEB(); - auto subsection_size = getU32LEB(); - WASM_UNUSED(subsection_size); - assert(name_type == BinaryConsts::UserSections::Subsection::NameFunction); - - auto num = getU32LEB(); - if (num == 0) return; - uint32_t imported_functions = 0; - for (auto& import : wasm.imports) { - if (import->kind != ExternalKind::Function) continue; - imported_functions++; - } - for (size_t i = 0; i < num; i++) { - auto index = getU32LEB(); - if (index < imported_functions) { - getInlineString(); // TODO: use this - } else if (index - imported_functions < functions.size()) { - functions[index - imported_functions]->name = getInlineString(); + auto sectionPos = pos; + while (pos < sectionPos + payloadLen) { + auto nameType = getU32LEB(); + auto subsectionSize = getU32LEB(); + auto subsectionPos = pos; + if (nameType != BinaryConsts::UserSections::Subsection::NameFunction) { + // TODO: locals + std::cerr << "unknown name subsection at " << pos << std::endl; + pos = subsectionPos + subsectionSize; + continue; + } + auto num = getU32LEB(); + uint32_t importedFunctions = 0; + for (auto& import : wasm.imports) { + if (import->kind != ExternalKind::Function) continue; + importedFunctions++; + } + for (size_t i = 0; i < num; i++) { + auto index = getU32LEB(); + if (index < importedFunctions) { + getInlineString(); // TODO: use this + } else if (index - importedFunctions < functions.size()) { + functions[index - importedFunctions]->name = getInlineString(); + } } + assert(pos == subsectionPos + subsectionSize); } - // TODO: locals + assert(pos == sectionPos + payloadLen); } BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) {