summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/binary-reader-logging.cc4
-rw-r--r--src/binary-reader-logging.h4
-rw-r--r--src/binary-reader-nop.h5
-rw-r--r--src/binary-reader-objdump.cc15
-rw-r--r--src/binary-reader.cc33
-rw-r--r--src/binary-reader.h5
-rw-r--r--src/binary-writer.cc6
-rw-r--r--src/binary-writer.h12
-rw-r--r--src/binary.cc24
-rw-r--r--src/binary.h21
-rw-r--r--src/tools/wast2json.cc1
-rw-r--r--src/tools/wat2wasm.cc1
-rw-r--r--test/binary/bad-data-count-mismatch.txt23
-rw-r--r--test/binary/bad-data-count-order-after-code.txt11
-rw-r--r--test/binary/bad-data-count-order-before-elem.txt11
-rw-r--r--test/dump/bulk-memory.txt52
-rw-r--r--test/dump/data-count-section.txt36
-rwxr-xr-xtest/gen-wasm.py1
-rw-r--r--test/spec/custom.txt2
19 files changed, 220 insertions, 47 deletions
diff --git a/src/binary-reader-logging.cc b/src/binary-reader-logging.cc
index bb89fb9d..9a383584 100644
--- a/src/binary-reader-logging.cc
+++ b/src/binary-reader-logging.cc
@@ -738,6 +738,10 @@ DEFINE_INDEX(EndDataSegmentInitExpr)
DEFINE_INDEX(EndDataSegment)
DEFINE_END(EndDataSection)
+DEFINE_BEGIN(BeginDataCountSection)
+DEFINE_INDEX(OnDataCount)
+DEFINE_END(EndDataCountSection)
+
DEFINE_BEGIN(BeginNamesSection)
DEFINE_INDEX(OnFunctionNamesCount)
DEFINE_INDEX(OnLocalNameFunctionCount)
diff --git a/src/binary-reader-logging.h b/src/binary-reader-logging.h
index 0f2c509a..edb6132e 100644
--- a/src/binary-reader-logging.h
+++ b/src/binary-reader-logging.h
@@ -233,6 +233,10 @@ class BinaryReaderLogging : public BinaryReaderDelegate {
Result EndDataSegment(Index index) override;
Result EndDataSection() override;
+ Result BeginDataCountSection(Offset size) override;
+ Result OnDataCount(Index count) override;
+ Result EndDataCountSection() override;
+
Result BeginNamesSection(Offset size) override;
Result OnModuleNameSubsection(Index index,
uint32_t name_type,
diff --git a/src/binary-reader-nop.h b/src/binary-reader-nop.h
index bfab11d8..20ac7158 100644
--- a/src/binary-reader-nop.h
+++ b/src/binary-reader-nop.h
@@ -307,6 +307,11 @@ class BinaryReaderNop : public BinaryReaderDelegate {
Result EndDataSegment(Index index) override { return Result::Ok; }
Result EndDataSection() override { return Result::Ok; }
+ /* DataCount section */
+ Result BeginDataCountSection(Offset size) override { return Result::Ok; }
+ Result OnDataCount(Index count) override { return Result::Ok; }
+ Result EndDataCountSection() override { return Result::Ok; }
+
/* Names section */
Result BeginNamesSection(Offset size) override { return Result::Ok; }
Result OnModuleNameSubsection(Index index,
diff --git a/src/binary-reader-objdump.cc b/src/binary-reader-objdump.cc
index 94ed487d..64cdaef0 100644
--- a/src/binary-reader-objdump.cc
+++ b/src/binary-reader-objdump.cc
@@ -717,6 +717,7 @@ class BinaryReaderObjdump : public BinaryReaderObjdumpBase {
string_view name) override;
Result OnStartFunction(Index func_index) override;
+ Result OnDataCount(Index count) override;
Result OnFunctionBodyCount(Index count) override;
Result BeginFunctionBody(Index index, Offset size) override;
@@ -866,9 +867,10 @@ Result BinaryReaderObjdump::BeginSection(BinarySection section_code,
case ObjdumpMode::Details:
if (section_match) {
printf("%s", name);
- // All known section types except the start section have a count
- // in which case this line gets completed in OnCount().
+ // All known section types except the Start and DataCount sections have
+ // a count in which case this line gets completed in OnCount().
if (section_code == BinarySection::Start ||
+ section_code == BinarySection::DataCount ||
section_code == BinarySection::Custom) {
printf(":\n");
}
@@ -994,6 +996,15 @@ Result BinaryReaderObjdump::OnStartFunction(Index func_index) {
return Result::Ok;
}
+Result BinaryReaderObjdump::OnDataCount(Index count) {
+ if (options_->mode == ObjdumpMode::Headers) {
+ printf("count: %" PRIindex "\n", count);
+ } else {
+ PrintDetails(" - data count: %" PRIindex "\n", count);
+ }
+ return Result::Ok;
+}
+
Result BinaryReaderObjdump::OnImportCount(Index count) {
return OnCount(count);
}
diff --git a/src/binary-reader.cc b/src/binary-reader.cc
index 089927cc..c01216e4 100644
--- a/src/binary-reader.cc
+++ b/src/binary-reader.cc
@@ -137,6 +137,7 @@ class BinaryReader {
Result ReadElemSection(Offset section_size) WABT_WARN_UNUSED;
Result ReadCodeSection(Offset section_size) WABT_WARN_UNUSED;
Result ReadDataSection(Offset section_size) WABT_WARN_UNUSED;
+ Result ReadDataCountSection(Offset section_size) WABT_WARN_UNUSED;
Result ReadExceptionSection(Offset section_size) WABT_WARN_UNUSED;
Result ReadSections() WABT_WARN_UNUSED;
Result ReportUnexpectedOpcode(Opcode opcode, const char* message = nullptr);
@@ -166,6 +167,7 @@ class BinaryReader {
Index num_exports_ = 0;
Index num_function_bodies_ = 0;
Index num_exceptions_ = 0;
+ Index data_count_ = kInvalidIndex;
using ReadEndRestoreGuard =
ValueRestoreGuard<size_t, &BinaryReader::read_end_>;
@@ -2071,6 +2073,9 @@ Result BinaryReader::ReadDataSection(Offset section_size) {
CALLBACK(OnDataSegmentCount, num_data_segments);
ERROR_UNLESS(num_data_segments == 0 || NumTotalMemories() > 0,
"data section without memory section");
+ // If the DataCount section is not present, then data_count_ will be invalid.
+ ERROR_UNLESS(data_count_ == kInvalidIndex || data_count_ == num_data_segments,
+ "data segment count does not equal count in DataCount section");
for (Index i = 0; i < num_data_segments; ++i) {
uint32_t flags_u32;
CHECK_RESULT(ReadU32Leb128(&flags_u32, "data segment flags"));
@@ -2098,6 +2103,16 @@ Result BinaryReader::ReadDataSection(Offset section_size) {
return Result::Ok;
}
+Result BinaryReader::ReadDataCountSection(Offset section_size) {
+ CALLBACK(BeginDataCountSection, section_size);
+ Index data_count;
+ CHECK_RESULT(ReadIndex(&data_count, "data count"));
+ CALLBACK(OnDataCount, data_count);
+ CALLBACK0(EndDataCountSection);
+ data_count_ = data_count;
+ return Result::Ok;
+}
+
Result BinaryReader::ReadSections() {
Result result = Result::Ok;
@@ -2109,8 +2124,7 @@ Result BinaryReader::ReadSections() {
ReadEndRestoreGuard guard(this);
read_end_ = state_.offset + section_size;
if (section_code >= kBinarySectionCount) {
- PrintError("invalid section code: %u; max is %u", section_code,
- kBinarySectionCount - 1);
+ PrintError("invalid section code: %u", section_code);
return Result::Error;
}
@@ -2119,10 +2133,11 @@ Result BinaryReader::ReadSections() {
ERROR_UNLESS(read_end_ <= state_.size,
"invalid section size: extends past end");
- ERROR_UNLESS(last_known_section_ == BinarySection::Invalid ||
- section == BinarySection::Custom ||
- section > last_known_section_,
- "section %s out of order", GetSectionName(section));
+ ERROR_UNLESS(
+ last_known_section_ == BinarySection::Invalid ||
+ section == BinarySection::Custom ||
+ GetSectionOrder(section) > GetSectionOrder(last_known_section_),
+ "section %s out of order", GetSectionName(section));
ERROR_UNLESS(!did_read_names_section_ || section == BinarySection::Custom,
"%s section can not occur after Name section",
@@ -2185,6 +2200,12 @@ Result BinaryReader::ReadSections() {
section_result = ReadDataSection(section_size);
result |= section_result;
break;
+ case BinarySection::DataCount:
+ ERROR_UNLESS(options_.features.bulk_memory_enabled(),
+ "invalid section code: %u", section);
+ section_result = ReadDataCountSection(section_size);
+ result |= section_result;
+ break;
case BinarySection::Invalid:
WABT_UNREACHABLE;
}
diff --git a/src/binary-reader.h b/src/binary-reader.h
index 9b100038..9fe0a17a 100644
--- a/src/binary-reader.h
+++ b/src/binary-reader.h
@@ -293,6 +293,11 @@ class BinaryReaderDelegate {
virtual Result EndDataSegment(Index index) = 0;
virtual Result EndDataSection() = 0;
+ /* DataCount section */
+ virtual Result BeginDataCountSection(Offset size) = 0;
+ virtual Result OnDataCount(Index count) = 0;
+ virtual Result EndDataCountSection() = 0;
+
/* Names section */
virtual Result BeginNamesSection(Offset size) = 0;
virtual Result OnModuleNameSubsection(Index index,
diff --git a/src/binary-writer.cc b/src/binary-writer.cc
index b8fa1702..b6c33ccc 100644
--- a/src/binary-writer.cc
+++ b/src/binary-writer.cc
@@ -993,6 +993,12 @@ Result BinaryWriter::WriteModule() {
EndSection();
}
+ if (options_.features.bulk_memory_enabled()) {
+ BeginKnownSection(BinarySection::DataCount);
+ WriteU32Leb128(stream_, module_->data_segments.size(), "data count");
+ EndSection();
+ }
+
if (num_funcs) {
BeginKnownSection(BinarySection::Code);
WriteU32Leb128(stream_, num_funcs, "num functions");
diff --git a/src/binary-writer.h b/src/binary-writer.h
index dc571f46..41e86ff1 100644
--- a/src/binary-writer.h
+++ b/src/binary-writer.h
@@ -18,6 +18,7 @@
#define WABT_BINARY_WRITER_H_
#include "src/common.h"
+#include "src/feature.h"
#include "src/opcode.h"
#include "src/stream.h"
@@ -27,6 +28,17 @@ struct Module;
struct Script;
struct WriteBinaryOptions {
+ WriteBinaryOptions() = default;
+ WriteBinaryOptions(const Features& features,
+ bool canonicalize_lebs,
+ bool relocatable,
+ bool write_debug_names)
+ : features(features),
+ canonicalize_lebs(canonicalize_lebs),
+ relocatable(relocatable),
+ write_debug_names(write_debug_names) {}
+
+ Features features;
bool canonicalize_lebs = true;
bool relocatable = false;
bool write_debug_names = false;
diff --git a/src/binary.cc b/src/binary.cc
index b0cd32a2..6e993ab6 100644
--- a/src/binary.cc
+++ b/src/binary.cc
@@ -18,10 +18,28 @@
namespace wabt {
-const char* g_section_name[] = {
-#define V(NAME, name, code) #NAME,
+BinarySectionOrder GetSectionOrder(BinarySection sec) {
+ switch (sec) {
+#define V(Name, name, code) \
+ case BinarySection::Name: \
+ return BinarySectionOrder::Name;
WABT_FOREACH_BINARY_SECTION(V)
#undef V
-};
+ default:
+ WABT_UNREACHABLE;
+ }
+}
+
+const char* GetSectionName(BinarySection sec) {
+ switch (sec) {
+#define V(Name, name, code) \
+ case BinarySection::Name: \
+ return #Name;
+ WABT_FOREACH_BINARY_SECTION(V)
+#undef V
+ default:
+ WABT_UNREACHABLE;
+ }
+}
} // namespace wabt
diff --git a/src/binary.h b/src/binary.h
index eee09f66..747c28e2 100644
--- a/src/binary.h
+++ b/src/binary.h
@@ -41,6 +41,7 @@
V(Export, export, 7) \
V(Start, start, 8) \
V(Elem, elem, 9) \
+ V(DataCount, data_count, 12) \
V(Code, code, 10) \
V(Data, data, 11)
@@ -51,14 +52,23 @@ enum class BinarySection {
#define V(Name, name, code) Name = code,
WABT_FOREACH_BINARY_SECTION(V)
#undef V
- Invalid,
+ Invalid = ~0,
First = Custom,
- Last = Data,
+ Last = DataCount,
};
/* clang-format on */
static const int kBinarySectionCount = WABT_ENUM_COUNT(BinarySection);
+enum class BinarySectionOrder {
+#define V(Name, name, code) Name,
+ WABT_FOREACH_BINARY_SECTION(V)
+#undef V
+};
+
+BinarySectionOrder GetSectionOrder(BinarySection);
+const char* GetSectionName(BinarySection);
+
enum class NameSectionSubsection {
Module = 0,
Function = 1,
@@ -71,13 +81,6 @@ enum class SegmentFlags : uint8_t {
IndexOther = 2,
};
-extern const char* g_section_name[];
-
-static WABT_INLINE const char* GetSectionName(BinarySection sec) {
- assert(static_cast<int>(sec) < kBinarySectionCount);
- return g_section_name[static_cast<size_t>(sec)];
-}
-
} // namespace wabt
#endif /* WABT_BINARY_H_ */
diff --git a/src/tools/wast2json.cc b/src/tools/wast2json.cc
index 5f5d211f..d48dcb1f 100644
--- a/src/tools/wast2json.cc
+++ b/src/tools/wast2json.cc
@@ -120,6 +120,7 @@ int ProgramMain(int argc, char** argv) {
std::string module_filename_noext =
StripExtension(s_outfile ? s_outfile : s_infile).to_string();
+ s_write_binary_options.features = s_features;
result = WriteBinarySpecScript(
&json_stream, script.get(), s_infile, module_filename_noext,
s_write_binary_options, &module_streams, s_log_stream.get());
diff --git a/src/tools/wat2wasm.cc b/src/tools/wat2wasm.cc
index fe41d49f..c8e04d4d 100644
--- a/src/tools/wat2wasm.cc
+++ b/src/tools/wat2wasm.cc
@@ -148,6 +148,7 @@ int ProgramMain(int argc, char** argv) {
if (Succeeded(result)) {
MemoryStream stream(s_log_stream.get());
+ s_write_binary_options.features = s_features;
result = WriteBinaryModule(&stream, module.get(), s_write_binary_options);
if (Succeeded(result)) {
diff --git a/test/binary/bad-data-count-mismatch.txt b/test/binary/bad-data-count-mismatch.txt
new file mode 100644
index 00000000..90f196d8
--- /dev/null
+++ b/test/binary/bad-data-count-mismatch.txt
@@ -0,0 +1,23 @@
+;;; TOOL: run-gen-wasm-bad
+;;; ARGS1: --enable-bulk-memory
+;;; ARGS2: --enable-bulk-memory
+magic
+version
+section(MEMORY) {
+ count[1]
+ has_max[0]
+ initial[1]
+}
+section(DATACOUNT) {
+ count[2]
+}
+section(DATA) {
+ count[1]
+ memory_index[0]
+ offset[i32.const 0 end]
+ data[str("whoops")]
+}
+(;; STDERR ;;;
+0000013: error: data segment count does not equal count in DataCount section
+0000013: error: data segment count does not equal count in DataCount section
+;;; STDERR ;;)
diff --git a/test/binary/bad-data-count-order-after-code.txt b/test/binary/bad-data-count-order-after-code.txt
new file mode 100644
index 00000000..6af64f24
--- /dev/null
+++ b/test/binary/bad-data-count-order-after-code.txt
@@ -0,0 +1,11 @@
+;;; TOOL: run-gen-wasm-bad
+;;; ARGS1: --enable-bulk-memory
+;;; ARGS2: --enable-bulk-memory
+magic
+version
+section(CODE) { count[0] }
+section(DATACOUNT) { count[0] }
+(;; STDERR ;;;
+000000d: error: section DataCount out of order
+000000d: error: section DataCount out of order
+;;; STDERR ;;)
diff --git a/test/binary/bad-data-count-order-before-elem.txt b/test/binary/bad-data-count-order-before-elem.txt
new file mode 100644
index 00000000..226b2c71
--- /dev/null
+++ b/test/binary/bad-data-count-order-before-elem.txt
@@ -0,0 +1,11 @@
+;;; TOOL: run-gen-wasm-bad
+;;; ARGS1: --enable-bulk-memory
+;;; ARGS2: --enable-bulk-memory
+magic
+version
+section(DATACOUNT) { count[0] }
+section(ELEM) { count[0] }
+(;; STDERR ;;;
+000000d: error: section Elem out of order
+000000d: error: section Elem out of order
+;;; STDERR ;;)
diff --git a/test/dump/bulk-memory.txt b/test/dump/bulk-memory.txt
index be06dba5..a3cdae98 100644
--- a/test/dump/bulk-memory.txt
+++ b/test/dump/bulk-memory.txt
@@ -25,30 +25,30 @@ bulk-memory.wasm: file format wasm 0x1
Code Disassembly:
-000028 func[0]:
- 000029: 41 00 | i32.const 0
- 00002b: 41 00 | i32.const 0
- 00002d: 41 00 | i32.const 0
- 00002f: fc 08 00 00 | memory.init 0 0
- 000033: fc 09 00 | memory.drop 0
- 000036: 41 00 | i32.const 0
- 000038: 41 00 | i32.const 0
- 00003a: 41 00 | i32.const 0
- 00003c: fc 0a 00 | memory.copy 0
- 00003f: 41 00 | i32.const 0
- 000041: 41 00 | i32.const 0
- 000043: 41 00 | i32.const 0
- 000045: fc 0b 00 | memory.fill 0
- 000048: 0b | end
-00004a func[1]:
- 00004b: 41 00 | i32.const 0
- 00004d: 41 00 | i32.const 0
- 00004f: 41 00 | i32.const 0
- 000051: fc 0c 00 00 | table.init 0 0
- 000055: fc 0d 00 | table.drop 0
- 000058: 41 00 | i32.const 0
- 00005a: 41 00 | i32.const 0
- 00005c: 41 00 | i32.const 0
- 00005e: fc 0e 00 | table.copy 0
- 000061: 0b | end
+00002b func[0]:
+ 00002c: 41 00 | i32.const 0
+ 00002e: 41 00 | i32.const 0
+ 000030: 41 00 | i32.const 0
+ 000032: fc 08 00 00 | memory.init 0 0
+ 000036: fc 09 00 | memory.drop 0
+ 000039: 41 00 | i32.const 0
+ 00003b: 41 00 | i32.const 0
+ 00003d: 41 00 | i32.const 0
+ 00003f: fc 0a 00 | memory.copy 0
+ 000042: 41 00 | i32.const 0
+ 000044: 41 00 | i32.const 0
+ 000046: 41 00 | i32.const 0
+ 000048: fc 0b 00 | memory.fill 0
+ 00004b: 0b | end
+00004d func[1]:
+ 00004e: 41 00 | i32.const 0
+ 000050: 41 00 | i32.const 0
+ 000052: 41 00 | i32.const 0
+ 000054: fc 0c 00 00 | table.init 0 0
+ 000058: fc 0d 00 | table.drop 0
+ 00005b: 41 00 | i32.const 0
+ 00005d: 41 00 | i32.const 0
+ 00005f: 41 00 | i32.const 0
+ 000061: fc 0e 00 | table.copy 0
+ 000064: 0b | end
;;; STDOUT ;;)
diff --git a/test/dump/data-count-section.txt b/test/dump/data-count-section.txt
new file mode 100644
index 00000000..0c995d58
--- /dev/null
+++ b/test/dump/data-count-section.txt
@@ -0,0 +1,36 @@
+;;; TOOL: run-objdump
+;;; ARGS0: --enable-bulk-memory
+;;; ARGS1: -hx
+(module
+ (memory 1)
+ (data (i32.const 0) "hi")
+ (data (i32.const 2) "world")
+ (data (i32.const 7) "goodbye")
+)
+(;; STDOUT ;;;
+
+data-count-section.wasm: file format wasm 0x1
+
+Sections:
+
+ Memory start=0x0000000a end=0x0000000d (size=0x00000003) count: 1
+DataCount start=0x0000000f end=0x00000010 (size=0x00000001) count: 3
+ Data start=0x00000012 end=0x00000030 (size=0x0000001e) count: 3
+
+Section Details:
+
+Memory[1]:
+ - memory[0] pages: initial=1
+DataCount:
+ - data count: 3
+Data[3]:
+ - segment[0] size=2 - init i32=0
+ - 0000000: 6869 hi
+ - segment[1] size=5 - init i32=2
+ - 0000002: 776f 726c 64 world
+ - segment[2] size=7 - init i32=7
+ - 0000007: 676f 6f64 6279 65 goodbye
+
+Code Disassembly:
+
+;;; STDOUT ;;)
diff --git a/test/gen-wasm.py b/test/gen-wasm.py
index 0e076c46..5e5467ea 100755
--- a/test/gen-wasm.py
+++ b/test/gen-wasm.py
@@ -62,6 +62,7 @@ NAMED_VALUES = {
'ELEM': 9,
'CODE': 10,
'DATA': 11,
+ 'DATACOUNT': 12,
# name subsection codes
'NAME_MODULE': 0,
diff --git a/test/spec/custom.txt b/test/spec/custom.txt
index 2e962408..9d74b871 100644
--- a/test/spec/custom.txt
+++ b/test/spec/custom.txt
@@ -10,7 +10,7 @@ out/test/spec/custom.wast:77: assert_malformed passed:
out/test/spec/custom.wast:85: assert_malformed passed:
000000a: error: invalid section size: extends past end
out/test/spec/custom.wast:93: assert_malformed passed:
- 0000031: error: invalid section code: 36; max is 11
+ 0000031: error: invalid section code: 36
out/test/spec/custom.wast:102: assert_malformed passed:
000003e: error: function signature count != function body count
out/test/spec/custom.wast:115: assert_malformed passed: