summaryrefslogtreecommitdiff
path: root/src/tools
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools')
-rw-r--r--src/tools/fuzzing/fuzzing.cpp171
-rw-r--r--src/tools/wasm-ctor-eval.cpp100
-rw-r--r--src/tools/wasm-shell.cpp13
-rw-r--r--src/tools/wasm-split/instrumenter.cpp55
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));
}
}
}