diff options
Diffstat (limited to 'src/tools')
-rw-r--r-- | src/tools/fuzzing/fuzzing.cpp | 171 | ||||
-rw-r--r-- | src/tools/wasm-ctor-eval.cpp | 100 | ||||
-rw-r--r-- | src/tools/wasm-shell.cpp | 13 | ||||
-rw-r--r-- | src/tools/wasm-split/instrumenter.cpp | 55 |
4 files changed, 216 insertions, 123 deletions
diff --git a/src/tools/fuzzing/fuzzing.cpp b/src/tools/fuzzing/fuzzing.cpp index 4d0a8d7b7..cdefe29f1 100644 --- a/src/tools/fuzzing/fuzzing.cpp +++ b/src/tools/fuzzing/fuzzing.cpp @@ -185,7 +185,7 @@ void TranslateToFuzzReader::build() { void TranslateToFuzzReader::setupMemory() { // Add memory itself - MemoryUtils::ensureExists(wasm.memory); + MemoryUtils::ensureExists(&wasm); if (wasm.features.hasBulkMemory()) { size_t memCovered = 0; // need at least one segment for memory.inits @@ -202,12 +202,14 @@ void TranslateToFuzzReader::setupMemory() { if (!segment->isPassive) { segment->offset = builder.makeConst(int32_t(memCovered)); memCovered += segSize; + segment->memory = wasm.memories[0]->name; } wasm.dataSegments.push_back(std::move(segment)); } } else { // init some data auto segment = builder.makeDataSegment(); + segment->memory = wasm.memories[0]->name; segment->offset = builder.makeConst(int32_t(0)); segment->setName(Name::fromInt(0), false); wasm.dataSegments.push_back(std::move(segment)); @@ -229,7 +231,7 @@ void TranslateToFuzzReader::setupMemory() { std::vector<Expression*> contents; contents.push_back( builder.makeLocalSet(0, builder.makeConst(uint32_t(5381)))); - auto zero = Literal::makeFromInt32(0, wasm.memory.indexType); + auto zero = Literal::makeFromInt32(0, wasm.memories[0]->indexType); for (Index i = 0; i < USABLE_MEMORY; i++) { contents.push_back(builder.makeLocalSet( 0, @@ -241,7 +243,13 @@ void TranslateToFuzzReader::setupMemory() { builder.makeLocalGet(0, Type::i32), builder.makeConst(uint32_t(5))), builder.makeLocalGet(0, Type::i32)), - builder.makeLoad(1, false, i, 1, builder.makeConst(zero), Type::i32)))); + builder.makeLoad(1, + false, + i, + 1, + builder.makeConst(zero), + Type::i32, + wasm.memories[0]->name)))); } contents.push_back(builder.makeLocalGet(0, Type::i32)); auto* body = builder.makeBlock(contents); @@ -251,7 +259,8 @@ void TranslateToFuzzReader::setupMemory() { builder.makeExport(hasher->name, hasher->name, ExternalKind::Function)); // Export memory so JS fuzzing can use it if (!wasm.getExportOrNull("memory")) { - wasm.addExport(builder.makeExport("memory", "0", ExternalKind::Memory)); + wasm.addExport(builder.makeExport( + "memory", wasm.memories[0]->name, ExternalKind::Memory)); } } @@ -354,25 +363,26 @@ void TranslateToFuzzReader::finalizeMemory() { maxOffset = maxOffset + offset->value.getInteger(); } } - wasm.memory.initial = std::max( - wasm.memory.initial, + wasm.memories[0]->initial = std::max( + wasm.memories[0]->initial, Address((maxOffset + Memory::kPageSize - 1) / Memory::kPageSize)); } - wasm.memory.initial = std::max(wasm.memory.initial, USABLE_MEMORY); + wasm.memories[0]->initial = + std::max(wasm.memories[0]->initial, USABLE_MEMORY); // Avoid an unlimited memory size, which would make fuzzing very difficult // as different VMs will run out of system memory in different ways. - if (wasm.memory.max == Memory::kUnlimitedSize) { - wasm.memory.max = wasm.memory.initial; + if (wasm.memories[0]->max == Memory::kUnlimitedSize) { + wasm.memories[0]->max = wasm.memories[0]->initial; } - if (wasm.memory.max <= wasm.memory.initial) { + if (wasm.memories[0]->max <= wasm.memories[0]->initial) { // To allow growth to work (which a testcase may assume), try to make the // maximum larger than the initial. // TODO: scan the wasm for grow instructions? - wasm.memory.max = - std::min(Address(wasm.memory.initial + 1), Address(Memory::kMaxSize32)); + wasm.memories[0]->max = std::min(Address(wasm.memories[0]->initial + 1), + Address(Memory::kMaxSize32)); } // Avoid an imported memory (which the fuzz harness would need to handle). - wasm.memory.module = wasm.memory.base = Name(); + wasm.memories[0]->module = wasm.memories[0]->base = Name(); } void TranslateToFuzzReader::finalizeTable() { @@ -1403,12 +1413,12 @@ Expression* TranslateToFuzzReader::makeTupleExtract(Type type) { } Expression* TranslateToFuzzReader::makePointer() { - auto* ret = make(wasm.memory.indexType); + auto* ret = make(wasm.memories[0]->indexType); // with high probability, mask the pointer so it's in a reasonable // range. otherwise, most pointers are going to be out of range and // most memory ops will just trap if (!allowOOB || !oneIn(10)) { - if (wasm.memory.is64()) { + if (wasm.memories[0]->is64()) { ret = builder.makeBinary( AndInt64, ret, builder.makeConst(int64_t(USABLE_MEMORY - 1))); } else { @@ -1427,11 +1437,19 @@ Expression* TranslateToFuzzReader::makeNonAtomicLoad(Type type) { bool signed_ = get() & 1; switch (upTo(3)) { case 0: - return builder.makeLoad(1, signed_, offset, 1, ptr, type); + return builder.makeLoad( + 1, signed_, offset, 1, ptr, type, wasm.memories[0]->name); case 1: - return builder.makeLoad(2, signed_, offset, pick(1, 2), ptr, type); + return builder.makeLoad( + 2, signed_, offset, pick(1, 2), ptr, type, wasm.memories[0]->name); case 2: - return builder.makeLoad(4, signed_, offset, pick(1, 2, 4), ptr, type); + return builder.makeLoad(4, + signed_, + offset, + pick(1, 2, 4), + ptr, + type, + wasm.memories[0]->name); } WASM_UNREACHABLE("unexpected value"); } @@ -1439,29 +1457,49 @@ Expression* TranslateToFuzzReader::makeNonAtomicLoad(Type type) { bool signed_ = get() & 1; switch (upTo(4)) { case 0: - return builder.makeLoad(1, signed_, offset, 1, ptr, type); + return builder.makeLoad( + 1, signed_, offset, 1, ptr, type, wasm.memories[0]->name); case 1: - return builder.makeLoad(2, signed_, offset, pick(1, 2), ptr, type); + return builder.makeLoad( + 2, signed_, offset, pick(1, 2), ptr, type, wasm.memories[0]->name); case 2: - return builder.makeLoad(4, signed_, offset, pick(1, 2, 4), ptr, type); + return builder.makeLoad(4, + signed_, + offset, + pick(1, 2, 4), + ptr, + type, + wasm.memories[0]->name); case 3: - return builder.makeLoad( - 8, signed_, offset, pick(1, 2, 4, 8), ptr, type); + return builder.makeLoad(8, + signed_, + offset, + pick(1, 2, 4, 8), + ptr, + type, + wasm.memories[0]->name); } WASM_UNREACHABLE("unexpected value"); } case Type::f32: { - return builder.makeLoad(4, false, offset, pick(1, 2, 4), ptr, type); + return builder.makeLoad( + 4, false, offset, pick(1, 2, 4), ptr, type, wasm.memories[0]->name); } case Type::f64: { - return builder.makeLoad(8, false, offset, pick(1, 2, 4, 8), ptr, type); + return builder.makeLoad( + 8, false, offset, pick(1, 2, 4, 8), ptr, type, wasm.memories[0]->name); } case Type::v128: { if (!wasm.features.hasSIMD()) { return makeTrivial(type); } - return builder.makeLoad( - 16, false, offset, pick(1, 2, 4, 8, 16), ptr, type); + return builder.makeLoad(16, + false, + offset, + pick(1, 2, 4, 8, 16), + ptr, + type, + wasm.memories[0]->name); } case Type::none: case Type::unreachable: @@ -1484,7 +1522,7 @@ Expression* TranslateToFuzzReader::makeLoad(Type type) { } // make it atomic auto* load = ret->cast<Load>(); - wasm.memory.shared = true; + wasm.memories[0]->shared = true; load->isAtomic = true; load->signed_ = false; load->align = load->bytes; @@ -1511,6 +1549,7 @@ Expression* TranslateToFuzzReader::makeNonAtomicStore(Type type) { store->value = make(Type::unreachable); break; } + store->memory = wasm.memories[0]->name; store->finalize(); return store; } @@ -1526,40 +1565,58 @@ Expression* TranslateToFuzzReader::makeNonAtomicStore(Type type) { case Type::i32: { switch (upTo(3)) { case 0: - return builder.makeStore(1, offset, 1, ptr, value, type); + return builder.makeStore( + 1, offset, 1, ptr, value, type, wasm.memories[0]->name); case 1: - return builder.makeStore(2, offset, pick(1, 2), ptr, value, type); + return builder.makeStore( + 2, offset, pick(1, 2), ptr, value, type, wasm.memories[0]->name); case 2: - return builder.makeStore(4, offset, pick(1, 2, 4), ptr, value, type); + return builder.makeStore( + 4, offset, pick(1, 2, 4), ptr, value, type, wasm.memories[0]->name); } WASM_UNREACHABLE("invalid value"); } case Type::i64: { switch (upTo(4)) { case 0: - return builder.makeStore(1, offset, 1, ptr, value, type); + return builder.makeStore( + 1, offset, 1, ptr, value, type, wasm.memories[0]->name); case 1: - return builder.makeStore(2, offset, pick(1, 2), ptr, value, type); + return builder.makeStore( + 2, offset, pick(1, 2), ptr, value, type, wasm.memories[0]->name); case 2: - return builder.makeStore(4, offset, pick(1, 2, 4), ptr, value, type); - case 3: return builder.makeStore( - 8, offset, pick(1, 2, 4, 8), ptr, value, type); + 4, offset, pick(1, 2, 4), ptr, value, type, wasm.memories[0]->name); + case 3: + return builder.makeStore(8, + offset, + pick(1, 2, 4, 8), + ptr, + value, + type, + wasm.memories[0]->name); } WASM_UNREACHABLE("invalid value"); } case Type::f32: { - return builder.makeStore(4, offset, pick(1, 2, 4), ptr, value, type); + return builder.makeStore( + 4, offset, pick(1, 2, 4), ptr, value, type, wasm.memories[0]->name); } case Type::f64: { - return builder.makeStore(8, offset, pick(1, 2, 4, 8), ptr, value, type); + return builder.makeStore( + 8, offset, pick(1, 2, 4, 8), ptr, value, type, wasm.memories[0]->name); } case Type::v128: { if (!wasm.features.hasSIMD()) { return makeTrivial(type); } - return builder.makeStore( - 16, offset, pick(1, 2, 4, 8, 16), ptr, value, type); + return builder.makeStore(16, + offset, + pick(1, 2, 4, 8, 16), + ptr, + value, + type, + wasm.memories[0]->name); } case Type::none: case Type::unreachable: @@ -1584,7 +1641,7 @@ Expression* TranslateToFuzzReader::makeStore(Type type) { return store; } // make it atomic - wasm.memory.shared = true; + wasm.memories[0]->shared = true; store->isAtomic = true; store->align = store->bytes; return store; @@ -2530,7 +2587,7 @@ Expression* TranslateToFuzzReader::makeAtomic(Type type) { if (!allowMemory) { return makeTrivial(type); } - wasm.memory.shared = true; + wasm.memories[0]->shared = true; if (type == Type::none) { return builder.makeAtomicFence(); } @@ -2540,12 +2597,17 @@ Expression* TranslateToFuzzReader::makeAtomic(Type type) { auto expectedType = pick(Type::i32, Type::i64); auto* expected = make(expectedType); auto* timeout = make(Type::i64); - return builder.makeAtomicWait( - ptr, expected, timeout, expectedType, logify(get())); + return builder.makeAtomicWait(ptr, + expected, + timeout, + expectedType, + logify(get()), + wasm.memories[0]->name); } else { auto* ptr = makePointer(); auto* count = make(Type::i32); - return builder.makeAtomicNotify(ptr, count, logify(get())); + return builder.makeAtomicNotify( + ptr, count, logify(get()), wasm.memories[0]->name); } } Index bytes; @@ -2598,12 +2660,13 @@ Expression* TranslateToFuzzReader::makeAtomic(Type type) { offset, ptr, value, - type); + type, + wasm.memories[0]->name); } else { auto* expected = make(type); auto* replacement = make(type); return builder.makeAtomicCmpxchg( - bytes, offset, ptr, expected, replacement, type); + bytes, offset, ptr, expected, replacement, type, wasm.memories[0]->name); } } @@ -2804,7 +2867,7 @@ Expression* TranslateToFuzzReader::makeSIMDLoad() { WASM_UNREACHABLE("Unexpected SIMD loads"); } Expression* ptr = makePointer(); - return builder.makeSIMDLoad(op, offset, align, ptr); + return builder.makeSIMDLoad(op, offset, align, ptr, wasm.memories[0]->name); } Expression* TranslateToFuzzReader::makeBulkMemory(Type type) { @@ -2868,7 +2931,8 @@ Expression* TranslateToFuzzReader::makeMemoryInit() { Expression* dest = makePointer(); Expression* offset = builder.makeConst(int32_t(offsetVal)); Expression* size = builder.makeConst(int32_t(sizeVal)); - return builder.makeMemoryInit(segment, dest, offset, size); + return builder.makeMemoryInit( + segment, dest, offset, size, wasm.memories[0]->name); } Expression* TranslateToFuzzReader::makeDataDrop() { @@ -2884,8 +2948,9 @@ Expression* TranslateToFuzzReader::makeMemoryCopy() { } Expression* dest = makePointer(); Expression* source = makePointer(); - Expression* size = make(wasm.memory.indexType); - return builder.makeMemoryCopy(dest, source, size); + Expression* size = make(wasm.memories[0]->indexType); + return builder.makeMemoryCopy( + dest, source, size, wasm.memories[0]->name, wasm.memories[0]->name); } Expression* TranslateToFuzzReader::makeMemoryFill() { @@ -2894,8 +2959,8 @@ Expression* TranslateToFuzzReader::makeMemoryFill() { } Expression* dest = makePointer(); Expression* value = make(Type::i32); - Expression* size = make(wasm.memory.indexType); - return builder.makeMemoryFill(dest, value, size); + Expression* size = make(wasm.memories[0]->indexType); + return builder.makeMemoryFill(dest, value, size, wasm.memories[0]->name); } Type TranslateToFuzzReader::getSingleConcreteType() { diff --git a/src/tools/wasm-ctor-eval.cpp b/src/tools/wasm-ctor-eval.cpp index 6150441cd..91128471c 100644 --- a/src/tools/wasm-ctor-eval.cpp +++ b/src/tools/wasm-ctor-eval.cpp @@ -122,14 +122,11 @@ std::unique_ptr<Module> buildEnvModule(Module& wasm) { // create an exported memory with the same initial and max size ModuleUtils::iterImportedMemories(wasm, [&](Memory* memory) { if (memory->module == env->name) { - env->memory.name = wasm.memory.name; - env->memory.exists = true; - env->memory.initial = memory->initial; - env->memory.max = memory->max; - env->memory.shared = memory->shared; - env->memory.indexType = memory->indexType; + auto* copied = ModuleUtils::copyMemory(memory, *env); + copied->module = Name(); + copied->base = Name(); env->addExport(Builder(*env).makeExport( - wasm.memory.base, wasm.memory.name, ExternalKind::Memory)); + memory->base, copied->name, ExternalKind::Memory)); } }); @@ -147,7 +144,7 @@ struct CtorEvalExternalInterface : EvallingModuleRunner::ExternalInterface { std::map<Name, std::shared_ptr<EvallingModuleRunner>> linkedInstances; // A representation of the contents of wasm memory as we execute. - std::vector<char> memory; + std::unordered_map<Name, std::vector<char>> memories; CtorEvalExternalInterface( std::map<Name, std::shared_ptr<EvallingModuleRunner>> linkedInstances_ = @@ -160,8 +157,8 @@ struct CtorEvalExternalInterface : EvallingModuleRunner::ExternalInterface { void applyToModule() { clearApplyState(); - // If nothing was ever written to memory then there is nothing to update. - if (!memory.empty()) { + // If nothing was ever written to memories then there is nothing to update. + if (!memories.empty()) { applyMemoryToModule(); } @@ -171,6 +168,12 @@ struct CtorEvalExternalInterface : EvallingModuleRunner::ExternalInterface { void init(Module& wasm_, EvallingModuleRunner& instance_) override { wasm = &wasm_; instance = &instance_; + for (auto& memory : wasm->memories) { + if (!memory->imported()) { + std::vector<char> data; + memories[memory->name] = data; + } + } } void importGlobals(GlobalValueSet& globals, Module& wasm_) override { @@ -204,7 +207,7 @@ struct CtorEvalExternalInterface : EvallingModuleRunner::ExternalInterface { } // Write out a count of i32(0) and return __WASI_ERRNO_SUCCESS (0). - store32(arguments[0].geti32(), 0); + store32(arguments[0].geti32(), 0, wasm->memories[0]->name); return {Literal(int32_t(0))}; } @@ -225,7 +228,7 @@ struct CtorEvalExternalInterface : EvallingModuleRunner::ExternalInterface { } // Write out an argc of i32(0) and return a __WASI_ERRNO_SUCCESS (0). - store32(arguments[0].geti32(), 0); + store32(arguments[0].geti32(), 0, wasm->memories[0]->name); return {Literal(int32_t(0))}; } @@ -336,29 +339,47 @@ struct CtorEvalExternalInterface : EvallingModuleRunner::ExternalInterface { // called during initialization void tableStore(Name tableName, Index index, const Literal& value) override {} - int8_t load8s(Address addr) override { return doLoad<int8_t>(addr); } - uint8_t load8u(Address addr) override { return doLoad<uint8_t>(addr); } - int16_t load16s(Address addr) override { return doLoad<int16_t>(addr); } - uint16_t load16u(Address addr) override { return doLoad<uint16_t>(addr); } - int32_t load32s(Address addr) override { return doLoad<int32_t>(addr); } - uint32_t load32u(Address addr) override { return doLoad<uint32_t>(addr); } - int64_t load64s(Address addr) override { return doLoad<int64_t>(addr); } - uint64_t load64u(Address addr) override { return doLoad<uint64_t>(addr); } + int8_t load8s(Address addr, Name memoryName) override { + return doLoad<int8_t>(addr, memoryName); + } + uint8_t load8u(Address addr, Name memoryName) override { + return doLoad<uint8_t>(addr, memoryName); + } + int16_t load16s(Address addr, Name memoryName) override { + return doLoad<int16_t>(addr, memoryName); + } + uint16_t load16u(Address addr, Name memoryName) override { + return doLoad<uint16_t>(addr, memoryName); + } + int32_t load32s(Address addr, Name memoryName) override { + return doLoad<int32_t>(addr, memoryName); + } + uint32_t load32u(Address addr, Name memoryName) override { + return doLoad<uint32_t>(addr, memoryName); + } + int64_t load64s(Address addr, Name memoryName) override { + return doLoad<int64_t>(addr, memoryName); + } + uint64_t load64u(Address addr, Name memoryName) override { + return doLoad<uint64_t>(addr, memoryName); + } - void store8(Address addr, int8_t value) override { - doStore<int8_t>(addr, value); + void store8(Address addr, int8_t value, Name memoryName) override { + doStore<int8_t>(addr, value, memoryName); } - void store16(Address addr, int16_t value) override { - doStore<int16_t>(addr, value); + void store16(Address addr, int16_t value, Name memoryName) override { + doStore<int16_t>(addr, value, memoryName); } - void store32(Address addr, int32_t value) override { - doStore<int32_t>(addr, value); + void store32(Address addr, int32_t value, Name memoryName) override { + doStore<int32_t>(addr, value, memoryName); } - void store64(Address addr, int64_t value) override { - doStore<int64_t>(addr, value); + void store64(Address addr, int64_t value, Name memoryName) override { + doStore<int64_t>(addr, value, memoryName); } - bool growMemory(Address /*oldSize*/, Address /*newSize*/) override { + bool growMemory(Name memoryName, + Address /*oldSize*/, + Address /*newSize*/) override { throw FailToEvalException("grow memory"); } @@ -385,8 +406,12 @@ struct CtorEvalExternalInterface : EvallingModuleRunner::ExternalInterface { private: // TODO: handle unaligned too, see shell-interface - - template<typename T> T* getMemory(Address address) { + template<typename T> T* getMemory(Address address, Name memoryName) { + auto it = memories.find(memoryName); + if (it == memories.end()) { + Fatal() << "memory not found: " << memoryName; + } + auto& memory = it->second; // resize the memory buffer as needed. auto max = address + sizeof(T); if (max > memory.size()) { @@ -395,15 +420,15 @@ private: return (T*)(&memory[address]); } - template<typename T> void doStore(Address address, T value) { + template<typename T> void doStore(Address address, T value, Name memoryName) { // do a memcpy to avoid undefined behavior if unaligned - memcpy(getMemory<T>(address), &value, sizeof(T)); + memcpy(getMemory<T>(address, memoryName), &value, sizeof(T)); } - template<typename T> T doLoad(Address address) { + template<typename T> T doLoad(Address address, Name memoryName) { // do a memcpy to avoid undefined behavior if unaligned T ret; - memcpy(&ret, getMemory<T>(address), sizeof(T)); + memcpy(&ret, getMemory<T>(address, memoryName), sizeof(T)); return ret; } @@ -431,14 +456,15 @@ private: auto curr = builder.makeDataSegment(); curr->offset = builder.makeConst(int32_t(0)); curr->setName(Name::fromInt(0), false); - wasm->dataSegments.push_back(std::move(curr)); + curr->memory = wasm->memories[0]->name; + wasm->addDataSegment(std::move(curr)); } auto& segment = wasm->dataSegments[0]; assert(segment->offset->cast<Const>()->value.getInteger() == 0); // Copy the current memory contents after execution into the Module's // memory. - segment->data = memory; + segment->data = memories[wasm->memories[0]->name]; } // Serializing GC data requires more work than linear memory, because diff --git a/src/tools/wasm-shell.cpp b/src/tools/wasm-shell.cpp index 51eafb652..4b20e922b 100644 --- a/src/tools/wasm-shell.cpp +++ b/src/tools/wasm-shell.cpp @@ -284,9 +284,7 @@ protected: } } }); - if (wasm.memory.imported()) { - reportUnknownImport(&wasm.memory); - } + ModuleUtils::iterImportedMemories(wasm, reportUnknownImport); } if (!invalid && id == ASSERT_TRAP) { @@ -352,11 +350,10 @@ protected: spectest->addExport( builder.makeExport("table", Name::fromInt(0), ExternalKind::Table)); - spectest->memory.exists = true; - spectest->memory.initial = 1; - spectest->memory.max = 2; - spectest->addExport(builder.makeExport( - "memory", spectest->memory.name, ExternalKind::Memory)); + Memory* memory = + spectest->addMemory(builder.makeMemory(Name::fromInt(0), 1, 2)); + spectest->addExport( + builder.makeExport("memory", memory->name, ExternalKind::Memory)); modules["spectest"].swap(spectest); modules["spectest"]->features = FeatureSet::All; diff --git a/src/tools/wasm-split/instrumenter.cpp b/src/tools/wasm-split/instrumenter.cpp index c23a70f06..50da9d034 100644 --- a/src/tools/wasm-split/instrumenter.cpp +++ b/src/tools/wasm-split/instrumenter.cpp @@ -108,13 +108,15 @@ void Instrumenter::instrumentFuncs() { } // (i32.atomic.store8 offset=funcidx (i32.const 0) (i32.const 1)) Index funcIdx = 0; + assert(!wasm->memories.empty()); ModuleUtils::iterDefinedFunctions(*wasm, [&](Function* func) { func->body = builder.makeSequence( builder.makeAtomicStore(1, funcIdx, - builder.makeConstPtr(0), + builder.makeConstPtr(0, Type::i32), builder.makeConst(uint32_t(1)), - Type::i32), + Type::i32, + wasm->memories[0]->name), func->body, func->body->type); ++funcIdx; @@ -168,9 +170,22 @@ void Instrumenter::addProfileExport() { return builder.makeConst(int32_t(profileSize)); }; + // Also make sure there is a memory with enough pages to write into + size_t pages = (profileSize + Memory::kPageSize - 1) / Memory::kPageSize; + if (wasm->memories.empty()) { + wasm->addMemory(Builder::makeMemory("0")); + wasm->memories[0]->initial = pages; + wasm->memories[0]->max = pages; + } else if (wasm->memories[0]->initial < pages) { + wasm->memories[0]->initial = pages; + if (wasm->memories[0]->max < pages) { + wasm->memories[0]->max = pages; + } + } + // Write the hash followed by all the time stamps - Expression* writeData = - builder.makeStore(8, 0, 1, getAddr(), hashConst(), Type::i64); + Expression* writeData = builder.makeStore( + 8, 0, 1, getAddr(), hashConst(), Type::i64, wasm->memories[0]->name); uint32_t offset = 8; switch (options.storageKind) { @@ -183,7 +198,8 @@ void Instrumenter::addProfileExport() { 1, getAddr(), builder.makeGlobalGet(global, Type::i32), - Type::i32)); + Type::i32, + wasm->memories[0]->name)); offset += 4; } break; @@ -232,8 +248,10 @@ void Instrumenter::addProfileExport() { getAddr(), builder.makeBinary( MulInt32, getFuncIdx(), builder.makeConst(uint32_t(4)))), - builder.makeAtomicLoad(1, 0, getFuncIdx(), Type::i32), - Type::i32), + builder.makeAtomicLoad( + 1, 0, getFuncIdx(), Type::i32, wasm->memories[0]->name), + Type::i32, + wasm->memories[0]->name), builder.makeLocalSet( funcIdxVar, builder.makeBinary( @@ -253,21 +271,8 @@ void Instrumenter::addProfileExport() { wasm->addExport( Builder::makeExport(options.profileExport, name, ExternalKind::Function)); - // Also make sure there is a memory with enough pages to write into - size_t pages = (profileSize + Memory::kPageSize - 1) / Memory::kPageSize; - if (!wasm->memory.exists) { - wasm->memory.exists = true; - wasm->memory.initial = pages; - wasm->memory.max = pages; - } else if (wasm->memory.initial < pages) { - wasm->memory.initial = pages; - if (wasm->memory.max < pages) { - wasm->memory.max = pages; - } - } - // Export the memory if it is not already exported or imported. - if (!wasm->memory.imported()) { + if (!wasm->memories[0]->imported()) { bool memoryExported = false; for (auto& ex : wasm->exports) { if (ex->kind == ExternalKind::Memory) { @@ -276,10 +281,10 @@ void Instrumenter::addProfileExport() { } } if (!memoryExported) { - wasm->addExport( - Builder::makeExport("profile-memory", - Names::getValidExportName(*wasm, wasm->memory.name), - ExternalKind::Memory)); + wasm->addExport(Builder::makeExport( + "profile-memory", + Names::getValidExportName(*wasm, wasm->memories[0]->name), + ExternalKind::Memory)); } } } |