diff options
Diffstat (limited to 'src/wasm/wasm-validator.cpp')
-rw-r--r-- | src/wasm/wasm-validator.cpp | 140 |
1 files changed, 76 insertions, 64 deletions
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index b7354ff3f..92f6c76bf 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -499,7 +499,10 @@ private: validateCallParamsAndResult(curr, sigType, curr); } - Type indexType() { return getModule()->memory.indexType; } + Type indexType(Name memoryName) { + auto memory = getModule()->getMemory(memoryName); + return memory->indexType; + } }; void FunctionValidator::noteLabelName(Name name) { @@ -934,8 +937,8 @@ void FunctionValidator::visitGlobalSet(GlobalSet* curr) { } void FunctionValidator::visitLoad(Load* curr) { - shouldBeTrue( - getModule()->memory.exists, curr, "Memory operations require a memory"); + auto* memory = getModule()->getMemoryOrNull(curr->memory); + shouldBeTrue(!!memory, curr, "memory.load memory must exist"); if (curr->isAtomic) { shouldBeTrue(getModule()->features.hasAtomics(), curr, @@ -954,7 +957,7 @@ void FunctionValidator::visitLoad(Load* curr) { validateAlignment(curr->align, curr->type, curr->bytes, curr->isAtomic, curr); shouldBeEqualOrFirstIsUnreachable( curr->ptr->type, - indexType(), + indexType(curr->memory), curr, "load pointer type must match memory index type"); if (curr->isAtomic) { @@ -965,8 +968,8 @@ void FunctionValidator::visitLoad(Load* curr) { } void FunctionValidator::visitStore(Store* curr) { - shouldBeTrue( - getModule()->memory.exists, curr, "Memory operations require a memory"); + auto* memory = getModule()->getMemoryOrNull(curr->memory); + shouldBeTrue(!!memory, curr, "memory.store memory must exist"); if (curr->isAtomic) { shouldBeTrue(getModule()->features.hasAtomics(), curr, @@ -986,7 +989,7 @@ void FunctionValidator::visitStore(Store* curr) { curr->align, curr->valueType, curr->bytes, curr->isAtomic, curr); shouldBeEqualOrFirstIsUnreachable( curr->ptr->type, - indexType(), + indexType(curr->memory), curr, "store pointer must match memory index type"); shouldBeUnequal(curr->value->type, @@ -1002,15 +1005,15 @@ void FunctionValidator::visitStore(Store* curr) { } void FunctionValidator::visitAtomicRMW(AtomicRMW* curr) { - shouldBeTrue( - getModule()->memory.exists, curr, "Memory operations require a memory"); + auto* memory = getModule()->getMemoryOrNull(curr->memory); + shouldBeTrue(!!memory, curr, "memory.atomicRMW memory must exist"); shouldBeTrue(getModule()->features.hasAtomics(), curr, "Atomic operation (atomics are disabled)"); validateMemBytes(curr->bytes, curr->type, curr); shouldBeEqualOrFirstIsUnreachable( curr->ptr->type, - indexType(), + indexType(curr->memory), curr, "AtomicRMW pointer type must match memory index type"); shouldBeEqualOrFirstIsUnreachable(curr->type, @@ -1022,15 +1025,15 @@ void FunctionValidator::visitAtomicRMW(AtomicRMW* curr) { } void FunctionValidator::visitAtomicCmpxchg(AtomicCmpxchg* curr) { - shouldBeTrue( - getModule()->memory.exists, curr, "Memory operations require a memory"); + auto* memory = getModule()->getMemoryOrNull(curr->memory); + shouldBeTrue(!!memory, curr, "memory.atomicCmpxchg memory must exist"); shouldBeTrue(getModule()->features.hasAtomics(), curr, "Atomic operation (atomics are disabled)"); validateMemBytes(curr->bytes, curr->type, curr); shouldBeEqualOrFirstIsUnreachable( curr->ptr->type, - indexType(), + indexType(curr->memory), curr, "cmpxchg pointer must match memory index type"); if (curr->expected->type != Type::unreachable && @@ -1055,8 +1058,8 @@ void FunctionValidator::visitAtomicCmpxchg(AtomicCmpxchg* curr) { } void FunctionValidator::visitAtomicWait(AtomicWait* curr) { - shouldBeTrue( - getModule()->memory.exists, curr, "Memory operations require a memory"); + auto* memory = getModule()->getMemoryOrNull(curr->memory); + shouldBeTrue(!!memory, curr, "memory.atomicWait memory must exist"); shouldBeTrue(getModule()->features.hasAtomics(), curr, "Atomic operation (atomics are disabled)"); @@ -1064,7 +1067,7 @@ void FunctionValidator::visitAtomicWait(AtomicWait* curr) { curr->type, Type(Type::i32), curr, "AtomicWait must have type i32"); shouldBeEqualOrFirstIsUnreachable( curr->ptr->type, - indexType(), + indexType(curr->memory), curr, "AtomicWait pointer must match memory index type"); shouldBeIntOrUnreachable( @@ -1081,8 +1084,8 @@ void FunctionValidator::visitAtomicWait(AtomicWait* curr) { } void FunctionValidator::visitAtomicNotify(AtomicNotify* curr) { - shouldBeTrue( - getModule()->memory.exists, curr, "Memory operations require a memory"); + auto* memory = getModule()->getMemoryOrNull(curr->memory); + shouldBeTrue(!!memory, curr, "memory.atomicNotify memory must exist"); shouldBeTrue(getModule()->features.hasAtomics(), curr, "Atomic operation (atomics are disabled)"); @@ -1090,7 +1093,7 @@ void FunctionValidator::visitAtomicNotify(AtomicNotify* curr) { curr->type, Type(Type::i32), curr, "AtomicNotify must have type i32"); shouldBeEqualOrFirstIsUnreachable( curr->ptr->type, - indexType(), + indexType(curr->memory), curr, "AtomicNotify pointer must match memory index type"); shouldBeEqualOrFirstIsUnreachable( @@ -1101,8 +1104,8 @@ void FunctionValidator::visitAtomicNotify(AtomicNotify* curr) { } void FunctionValidator::visitAtomicFence(AtomicFence* curr) { - shouldBeTrue( - getModule()->memory.exists, curr, "Memory operations require a memory"); + shouldBeFalse( + getModule()->memories.empty(), curr, "Memory operations require a memory"); shouldBeTrue(getModule()->features.hasAtomics(), curr, "Atomic operation (atomics are disabled)"); @@ -1240,15 +1243,15 @@ void FunctionValidator::visitSIMDShift(SIMDShift* curr) { } void FunctionValidator::visitSIMDLoad(SIMDLoad* curr) { - shouldBeTrue( - getModule()->memory.exists, curr, "Memory operations require a memory"); + auto* memory = getModule()->getMemoryOrNull(curr->memory); + shouldBeTrue(!!memory, curr, "memory.SIMDLoad memory must exist"); shouldBeTrue( getModule()->features.hasSIMD(), curr, "SIMD operation (SIMD is disabled)"); shouldBeEqualOrFirstIsUnreachable( curr->type, Type(Type::v128), curr, "load_splat must have type v128"); shouldBeEqualOrFirstIsUnreachable( curr->ptr->type, - indexType(), + indexType(curr->memory), curr, "load_splat address must match memory index type"); Type memAlignType = Type::none; @@ -1275,8 +1278,8 @@ void FunctionValidator::visitSIMDLoad(SIMDLoad* curr) { } void FunctionValidator::visitSIMDLoadStoreLane(SIMDLoadStoreLane* curr) { - shouldBeTrue( - getModule()->memory.exists, curr, "Memory operations require a memory"); + auto* memory = getModule()->getMemoryOrNull(curr->memory); + shouldBeTrue(!!memory, curr, "memory.SIMDLoadStoreLane memory must exist"); shouldBeTrue( getModule()->features.hasSIMD(), curr, "SIMD operation (SIMD is disabled)"); if (curr->isLoad()) { @@ -1288,7 +1291,7 @@ void FunctionValidator::visitSIMDLoadStoreLane(SIMDLoadStoreLane* curr) { } shouldBeEqualOrFirstIsUnreachable( curr->ptr->type, - indexType(), + indexType(curr->memory), curr, "loadX_lane or storeX_lane address must match memory index type"); shouldBeEqualOrFirstIsUnreachable( @@ -1335,7 +1338,7 @@ void FunctionValidator::visitMemoryInit(MemoryInit* curr) { curr->type, Type(Type::none), curr, "memory.init must have type none"); shouldBeEqualOrFirstIsUnreachable( curr->dest->type, - indexType(), + indexType(curr->memory), curr, "memory.init dest must match memory index type"); shouldBeEqualOrFirstIsUnreachable(curr->offset->type, @@ -1344,9 +1347,8 @@ void FunctionValidator::visitMemoryInit(MemoryInit* curr) { "memory.init offset must be an i32"); shouldBeEqualOrFirstIsUnreachable( curr->size->type, Type(Type::i32), curr, "memory.init size must be an i32"); - if (!shouldBeTrue(getModule()->memory.exists, - curr, - "Memory operations require a memory")) { + auto* memory = getModule()->getMemoryOrNull(curr->memory); + if (!shouldBeTrue(!!memory, curr, "memory.init memory must exist")) { return; } shouldBeTrue(curr->segment < getModule()->dataSegments.size(), @@ -1360,9 +1362,9 @@ void FunctionValidator::visitDataDrop(DataDrop* curr) { "Bulk memory operation (bulk memory is disabled)"); shouldBeEqualOrFirstIsUnreachable( curr->type, Type(Type::none), curr, "data.drop must have type none"); - if (!shouldBeTrue(getModule()->memory.exists, - curr, - "Memory operations require a memory")) { + if (!shouldBeFalse(getModule()->memories.empty(), + curr, + "Memory operations require a memory")) { return; } shouldBeTrue(curr->segment < getModule()->dataSegments.size(), @@ -1376,23 +1378,30 @@ void FunctionValidator::visitMemoryCopy(MemoryCopy* curr) { "Bulk memory operation (bulk memory is disabled)"); shouldBeEqualOrFirstIsUnreachable( curr->type, Type(Type::none), curr, "memory.copy must have type none"); + auto* destMemory = getModule()->getMemoryOrNull(curr->destMemory); + shouldBeTrue(!!destMemory, curr, "memory.copy destMemory must exist"); + auto* sourceMemory = getModule()->getMemoryOrNull(curr->sourceMemory); + shouldBeTrue(!!sourceMemory, curr, "memory.copy sourceMemory must exist"); shouldBeEqualOrFirstIsUnreachable( curr->dest->type, - indexType(), + indexType(curr->destMemory), curr, - "memory.copy dest must match memory index type"); + "memory.copy dest must match destMemory index type"); shouldBeEqualOrFirstIsUnreachable( curr->source->type, - indexType(), + indexType(curr->sourceMemory), curr, - "memory.copy source must match memory index type"); + "memory.copy source must match sourceMemory index type"); shouldBeEqualOrFirstIsUnreachable( curr->size->type, - indexType(), + indexType(curr->destMemory), curr, - "memory.copy size must match memory index type"); - shouldBeTrue( - getModule()->memory.exists, curr, "Memory operations require a memory"); + "memory.copy size must match destMemory index type"); + shouldBeEqualOrFirstIsUnreachable( + curr->size->type, + indexType(curr->sourceMemory), + curr, + "memory.copy size must match destMemory index type"); } void FunctionValidator::visitMemoryFill(MemoryFill* curr) { @@ -1403,7 +1412,7 @@ void FunctionValidator::visitMemoryFill(MemoryFill* curr) { curr->type, Type(Type::none), curr, "memory.fill must have type none"); shouldBeEqualOrFirstIsUnreachable( curr->dest->type, - indexType(), + indexType(curr->memory), curr, "memory.fill dest must match memory index type"); shouldBeEqualOrFirstIsUnreachable(curr->value->type, @@ -1412,11 +1421,11 @@ void FunctionValidator::visitMemoryFill(MemoryFill* curr) { "memory.fill value must be an i32"); shouldBeEqualOrFirstIsUnreachable( curr->size->type, - indexType(), + indexType(curr->memory), curr, "memory.fill size must match memory index type"); - shouldBeTrue( - getModule()->memory.exists, curr, "Memory operations require a memory"); + auto* memory = getModule()->getMemoryOrNull(curr->memory); + shouldBeTrue(!!memory, curr, "memory.fill memory must exist"); } void FunctionValidator::validateMemBytes(uint8_t bytes, @@ -2020,15 +2029,15 @@ void FunctionValidator::visitReturn(Return* curr) { } void FunctionValidator::visitMemorySize(MemorySize* curr) { - shouldBeTrue( - getModule()->memory.exists, curr, "Memory operations require a memory"); + auto* memory = getModule()->getMemoryOrNull(curr->memory); + shouldBeTrue(!!memory, curr, "memory.size memory must exist"); } void FunctionValidator::visitMemoryGrow(MemoryGrow* curr) { - shouldBeTrue( - getModule()->memory.exists, curr, "Memory operations require a memory"); + auto* memory = getModule()->getMemoryOrNull(curr->memory); + shouldBeTrue(!!memory, curr, "memory.grow memory must exist"); shouldBeEqualOrFirstIsUnreachable(curr->delta->type, - indexType(), + indexType(curr->memory), curr, "memory.grow must match memory index type"); } @@ -2940,7 +2949,7 @@ static void validateExports(Module& module, ValidationInfo& info) { name, "module table exports must be found"); } else if (exp->kind == ExternalKind::Memory) { - info.shouldBeTrue(name == Name("0") || name == module.memory.name, + info.shouldBeTrue(module.getMemoryOrNull(name), name, "module memory exports must be found"); } else if (exp->kind == ExternalKind::Tag) { @@ -2982,25 +2991,28 @@ static void validateGlobals(Module& module, ValidationInfo& info) { } static void validateMemory(Module& module, ValidationInfo& info) { - auto& curr = module.memory; + if (module.memories.empty()) { + return; + } + auto& curr = module.memories[0]; info.shouldBeFalse( - curr.initial > curr.max, "memory", "memory max >= initial"); - if (curr.is64()) { + curr->initial > curr->max, "memory", "memory max >= initial"); + if (curr->is64()) { info.shouldBeTrue(module.features.hasMemory64(), "memory", "memory is 64-bit, but memory64 is disabled"); } else { - info.shouldBeTrue(curr.initial <= Memory::kMaxSize32, + info.shouldBeTrue(curr->initial <= Memory::kMaxSize32, "memory", "initial memory must be <= 4GB"); - info.shouldBeTrue(!curr.hasMax() || curr.max <= Memory::kMaxSize32, + info.shouldBeTrue(!curr->hasMax() || curr->max <= Memory::kMaxSize32, "memory", "max memory must be <= 4GB, or unlimited"); } - info.shouldBeTrue(!curr.shared || curr.hasMax(), + info.shouldBeTrue(!curr->shared || curr->hasMax(), "memory", "shared memory must have max size"); - if (curr.shared) { + if (curr->shared) { info.shouldBeTrue(module.features.hasAtomics(), "memory", "memory is shared, but atomics are disabled"); @@ -3016,7 +3028,7 @@ static void validateMemory(Module& module, ValidationInfo& info) { segment->offset, "passive segment should not have an offset"); } else { - if (curr.is64()) { + if (curr->is64()) { if (!info.shouldBeEqual(segment->offset->type, Type(Type::i64), segment->offset, @@ -3033,14 +3045,14 @@ static void validateMemory(Module& module, ValidationInfo& info) { } info.shouldBeTrue(checkSegmentOffset(segment->offset, segment->data.size(), - curr.initial * Memory::kPageSize, + curr->initial * Memory::kPageSize, module.features), segment->offset, "memory segment offset should be reasonable"); if (segment->offset->is<Const>()) { auto start = segment->offset->cast<Const>()->value.getUnsigned(); auto end = start + size; - info.shouldBeTrue(end <= curr.initial * Memory::kPageSize, + info.shouldBeTrue(end <= curr->initial * Memory::kPageSize, segment->data.size(), "segment size should fit in memory (end)"); } @@ -3049,8 +3061,8 @@ static void validateMemory(Module& module, ValidationInfo& info) { // If the memory is imported we don't actually know its initial size. // Specifically wasm dll's import a zero sized memory which is perfectly // valid. - if (!curr.imported()) { - info.shouldBeTrue(size <= curr.initial * Memory::kPageSize, + if (!curr->imported()) { + info.shouldBeTrue(size <= curr->initial * Memory::kPageSize, segment->data.size(), "segment size should fit in memory (initial)"); } |