From 094909bd4f9a07ee8a2e331b8cd03e7f9f7fc745 Mon Sep 17 00:00:00 2001 From: Thomas Lively Date: Wed, 10 Jul 2019 17:27:31 -0700 Subject: [PATCH 1/6] Handle passive segments in wasm-emscripten-finalize --- scripts/test/lld.py | 15 +++- src/wasm/wasm-emscripten.cpp | 33 +++++++- test/lld/hello_world.passive.wast | 40 ++++++++++ test/lld/hello_world.passive.wast.out | 111 ++++++++++++++++++++++++++ 4 files changed, 195 insertions(+), 4 deletions(-) create mode 100644 test/lld/hello_world.passive.wast create mode 100644 test/lld/hello_world.passive.wast.out diff --git a/scripts/test/lld.py b/scripts/test/lld.py index 66c4ebb473c..dc00e2e03a1 100755 --- a/scripts/test/lld.py +++ b/scripts/test/lld.py @@ -33,11 +33,15 @@ def test_wasm_emscripten_finalize(): for wast_path in files_with_pattern(options.binaryen_test, 'lld', '*.wast'): print '..', wast_path + is_passive = '.passive.' in wast_path mem_file = wast_path + '.mem' extension_arg_map = { - '.out': [], - '.mem.out': ['--separate-data-segments', mem_file], + '.out': [] , } + if not is_passive: + extension_arg_map.update({ + '.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): @@ -58,16 +62,21 @@ def test_wasm_emscripten_finalize(): os.remove(mem_file) + def update_lld_tests(): print '\n[ updatring wasm-emscripten-finalize testcases... ]\n' for wast_path in files_with_pattern(options.binaryen_test, 'lld', '*.wast'): print '..', wast_path + is_passive = '.passive.' in wast_path mem_file = wast_path + '.mem' extension_arg_map = { '.out': [], - '.mem.out': ['--separate-data-segments', mem_file + '.mem'], } + if not is_passive: + extension_arg_map.update({ + '.mem.out': ['--separate-data-segments', mem_file + '.mem'], + }) for ext, ext_args in extension_arg_map.items(): out_path = wast_path + ext if ext != '.out' and not os.path.exists(out_path): diff --git a/src/wasm/wasm-emscripten.cpp b/src/wasm/wasm-emscripten.cpp index 8463354e89c..a00b9c91e12 100644 --- a/src/wasm/wasm-emscripten.cpp +++ b/src/wasm/wasm-emscripten.cpp @@ -445,9 +445,40 @@ void EmscriptenGlueGenerator::replaceStackPointerGlobal() { } std::vector
getSegmentOffsets(Module& wasm) { + std::unordered_map passiveOffsets; + if (wasm.features.hasBulkMemory()) { + // Fetch passive segment offsets out of memory.init instructions + struct OffsetSearcher : PostWalker { + std::unordered_map& offsets; + OffsetSearcher(std::unordered_map& offsets) + : offsets(offsets) {} + void visitMemoryInit(MemoryInit* curr) { + auto* dest = curr->dest->dynCast(); + if (!dest) { + return; + } + auto it = offsets.find(curr->segment); + if (it != offsets.end()) { + Fatal() << "Cannot get offset of passive segment initialized " + "multiple times"; + } + offsets[curr->segment] = dest->value.geti32(); + } + } searcher(passiveOffsets); + searcher.walkModule(&wasm); + } std::vector
segmentOffsets; for (unsigned i = 0; i < wasm.memory.segments.size(); ++i) { - if (auto* addrConst = wasm.memory.segments[i].offset->dynCast()) { + auto& segment = wasm.memory.segments[i]; + if (segment.isPassive) { + auto it = passiveOffsets.find(i); + if (it != passiveOffsets.end()) { + segmentOffsets.push_back(it->second); + } else { + // This was a non-constant offset (perhaps TLS) + segmentOffsets.push_back(0); + } + } else if (auto* addrConst = segment.offset->dynCast()) { auto address = addrConst->value.geti32(); segmentOffsets.push_back(address); } else { diff --git a/test/lld/hello_world.passive.wast b/test/lld/hello_world.passive.wast new file mode 100644 index 00000000000..27ccb8f90fb --- /dev/null +++ b/test/lld/hello_world.passive.wast @@ -0,0 +1,40 @@ +(module + (type $0 (func (param i32) (result i32))) + (type $1 (func)) + (type $2 (func (result i32))) + (type $3 (func (param i32 i32) (result i32))) + (import "env" "puts" (func $puts (param i32) (result i32))) + (memory $0 2) + (data passive "Hello, world\00") + (table $0 1 1 funcref) + (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 "__heap_base" (global $global$1)) + (export "__data_end" (global $global$2)) + (export "main" (func $main)) + (func $__wasm_call_ctors (; 1 ;) (type $1) + (call $__wasm_init_memory) + ) + (func $__wasm_init_memory (; 2 ;) (type $1) + (memory.init 0 + (i32.const 568) + (i32.const 0) + (i32.const 14) + ) + ) + (func $__original_main (; 3 ;) (type $2) (result i32) + (drop + (call $puts + (i32.const 568) + ) + ) + (i32.const 0) + ) + (func $main (; 3 ;) (type $3) (param $0 i32) (param $1 i32) (result i32) + (call $__original_main) + ) + ;; custom section "producers", size 111 +) diff --git a/test/lld/hello_world.passive.wast.out b/test/lld/hello_world.passive.wast.out new file mode 100644 index 00000000000..88a06c1f3bd --- /dev/null +++ b/test/lld/hello_world.passive.wast.out @@ -0,0 +1,111 @@ +(module + (type $0 (func (param i32) (result i32))) + (type $1 (func)) + (type $2 (func (result i32))) + (type $3 (func (param i32 i32) (result i32))) + (import "env" "puts" (func $puts (param i32) (result i32))) + (memory $0 2) + (data passive "Hello, world\00") + (table $0 1 1 funcref) + (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 "__heap_base" (global $global$1)) + (export "__data_end" (global $global$2)) + (export "main" (func $main)) + (export "stackSave" (func $stackSave)) + (export "stackAlloc" (func $stackAlloc)) + (export "stackRestore" (func $stackRestore)) + (export "__growWasmMemory" (func $__growWasmMemory)) + (func $__wasm_call_ctors (; 1 ;) (type $1) + (call $__wasm_init_memory) + ) + (func $__wasm_init_memory (; 2 ;) (type $1) + (memory.init 0 + (i32.const 568) + (i32.const 0) + (i32.const 14) + ) + ) + (func $__original_main (; 3 ;) (type $2) (result i32) + (drop + (call $puts + (i32.const 568) + ) + ) + (i32.const 0) + ) + (func $main (; 4 ;) (type $3) (param $0 i32) (param $1 i32) (result i32) + (call $__original_main) + ) + (func $stackSave (; 5 ;) (result i32) + (global.get $global$0) + ) + (func $stackAlloc (; 6 ;) (param $0 i32) (result i32) + (local $1 i32) + (global.set $global$0 + (local.tee $1 + (i32.and + (i32.sub + (global.get $global$0) + (local.get $0) + ) + (i32.const -16) + ) + ) + ) + (local.get $1) + ) + (func $stackRestore (; 7 ;) (param $0 i32) + (global.set $global$0 + (local.get $0) + ) + ) + (func $__growWasmMemory (; 8 ;) (param $newSize i32) (result i32) + (memory.grow + (local.get $newSize) + ) + ) +) +(; +--BEGIN METADATA -- +{ + "staticBump": 13, + "tableSize": 1, + "initializers": [ + "__wasm_call_ctors" + ], + "declares": [ + "puts" + ], + "externs": [ + ], + "implementedFunctions": [ + "___wasm_call_ctors", + "_main", + "_stackSave", + "_stackAlloc", + "_stackRestore", + "___growWasmMemory" + ], + "exports": [ + "__wasm_call_ctors", + "main", + "stackSave", + "stackAlloc", + "stackRestore", + "__growWasmMemory" + ], + "namedGlobals": { + "__heap_base" : "66128", + "__data_end" : "581" + }, + "invokeFuncs": [ + ], + "features": [ + ] +} +-- END METADATA -- +;) From d6065774711ec6882d5d5e38f81464e3d91295dd Mon Sep 17 00:00:00 2001 From: Thomas Lively Date: Wed, 10 Jul 2019 17:29:47 -0700 Subject: [PATCH 2/6] Fix flake8 --- scripts/test/lld.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/test/lld.py b/scripts/test/lld.py index dc00e2e03a1..c573f648080 100755 --- a/scripts/test/lld.py +++ b/scripts/test/lld.py @@ -36,7 +36,7 @@ def test_wasm_emscripten_finalize(): is_passive = '.passive.' in wast_path mem_file = wast_path + '.mem' extension_arg_map = { - '.out': [] , + '.out': [], } if not is_passive: extension_arg_map.update({ @@ -62,7 +62,6 @@ def test_wasm_emscripten_finalize(): os.remove(mem_file) - def update_lld_tests(): print '\n[ updatring wasm-emscripten-finalize testcases... ]\n' From 995115d776362456d5cbe6b8efffee7f9d2f7dc3 Mon Sep 17 00:00:00 2001 From: Thomas Lively Date: Thu, 11 Jul 2019 13:23:03 -0700 Subject: [PATCH 3/6] unsigned -> Index --- src/wasm/wasm-emscripten.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wasm/wasm-emscripten.cpp b/src/wasm/wasm-emscripten.cpp index a00b9c91e12..be87c16f95f 100644 --- a/src/wasm/wasm-emscripten.cpp +++ b/src/wasm/wasm-emscripten.cpp @@ -445,11 +445,11 @@ void EmscriptenGlueGenerator::replaceStackPointerGlobal() { } std::vector
getSegmentOffsets(Module& wasm) { - std::unordered_map passiveOffsets; + std::unordered_map passiveOffsets; if (wasm.features.hasBulkMemory()) { // Fetch passive segment offsets out of memory.init instructions struct OffsetSearcher : PostWalker { - std::unordered_map& offsets; + std::unordered_map& offsets; OffsetSearcher(std::unordered_map& offsets) : offsets(offsets) {} void visitMemoryInit(MemoryInit* curr) { From 3578a644deafac3f22bef2821b4c4c7377a5ec29 Mon Sep 17 00:00:00 2001 From: Thomas Lively Date: Thu, 11 Jul 2019 13:30:55 -0700 Subject: [PATCH 4/6] Prevent use of bogus addresses --- src/wasm/wasm-emscripten.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/wasm/wasm-emscripten.cpp b/src/wasm/wasm-emscripten.cpp index be87c16f95f..4d888667632 100644 --- a/src/wasm/wasm-emscripten.cpp +++ b/src/wasm/wasm-emscripten.cpp @@ -525,7 +525,8 @@ const char* stringAtAddr(Module& wasm, for (unsigned i = 0; i < wasm.memory.segments.size(); ++i) { Memory::Segment& segment = wasm.memory.segments[i]; Address offset = segmentOffsets[i]; - if (address >= offset && address < offset + segment.data.size()) { + if (offset != 0 && address >= offset && + address < offset + segment.data.size()) { return &segment.data[address - offset]; } } From 18e35d5f032cbb6d510a27d7a4bb80f89d1a1f71 Mon Sep 17 00:00:00 2001 From: Thomas Lively Date: Thu, 11 Jul 2019 14:36:42 -0700 Subject: [PATCH 5/6] Use -1 as invalid offset --- src/wasm/wasm-emscripten.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/wasm/wasm-emscripten.cpp b/src/wasm/wasm-emscripten.cpp index 4d888667632..b04ae70a7f4 100644 --- a/src/wasm/wasm-emscripten.cpp +++ b/src/wasm/wasm-emscripten.cpp @@ -444,6 +444,8 @@ void EmscriptenGlueGenerator::replaceStackPointerGlobal() { wasm.removeGlobal(stackPointer->name); } +const Address UNKNOWN_OFFSET(uint32_t(-1)); + std::vector
getSegmentOffsets(Module& wasm) { std::unordered_map passiveOffsets; if (wasm.features.hasBulkMemory()) { @@ -476,7 +478,7 @@ std::vector
getSegmentOffsets(Module& wasm) { segmentOffsets.push_back(it->second); } else { // This was a non-constant offset (perhaps TLS) - segmentOffsets.push_back(0); + segmentOffsets.push_back(UNKNOWN_OFFSET); } } else if (auto* addrConst = segment.offset->dynCast()) { auto address = addrConst->value.geti32(); @@ -484,7 +486,7 @@ std::vector
getSegmentOffsets(Module& wasm) { } else { // TODO(sbc): Wasm shared libraries have data segments with non-const // offset. - segmentOffsets.push_back(0); + segmentOffsets.push_back(UNKNOWN_OFFSET); } } return segmentOffsets; @@ -525,7 +527,7 @@ const char* stringAtAddr(Module& wasm, for (unsigned i = 0; i < wasm.memory.segments.size(); ++i) { Memory::Segment& segment = wasm.memory.segments[i]; Address offset = segmentOffsets[i]; - if (offset != 0 && address >= offset && + if (offset != UNKNOWN_OFFSET && address >= offset && address < offset + segment.data.size()) { return &segment.data[address - offset]; } From db00af813a5727834bf4837b2eb125f9891826fa Mon Sep 17 00:00:00 2001 From: Thomas Lively Date: Thu, 11 Jul 2019 15:45:46 -0700 Subject: [PATCH 6/6] Fix shared library test failure --- src/wasm/wasm-emscripten.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wasm/wasm-emscripten.cpp b/src/wasm/wasm-emscripten.cpp index b04ae70a7f4..93706b3a1cc 100644 --- a/src/wasm/wasm-emscripten.cpp +++ b/src/wasm/wasm-emscripten.cpp @@ -486,7 +486,7 @@ std::vector
getSegmentOffsets(Module& wasm) { } else { // TODO(sbc): Wasm shared libraries have data segments with non-const // offset. - segmentOffsets.push_back(UNKNOWN_OFFSET); + segmentOffsets.push_back(0); } } return segmentOffsets;