diff options
-rwxr-xr-x | scripts/test/lld.py | 14 | ||||
-rw-r--r-- | src/wasm/wasm-emscripten.cpp | 38 | ||||
-rw-r--r-- | test/lld/hello_world.passive.wast | 40 | ||||
-rw-r--r-- | test/lld/hello_world.passive.wast.out | 111 |
4 files changed, 198 insertions, 5 deletions
diff --git a/scripts/test/lld.py b/scripts/test/lld.py index 66c4ebb47..c573f6480 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): @@ -63,11 +67,15 @@ def update_lld_tests(): 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 65f877d92..df5da949e 100644 --- a/src/wasm/wasm-emscripten.cpp +++ b/src/wasm/wasm-emscripten.cpp @@ -444,10 +444,43 @@ void EmscriptenGlueGenerator::replaceStackPointerGlobal() { wasm.removeGlobal(stackPointer->name); } +const Address UNKNOWN_OFFSET(uint32_t(-1)); + std::vector<Address> getSegmentOffsets(Module& wasm) { + std::unordered_map<Index, Address> passiveOffsets; + if (wasm.features.hasBulkMemory()) { + // Fetch passive segment offsets out of memory.init instructions + struct OffsetSearcher : PostWalker<OffsetSearcher> { + std::unordered_map<Index, Address>& offsets; + OffsetSearcher(std::unordered_map<unsigned, Address>& offsets) + : offsets(offsets) {} + void visitMemoryInit(MemoryInit* curr) { + auto* dest = curr->dest->dynCast<Const>(); + 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<Address> segmentOffsets; for (unsigned i = 0; i < wasm.memory.segments.size(); ++i) { - if (auto* addrConst = wasm.memory.segments[i].offset->dynCast<Const>()) { + 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(UNKNOWN_OFFSET); + } + } else if (auto* addrConst = segment.offset->dynCast<Const>()) { auto address = addrConst->value.geti32(); segmentOffsets.push_back(address); } else { @@ -494,7 +527,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 != UNKNOWN_OFFSET && address >= offset && + address < offset + segment.data.size()) { return &segment.data[address - offset]; } } diff --git a/test/lld/hello_world.passive.wast b/test/lld/hello_world.passive.wast new file mode 100644 index 000000000..27ccb8f90 --- /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 000000000..88a06c1f3 --- /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 -- +;) |