summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorThomas Lively <7121787+tlively@users.noreply.github.com>2019-07-11 17:40:58 -0700
committerGitHub <noreply@github.com>2019-07-11 17:40:58 -0700
commit29b6458350747ef325bcbc98ec79860edb2e1867 (patch)
tree7d449013236ca6301ef76d0f7435b402ce0c23e6 /src
parent39b9e38f8b76f64afdd8c146357d35699fafc347 (diff)
downloadbinaryen-29b6458350747ef325bcbc98ec79860edb2e1867.tar.gz
binaryen-29b6458350747ef325bcbc98ec79860edb2e1867.tar.bz2
binaryen-29b6458350747ef325bcbc98ec79860edb2e1867.zip
Handle passive segments in wasm-emscripten-finalize (#2217)
Diffstat (limited to 'src')
-rw-r--r--src/wasm/wasm-emscripten.cpp38
1 files changed, 36 insertions, 2 deletions
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];
}
}