Skip to content

Commit 29b6458

Browse files
authored
Handle passive segments in wasm-emscripten-finalize (#2217)
1 parent 39b9e38 commit 29b6458

File tree

4 files changed

+198
-5
lines changed

4 files changed

+198
-5
lines changed

scripts/test/lld.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,15 @@ def test_wasm_emscripten_finalize():
3333

3434
for wast_path in files_with_pattern(options.binaryen_test, 'lld', '*.wast'):
3535
print '..', wast_path
36+
is_passive = '.passive.' in wast_path
3637
mem_file = wast_path + '.mem'
3738
extension_arg_map = {
38-
'.out': [],
39-
'.mem.out': ['--separate-data-segments', mem_file],
39+
'.out': [],
4040
}
41+
if not is_passive:
42+
extension_arg_map.update({
43+
'.mem.out': ['--separate-data-segments', mem_file],
44+
})
4145
for ext, ext_args in extension_arg_map.items():
4246
expected_file = wast_path + ext
4347
if ext != '.out' and not os.path.exists(expected_file):
@@ -63,11 +67,15 @@ def update_lld_tests():
6367

6468
for wast_path in files_with_pattern(options.binaryen_test, 'lld', '*.wast'):
6569
print '..', wast_path
70+
is_passive = '.passive.' in wast_path
6671
mem_file = wast_path + '.mem'
6772
extension_arg_map = {
6873
'.out': [],
69-
'.mem.out': ['--separate-data-segments', mem_file + '.mem'],
7074
}
75+
if not is_passive:
76+
extension_arg_map.update({
77+
'.mem.out': ['--separate-data-segments', mem_file + '.mem'],
78+
})
7179
for ext, ext_args in extension_arg_map.items():
7280
out_path = wast_path + ext
7381
if ext != '.out' and not os.path.exists(out_path):

src/wasm/wasm-emscripten.cpp

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -444,10 +444,43 @@ void EmscriptenGlueGenerator::replaceStackPointerGlobal() {
444444
wasm.removeGlobal(stackPointer->name);
445445
}
446446

447+
const Address UNKNOWN_OFFSET(uint32_t(-1));
448+
447449
std::vector<Address> getSegmentOffsets(Module& wasm) {
450+
std::unordered_map<Index, Address> passiveOffsets;
451+
if (wasm.features.hasBulkMemory()) {
452+
// Fetch passive segment offsets out of memory.init instructions
453+
struct OffsetSearcher : PostWalker<OffsetSearcher> {
454+
std::unordered_map<Index, Address>& offsets;
455+
OffsetSearcher(std::unordered_map<unsigned, Address>& offsets)
456+
: offsets(offsets) {}
457+
void visitMemoryInit(MemoryInit* curr) {
458+
auto* dest = curr->dest->dynCast<Const>();
459+
if (!dest) {
460+
return;
461+
}
462+
auto it = offsets.find(curr->segment);
463+
if (it != offsets.end()) {
464+
Fatal() << "Cannot get offset of passive segment initialized "
465+
"multiple times";
466+
}
467+
offsets[curr->segment] = dest->value.geti32();
468+
}
469+
} searcher(passiveOffsets);
470+
searcher.walkModule(&wasm);
471+
}
448472
std::vector<Address> segmentOffsets;
449473
for (unsigned i = 0; i < wasm.memory.segments.size(); ++i) {
450-
if (auto* addrConst = wasm.memory.segments[i].offset->dynCast<Const>()) {
474+
auto& segment = wasm.memory.segments[i];
475+
if (segment.isPassive) {
476+
auto it = passiveOffsets.find(i);
477+
if (it != passiveOffsets.end()) {
478+
segmentOffsets.push_back(it->second);
479+
} else {
480+
// This was a non-constant offset (perhaps TLS)
481+
segmentOffsets.push_back(UNKNOWN_OFFSET);
482+
}
483+
} else if (auto* addrConst = segment.offset->dynCast<Const>()) {
451484
auto address = addrConst->value.geti32();
452485
segmentOffsets.push_back(address);
453486
} else {
@@ -494,7 +527,8 @@ const char* stringAtAddr(Module& wasm,
494527
for (unsigned i = 0; i < wasm.memory.segments.size(); ++i) {
495528
Memory::Segment& segment = wasm.memory.segments[i];
496529
Address offset = segmentOffsets[i];
497-
if (address >= offset && address < offset + segment.data.size()) {
530+
if (offset != UNKNOWN_OFFSET && address >= offset &&
531+
address < offset + segment.data.size()) {
498532
return &segment.data[address - offset];
499533
}
500534
}

test/lld/hello_world.passive.wast

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
(module
2+
(type $0 (func (param i32) (result i32)))
3+
(type $1 (func))
4+
(type $2 (func (result i32)))
5+
(type $3 (func (param i32 i32) (result i32)))
6+
(import "env" "puts" (func $puts (param i32) (result i32)))
7+
(memory $0 2)
8+
(data passive "Hello, world\00")
9+
(table $0 1 1 funcref)
10+
(global $global$0 (mut i32) (i32.const 66128))
11+
(global $global$1 i32 (i32.const 66128))
12+
(global $global$2 i32 (i32.const 581))
13+
(export "memory" (memory $0))
14+
(export "__wasm_call_ctors" (func $__wasm_call_ctors))
15+
(export "__heap_base" (global $global$1))
16+
(export "__data_end" (global $global$2))
17+
(export "main" (func $main))
18+
(func $__wasm_call_ctors (; 1 ;) (type $1)
19+
(call $__wasm_init_memory)
20+
)
21+
(func $__wasm_init_memory (; 2 ;) (type $1)
22+
(memory.init 0
23+
(i32.const 568)
24+
(i32.const 0)
25+
(i32.const 14)
26+
)
27+
)
28+
(func $__original_main (; 3 ;) (type $2) (result i32)
29+
(drop
30+
(call $puts
31+
(i32.const 568)
32+
)
33+
)
34+
(i32.const 0)
35+
)
36+
(func $main (; 3 ;) (type $3) (param $0 i32) (param $1 i32) (result i32)
37+
(call $__original_main)
38+
)
39+
;; custom section "producers", size 111
40+
)
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
(module
2+
(type $0 (func (param i32) (result i32)))
3+
(type $1 (func))
4+
(type $2 (func (result i32)))
5+
(type $3 (func (param i32 i32) (result i32)))
6+
(import "env" "puts" (func $puts (param i32) (result i32)))
7+
(memory $0 2)
8+
(data passive "Hello, world\00")
9+
(table $0 1 1 funcref)
10+
(global $global$0 (mut i32) (i32.const 66128))
11+
(global $global$1 i32 (i32.const 66128))
12+
(global $global$2 i32 (i32.const 581))
13+
(export "memory" (memory $0))
14+
(export "__wasm_call_ctors" (func $__wasm_call_ctors))
15+
(export "__heap_base" (global $global$1))
16+
(export "__data_end" (global $global$2))
17+
(export "main" (func $main))
18+
(export "stackSave" (func $stackSave))
19+
(export "stackAlloc" (func $stackAlloc))
20+
(export "stackRestore" (func $stackRestore))
21+
(export "__growWasmMemory" (func $__growWasmMemory))
22+
(func $__wasm_call_ctors (; 1 ;) (type $1)
23+
(call $__wasm_init_memory)
24+
)
25+
(func $__wasm_init_memory (; 2 ;) (type $1)
26+
(memory.init 0
27+
(i32.const 568)
28+
(i32.const 0)
29+
(i32.const 14)
30+
)
31+
)
32+
(func $__original_main (; 3 ;) (type $2) (result i32)
33+
(drop
34+
(call $puts
35+
(i32.const 568)
36+
)
37+
)
38+
(i32.const 0)
39+
)
40+
(func $main (; 4 ;) (type $3) (param $0 i32) (param $1 i32) (result i32)
41+
(call $__original_main)
42+
)
43+
(func $stackSave (; 5 ;) (result i32)
44+
(global.get $global$0)
45+
)
46+
(func $stackAlloc (; 6 ;) (param $0 i32) (result i32)
47+
(local $1 i32)
48+
(global.set $global$0
49+
(local.tee $1
50+
(i32.and
51+
(i32.sub
52+
(global.get $global$0)
53+
(local.get $0)
54+
)
55+
(i32.const -16)
56+
)
57+
)
58+
)
59+
(local.get $1)
60+
)
61+
(func $stackRestore (; 7 ;) (param $0 i32)
62+
(global.set $global$0
63+
(local.get $0)
64+
)
65+
)
66+
(func $__growWasmMemory (; 8 ;) (param $newSize i32) (result i32)
67+
(memory.grow
68+
(local.get $newSize)
69+
)
70+
)
71+
)
72+
(;
73+
--BEGIN METADATA --
74+
{
75+
"staticBump": 13,
76+
"tableSize": 1,
77+
"initializers": [
78+
"__wasm_call_ctors"
79+
],
80+
"declares": [
81+
"puts"
82+
],
83+
"externs": [
84+
],
85+
"implementedFunctions": [
86+
"___wasm_call_ctors",
87+
"_main",
88+
"_stackSave",
89+
"_stackAlloc",
90+
"_stackRestore",
91+
"___growWasmMemory"
92+
],
93+
"exports": [
94+
"__wasm_call_ctors",
95+
"main",
96+
"stackSave",
97+
"stackAlloc",
98+
"stackRestore",
99+
"__growWasmMemory"
100+
],
101+
"namedGlobals": {
102+
"__heap_base" : "66128",
103+
"__data_end" : "581"
104+
},
105+
"invokeFuncs": [
106+
],
107+
"features": [
108+
]
109+
}
110+
-- END METADATA --
111+
;)

0 commit comments

Comments
 (0)