summaryrefslogtreecommitdiff
path: root/src/wasm
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm')
-rw-r--r--src/wasm/wasm-binary.cpp74
-rw-r--r--src/wasm/wasm-s-parser.cpp75
-rw-r--r--src/wasm/wasm-stack.cpp2
-rw-r--r--src/wasm/wasm-validator.cpp128
-rw-r--r--src/wasm/wasm.cpp7
5 files changed, 198 insertions, 88 deletions
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index e958dca6e..18a66fb2c 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -99,12 +99,11 @@ int32_t WasmBinaryWriter::writeU32LEBPlaceholder() {
return ret;
}
-void WasmBinaryWriter::writeResizableLimits(Address initial,
- Address maximum,
- bool hasMaximum,
- bool shared) {
+void WasmBinaryWriter::writeResizableLimits(
+ Address initial, Address maximum, bool hasMaximum, bool shared, bool is64) {
uint32_t flags = (hasMaximum ? (uint32_t)BinaryConsts::HasMaximum : 0U) |
- (shared ? (uint32_t)BinaryConsts::IsShared : 0U);
+ (shared ? (uint32_t)BinaryConsts::IsShared : 0U) |
+ (is64 ? (uint32_t)BinaryConsts::Is64 : 0U);
o << U32LEB(flags);
o << U32LEB(initial);
if (hasMaximum) {
@@ -203,7 +202,8 @@ void WasmBinaryWriter::writeMemory() {
writeResizableLimits(wasm->memory.initial,
wasm->memory.max,
wasm->memory.hasMax(),
- wasm->memory.shared);
+ wasm->memory.shared,
+ wasm->memory.is64());
finishSection(start);
}
@@ -267,7 +267,8 @@ void WasmBinaryWriter::writeImports() {
writeResizableLimits(wasm->memory.initial,
wasm->memory.max,
wasm->memory.hasMax(),
- wasm->memory.shared);
+ wasm->memory.shared,
+ wasm->memory.is64());
}
if (wasm->table.imported()) {
BYN_TRACE("write one table\n");
@@ -277,7 +278,8 @@ void WasmBinaryWriter::writeImports() {
writeResizableLimits(wasm->table.initial,
wasm->table.max,
wasm->table.hasMax(),
- /*shared=*/false);
+ /*shared=*/false,
+ /*is64*/ false);
}
finishSection(start);
}
@@ -505,7 +507,8 @@ void WasmBinaryWriter::writeFunctionTableDeclaration() {
writeResizableLimits(wasm->table.initial,
wasm->table.max,
wasm->table.hasMax(),
- /*shared=*/false);
+ /*shared=*/false,
+ /*is64*/ false);
finishSection(start);
}
@@ -752,6 +755,8 @@ void WasmBinaryWriter::writeFeaturesSection() {
return BinaryConsts::UserSections::MultivalueFeature;
case FeatureSet::GC:
return BinaryConsts::UserSections::GCFeature;
+ case FeatureSet::Memory64:
+ return BinaryConsts::UserSections::Memory64Feature;
default:
WASM_UNREACHABLE("unexpected feature flag");
}
@@ -1317,6 +1322,7 @@ void WasmBinaryBuilder::readMemory() {
getResizableLimits(wasm.memory.initial,
wasm.memory.max,
wasm.memory.shared,
+ wasm.memory.indexType,
Memory::kUnlimitedSize);
}
@@ -1370,15 +1376,18 @@ Name WasmBinaryBuilder::getEventName(Index index) {
void WasmBinaryBuilder::getResizableLimits(Address& initial,
Address& max,
bool& shared,
+ Type& indexType,
Address defaultIfNoMax) {
auto flags = getU32LEB();
initial = getU32LEB();
bool hasMax = (flags & BinaryConsts::HasMaximum) != 0;
bool isShared = (flags & BinaryConsts::IsShared) != 0;
+ bool is64 = (flags & BinaryConsts::Is64) != 0;
if (isShared && !hasMax) {
throwError("shared memory must have max size");
}
shared = isShared;
+ indexType = is64 ? Type::i64 : Type::i32;
if (hasMax) {
max = getU32LEB();
} else {
@@ -1425,11 +1434,18 @@ void WasmBinaryBuilder::readImports() {
}
wasm.table.exists = true;
bool is_shared;
- getResizableLimits(
- wasm.table.initial, wasm.table.max, is_shared, Table::kUnlimitedSize);
+ Type indexType;
+ getResizableLimits(wasm.table.initial,
+ wasm.table.max,
+ is_shared,
+ indexType,
+ Table::kUnlimitedSize);
if (is_shared) {
throwError("Tables may not be shared");
}
+ if (indexType == Type::i64) {
+ throwError("Tables may not be 64-bit");
+ }
break;
}
case ExternalKind::Memory: {
@@ -1440,6 +1456,7 @@ void WasmBinaryBuilder::readImports() {
getResizableLimits(wasm.memory.initial,
wasm.memory.max,
wasm.memory.shared,
+ wasm.memory.indexType,
Memory::kUnlimitedSize);
break;
}
@@ -2096,11 +2113,18 @@ void WasmBinaryBuilder::readFunctionTableDeclaration() {
throwError("ElementType must be funcref in MVP");
}
bool is_shared;
- getResizableLimits(
- wasm.table.initial, wasm.table.max, is_shared, Table::kUnlimitedSize);
+ Type indexType;
+ getResizableLimits(wasm.table.initial,
+ wasm.table.max,
+ is_shared,
+ indexType,
+ Table::kUnlimitedSize);
if (is_shared) {
throwError("Tables may not be shared");
}
+ if (indexType == Type::i64) {
+ throwError("Tables may not be 64-bit");
+ }
}
void WasmBinaryBuilder::readTableElements() {
@@ -2309,6 +2333,8 @@ void WasmBinaryBuilder::readFeatures(size_t payloadLen) {
wasm.features.setMultivalue();
} else if (name == BinaryConsts::UserSections::GCFeature) {
wasm.features.setGC();
+ } else if (name == BinaryConsts::UserSections::Memory64Feature) {
+ wasm.features.setMemory64();
}
}
}
@@ -2452,14 +2478,24 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) {
case BinaryConsts::BrOnExn:
visitBrOnExn((curr = allocator.alloc<BrOnExn>())->cast<BrOnExn>());
break;
- case BinaryConsts::MemorySize:
- visitMemorySize(
- (curr = allocator.alloc<MemorySize>())->cast<MemorySize>());
+ case BinaryConsts::MemorySize: {
+ auto size = allocator.alloc<MemorySize>();
+ if (wasm.memory.is64()) {
+ size->make64();
+ }
+ curr = size;
+ visitMemorySize(size);
break;
- case BinaryConsts::MemoryGrow:
- visitMemoryGrow(
- (curr = allocator.alloc<MemoryGrow>())->cast<MemoryGrow>());
+ }
+ case BinaryConsts::MemoryGrow: {
+ auto grow = allocator.alloc<MemoryGrow>();
+ if (wasm.memory.is64()) {
+ grow->make64();
+ }
+ curr = grow;
+ visitMemoryGrow(grow);
break;
+ }
case BinaryConsts::AtomicPrefix: {
code = static_cast<uint8_t>(getU32LEB());
if (maybeVisitLoad(curr, code, /*isAtomic=*/true)) {
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp
index 2883519f2..8bbcc9ac0 100644
--- a/src/wasm/wasm-s-parser.cpp
+++ b/src/wasm/wasm-s-parser.cpp
@@ -50,12 +50,13 @@ int unhex(char c) {
namespace wasm {
-static Address getCheckedAddress(const Element* s, const char* errorText) {
- uint64_t num = atoll(s->c_str());
- if (num > std::numeric_limits<Address::address_t>::max()) {
- throw ParseException(errorText, s->line, s->col);
+static Address getAddress(const Element* s) { return atoll(s->c_str()); }
+
+static void
+checkAddress(Address a, const char* errorText, const Element* errorElem) {
+ if (a > std::numeric_limits<Address::address32_t>::max()) {
+ throw ParseException(errorText, errorElem->line, errorElem->col);
}
- return num;
}
static bool elementStartsWith(Element& s, IString str) {
@@ -1023,12 +1024,18 @@ Expression* SExpressionWasmBuilder::makeDrop(Element& s) {
Expression* SExpressionWasmBuilder::makeMemorySize(Element& s) {
auto ret = allocator.alloc<MemorySize>();
+ if (wasm.memory.is64()) {
+ ret->make64();
+ }
ret->finalize();
return ret;
}
Expression* SExpressionWasmBuilder::makeMemoryGrow(Element& s) {
auto ret = allocator.alloc<MemoryGrow>();
+ if (wasm.memory.is64()) {
+ ret->make64();
+ }
ret->delta = parseExpression(s[1]);
ret->finalize();
return ret;
@@ -2007,18 +2014,40 @@ void SExpressionWasmBuilder::stringToBinary(const char* input,
data.resize(actual);
}
+Index SExpressionWasmBuilder::parseMemoryIndex(Element& s, Index i) {
+ if (i < s.size() && s[i]->isStr()) {
+ if (s[i]->str() == "i64") {
+ i++;
+ wasm.memory.indexType = Type::i64;
+ } else if (s[i]->str() == "i32") {
+ i++;
+ wasm.memory.indexType = Type::i32;
+ }
+ }
+ return i;
+}
+
Index SExpressionWasmBuilder::parseMemoryLimits(Element& s, Index i) {
- wasm.memory.initial = getCheckedAddress(s[i++], "excessive memory init");
+ i = parseMemoryIndex(s, i);
if (i == s.size()) {
- wasm.memory.max = Memory::kUnlimitedSize;
- return i;
+ throw ParseException("missing memory limits", s.line, s.col);
}
- uint64_t max = atoll(s[i]->c_str());
- if (max > Memory::kMaxSize) {
- throw ParseException("total memory must be <= 4GB", s[i]->line, s[i]->col);
+ auto initElem = s[i++];
+ wasm.memory.initial = getAddress(initElem);
+ if (!wasm.memory.is64()) {
+ checkAddress(wasm.memory.initial, "excessive memory init", initElem);
}
- wasm.memory.max = max;
- return ++i;
+ if (i == s.size()) {
+ wasm.memory.max = Memory::kUnlimitedSize;
+ } else {
+ auto maxElem = s[i++];
+ wasm.memory.max = getAddress(maxElem);
+ if (!wasm.memory.is64() && wasm.memory.max > Memory::kMaxSize32) {
+ throw ParseException(
+ "total memory must be <= 4GB", maxElem->line, maxElem->col);
+ }
+ }
+ return i;
}
void SExpressionWasmBuilder::parseMemory(Element& s, bool preParseImport) {
@@ -2031,6 +2060,7 @@ void SExpressionWasmBuilder::parseMemory(Element& s, bool preParseImport) {
if (s[i]->dollared()) {
wasm.memory.name = s[i++]->str();
}
+ i = parseMemoryIndex(s, i);
Name importModule, importBase;
if (s[i]->isList()) {
auto& inner = *s[i];
@@ -2057,8 +2087,9 @@ void SExpressionWasmBuilder::parseMemory(Element& s, bool preParseImport) {
throw ParseException("bad import ending", inner.line, inner.col);
}
// (memory (data ..)) format
+ auto j = parseMemoryIndex(inner, 1);
auto offset = allocator.alloc<Const>()->set(Literal(int32_t(0)));
- parseInnerData(*s[i], 1, offset, false);
+ parseInnerData(inner, j, offset, false);
wasm.memory.initial = wasm.memory.segments[0].data.size();
return;
}
@@ -2075,7 +2106,11 @@ void SExpressionWasmBuilder::parseMemory(Element& s, bool preParseImport) {
if (elementStartsWith(curr, DATA)) {
offsetValue = 0;
} else {
- offsetValue = getCheckedAddress(curr[j++], "excessive memory offset");
+ auto offsetElem = curr[j++];
+ offsetValue = getAddress(offsetElem);
+ if (!wasm.memory.is64()) {
+ checkAddress(offsetValue, "excessive memory offset", offsetElem);
+ }
}
const char* input = curr[j]->c_str();
auto* offset = allocator.alloc<Const>();
@@ -2263,12 +2298,14 @@ void SExpressionWasmBuilder::parseImport(Element& s) {
wasm.table.module = module;
wasm.table.base = base;
if (j < inner.size() - 1) {
- wasm.table.initial =
- getCheckedAddress(inner[j++], "excessive table init size");
+ auto initElem = inner[j++];
+ wasm.table.initial = getAddress(initElem);
+ checkAddress(wasm.table.initial, "excessive table init size", initElem);
}
if (j < inner.size() - 1) {
- wasm.table.max =
- getCheckedAddress(inner[j++], "excessive table max size");
+ auto maxElem = inner[j++];
+ wasm.table.max = getAddress(maxElem);
+ checkAddress(wasm.table.max, "excessive table max size", maxElem);
} else {
wasm.table.max = Table::kUnlimitedSize;
}
diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp
index edfdf31d1..30816546a 100644
--- a/src/wasm/wasm-stack.cpp
+++ b/src/wasm/wasm-stack.cpp
@@ -1907,7 +1907,7 @@ void StackIRGenerator::emitScopeEnd(Expression* curr) {
StackInst* StackIRGenerator::makeStackInst(StackInst::Op op,
Expression* origin) {
- auto* ret = allocator.alloc<StackInst>();
+ auto* ret = module.allocator.alloc<StackInst>();
ret->op = op;
ret->origin = origin;
auto stackType = origin->type;
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index c141fdd6f..505753c88 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -388,6 +388,8 @@ private:
void validateAlignment(
size_t align, Type type, Index bytes, bool isAtomic, Expression* curr);
void validateMemBytes(uint8_t bytes, Type type, Expression* curr);
+
+ Type indexType() { return getModule()->memory.indexType; }
};
void FunctionValidator::noteLabelName(Name name) {
@@ -931,7 +933,10 @@ void FunctionValidator::visitLoad(Load* curr) {
validateMemBytes(curr->bytes, curr->type, curr);
validateAlignment(curr->align, curr->type, curr->bytes, curr->isAtomic, curr);
shouldBeEqualOrFirstIsUnreachable(
- curr->ptr->type, Type(Type::i32), curr, "load pointer type must be i32");
+ curr->ptr->type,
+ indexType(),
+ curr,
+ "load pointer type must match memory index type");
if (curr->isAtomic) {
shouldBeFalse(curr->signed_, curr, "atomic loads must be unsigned");
shouldBeIntOrUnreachable(
@@ -963,7 +968,10 @@ void FunctionValidator::visitStore(Store* curr) {
validateAlignment(
curr->align, curr->valueType, curr->bytes, curr->isAtomic, curr);
shouldBeEqualOrFirstIsUnreachable(
- curr->ptr->type, Type(Type::i32), curr, "store pointer type must be i32");
+ curr->ptr->type,
+ indexType(),
+ curr,
+ "store pointer must match memory index type");
shouldBeUnequal(curr->value->type,
Type(Type::none),
curr,
@@ -986,10 +994,11 @@ void FunctionValidator::visitAtomicRMW(AtomicRMW* curr) {
curr,
"Atomic operation with non-shared memory");
validateMemBytes(curr->bytes, curr->type, curr);
- shouldBeEqualOrFirstIsUnreachable(curr->ptr->type,
- Type(Type::i32),
- curr,
- "AtomicRMW pointer type must be i32");
+ shouldBeEqualOrFirstIsUnreachable(
+ curr->ptr->type,
+ indexType(),
+ curr,
+ "AtomicRMW pointer type must match memory index type");
shouldBeEqualOrFirstIsUnreachable(curr->type,
curr->value->type,
curr,
@@ -1009,7 +1018,10 @@ void FunctionValidator::visitAtomicCmpxchg(AtomicCmpxchg* curr) {
"Atomic operation with non-shared memory");
validateMemBytes(curr->bytes, curr->type, curr);
shouldBeEqualOrFirstIsUnreachable(
- curr->ptr->type, Type(Type::i32), curr, "cmpxchg pointer type must be i32");
+ curr->ptr->type,
+ indexType(),
+ curr,
+ "cmpxchg pointer must match memory index type");
if (curr->expected->type != Type::unreachable &&
curr->replacement->type != Type::unreachable) {
shouldBeEqual(curr->expected->type,
@@ -1042,10 +1054,11 @@ void FunctionValidator::visitAtomicWait(AtomicWait* curr) {
"Atomic operation with non-shared memory");
shouldBeEqualOrFirstIsUnreachable(
curr->type, Type(Type::i32), curr, "AtomicWait must have type i32");
- shouldBeEqualOrFirstIsUnreachable(curr->ptr->type,
- Type(Type::i32),
- curr,
- "AtomicWait pointer type must be i32");
+ shouldBeEqualOrFirstIsUnreachable(
+ curr->ptr->type,
+ indexType(),
+ curr,
+ "AtomicWait pointer must match memory index type");
shouldBeIntOrUnreachable(
curr->expected->type, curr, "AtomicWait expected type must be int");
shouldBeEqualOrFirstIsUnreachable(
@@ -1070,10 +1083,11 @@ void FunctionValidator::visitAtomicNotify(AtomicNotify* curr) {
"Atomic operation with non-shared memory");
shouldBeEqualOrFirstIsUnreachable(
curr->type, Type(Type::i32), curr, "AtomicNotify must have type i32");
- shouldBeEqualOrFirstIsUnreachable(curr->ptr->type,
- Type(Type::i32),
- curr,
- "AtomicNotify pointer type must be i32");
+ shouldBeEqualOrFirstIsUnreachable(
+ curr->ptr->type,
+ indexType(),
+ curr,
+ "AtomicNotify pointer must match memory index type");
shouldBeEqualOrFirstIsUnreachable(
curr->notifyCount->type,
Type(Type::i32),
@@ -1230,10 +1244,11 @@ void FunctionValidator::visitSIMDLoad(SIMDLoad* curr) {
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,
- Type(Type::i32),
- curr,
- "load_splat address must have type i32");
+ shouldBeEqualOrFirstIsUnreachable(
+ curr->ptr->type,
+ indexType(),
+ curr,
+ "load_splat address must match memory index type");
Type memAlignType = Type::none;
switch (curr->op) {
case LoadSplatVec8x16:
@@ -1264,7 +1279,10 @@ void FunctionValidator::visitMemoryInit(MemoryInit* curr) {
shouldBeEqualOrFirstIsUnreachable(
curr->type, Type(Type::none), curr, "memory.init must have type none");
shouldBeEqualOrFirstIsUnreachable(
- curr->dest->type, Type(Type::i32), curr, "memory.init dest must be an i32");
+ curr->dest->type,
+ indexType(),
+ curr,
+ "memory.init dest must match memory index type");
shouldBeEqualOrFirstIsUnreachable(curr->offset->type,
Type(Type::i32),
curr,
@@ -1304,13 +1322,20 @@ void FunctionValidator::visitMemoryCopy(MemoryCopy* curr) {
shouldBeEqualOrFirstIsUnreachable(
curr->type, Type(Type::none), curr, "memory.copy must have type none");
shouldBeEqualOrFirstIsUnreachable(
- curr->dest->type, Type(Type::i32), curr, "memory.copy dest must be an i32");
- shouldBeEqualOrFirstIsUnreachable(curr->source->type,
- Type(Type::i32),
- curr,
- "memory.copy source must be an i32");
+ curr->dest->type,
+ indexType(),
+ curr,
+ "memory.copy dest must match memory index type");
+ shouldBeEqualOrFirstIsUnreachable(
+ curr->source->type,
+ indexType(),
+ curr,
+ "memory.copy source must match memory index type");
shouldBeEqualOrFirstIsUnreachable(
- curr->size->type, Type(Type::i32), curr, "memory.copy size must be an i32");
+ curr->size->type,
+ indexType(),
+ curr,
+ "memory.copy size must match memory index type");
shouldBeTrue(
getModule()->memory.exists, curr, "Memory operations require a memory");
}
@@ -1322,13 +1347,19 @@ void FunctionValidator::visitMemoryFill(MemoryFill* curr) {
shouldBeEqualOrFirstIsUnreachable(
curr->type, Type(Type::none), curr, "memory.fill must have type none");
shouldBeEqualOrFirstIsUnreachable(
- curr->dest->type, Type(Type::i32), curr, "memory.fill dest must be an i32");
+ curr->dest->type,
+ indexType(),
+ curr,
+ "memory.fill dest must match memory index type");
shouldBeEqualOrFirstIsUnreachable(curr->value->type,
Type(Type::i32),
curr,
"memory.fill value must be an i32");
shouldBeEqualOrFirstIsUnreachable(
- curr->size->type, Type(Type::i32), curr, "memory.fill size must be an i32");
+ curr->size->type,
+ indexType(),
+ curr,
+ "memory.fill size must match memory index type");
shouldBeTrue(
getModule()->memory.exists, curr, "Memory operations require a memory");
}
@@ -1907,9 +1938,9 @@ void FunctionValidator::visitMemoryGrow(MemoryGrow* curr) {
shouldBeTrue(
getModule()->memory.exists, curr, "Memory operations require a memory");
shouldBeEqualOrFirstIsUnreachable(curr->delta->type,
- Type(Type::i32),
+ indexType(),
curr,
- "memory.grow must have i32 operand");
+ "memory.grow must match memory index type");
}
void FunctionValidator::visitRefIsNull(RefIsNull* curr) {
@@ -2113,7 +2144,7 @@ void FunctionValidator::visitFunction(Function* curr) {
}
}
-static bool checkOffset(Expression* curr, Address add, Address max) {
+static bool checkSegmentOffset(Expression* curr, Address add, Address max) {
if (curr->is<GlobalGet>()) {
return true;
}
@@ -2122,10 +2153,10 @@ static bool checkOffset(Expression* curr, Address add, Address max) {
return false;
}
uint64_t raw = c->value.getInteger();
- if (raw > std::numeric_limits<Address::address_t>::max()) {
+ if (raw > std::numeric_limits<Address::address32_t>::max()) {
return false;
}
- if (raw + uint64_t(add) > std::numeric_limits<Address::address_t>::max()) {
+ if (raw + uint64_t(add) > std::numeric_limits<Address::address32_t>::max()) {
return false;
}
Address offset = raw;
@@ -2354,12 +2385,14 @@ static void validateMemory(Module& module, ValidationInfo& info) {
auto& curr = module.memory;
info.shouldBeFalse(
curr.initial > curr.max, "memory", "memory max >= initial");
- info.shouldBeTrue(curr.initial <= Memory::kMaxSize,
- "memory",
- "initial memory must be <= 4GB");
- info.shouldBeTrue(!curr.hasMax() || curr.max <= Memory::kMaxSize,
- "memory",
- "max memory must be <= 4GB, or unlimited");
+ if (!curr.is64()) {
+ info.shouldBeTrue(curr.initial <= Memory::kMaxSize32,
+ "memory",
+ "initial memory must be <= 4GB");
+ info.shouldBeTrue(!curr.hasMax() || curr.max <= Memory::kMaxSize32,
+ "memory",
+ "max memory must be <= 4GB, or unlimited");
+ }
info.shouldBeTrue(!curr.shared || curr.hasMax(),
"memory",
"shared memory must have max size");
@@ -2385,9 +2418,9 @@ static void validateMemory(Module& module, ValidationInfo& info) {
"segment offset should be i32")) {
continue;
}
- info.shouldBeTrue(checkOffset(segment.offset,
- segment.data.size(),
- curr.initial * Memory::kPageSize),
+ info.shouldBeTrue(checkSegmentOffset(segment.offset,
+ segment.data.size(),
+ curr.initial * Memory::kPageSize),
segment.offset,
"segment offset should be reasonable");
if (segment.offset->is<Const>()) {
@@ -2416,11 +2449,12 @@ static void validateTable(Module& module, ValidationInfo& info) {
Type(Type::i32),
segment.offset,
"segment offset should be i32");
- info.shouldBeTrue(checkOffset(segment.offset,
- segment.data.size(),
- module.table.initial * Table::kPageSize),
- segment.offset,
- "segment offset should be reasonable");
+ info.shouldBeTrue(
+ checkSegmentOffset(segment.offset,
+ segment.data.size(),
+ module.table.initial * Table::kPageSize),
+ segment.offset,
+ "segment offset should be reasonable");
for (auto name : segment.data) {
info.shouldBeTrue(
module.getFunctionOrNull(name), name, "segment name should be valid");
diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp
index 87488cfaf..6cc61a8a1 100644
--- a/src/wasm/wasm.cpp
+++ b/src/wasm/wasm.cpp
@@ -46,6 +46,7 @@ const char* TailCallFeature = "tail-call";
const char* ReferenceTypesFeature = "reference-types";
const char* MultivalueFeature = "multivalue";
const char* GCFeature = "gc";
+const char* Memory64Feature = "memory64";
} // namespace UserSections
} // namespace BinaryConsts
@@ -881,13 +882,15 @@ void Drop::finalize() {
}
}
-void MemorySize::finalize() { type = Type::i32; }
+void MemorySize::make64() { type = ptrType = Type::i64; }
+void MemorySize::finalize() { type = ptrType; }
+void MemoryGrow::make64() { type = ptrType = Type::i64; }
void MemoryGrow::finalize() {
if (delta->type == Type::unreachable) {
type = Type::unreachable;
} else {
- type = Type::i32;
+ type = ptrType;
}
}