diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 225bb490752..51aa1fe352c 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -1678,6 +1678,20 @@ class WasmBinaryReader { uint8_t& pageSizeLog2, Address defaultIfNoMax); void readImports(); + void readImport(Name module, Name base, uint32_t kind); + + void addImport(std::unique_ptr func); + void addImport(std::unique_ptr table); + void addImport(std::unique_ptr memory); + void addImport(std::unique_ptr global); + void addImport(std::unique_ptr tag); + + std::unique_ptr + readFunctionImport(Name module, Name base, uint32_t kind); + std::unique_ptr
readTableImport(Name module, Name base); + std::unique_ptr readMemoryImport(Name module, Name base); + std::unique_ptr readGlobalImport(Name module, Name base); + std::unique_ptr readTagImport(Name module, Name base); // The signatures of each function, including imported functions, given in the // import and function sections. Store HeapTypes instead of Signatures because diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index c25553ed5f3..91f8e9824dd 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -3017,130 +3017,174 @@ void WasmBinaryReader::getResizableLimits(Address& initial, } } +void WasmBinaryReader::addImport(std::unique_ptr func) { + auto [name, isExplicit] = + getOrMakeName(functionNames, + wasm.functions.size(), + makeName("fimport$", wasm.functions.size()), + usedFunctionNames); + func->name = name; + func->hasExplicitName = isExplicit; + functionTypes.push_back(func->type.getHeapType()); + setLocalNames(*func, wasm.functions.size()); + wasm.addFunction(std::move(func)); +} + +void WasmBinaryReader::addImport(std::unique_ptr
table) { + auto [name, isExplicit] = + getOrMakeName(tableNames, + wasm.tables.size(), + makeName("timport$", wasm.tables.size()), + usedTableNames); + table->name = name; + table->hasExplicitName = isExplicit; + wasm.addTable(std::move(table)); +} + +void WasmBinaryReader::addImport(std::unique_ptr memory) { + auto [name, isExplicit] = + getOrMakeName(memoryNames, + wasm.memories.size(), + makeName("mimport$", wasm.memories.size()), + usedMemoryNames); + memory->name = name; + memory->hasExplicitName = isExplicit; + wasm.addMemory(std::move(memory)); +} + +void WasmBinaryReader::addImport(std::unique_ptr global) { + auto [name, isExplicit] = + getOrMakeName(globalNames, + wasm.globals.size(), + makeName("gimport$", wasm.globals.size()), + usedGlobalNames); + global->name = name; + global->hasExplicitName = isExplicit; + wasm.addGlobal(std::move(global)); +} + +void WasmBinaryReader::addImport(std::unique_ptr tag) { + auto [name, isExplicit] = + getOrMakeName(tagNames, + wasm.tags.size(), + makeName("eimport$", wasm.tags.size()), + usedTagNames); + tag->name = name; + tag->hasExplicitName = isExplicit; + wasm.addTag(std::move(tag)); +} + +std::unique_ptr +WasmBinaryReader::readFunctionImport(Name module, Name base, uint32_t kind) { + Builder builder(wasm); + auto index = getU32LEB(); + auto type = getTypeByIndex(index); + if (!type.isSignature()) { + throwError(std::string("Imported function ") + module.toString() + '.' + + base.toString() + + "'s type must be a signature. Given: " + type.toString()); + } + auto exact = (kind & BinaryConsts::ExactImport) ? Exact : Inexact; + auto curr = builder.makeFunction("", Type(type, NonNullable, exact), {}); + curr->module = module; + curr->base = base; + return curr; +} + +std::unique_ptr
WasmBinaryReader::readTableImport(Name module, + Name base) { + Builder builder(wasm); + auto table = builder.makeTable(""); + table->module = module; + table->base = base; + table->type = getType(); + + bool is_shared; + uint8_t page_size = 0xff; + getResizableLimits(table->initial, + table->max, + is_shared, + table->addressType, + page_size, + Table::kUnlimitedSize); + if (is_shared) { + throwError("Tables may not be shared"); + } + if (page_size != 0xff) { + throwError("Tables may not have a custom page size"); + } + return table; +} + +std::unique_ptr WasmBinaryReader::readMemoryImport(Name module, + Name base) { + Builder builder(wasm); + auto memory = builder.makeMemory(""); + memory->module = module; + memory->base = base; + getResizableLimits(memory->initial, + memory->max, + memory->shared, + memory->addressType, + memory->pageSizeLog2, + Memory::kUnlimitedSize); + return memory; +} + +std::unique_ptr WasmBinaryReader::readGlobalImport(Name module, + Name base) { + Builder builder(wasm); + auto type = getConcreteType(); + auto mutable_ = getU32LEB(); + if (mutable_ & ~1) { + throwError("Global mutability must be 0 or 1"); + } + auto curr = builder.makeGlobal( + "", type, nullptr, mutable_ ? Builder::Mutable : Builder::Immutable); + curr->module = module; + curr->base = base; + return curr; +} + +std::unique_ptr WasmBinaryReader::readTagImport(Name module, Name base) { + Builder builder(wasm); + getInt8(); // Reserved 'attribute' field + auto index = getU32LEB(); + auto curr = builder.makeTag("", getSignatureByTypeIndex(index)); + curr->module = module; + curr->base = base; + return curr; +} + +void WasmBinaryReader::readImport(Name module, Name base, uint32_t kind) { + switch (kind & ~BinaryConsts::ExactImport) { + case ExternalKind::Function: + addImport(readFunctionImport(module, base, kind)); + break; + case ExternalKind::Table: + addImport(readTableImport(module, base)); + break; + case ExternalKind::Memory: + addImport(readMemoryImport(module, base)); + break; + case ExternalKind::Global: + addImport(readGlobalImport(module, base)); + break; + case ExternalKind::Tag: + addImport(readTagImport(module, base)); + break; + default: + throwError("bad import kind"); + } +} + void WasmBinaryReader::readImports() { size_t num = getU32LEB(); - Builder builder(wasm); for (size_t i = 0; i < num; i++) { auto module = getInlineString(); auto base = getInlineString(); auto kind = getU32LEB(); - // We set a unique prefix for the name based on the kind. This ensures no - // collisions between them, which can't occur here (due to the index i) but - // could occur later due to the names section. - switch (kind) { - case ExternalKind::Function: - case ExternalKind::Function | BinaryConsts::ExactImport: { - auto [name, isExplicit] = - getOrMakeName(functionNames, - wasm.functions.size(), - makeName("fimport$", wasm.functions.size()), - usedFunctionNames); - auto index = getU32LEB(); - functionTypes.push_back(getTypeByIndex(index)); - auto type = getTypeByIndex(index); - if (!type.isSignature()) { - throwError(std::string("Imported function ") + module.toString() + - '.' + base.toString() + - "'s type must be a signature. Given: " + type.toString()); - } - auto exact = (kind & BinaryConsts::ExactImport) ? Exact : Inexact; - auto curr = - builder.makeFunction(name, Type(type, NonNullable, exact), {}); - curr->hasExplicitName = isExplicit; - curr->module = module; - curr->base = base; - setLocalNames(*curr, wasm.functions.size()); - wasm.addFunction(std::move(curr)); - break; - } - case ExternalKind::Table: { - auto [name, isExplicit] = - getOrMakeName(tableNames, - wasm.tables.size(), - makeName("timport$", wasm.tables.size()), - usedTableNames); - auto table = builder.makeTable(name); - table->hasExplicitName = isExplicit; - table->module = module; - table->base = base; - table->type = getType(); - bool is_shared; - uint8_t page_size = 0xff; - getResizableLimits(table->initial, - table->max, - is_shared, - table->addressType, - page_size, - Table::kUnlimitedSize); - if (is_shared) { - throwError("Tables may not be shared"); - } - if (page_size != 0xff) { - throwError("Tables may not have a custom page size"); - } - wasm.addTable(std::move(table)); - break; - } - case ExternalKind::Memory: { - auto [name, isExplicit] = - getOrMakeName(memoryNames, - wasm.memories.size(), - makeName("mimport$", wasm.memories.size()), - usedMemoryNames); - auto memory = builder.makeMemory(name); - memory->hasExplicitName = isExplicit; - memory->module = module; - memory->base = base; - getResizableLimits(memory->initial, - memory->max, - memory->shared, - memory->addressType, - memory->pageSizeLog2, - Memory::kUnlimitedSize); - wasm.addMemory(std::move(memory)); - break; - } - case ExternalKind::Global: { - auto [name, isExplicit] = - getOrMakeName(globalNames, - wasm.globals.size(), - makeName("gimport$", wasm.globals.size()), - usedGlobalNames); - auto type = getConcreteType(); - auto mutable_ = getU32LEB(); - if (mutable_ & ~1) { - throwError("Global mutability must be 0 or 1"); - } - auto curr = - builder.makeGlobal(name, - type, - nullptr, - mutable_ ? Builder::Mutable : Builder::Immutable); - curr->hasExplicitName = isExplicit; - curr->module = module; - curr->base = base; - wasm.addGlobal(std::move(curr)); - break; - } - case ExternalKind::Tag: { - auto [name, isExplicit] = - getOrMakeName(tagNames, - wasm.tags.size(), - makeName("eimport$", wasm.tags.size()), - usedTagNames); - getInt8(); // Reserved 'attribute' field - auto index = getU32LEB(); - auto curr = builder.makeTag(name, getSignatureByTypeIndex(index)); - curr->hasExplicitName = isExplicit; - curr->module = module; - curr->base = base; - wasm.addTag(std::move(curr)); - break; - } - default: { - throwError("bad import kind"); - } - } + readImport(module, base, kind); } numFuncImports = wasm.functions.size(); }