summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/wasm-binary.h10
-rw-r--r--src/wasm/wasm-binary.cpp24
-rw-r--r--test/debugInfo.fromasm.clamp.map2
-rw-r--r--test/debugInfo.fromasm.map2
-rwxr-xr-xtest/unit/input/bulkmem_bad_datacount.wasmbin0 -> 177 bytes
-rwxr-xr-xtest/unit/input/bulkmem_data.wasmbin0 -> 177 bytes
-rw-r--r--test/unit/test_datacount.py16
-rw-r--r--test/unit/test_features.py33
-rw-r--r--test/unit/utils.py16
9 files changed, 78 insertions, 25 deletions
diff --git a/src/wasm-binary.h b/src/wasm-binary.h
index 50b78fbae..1f6222cba 100644
--- a/src/wasm-binary.h
+++ b/src/wasm-binary.h
@@ -322,7 +322,8 @@ enum Section {
Start = 8,
Element = 9,
Code = 10,
- Data = 11
+ Data = 11,
+ DataCount = 12,
};
enum SegmentFlag {
@@ -891,6 +892,7 @@ public:
void writeFunctions();
void writeGlobals();
void writeExports();
+ void writeDataCount();
void writeDataSegments();
std::unordered_map<Name, Index> mappedFunctions; // name of the Function => index. first imports, then internals
@@ -1083,8 +1085,14 @@ public:
std::map<Index, Name> mappedGlobals; // index of the Global => name. first imported globals, then internal globals
Name getGlobalName(Index index);
+ void validateBinary(); // validations that cannot be performed on the Module
void processFunctions();
+
+ size_t dataCount = 0;
+ bool hasDataCount = false;
+
void readDataSegments();
+ void readDataCount();
std::map<Index, std::vector<Index>> functionTable;
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index b351a46e5..f3642203d 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -58,6 +58,7 @@ void WasmBinaryWriter::write() {
writeExports();
writeStart();
writeTableElements();
+ writeDataCount();
writeFunctions();
writeDataSegments();
if (debugInfo) writeNames();
@@ -312,6 +313,15 @@ void WasmBinaryWriter::writeExports() {
finishSection(start);
}
+void WasmBinaryWriter::writeDataCount() {
+ if (!wasm->features.hasBulkMemory() || !wasm->memory.segments.size()) {
+ return;
+ }
+ auto start = startSection(BinaryConsts::Section::DataCount);
+ o << U32LEB(wasm->memory.segments.size());
+ finishSection(start);
+}
+
void WasmBinaryWriter::writeDataSegments() {
if (wasm->memory.segments.size() == 0) return;
if (wasm->memory.segments.size() > WebLimitations::MaxDataSegments) {
@@ -657,6 +667,7 @@ void WasmBinaryBuilder::read() {
break;
}
case BinaryConsts::Section::Data: readDataSegments(); break;
+ case BinaryConsts::Section::DataCount: readDataCount(); break;
case BinaryConsts::Section::Table: readFunctionTableDeclaration(); break;
default: {
readUserSection(payloadLen);
@@ -673,6 +684,7 @@ void WasmBinaryBuilder::read() {
}
}
+ validateBinary();
processFunctions();
}
@@ -1457,6 +1469,12 @@ Name WasmBinaryBuilder::getGlobalName(Index index) {
return mappedGlobals[index];
}
+void WasmBinaryBuilder::validateBinary() {
+ if (hasDataCount && wasm.memory.segments.size() != dataCount) {
+ throwError("Number of segments does not agree with DataCount section");
+ }
+}
+
void WasmBinaryBuilder::processFunctions() {
for (auto* func : functions) {
wasm.addFunction(func);
@@ -1504,6 +1522,12 @@ void WasmBinaryBuilder::processFunctions() {
wasm.updateMaps();
}
+void WasmBinaryBuilder::readDataCount() {
+ if (debug) std::cerr << "== readDataCount" << std::endl;
+ hasDataCount = true;
+ dataCount = getU32LEB();
+}
+
void WasmBinaryBuilder::readDataSegments() {
if (debug) std::cerr << "== readDataSegments" << std::endl;
auto num = getU32LEB();
diff --git a/test/debugInfo.fromasm.clamp.map b/test/debugInfo.fromasm.clamp.map
index e49a7309c..e922a9c4b 100644
--- a/test/debugInfo.fromasm.clamp.map
+++ b/test/debugInfo.fromasm.clamp.map
@@ -1 +1 @@
-{"version":3,"sources":["tests/hello_world.c","tests/other_file.cpp","return.cpp","even-opted.cpp","fib.c","/tmp/emscripten_test_binaryen2_28hnAe/src.c","(unknown)"],"names":[],"mappings":"qIC8ylTA,QC7vlTA,OAkDA,UCjGA,AADA,EADA,+BCEA,cAKA,QAJA,OADA,0BAKA,sECsi1DA,KCrvyDA"} \ No newline at end of file
+{"version":3,"sources":["tests/hello_world.c","tests/other_file.cpp","return.cpp","even-opted.cpp","fib.c","/tmp/emscripten_test_binaryen2_28hnAe/src.c","(unknown)"],"names":[],"mappings":"wIC8ylTA,QC7vlTA,OAkDA,UCjGA,AADA,EADA,+BCEA,cAKA,QAJA,OADA,0BAKA,sECsi1DA,KCrvyDA"} \ No newline at end of file
diff --git a/test/debugInfo.fromasm.map b/test/debugInfo.fromasm.map
index e49a7309c..e922a9c4b 100644
--- a/test/debugInfo.fromasm.map
+++ b/test/debugInfo.fromasm.map
@@ -1 +1 @@
-{"version":3,"sources":["tests/hello_world.c","tests/other_file.cpp","return.cpp","even-opted.cpp","fib.c","/tmp/emscripten_test_binaryen2_28hnAe/src.c","(unknown)"],"names":[],"mappings":"qIC8ylTA,QC7vlTA,OAkDA,UCjGA,AADA,EADA,+BCEA,cAKA,QAJA,OADA,0BAKA,sECsi1DA,KCrvyDA"} \ No newline at end of file
+{"version":3,"sources":["tests/hello_world.c","tests/other_file.cpp","return.cpp","even-opted.cpp","fib.c","/tmp/emscripten_test_binaryen2_28hnAe/src.c","(unknown)"],"names":[],"mappings":"wIC8ylTA,QC7vlTA,OAkDA,UCjGA,AADA,EADA,+BCEA,cAKA,QAJA,OADA,0BAKA,sECsi1DA,KCrvyDA"} \ No newline at end of file
diff --git a/test/unit/input/bulkmem_bad_datacount.wasm b/test/unit/input/bulkmem_bad_datacount.wasm
new file mode 100755
index 000000000..e7b6e4bb7
--- /dev/null
+++ b/test/unit/input/bulkmem_bad_datacount.wasm
Binary files differ
diff --git a/test/unit/input/bulkmem_data.wasm b/test/unit/input/bulkmem_data.wasm
new file mode 100755
index 000000000..aa9e535b5
--- /dev/null
+++ b/test/unit/input/bulkmem_data.wasm
Binary files differ
diff --git a/test/unit/test_datacount.py b/test/unit/test_datacount.py
new file mode 100644
index 000000000..87ddbd58d
--- /dev/null
+++ b/test/unit/test_datacount.py
@@ -0,0 +1,16 @@
+import unittest
+from scripts.test.shared import WASM_OPT, run_process
+from utils import roundtrip, input_path
+
+
+class DataCountTest(unittest.TestCase):
+ def test_datacount(self):
+ roundtrip(self, 'bulkmem_data.wasm')
+
+ def test_bad_datacount(self):
+ path = input_path('bulkmem_bad_datacount.wasm')
+ p = run_process(WASM_OPT + ['-g', '-o', '-', path], check=False,
+ capture_output=True)
+ self.assertNotEqual(p.returncode, 0)
+ self.assertIn('Number of segments does not agree with DataCount section',
+ p.stderr)
diff --git a/test/unit/test_features.py b/test/unit/test_features.py
index f130e1408..1672b957a 100644
--- a/test/unit/test_features.py
+++ b/test/unit/test_features.py
@@ -1,6 +1,7 @@
import os
import unittest
-from scripts.test.shared import WASM_OPT, run_process, options
+from scripts.test.shared import WASM_OPT, run_process
+from utils import input_path, roundtrip
class FeatureValidationTest(unittest.TestCase):
@@ -117,50 +118,40 @@ class FeatureValidationTest(unittest.TestCase):
class TargetFeaturesSectionTest(unittest.TestCase):
def disassemble(self, filename):
- path = os.path.join(options.binaryen_test, 'unit', 'input', filename)
+ path = input_path(filename)
p = run_process(WASM_OPT + ['--print', '-o', os.devnull, path], check=False,
capture_output=True)
self.assertEqual(p.returncode, 0)
self.assertEqual(p.stderr, '')
return p.stdout
- def roundtrip(self, filename):
- path = os.path.join(options.binaryen_test, 'unit', 'input', filename)
- p = run_process(WASM_OPT + ['-g', '-o', '-', path], check=False,
- capture_output=True)
- self.assertEqual(p.returncode, 0)
- self.assertEqual(p.stderr, '')
- with open(path, 'rb') as f:
- self.assertEqual(str(p.stdout), str(f.read()))
-
def test_atomics(self):
- self.roundtrip('atomics_target_feature.wasm')
+ roundtrip(self, 'atomics_target_feature.wasm')
module = self.disassemble('atomics_target_feature.wasm')
self.assertIn('i32.atomic.rmw.add', module)
def test_bulk_memory(self):
- self.roundtrip('bulkmem_target_feature.wasm')
+ roundtrip(self, 'bulkmem_target_feature.wasm')
module = self.disassemble('bulkmem_target_feature.wasm')
self.assertIn('memory.copy', module)
def test_nontrapping_fptoint(self):
- self.roundtrip('truncsat_target_feature.wasm')
+ roundtrip(self, 'truncsat_target_feature.wasm')
module = self.disassemble('truncsat_target_feature.wasm')
self.assertIn('i32.trunc_sat_f32_u', module)
def test_sign_ext(self):
- self.roundtrip('signext_target_feature.wasm')
+ roundtrip(self, 'signext_target_feature.wasm')
module = self.disassemble('signext_target_feature.wasm')
self.assertIn('i32.extend8_s', module)
def test_simd(self):
- self.roundtrip('simd_target_feature.wasm')
+ roundtrip(self, 'simd_target_feature.wasm')
module = self.disassemble('simd_target_feature.wasm')
self.assertIn('i32x4.splat', module)
def test_incompatible_features(self):
- path = os.path.join(options.binaryen_test, 'unit', 'input',
- 'signext_target_feature.wasm')
+ path = input_path('signext_target_feature.wasm')
p = run_process(
WASM_OPT + ['--print', '-mvp', '--enable-simd', '-o', os.devnull, path],
check=False, capture_output=True
@@ -171,8 +162,7 @@ class TargetFeaturesSectionTest(unittest.TestCase):
p.stderr)
def test_incompatible_features_forced(self):
- path = os.path.join(options.binaryen_test, 'unit', 'input',
- 'signext_target_feature.wasm')
+ path = input_path('signext_target_feature.wasm')
p = run_process(
WASM_OPT + ['--print', '--detect-features', '-mvp', '--enable-simd',
'-o', os.devnull, path],
@@ -182,8 +172,7 @@ class TargetFeaturesSectionTest(unittest.TestCase):
self.assertIn('all used features should be allowed', p.stderr)
def test_explicit_detect_features(self):
- path = os.path.join(options.binaryen_test, 'unit', 'input',
- 'signext_target_feature.wasm')
+ path = input_path('signext_target_feature.wasm')
p = run_process(
WASM_OPT + ['--print', '-mvp', '--detect-features',
'-o', os.devnull, path],
diff --git a/test/unit/utils.py b/test/unit/utils.py
new file mode 100644
index 000000000..eaeb29d42
--- /dev/null
+++ b/test/unit/utils.py
@@ -0,0 +1,16 @@
+import os
+from scripts.test.shared import WASM_OPT, run_process, options
+
+
+def input_path(filename):
+ return os.path.join(options.binaryen_test, 'unit', 'input', filename)
+
+
+def roundtrip(testcase, filename, opts=[]):
+ path = input_path(filename)
+ p = run_process(WASM_OPT + ['-g', '-o', '-', path] + opts, check=False,
+ capture_output=True)
+ testcase.assertEqual(p.returncode, 0)
+ testcase.assertEqual(p.stderr, '')
+ with open(path, 'rb') as f:
+ testcase.assertEqual(str(p.stdout), str(f.read()))