summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xscripts/test/lld.py14
-rw-r--r--src/wasm/wasm-emscripten.cpp38
-rw-r--r--test/lld/hello_world.passive.wast40
-rw-r--r--test/lld/hello_world.passive.wast.out111
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 --
+;)