summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDerek Schuff <dschuff@chromium.org>2018-11-14 13:03:30 -0800
committerGitHub <noreply@github.com>2018-11-14 13:03:30 -0800
commit7e9f7f62d230f7ed083c0c2d425ae47dac4f513f (patch)
tree0c9967b8d9708160b5fef2eef6be8ab4046a22dd
parent37d82ba9574d440a89b1d7f91af89cd30b35b158 (diff)
downloadbinaryen-7e9f7f62d230f7ed083c0c2d425ae47dac4f513f.tar.gz
binaryen-7e9f7f62d230f7ed083c0c2d425ae47dac4f513f.tar.bz2
binaryen-7e9f7f62d230f7ed083c0c2d425ae47dac4f513f.zip
Add wasm-emscripten-finalize flag to separate data segments into a file (#1741)
This writes the data section into a file suitable for use with emscripten's --memory-init-file flag
-rwxr-xr-xscripts/test/lld.py16
-rw-r--r--src/support/file.h4
-rw-r--r--src/tools/wasm-emscripten-finalize.cpp8
-rw-r--r--src/wasm-emscripten.h4
-rw-r--r--src/wasm/wasm-emscripten.cpp15
-rw-r--r--test/lld/hello_world.wast.mem.membin0 -> 581 bytes
-rw-r--r--test/lld/hello_world.wast.mem.out61
7 files changed, 103 insertions, 5 deletions
diff --git a/scripts/test/lld.py b/scripts/test/lld.py
index 4f976ae30..03a0733e6 100755
--- a/scripts/test/lld.py
+++ b/scripts/test/lld.py
@@ -24,13 +24,14 @@ from shared import (
def test_wasm_emscripten_finalize():
print '\n[ checking wasm-emscripten-finalize testcases... ]\n'
- extension_arg_map = {
- '.out': [],
- '.jscall.out': ['--emscripten-reserved-function-pointers=3'],
- }
-
for wast_path in files_with_pattern(options.binaryen_test, 'lld', '*.wast'):
print '..', wast_path
+ mem_file = wast_path + '.mem'
+ extension_arg_map = {
+ '.out': [],
+ '.jscall.out': ['--emscripten-reserved-function-pointers=3'],
+ '.mem.out': ['--separate-data-segments', mem_file],
+ }
for ext, ext_args in extension_arg_map.items():
expected_file = wast_path + ext
if ext != '.out' and not os.path.exists(expected_file):
@@ -44,6 +45,11 @@ def test_wasm_emscripten_finalize():
print actual
fail_with_error('output ' + expected_file + ' does not exist')
fail_if_not_identical_to_file(actual, expected_file)
+ if ext == '.mem.out':
+ with open(mem_file) as mf:
+ mem = mf.read()
+ fail_if_not_identical_to_file(mem, wast_path + '.mem.mem')
+ os.remove(mem_file)
if __name__ == '__main__':
diff --git a/src/support/file.h b/src/support/file.h
index c15e3f6ce..8355767ee 100644
--- a/src/support/file.h
+++ b/src/support/file.h
@@ -59,6 +59,10 @@ class Output {
return out;
}
+ std::ostream& write(const char* s, std::streamsize c) {
+ return out.write(s, c);
+ }
+
private:
Output() = delete;
Output(const Output &) = delete;
diff --git a/src/tools/wasm-emscripten-finalize.cpp b/src/tools/wasm-emscripten-finalize.cpp
index 4c9f8df36..495ed5df9 100644
--- a/src/tools/wasm-emscripten-finalize.cpp
+++ b/src/tools/wasm-emscripten-finalize.cpp
@@ -40,6 +40,7 @@ int main(int argc, const char *argv[]) {
std::string inputSourceMapFilename;
std::string outputSourceMapFilename;
std::string outputSourceMapUrl;
+ std::string dataSegmentFile;
bool emitBinary = true;
bool debugInfo = false;
bool legalizeJavaScriptFFI = true;
@@ -94,6 +95,9 @@ int main(int argc, const char *argv[]) {
.add("--output-source-map-url", "-osu", "Emit specified string as source map URL",
Options::Arguments::One,
[&outputSourceMapUrl](Options *o, const std::string& argument) { outputSourceMapUrl = argument; })
+ .add("--separate-data-segments", "", "Separate data segments to a file",
+ Options::Arguments::One,
+ [&dataSegmentFile](Options *o, const std::string& argument) { dataSegmentFile = argument;})
.add_positional("INFILE", Options::Arguments::One,
[&infile](Options *o, const std::string& argument) {
infile = argument;
@@ -161,6 +165,10 @@ int main(int argc, const char *argv[]) {
generator.generateDynCallThunks();
generator.generateJSCallThunks(numReservedFunctionPointers);
std::string metadata = generator.generateEmscriptenMetadata(dataSize, initializerFunctions, numReservedFunctionPointers);
+ if (!dataSegmentFile.empty()) {
+ Output memInitFile(dataSegmentFile, Flags::Binary, Flags::Release);
+ generator.separateDataSegments(&memInitFile);
+ }
if (options.debug) {
std::cerr << "Module after:\n";
diff --git a/src/wasm-emscripten.h b/src/wasm-emscripten.h
index 21bd21bea..78d24b13f 100644
--- a/src/wasm-emscripten.h
+++ b/src/wasm-emscripten.h
@@ -19,6 +19,8 @@
#include "wasm.h"
#include "wasm-builder.h"
+#include "support/file.h"
+
namespace wasm {
@@ -53,6 +55,8 @@ public:
void fixInvokeFunctionNames();
+ void separateDataSegments(Output* outfile);
+
private:
Module& wasm;
Builder builder;
diff --git a/src/wasm/wasm-emscripten.cpp b/src/wasm/wasm-emscripten.cpp
index d7c323da9..a99482d39 100644
--- a/src/wasm/wasm-emscripten.cpp
+++ b/src/wasm/wasm-emscripten.cpp
@@ -810,4 +810,19 @@ std::string EmscriptenGlueGenerator::generateEmscriptenMetadata(
return meta.str();
}
+void EmscriptenGlueGenerator::separateDataSegments(Output* outfile) {
+ size_t lastEnd = 0;
+ for (Memory::Segment& seg : wasm.memory.segments) {
+ size_t offset = seg.offset->cast<Const>()->value.geti32();
+ size_t fill = offset - lastEnd;
+ if (fill > 0) {
+ std::vector<char> buf(fill);
+ outfile->write(buf.data(), fill);
+ }
+ outfile->write(seg.data.data(), seg.data.size());
+ lastEnd = offset + seg.data.size();
+ }
+ wasm.memory.segments.clear();
+}
+
} // namespace wasm
diff --git a/test/lld/hello_world.wast.mem.mem b/test/lld/hello_world.wast.mem.mem
new file mode 100644
index 000000000..674c410a9
--- /dev/null
+++ b/test/lld/hello_world.wast.mem.mem
Binary files differ
diff --git a/test/lld/hello_world.wast.mem.out b/test/lld/hello_world.wast.mem.out
new file mode 100644
index 000000000..f54d9cbbd
--- /dev/null
+++ b/test/lld/hello_world.wast.mem.out
@@ -0,0 +1,61 @@
+(module
+ (type $0 (func (param i32) (result i32)))
+ (type $1 (func (result i32)))
+ (type $2 (func))
+ (type $FUNCSIG$ii (func (param i32) (result i32)))
+ (import "env" "puts" (func $puts (param i32) (result i32)))
+ (memory $0 2)
+ (table $0 1 1 anyfunc)
+ (global $global$0 (mut i32) (i32.const 66128))
+ (global $global$1 i32 (i32.const 66128))
+ (global $global$2 i32 (i32.const 581))
+ (export "memory" (memory $0))
+ (export "__wasm_call_ctors" (func $__wasm_call_ctors))
+ (export "main" (func $main))
+ (export "__heap_base" (global $global$1))
+ (export "__data_end" (global $global$2))
+ (export "stackSave" (func $stackSave))
+ (export "stackAlloc" (func $stackAlloc))
+ (export "stackRestore" (func $stackRestore))
+ (export "__growWasmMemory" (func $__growWasmMemory))
+ (func $main (; 1 ;) (type $1) (result i32)
+ (drop
+ (call $puts
+ (i32.const 568)
+ )
+ )
+ (i32.const 0)
+ )
+ (func $__wasm_call_ctors (; 2 ;) (type $2)
+ (nop)
+ )
+ (func $stackSave (; 3 ;) (result i32)
+ (get_global $global$0)
+ )
+ (func $stackAlloc (; 4 ;) (param $0 i32) (result i32)
+ (local $1 i32)
+ (set_global $global$0
+ (tee_local $1
+ (i32.and
+ (i32.sub
+ (get_global $global$0)
+ (get_local $0)
+ )
+ (i32.const -16)
+ )
+ )
+ )
+ (get_local $1)
+ )
+ (func $stackRestore (; 5 ;) (param $0 i32)
+ (set_global $global$0
+ (get_local $0)
+ )
+ )
+ (func $__growWasmMemory (; 6 ;) (param $newSize i32) (result i32)
+ (grow_memory
+ (get_local $newSize)
+ )
+ )
+)
+;; METADATA: { "asmConsts": {},"staticBump": 13, "initializers": ["__wasm_call_ctors"], "declares": ["puts"], "externs": [], "implementedFunctions": ["___wasm_call_ctors","_main","_stackSave","_stackAlloc","_stackRestore","___growWasmMemory"], "exports": ["memory","__wasm_call_ctors","main","__heap_base","__data_end","stackSave","stackAlloc","stackRestore","__growWasmMemory"], "invokeFuncs": [] }