summaryrefslogtreecommitdiff
path: root/src/wasm
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm')
-rw-r--r--src/wasm/wasm-binary.cpp272
-rw-r--r--src/wasm/wasm-emscripten.cpp89
-rw-r--r--src/wasm/wasm-s-parser.cpp166
-rw-r--r--src/wasm/wasm-validator.cpp63
-rw-r--r--src/wasm/wasm.cpp57
5 files changed, 254 insertions, 393 deletions
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index b643eaec8..1839c9cbd 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -35,6 +35,8 @@ void WasmBinaryWriter::prepare() {
ModuleUtils::BinaryIndexes indexes(*wasm);
mappedFunctions = std::move(indexes.functionIndexes);
mappedGlobals = std::move(indexes.globalIndexes);
+
+ importInfo = wasm::make_unique<ImportInfo>(*wasm);
}
void WasmBinaryWriter::write() {
@@ -136,7 +138,7 @@ void WasmBinaryWriter::writeStart() {
}
void WasmBinaryWriter::writeMemory() {
- if (!wasm->memory.exists || wasm->memory.imported) return;
+ if (!wasm->memory.exists || wasm->memory.imported()) return;
if (debug) std::cerr << "== writeMemory" << std::endl;
auto start = startSection(BinaryConsts::Section::Memory);
o << U32LEB(1); // Define 1 memory
@@ -176,46 +178,54 @@ int32_t WasmBinaryWriter::getFunctionTypeIndex(Name type) {
}
void WasmBinaryWriter::writeImports() {
- if (wasm->imports.size() == 0) return;
+ auto num = importInfo->getNumImports();
+ if (num == 0) return;
if (debug) std::cerr << "== writeImports" << std::endl;
auto start = startSection(BinaryConsts::Section::Import);
- o << U32LEB(wasm->imports.size());
- for (auto& import : wasm->imports) {
- if (debug) std::cerr << "write one" << std::endl;
+ o << U32LEB(num);
+ auto writeImportHeader = [&](Importable* import) {
writeInlineString(import->module.str);
writeInlineString(import->base.str);
- o << U32LEB(int32_t(import->kind));
- switch (import->kind) {
- case ExternalKind::Function: o << U32LEB(getFunctionTypeIndex(import->functionType)); break;
- case ExternalKind::Table: {
- o << S32LEB(BinaryConsts::EncodedType::AnyFunc);
- writeResizableLimits(wasm->table.initial, wasm->table.max, wasm->table.max != Table::kMaxSize, /*shared=*/false);
- break;
- }
- case ExternalKind::Memory: {
- writeResizableLimits(wasm->memory.initial, wasm->memory.max,
- wasm->memory.max != Memory::kMaxSize, wasm->memory.shared);
- break;
- }
- case ExternalKind::Global:
- o << binaryType(import->globalType);
- o << U32LEB(0); // Mutable global's can't be imported for now.
- break;
- default: WASM_UNREACHABLE();
- }
+ };
+ ModuleUtils::iterImportedFunctions(*wasm, [&](Function* func) {
+ if (debug) std::cerr << "write one function" << std::endl;
+ writeImportHeader(func);
+ o << U32LEB(int32_t(ExternalKind::Function));
+ o << U32LEB(getFunctionTypeIndex(func->type));
+ });
+ ModuleUtils::iterImportedGlobals(*wasm, [&](Global* global) {
+ if (debug) std::cerr << "write one global" << std::endl;
+ writeImportHeader(global);
+ o << U32LEB(int32_t(ExternalKind::Global));
+ o << binaryType(global->type);
+ o << U32LEB(0); // Mutable globals can't be imported for now.
+ });
+ if (wasm->memory.imported()) {
+ if (debug) std::cerr << "write one memory" << std::endl;
+ writeImportHeader(&wasm->memory);
+ o << U32LEB(int32_t(ExternalKind::Memory));
+ writeResizableLimits(wasm->memory.initial, wasm->memory.max,
+ wasm->memory.max != Memory::kMaxSize, wasm->memory.shared);
+ }
+ if (wasm->table.imported()) {
+ if (debug) std::cerr << "write one table" << std::endl;
+ writeImportHeader(&wasm->table);
+ o << U32LEB(int32_t(ExternalKind::Table));
+ o << S32LEB(BinaryConsts::EncodedType::AnyFunc);
+ writeResizableLimits(wasm->table.initial, wasm->table.max, wasm->table.max != Table::kMaxSize, /*shared=*/false);
}
finishSection(start);
}
void WasmBinaryWriter::writeFunctionSignatures() {
- if (wasm->functions.size() == 0) return;
+ if (importInfo->getNumDefinedFunctions() == 0) return;
if (debug) std::cerr << "== writeFunctionSignatures" << std::endl;
auto start = startSection(BinaryConsts::Section::Function);
- o << U32LEB(wasm->functions.size());
- for (auto& curr : wasm->functions) {
+ o << U32LEB(importInfo->getNumDefinedFunctions());
+ ModuleUtils::iterDefinedFunctions(*wasm, [&](Function* func) {
if (debug) std::cerr << "write one" << std::endl;
- o << U32LEB(getFunctionTypeIndex(curr->type));
- }
+ o << U32LEB(getFunctionTypeIndex(func->type));
+ });
finishSection(start);
}
@@ -224,17 +234,15 @@ void WasmBinaryWriter::writeExpression(Expression* curr) {
}
void WasmBinaryWriter::writeFunctions() {
- if (wasm->functions.size() == 0) return;
+ if (importInfo->getNumDefinedFunctions() == 0) return;
if (debug) std::cerr << "== writeFunctions" << std::endl;
auto start = startSection(BinaryConsts::Section::Code);
- size_t total = wasm->functions.size();
- o << U32LEB(total);
- for (size_t i = 0; i < total; i++) {
+ o << U32LEB(importInfo->getNumDefinedFunctions());
+ ModuleUtils::iterDefinedFunctions(*wasm, [&](Function* func) {
size_t sourceMapLocationsSizeAtFunctionStart = sourceMapLocations.size();
if (debug) std::cerr << "write one at" << o.size() << std::endl;
size_t sizePos = writeU32LEBPlaceholder();
size_t start = o.size();
- Function* func = wasm->functions[i].get();
if (debug) std::cerr << "writing" << func->name << std::endl;
// Emit Stack IR if present, and if we can
if (func->stackIR && !sourceMap) {
@@ -261,22 +269,23 @@ void WasmBinaryWriter::writeFunctions() {
}
}
tableOfContents.functionBodies.emplace_back(func->name, sizePos + sizeFieldSize, size);
- }
+ });
finishSection(start);
}
void WasmBinaryWriter::writeGlobals() {
- if (wasm->globals.size() == 0) return;
+ if (importInfo->getNumDefinedGlobals() == 0) return;
if (debug) std::cerr << "== writeglobals" << std::endl;
auto start = startSection(BinaryConsts::Section::Global);
- o << U32LEB(wasm->globals.size());
- for (auto& curr : wasm->globals) {
+ auto num = importInfo->getNumDefinedGlobals();
+ o << U32LEB(num);
+ ModuleUtils::iterDefinedGlobals(*wasm, [&](Global* global) {
if (debug) std::cerr << "write one" << std::endl;
- o << binaryType(curr->type);
- o << U32LEB(curr->mutable_);
- writeExpression(curr->init);
+ o << binaryType(global->type);
+ o << U32LEB(global->mutable_);
+ writeExpression(global->init);
o << int8_t(BinaryConsts::End);
- }
+ });
finishSection(start);
}
@@ -404,7 +413,7 @@ uint32_t WasmBinaryWriter::getGlobalIndex(Name name) {
}
void WasmBinaryWriter::writeFunctionTableDeclaration() {
- if (!wasm->table.exists || wasm->table.imported) return;
+ if (!wasm->table.exists || wasm->table.imported()) return;
if (debug) std::cerr << "== writeFunctionTableDeclaration" << std::endl;
auto start = startSection(BinaryConsts::Section::Table);
o << U32LEB(1); // Declare 1 table.
@@ -436,14 +445,6 @@ void WasmBinaryWriter::writeNames() {
if (wasm->functions.size() > 0) {
hasContents = true;
getFunctionIndex(wasm->functions[0]->name); // generate mappedFunctions
- } else {
- for (auto& import : wasm->imports) {
- if (import->kind == ExternalKind::Function) {
- hasContents = true;
- getFunctionIndex(import->name); // generate mappedFunctions
- break;
- }
- }
}
if (!hasContents) return;
if (debug) std::cerr << "== writeNames" << std::endl;
@@ -452,18 +453,13 @@ void WasmBinaryWriter::writeNames() {
auto substart = startSubsection(BinaryConsts::UserSections::Subsection::NameFunction);
o << U32LEB(mappedFunctions.size());
Index emitted = 0;
- for (auto& import : wasm->imports) {
- if (import->kind == ExternalKind::Function) {
- o << U32LEB(emitted);
- writeEscapedName(import->name.str);
- emitted++;
- }
- }
- for (auto& curr : wasm->functions) {
+ auto add = [&](Function* curr) {
o << U32LEB(emitted);
writeEscapedName(curr->name.str);
emitted++;
- }
+ };
+ ModuleUtils::iterImportedFunctions(*wasm, add);
+ ModuleUtils::iterDefinedFunctions(*wasm, add);
assert(emitted == mappedFunctions.size());
finishSubsection(substart);
/* TODO: locals */
@@ -480,14 +476,11 @@ void WasmBinaryWriter::writeSourceMapUrl() {
void WasmBinaryWriter::writeSymbolMap() {
std::ofstream file(symbolMap);
- for (auto& import : wasm->imports) {
- if (import->kind == ExternalKind::Function) {
- file << getFunctionIndex(import->name) << ":" << import->name.str << std::endl;
- }
- }
- for (auto& func : wasm->functions) {
+ auto write = [&](Function* func) {
file << getFunctionIndex(func->name) << ":" << func->name.str << std::endl;
- }
+ };
+ ModuleUtils::iterImportedFunctions(*wasm, write);
+ ModuleUtils::iterDefinedFunctions(*wasm, write);
file.close();
}
@@ -940,17 +933,7 @@ void WasmBinaryBuilder::readSignatures() {
}
Name WasmBinaryBuilder::getFunctionIndexName(Index i) {
- if (i < functionImports.size()) {
- auto* import = functionImports[i];
- assert(import->kind == ExternalKind::Function);
- return import->name;
- } else {
- i -= functionImports.size();
- if (i >= wasm.functions.size()) {
- throwError("bad function index");
- }
- return wasm.functions[i]->name;
- }
+ return wasm.functions[i]->name;
}
void WasmBinaryBuilder::getResizableLimits(Address& initial, Address& max, bool &shared, Address defaultIfNoMax) {
@@ -968,61 +951,69 @@ void WasmBinaryBuilder::readImports() {
if (debug) std::cerr << "== readImports" << std::endl;
size_t num = getU32LEB();
if (debug) std::cerr << "num: " << num << std::endl;
+ Builder builder(wasm);
for (size_t i = 0; i < num; i++) {
if (debug) std::cerr << "read one" << std::endl;
- auto curr = new Import;
- curr->module = getInlineString();
- curr->base = getInlineString();
- curr->kind = (ExternalKind)getU32LEB();
+ auto module = getInlineString();
+ auto base = getInlineString();
+ auto kind = (ExternalKind)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 (curr->kind) {
+ switch (kind) {
case ExternalKind::Function: {
- curr->name = Name(std::string("fimport$") + std::to_string(i));
+ auto name = Name(std::string("fimport$") + std::to_string(i));
auto index = getU32LEB();
if (index >= wasm.functionTypes.size()) {
throwError("invalid function index " + std::to_string(index) + " / " + std::to_string(wasm.functionTypes.size()));
}
- curr->functionType = wasm.functionTypes[index]->name;
- assert(curr->functionType.is());
+ auto* functionType = wasm.functionTypes[index].get();
+ auto params = functionType->params;
+ auto result = functionType->result;
+ auto* curr = builder.makeFunction(name, std::move(params), result, {});
+ curr->module = module;
+ curr->base = base;
+ curr->type = functionType->name;
+ wasm.addFunction(curr);
functionImports.push_back(curr);
- continue; // don't add the import yet, we add them later after we know their names
break;
}
case ExternalKind::Table: {
- curr->name = Name(std::string("timport$") + std::to_string(i));
+ wasm.table.module = module;
+ wasm.table.base = base;
+ wasm.table.name = Name(std::string("timport$") + std::to_string(i));
auto elementType = getS32LEB();
WASM_UNUSED(elementType);
if (elementType != BinaryConsts::EncodedType::AnyFunc) throwError("Imported table type is not AnyFunc");
wasm.table.exists = true;
- wasm.table.imported = true;
bool is_shared;
getResizableLimits(wasm.table.initial, wasm.table.max, is_shared, Table::kMaxSize);
if (is_shared) throwError("Tables may not be shared");
break;
}
case ExternalKind::Memory: {
- curr->name = Name(std::string("mimport$") + std::to_string(i));
+ wasm.memory.module = module;
+ wasm.memory.base = base;
+ wasm.memory.name = Name(std::to_string(i));
wasm.memory.exists = true;
- wasm.memory.imported = true;
getResizableLimits(wasm.memory.initial, wasm.memory.max, wasm.memory.shared, Memory::kMaxSize);
break;
}
case ExternalKind::Global: {
- curr->name = Name(std::string("gimport$") + std::to_string(i));
- curr->globalType = getConcreteType();
- auto globalMutable = getU32LEB();
- // TODO: actually use the globalMutable flag. Currently mutable global
- // imports is a future feature, to be implemented with thread support.
- (void)globalMutable;
+ auto name = Name(std::string("gimport$") + std::to_string(i));
+ auto type = getConcreteType();
+ auto mutable_ = getU32LEB();
+ assert(!mutable_); // for now, until mutable globals
+ auto* curr = builder.makeGlobal(name, type, nullptr, mutable_ ? Builder::Mutable : Builder::Immutable);
+ curr->module = module;
+ curr->base = base;
+ wasm.addGlobal(curr);
break;
}
default: {
throwError("bad import kind");
}
}
- wasm.addImport(curr);
}
}
@@ -1332,7 +1323,7 @@ void WasmBinaryBuilder::readGlobals() {
if (mutable_ & ~1) throwError("Global mutability must be 0 or 1");
auto* init = readExpression();
wasm.addGlobal(Builder::makeGlobal(
- "global$" + std::to_string(wasm.globals.size()),
+ "global$" + std::to_string(i),
type,
init,
mutable_ ? Builder::Mutable : Builder::Immutable
@@ -1460,15 +1451,12 @@ Expression* WasmBinaryBuilder::popNonVoidExpression() {
Name WasmBinaryBuilder::getGlobalName(Index index) {
if (!mappedGlobals.size()) {
// Create name => index mapping.
- for (auto& import : wasm.imports) {
- if (import->kind != ExternalKind::Global) continue;
- auto index = mappedGlobals.size();
- mappedGlobals[index] = import->name;
- }
- for (size_t i = 0; i < wasm.globals.size(); i++) {
+ auto add = [&](Global* curr) {
auto index = mappedGlobals.size();
- mappedGlobals[index] = wasm.globals[i]->name;
- }
+ mappedGlobals[index] = curr->name;
+ };
+ ModuleUtils::iterImportedGlobals(wasm, add);
+ ModuleUtils::iterDefinedGlobals(wasm, add);
}
if (index == Index(-1)) return Name("null"); // just a force-rebuild
if (mappedGlobals.count(index) == 0) {
@@ -1482,17 +1470,6 @@ void WasmBinaryBuilder::processFunctions() {
wasm.addFunction(func);
}
- for (auto* import : functionImports) {
- wasm.addImport(import);
- }
-
- // we should have seen all the functions
- // we assume this later down in fact, when we read wasm.functions[index],
- // as index was validated vs functionTypes.size()
- if (wasm.functions.size() != functionTypes.size()) {
- throwError("did not see the right number of functions");
- }
-
// now that we have names for each function, apply things
if (startIndex != static_cast<Index>(-1)) {
@@ -1518,15 +1495,7 @@ void WasmBinaryBuilder::processFunctions() {
size_t index = iter.first;
auto& calls = iter.second;
for (auto* call : calls) {
- call->target = wasm.functions[index]->name;
- }
- }
-
- for (auto& iter : functionImportCalls) {
- size_t index = iter.first;
- auto& calls = iter.second;
- for (auto* call : calls) {
- call->target = functionImports[index]->name;
+ call->target = getFunctionIndexName(index);
}
}
@@ -1537,6 +1506,10 @@ void WasmBinaryBuilder::processFunctions() {
wasm.table.segments[i].data.push_back(getFunctionIndexName(j));
}
}
+
+ // Everything now has its proper name.
+
+ wasm.updateMaps();
}
void WasmBinaryBuilder::readDataSegments() {
@@ -1689,7 +1662,7 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) {
case BinaryConsts::Br:
case BinaryConsts::BrIf: visitBreak((curr = allocator.alloc<Break>())->cast<Break>(), code); break; // code distinguishes br from br_if
case BinaryConsts::TableSwitch: visitSwitch((curr = allocator.alloc<Switch>())->cast<Switch>()); break;
- case BinaryConsts::CallFunction: curr = visitCall(); break; // we don't know if it's a call or call_import yet
+ case BinaryConsts::CallFunction: visitCall((curr = allocator.alloc<Call>())->cast<Call>()); break;
case BinaryConsts::CallIndirect: visitCallIndirect((curr = allocator.alloc<CallIndirect>())->cast<CallIndirect>()); break;
case BinaryConsts::GetLocal: visitGetLocal((curr = allocator.alloc<GetLocal>())->cast<GetLocal>()); break;
case BinaryConsts::TeeLocal:
@@ -1928,35 +1901,26 @@ void WasmBinaryBuilder::visitSwitch(Switch* curr) {
curr->finalize();
}
-Expression* WasmBinaryBuilder::visitCall() {
+void WasmBinaryBuilder::visitCall(Call* curr) {
if (debug) std::cerr << "zz node: Call" << std::endl;
auto index = getU32LEB();
FunctionType* type;
- Expression* ret;
if (index < functionImports.size()) {
- // this is a call of an imported function
- auto* call = allocator.alloc<CallImport>();
auto* import = functionImports[index];
- type = wasm.getFunctionType(import->functionType);
- functionImportCalls[index].push_back(call);
- call->target = import->name; // name section may modify it
- fillCall(call, type);
- call->finalize();
- ret = call;
+ type = wasm.getFunctionType(import->type);
} else {
- // this is a call of a defined function
- auto* call = allocator.alloc<Call>();
auto adjustedIndex = index - functionImports.size();
- if (adjustedIndex >= functionTypes.size()) {
- throwError("bad call index");
- }
type = functionTypes[adjustedIndex];
- fillCall(call, type);
- functionCalls[adjustedIndex].push_back(call); // we don't know function names yet
- call->finalize();
- ret = call;
}
- return ret;
+ assert(type);
+ auto num = type->params.size();
+ curr->operands.resize(num);
+ for (size_t i = 0; i < num; i++) {
+ curr->operands[num - i - 1] = popNonVoidExpression();
+ }
+ curr->type = type->result;
+ functionCalls[index].push_back(curr); // we don't know function names yet
+ curr->finalize();
}
void WasmBinaryBuilder::visitCallIndirect(CallIndirect* curr) {
@@ -2007,17 +1971,7 @@ void WasmBinaryBuilder::visitGetGlobal(GetGlobal* curr) {
if (debug) std::cerr << "zz node: GetGlobal " << pos << std::endl;
auto index = getU32LEB();
curr->name = getGlobalName(index);
- auto* global = wasm.getGlobalOrNull(curr->name);
- if (global) {
- curr->type = global->type;
- return;
- }
- auto* import = wasm.getImportOrNull(curr->name);
- if (import && import->kind == ExternalKind::Global) {
- curr->type = import->globalType;
- return;
- }
- throwError("bad get_global");
+ curr->type = wasm.getGlobal(curr->name)->type;
}
void WasmBinaryBuilder::visitSetGlobal(SetGlobal* curr) {
diff --git a/src/wasm/wasm-emscripten.cpp b/src/wasm/wasm-emscripten.cpp
index 65d385870..635b5dfc5 100644
--- a/src/wasm/wasm-emscripten.cpp
+++ b/src/wasm/wasm-emscripten.cpp
@@ -24,6 +24,8 @@
#include "wasm-builder.h"
#include "wasm-traversal.h"
#include "wasm.h"
+#include "ir/function-type-utils.h"
+#include "ir/module-utils.h"
namespace wasm {
@@ -181,12 +183,7 @@ void EmscriptenGlueGenerator::generateDynCallThunks() {
if (indirectFunc == dummyFunction) {
continue;
}
- std::string sig;
- if (auto import = wasm.getImportOrNull(indirectFunc)) {
- sig = getSig(wasm.getFunctionType(import->functionType));
- } else {
- sig = getSig(wasm.getFunction(indirectFunc));
- }
+ std::string sig = getSig(wasm.getFunction(indirectFunc));
auto* funcType = ensureFunctionType(sig, &wasm);
if (hasI64ResultOrParam(funcType)) continue; // Can't export i64s on the web.
if (!sigs.insert(sig).second) continue; // Sig is already in the set
@@ -269,12 +266,12 @@ void EmscriptenGlueGenerator::generateJSCallThunks(
// function would have signature 'vii'.)
std::string importSig = std::string(1, sig[0]) + 'i' + sig.substr(1);
FunctionType *importType = ensureFunctionType(importSig, &wasm);
- auto import = new Import;
+ auto import = new Function;
import->name = import->base = "jsCall_" + sig;
import->module = ENV;
- import->functionType = importType->name;
- import->kind = ExternalKind::Function;
- wasm.addImport(import);
+ import->type = importType->name;
+ FunctionTypeUtils::fillFunction(import, importType);
+ wasm.addFunction(import);
FunctionType *funcType = ensureFunctionType(sig, &wasm);
// Create jsCall_sig_index thunks (e.g. jsCall_vi_0, jsCall_vi_1, ...)
@@ -297,7 +294,7 @@ void EmscriptenGlueGenerator::generateJSCallThunks(
args.push_back(builder.makeGetLocal(i, funcType->params[i]));
}
Expression* call =
- builder.makeCallImport(import->name, args, funcType->result);
+ builder.makeCall(import->name, args, funcType->result);
f->body = call;
wasm.addFunction(f);
tableSegmentData.push_back(f->name);
@@ -378,7 +375,7 @@ struct AsmConstWalker : public PostWalker<AsmConstWalker> {
: wasm(_wasm),
segmentOffsets(getSegmentOffsets(wasm)) { }
- void visitCallImport(CallImport* curr);
+ void visitCall(Call* curr);
private:
Literal idLiteralForCode(std::string code);
@@ -387,9 +384,9 @@ private:
void addImport(Name importName, std::string baseSig);
};
-void AsmConstWalker::visitCallImport(CallImport* curr) {
- Import* import = wasm.getImport(curr->target);
- if (import->base.hasSubstring(EMSCRIPTEN_ASM_CONST)) {
+void AsmConstWalker::visitCall(Call* curr) {
+ auto* import = wasm.getFunction(curr->target);
+ if (import->imported() && import->base.hasSubstring(EMSCRIPTEN_ASM_CONST)) {
auto arg = curr->operands[0]->cast<Const>();
auto code = codeForConstAddr(wasm, segmentOffsets, arg);
arg->value = idLiteralForCode(code);
@@ -434,20 +431,19 @@ Name AsmConstWalker::nameForImportWithSig(std::string sig) {
}
void AsmConstWalker::addImport(Name importName, std::string baseSig) {
- auto import = new Import;
+ auto import = new Function;
import->name = import->base = importName;
import->module = ENV;
- import->functionType = ensureFunctionType(baseSig, &wasm)->name;
- import->kind = ExternalKind::Function;
- wasm.addImport(import);
+ import->type = ensureFunctionType(baseSig, &wasm)->name;
+ wasm.addFunction(import);
}
AsmConstWalker fixEmAsmConstsAndReturnWalker(Module& wasm) {
// Collect imports to remove
// This would find our generated functions if we ran it later
std::vector<Name> toRemove;
- for (auto& import : wasm.imports) {
- if (import->base.hasSubstring(EMSCRIPTEN_ASM_CONST)) {
+ for (auto& import : wasm.functions) {
+ if (import->imported() && import->base.hasSubstring(EMSCRIPTEN_ASM_CONST)) {
toRemove.push_back(import->name);
}
}
@@ -458,7 +454,7 @@ AsmConstWalker fixEmAsmConstsAndReturnWalker(Module& wasm) {
// Remove the base functions that we didn't generate
for (auto importName : toRemove) {
- wasm.removeImport(importName);
+ wasm.removeFunction(importName);
}
return walker;
}
@@ -590,19 +586,21 @@ struct FixInvokeFunctionNamesWalker : public PostWalker<FixInvokeFunctionNamesWa
return fixEmExceptionInvoke(name, sig);
}
- void visitImport(Import* curr) {
- if (curr->kind != ExternalKind::Function)
+ void visitFunction(Function* curr) {
+ if (!curr->imported()) {
return;
+ }
- FunctionType* func = wasm.getFunctionType(curr->functionType);
+ FunctionType* func = wasm.getFunctionType(curr->type);
Name newname = fixEmEHSjLjNames(curr->base, getSig(func));
- if (newname == curr->base)
+ if (newname == curr->base) {
return;
+ }
assert(importRenames.count(curr->name) == 0);
importRenames[curr->name] = newname;
// Either rename or remove the existing import
- if (wasm.getImportOrNull(newname) || !newImports.insert(newname).second) {
+ if (wasm.getFunctionOrNull(newname) || !newImports.insert(newname).second) {
toRemove.push_back(curr->name);
} else {
curr->base = newname;
@@ -621,16 +619,18 @@ struct FixInvokeFunctionNamesWalker : public PostWalker<FixInvokeFunctionNamesWa
}
}
- void visitCallImport(CallImport* curr) {
- auto it = importRenames.find(curr->target);
- if (it != importRenames.end()) {
- curr->target = it->second;
+ void visitCall(Call* curr) {
+ if (wasm.getFunction(curr->target)->imported()) {
+ auto it = importRenames.find(curr->target);
+ if (it != importRenames.end()) {
+ curr->target = it->second;
+ }
}
}
void visitModule(Module* curr) {
for (auto importName : toRemove) {
- wasm.removeImport(importName);
+ wasm.removeFunction(importName);
}
wasm.updateMaps();
}
@@ -731,25 +731,23 @@ std::string EmscriptenGlueGenerator::generateEmscriptenMetadata(
// see.
meta << ", \"declares\": [";
commaFirst = true;
- for (const auto& import : wasm.imports) {
- if (import->kind == ExternalKind::Function &&
- (emJsWalker.codeByName.count(import->base.str) == 0) &&
+ ModuleUtils::iterImportedFunctions(wasm, [&](Function* import) {
+ if (emJsWalker.codeByName.count(import->base.str) == 0 &&
!import->base.startsWith(EMSCRIPTEN_ASM_CONST.str) &&
!import->base.startsWith("invoke_") &&
!import->base.startsWith("jsCall_")) {
- if (declares.insert(import->base.str).second)
+ if (declares.insert(import->base.str).second) {
meta << maybeComma() << '"' << import->base.str << '"';
+ }
}
- }
+ });
meta << "]";
meta << ", \"externs\": [";
commaFirst = true;
- for (const auto& import : wasm.imports) {
- if (import->kind == ExternalKind::Global) {
- meta << maybeComma() << "\"_" << import->base.str << '"';
- }
- }
+ ModuleUtils::iterImportedGlobals(wasm, [&](Global* import) {
+ meta << maybeComma() << "\"_" << import->base.str << '"';
+ });
meta << "]";
meta << ", \"implementedFunctions\": [";
@@ -770,12 +768,13 @@ std::string EmscriptenGlueGenerator::generateEmscriptenMetadata(
meta << ", \"invokeFuncs\": [";
commaFirst = true;
- for (const auto& import : wasm.imports) {
+ ModuleUtils::iterImportedFunctions(wasm, [&](Function* import) {
if (import->base.startsWith("invoke_")) {
- if (invokeFuncs.insert(import->base.str).second)
+ if (invokeFuncs.insert(import->base.str).second) {
meta << maybeComma() << '"' << import->base.str << '"';
+ }
}
- }
+ });
meta << "]";
meta << " }\n";
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp
index e4c171b5c..7085666bb 100644
--- a/src/wasm/wasm-s-parser.cpp
+++ b/src/wasm/wasm-s-parser.cpp
@@ -23,6 +23,7 @@
#include "asm_v_wasm.h"
#include "asmjs/shared-constants.h"
#include "ir/branch-utils.h"
+#include "ir/function-type-utils.h"
#include "shared-constants.h"
#include "wasm-binary.h"
#include "wasm-builder.h"
@@ -581,14 +582,15 @@ void SExpressionWasmBuilder::parseFunction(Element& s, bool preParseImport) {
if (importModule.is()) {
// this is an import, actually
if (!preParseImport) throw ParseException("!preParseImport in func");
- std::unique_ptr<Import> im = make_unique<Import>();
+ auto im = make_unique<Function>();
im->name = name;
im->module = importModule;
im->base = importBase;
- im->kind = ExternalKind::Function;
- im->functionType = wasm.getFunctionType(type)->name;
- if (wasm.getImportOrNull(im->name)) throw ParseException("duplicate import", s.line, s.col);
- wasm.addImport(im.release());
+ im->type = type;
+ FunctionTypeUtils::fillFunction(im.get(), wasm.getFunctionType(type));
+ functionTypes[name] = im->result;
+ if (wasm.getFunctionOrNull(im->name)) throw ParseException("duplicate import", s.line, s.col);
+ wasm.addFunction(im.release());
if (currFunction) throw ParseException("import module inside function dec");
currLocalTypes.clear();
nameMapper.clear();
@@ -821,7 +823,6 @@ Expression* SExpressionWasmBuilder::makeExpression(Element& s) {
case 'c': {
if (str[1] == 'a') {
if (id == CALL) return makeCall(s);
- if (id == CALL_IMPORT) return makeCallImport(s);
if (id == CALL_INDIRECT) return makeCallIndirect(s);
} else if (str[1] == 'u') return makeHost(s, HostOp::CurrentMemory);
abort_on(str);
@@ -1040,16 +1041,11 @@ Expression* SExpressionWasmBuilder::makeGetGlobal(Element& s) {
auto ret = allocator.alloc<GetGlobal>();
ret->name = getGlobalName(*s[1]);
auto* global = wasm.getGlobalOrNull(ret->name);
- if (global) {
- ret->type = global->type;
- return ret;
+ if (!global) {
+ throw ParseException("bad get_global name", s.line, s.col);
}
- auto* import = wasm.getImportOrNull(ret->name);
- if (import && import->kind == ExternalKind::Global) {
- ret->type = import->globalType;
- return ret;
- }
- throw ParseException("bad get_global name", s.line, s.col);
+ ret->type = global->type;
+ return ret;
}
Expression* SExpressionWasmBuilder::makeSetGlobal(Element& s) {
@@ -1377,15 +1373,6 @@ Expression* SExpressionWasmBuilder::makeLoop(Element& s) {
Expression* SExpressionWasmBuilder::makeCall(Element& s) {
auto target = getFunctionName(*s[1]);
- auto* import = wasm.getImportOrNull(target);
- if (import && import->kind == ExternalKind::Function) {
- auto ret = allocator.alloc<CallImport>();
- ret->target = target;
- Import* import = wasm.getImport(ret->target);
- ret->type = wasm.getFunctionType(import->functionType)->result;
- parseCallOperands(s, 2, s.size(), ret);
- return ret;
- }
auto ret = allocator.alloc<Call>();
ret->target = target;
ret->type = functionTypes[ret->target];
@@ -1394,16 +1381,6 @@ Expression* SExpressionWasmBuilder::makeCall(Element& s) {
return ret;
}
-Expression* SExpressionWasmBuilder::makeCallImport(Element& s) {
- auto ret = allocator.alloc<CallImport>();
- ret->target = s[1]->str();
- Import* import = wasm.getImport(ret->target);
- ret->type = wasm.getFunctionType(import->functionType)->result;
- parseCallOperands(s, 2, s.size(), ret);
- ret->finalize();
- return ret;
-}
-
Expression* SExpressionWasmBuilder::makeCallIndirect(Element& s) {
if (!wasm.table.exists) throw ParseException("no table");
auto ret = allocator.alloc<CallIndirect>();
@@ -1543,7 +1520,6 @@ Index SExpressionWasmBuilder::parseMemoryLimits(Element& s, Index i) {
void SExpressionWasmBuilder::parseMemory(Element& s, bool preParseImport) {
if (wasm.memory.exists) throw ParseException("too many memories");
wasm.memory.exists = true;
- wasm.memory.imported = preParseImport;
wasm.memory.shared = false;
Index i = 1;
if (s[i]->dollared()) {
@@ -1561,15 +1537,8 @@ void SExpressionWasmBuilder::parseMemory(Element& s, bool preParseImport) {
wasm.addExport(ex.release());
i++;
} else if (inner[0]->str() == IMPORT) {
- importModule = inner[1]->str();
- importBase = inner[2]->str();
- auto im = make_unique<Import>();
- im->kind = ExternalKind::Memory;
- im->module = importModule;
- im->base = importBase;
- im->name = importModule;
- if (wasm.getImportOrNull(im->name)) throw ParseException("duplicate import", s.line, s.col);
- wasm.addImport(im.release());
+ wasm.memory.module = inner[1]->str();
+ wasm.memory.base = inner[2]->str();
i++;
} else if (inner[0]->str() == "shared") {
wasm.memory.shared = true;
@@ -1675,70 +1644,69 @@ void SExpressionWasmBuilder::parseExport(Element& s) {
}
void SExpressionWasmBuilder::parseImport(Element& s) {
- std::unique_ptr<Import> im = make_unique<Import>();
size_t i = 1;
bool newStyle = s.size() == 4 && s[3]->isList(); // (import "env" "STACKTOP" (global $stackTop i32))
+ auto kind = ExternalKind::Invalid;
if (newStyle) {
if ((*s[3])[0]->str() == FUNC) {
- im->kind = ExternalKind::Function;
+ kind = ExternalKind::Function;
} else if ((*s[3])[0]->str() == MEMORY) {
- im->kind = ExternalKind::Memory;
+ kind = ExternalKind::Memory;
if (wasm.memory.exists) throw ParseException("more than one memory");
wasm.memory.exists = true;
- wasm.memory.imported = true;
} else if ((*s[3])[0]->str() == TABLE) {
- im->kind = ExternalKind::Table;
+ kind = ExternalKind::Table;
if (wasm.table.exists) throw ParseException("more than one table");
wasm.table.exists = true;
- wasm.table.imported = true;
} else if ((*s[3])[0]->str() == GLOBAL) {
- im->kind = ExternalKind::Global;
+ kind = ExternalKind::Global;
} else {
newStyle = false; // either (param..) or (result..)
}
}
Index newStyleInner = 1;
+ Name name;
if (s.size() > 3 && s[3]->isStr()) {
- im->name = s[i++]->str();
+ name = s[i++]->str();
} else if (newStyle && newStyleInner < s[3]->size() && (*s[3])[newStyleInner]->dollared()) {
- im->name = (*s[3])[newStyleInner++]->str();
- }
- if (!im->name.is()) {
- if (im->kind == ExternalKind::Function) {
- im->name = Name("import$function$" + std::to_string(functionCounter++));
- functionNames.push_back(im->name);
- } else if (im->kind == ExternalKind::Global) {
- im->name = Name("import$global" + std::to_string(globalCounter++));
- globalNames.push_back(im->name);
- } else if (im->kind == ExternalKind::Memory) {
- im->name = Name("import$memory$" + std::to_string(0));
- } else if (im->kind == ExternalKind::Table) {
- im->name = Name("import$table$" + std::to_string(0));
+ name = (*s[3])[newStyleInner++]->str();
+ }
+ if (!name.is()) {
+ if (kind == ExternalKind::Function) {
+ name = Name("import$function$" + std::to_string(functionCounter++));
+ functionNames.push_back(name);
+ } else if (kind == ExternalKind::Global) {
+ name = Name("import$global" + std::to_string(globalCounter++));
+ globalNames.push_back(name);
+ } else if (kind == ExternalKind::Memory) {
+ name = Name("import$memory$" + std::to_string(0));
+ } else if (kind == ExternalKind::Table) {
+ name = Name("import$table$" + std::to_string(0));
} else {
throw ParseException("invalid import");
}
}
if (!s[i]->quoted()) {
if (s[i]->str() == MEMORY) {
- im->kind = ExternalKind::Memory;
+ kind = ExternalKind::Memory;
} else if (s[i]->str() == TABLE) {
- im->kind = ExternalKind::Table;
+ kind = ExternalKind::Table;
} else if (s[i]->str() == GLOBAL) {
- im->kind = ExternalKind::Global;
+ kind = ExternalKind::Global;
} else {
throw ParseException("invalid ext import");
}
i++;
} else if (!newStyle) {
- im->kind = ExternalKind::Function;
+ kind = ExternalKind::Function;
}
- im->module = s[i++]->str();
+ auto module = s[i++]->str();
if (!s[i]->isStr()) throw ParseException("no name for import");
- im->base = s[i++]->str();
+ auto base = s[i++]->str();
// parse internals
Element& inner = newStyle ? *s[3] : s;
Index j = newStyle ? newStyleInner : i;
- if (im->kind == ExternalKind::Function) {
+ if (kind == ExternalKind::Function) {
std::unique_ptr<FunctionType> type = make_unique<FunctionType>();
if (inner.size() > j) {
Element& params = *inner[j];
@@ -1762,17 +1730,34 @@ void SExpressionWasmBuilder::parseImport(Element& s) {
type->result = stringToType(result[1]->str());
}
}
- im->functionType = ensureFunctionType(getSig(type.get()), &wasm)->name;
- } else if (im->kind == ExternalKind::Global) {
+ auto func = make_unique<Function>();
+ func->name = name;
+ func->module = module;
+ func->base = base;
+ auto* functionType = ensureFunctionType(getSig(type.get()), &wasm);
+ func->type = functionType->name;
+ FunctionTypeUtils::fillFunction(func.get(), functionType);
+ functionTypes[name] = func->result;
+ wasm.addFunction(func.release());
+ } else if (kind == ExternalKind::Global) {
+ Type type;
if (inner[j]->isStr()) {
- im->globalType = stringToType(inner[j]->str());
+ type = stringToType(inner[j]->str());
} else {
auto& inner2 = *inner[j];
if (inner2[0]->str() != MUT) throw ParseException("expected mut");
- im->globalType = stringToType(inner2[1]->str());
+ type = stringToType(inner2[1]->str());
throw ParseException("cannot import a mutable global", s.line, s.col);
}
- } else if (im->kind == ExternalKind::Table) {
+ auto global = make_unique<Global>();
+ global->name = name;
+ global->module = module;
+ global->base = base;
+ global->type = type;
+ wasm.addGlobal(global.release());
+ } else if (kind == ExternalKind::Table) {
+ wasm.table.module = module;
+ wasm.table.base = base;
if (j < inner.size() - 1) {
wasm.table.initial = getCheckedAddress(inner[j++], "excessive table init size");
}
@@ -1782,7 +1767,9 @@ void SExpressionWasmBuilder::parseImport(Element& s) {
wasm.table.max = Table::kMaxSize;
}
// ends with the table element type
- } else if (im->kind == ExternalKind::Memory) {
+ } else if (kind == ExternalKind::Memory) {
+ wasm.memory.module = module;
+ wasm.memory.base = base;
if (inner[j]->isList()) {
auto& limits = *inner[j];
if (!(limits[0]->isStr() && limits[0]->str() == "shared")) throw ParseException("bad memory limit declaration");
@@ -1792,8 +1779,6 @@ void SExpressionWasmBuilder::parseImport(Element& s) {
parseMemoryLimits(inner, j);
}
}
- if (wasm.getImportOrNull(im->name)) throw ParseException("duplicate import", s.line, s.col);
- wasm.addImport(im.release());
}
void SExpressionWasmBuilder::parseGlobal(Element& s, bool preParseImport) {
@@ -1841,14 +1826,13 @@ void SExpressionWasmBuilder::parseGlobal(Element& s, bool preParseImport) {
// this is an import, actually
if (!preParseImport) throw ParseException("!preParseImport in global");
if (mutable_) throw ParseException("cannot import a mutable global", s.line, s.col);
- std::unique_ptr<Import> im = make_unique<Import>();
+ auto im = make_unique<Global>();
im->name = global->name;
im->module = importModule;
im->base = importBase;
- im->kind = ExternalKind::Global;
- im->globalType = type;
- if (wasm.getImportOrNull(im->name)) throw ParseException("duplicate import", s.line, s.col);
- wasm.addImport(im.release());
+ im->type = type;
+ if (wasm.getGlobalOrNull(im->name)) throw ParseException("duplicate import", s.line, s.col);
+ wasm.addGlobal(im.release());
return;
}
if (preParseImport) throw ParseException("preParseImport in global");
@@ -1868,7 +1852,6 @@ void SExpressionWasmBuilder::parseGlobal(Element& s, bool preParseImport) {
void SExpressionWasmBuilder::parseTable(Element& s, bool preParseImport) {
if (wasm.table.exists) throw ParseException("more than one table");
wasm.table.exists = true;
- wasm.table.imported = preParseImport;
Index i = 1;
if (i == s.size()) return; // empty table in old notation
if (s[i]->dollared()) {
@@ -1887,16 +1870,9 @@ void SExpressionWasmBuilder::parseTable(Element& s, bool preParseImport) {
wasm.addExport(ex.release());
i++;
} else if (inner[0]->str() == IMPORT) {
- importModule = inner[1]->str();
- importBase = inner[2]->str();
if (!preParseImport) throw ParseException("!preParseImport in table");
- auto im = make_unique<Import>();
- im->kind = ExternalKind::Table;
- im->module = importModule;
- im->base = importBase;
- im->name = importModule;
- if (wasm.getImportOrNull(im->name)) throw ParseException("duplicate import", s.line, s.col);
- wasm.addImport(im.release());
+ wasm.table.module = inner[1]->str();
+ wasm.table.base = inner[2]->str();
i++;
} else {
throw ParseException("invalid table");
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index d57607ce6..36069f8db 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -24,6 +24,7 @@
#include "wasm-validator.h"
#include "ir/utils.h"
#include "ir/branch-utils.h"
+#include "ir/module-utils.h"
#include "support/colors.h"
@@ -233,7 +234,6 @@ public:
void visitBreak(Break* curr);
void visitSwitch(Switch* curr);
void visitCall(Call* curr);
- void visitCallImport(CallImport* curr);
void visitCallIndirect(CallIndirect* curr);
void visitGetLocal(GetLocal* curr);
void visitSetLocal(SetLocal* curr);
@@ -444,12 +444,7 @@ void FunctionValidator::visitSwitch(Switch* curr) {
void FunctionValidator::visitCall(Call* curr) {
if (!info.validateGlobally) return;
auto* target = getModule()->getFunctionOrNull(curr->target);
- if (!shouldBeTrue(!!target, curr, "call target must exist")) {
- if (getModule()->getImportOrNull(curr->target) && !info.quiet) {
- getStream() << "(perhaps it should be a CallImport instead of Call?)\n";
- }
- return;
- }
+ if (!shouldBeTrue(!!target, curr, "call target must exist")) return;
if (!shouldBeTrue(curr->operands.size() == target->params.size(), curr, "call param number must match")) return;
for (size_t i = 0; i < curr->operands.size(); i++) {
if (!shouldBeEqualOrFirstIsUnreachable(curr->operands[i]->type, target->params[i], curr, "call param types must match") && !info.quiet) {
@@ -458,20 +453,6 @@ void FunctionValidator::visitCall(Call* curr) {
}
}
-void FunctionValidator::visitCallImport(CallImport* curr) {
- if (!info.validateGlobally) return;
- auto* import = getModule()->getImportOrNull(curr->target);
- if (!shouldBeTrue(!!import, curr, "call_import target must exist")) return;
- if (!shouldBeTrue(!!import->functionType.is(), curr, "called import must be function")) return;
- auto* type = getModule()->getFunctionType(import->functionType);
- if (!shouldBeTrue(curr->operands.size() == type->params.size(), curr, "call param number must match")) return;
- for (size_t i = 0; i < curr->operands.size(); i++) {
- if (!shouldBeEqualOrFirstIsUnreachable(curr->operands[i]->type, type->params[i], curr, "call param types must match") && !info.quiet) {
- getStream() << "(on argument " << i << ")\n";
- }
- }
-}
-
void FunctionValidator::visitCallIndirect(CallIndirect* curr) {
if (!info.validateGlobally) return;
auto* type = getModule()->getFunctionTypeOrNull(curr->fullType);
@@ -503,13 +484,13 @@ void FunctionValidator::visitSetLocal(SetLocal* curr) {
void FunctionValidator::visitGetGlobal(GetGlobal* curr) {
if (!info.validateGlobally) return;
- shouldBeTrue(getModule()->getGlobalOrNull(curr->name) || getModule()->getImportOrNull(curr->name), curr, "get_global name must be valid");
+ shouldBeTrue(getModule()->getGlobalOrNull(curr->name), curr, "get_global name must be valid");
}
void FunctionValidator::visitSetGlobal(SetGlobal* curr) {
if (!info.validateGlobally) return;
auto* global = getModule()->getGlobalOrNull(curr->name);
- if (shouldBeTrue(global != NULL, curr, "set_global name must be valid (and not an import; imports can't be modified)")) {
+ if (shouldBeTrue(global, curr, "set_global name must be valid (and not an import; imports can't be modified)")) {
shouldBeTrue(global->mutable_, curr, "set_global global must be mutable");
shouldBeEqualOrFirstIsUnreachable(curr->value->type, global->type, curr, "set_global value must have right type");
}
@@ -926,23 +907,15 @@ static void validateBinaryenIR(Module& wasm, ValidationInfo& info) {
// Main validator class
static void validateImports(Module& module, ValidationInfo& info) {
- for (auto& curr : module.imports) {
- if (curr->kind == ExternalKind::Function) {
- if (info.validateWeb) {
- auto* functionType = module.getFunctionType(curr->functionType);
- info.shouldBeUnequal(functionType->result, i64, curr->name, "Imported function must not have i64 return type");
- for (Type param : functionType->params) {
- info.shouldBeUnequal(param, i64, curr->name, "Imported function must not have i64 parameters");
- }
+ ModuleUtils::iterImportedFunctions(module, [&](Function* curr) {
+ if (info.validateWeb) {
+ auto* functionType = module.getFunctionType(curr->type);
+ info.shouldBeUnequal(functionType->result, i64, curr->name, "Imported function must not have i64 return type");
+ for (Type param : functionType->params) {
+ info.shouldBeUnequal(param, i64, curr->name, "Imported function must not have i64 parameters");
}
}
- if (curr->kind == ExternalKind::Table) {
- info.shouldBeTrue(module.table.imported, curr->name, "Table import record exists but table is not marked as imported");
- }
- if (curr->kind == ExternalKind::Memory) {
- info.shouldBeTrue(module.memory.imported, curr->name, "Memory import record exists but memory is not marked as imported");
- }
- }
+ });
}
static void validateExports(Module& module, ValidationInfo& info) {
@@ -961,13 +934,9 @@ static void validateExports(Module& module, ValidationInfo& info) {
for (auto& exp : module.exports) {
Name name = exp->value;
if (exp->kind == ExternalKind::Function) {
- Import* imp;
- info.shouldBeTrue(module.getFunctionOrNull(name) ||
- ((imp = module.getImportOrNull(name)) && imp->kind == ExternalKind::Function), name, "module function exports must be found");
+ info.shouldBeTrue(module.getFunctionOrNull(name), name, "module function exports must be found");
} else if (exp->kind == ExternalKind::Global) {
- Import* imp;
- info.shouldBeTrue(module.getGlobalOrNull(name) ||
- ((imp = module.getImportOrNull(name)) && imp->kind == ExternalKind::Global), name, "module global exports must be found");
+ info.shouldBeTrue(module.getGlobalOrNull(name), name, "module global exports must be found");
} else if (exp->kind == ExternalKind::Table) {
info.shouldBeTrue(name == Name("0") || name == module.table.name, name, "module table exports must be found");
} else if (exp->kind == ExternalKind::Memory) {
@@ -982,13 +951,13 @@ static void validateExports(Module& module, ValidationInfo& info) {
}
static void validateGlobals(Module& module, ValidationInfo& info) {
- for (auto& curr : module.globals) {
+ ModuleUtils::iterDefinedGlobals(module, [&](Global* curr) {
info.shouldBeTrue(curr->init != nullptr, curr->name, "global init must be non-null");
info.shouldBeTrue(curr->init->is<Const>() || curr->init->is<GetGlobal>(), curr->name, "global init must be valid");
if (!info.shouldBeEqual(curr->type, curr->init->type, curr->init, "global init must have correct type") && !info.quiet) {
info.getStream(nullptr) << "(on global " << curr->name << ")\n";
}
- }
+ });
}
static void validateMemory(Module& module, ValidationInfo& info) {
@@ -1016,7 +985,7 @@ static void validateTable(Module& module, ValidationInfo& info) {
info.shouldBeEqual(segment.offset->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");
for (auto name : segment.data) {
- info.shouldBeTrue(module.getFunctionOrNull(name) || module.getImportOrNull(name), name, "segment name should be valid");
+ info.shouldBeTrue(module.getFunctionOrNull(name), name, "segment name should be valid");
}
}
}
diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp
index ac3623cee..ad4d6343a 100644
--- a/src/wasm/wasm.cpp
+++ b/src/wasm/wasm.cpp
@@ -53,7 +53,6 @@ Name GROW_WASM_MEMORY("__growWasmMemory"),
LOCAL("local"),
TYPE("type"),
CALL("call"),
- CALL_IMPORT("call_import"),
CALL_INDIRECT("call_indirect"),
BLOCK("block"),
BR_IF("br_if"),
@@ -83,7 +82,6 @@ const char* getExpressionName(Expression* curr) {
case Expression::Id::BreakId: return "break";
case Expression::Id::SwitchId: return "switch";
case Expression::Id::CallId: return "call";
- case Expression::Id::CallImportId: return "call_import";
case Expression::Id::CallIndirectId: return "call_indirect";
case Expression::Id::GetLocalId: return "get_local";
case Expression::Id::SetLocalId: return "set_local";
@@ -324,10 +322,6 @@ void Call::finalize() {
handleUnreachableOperands(this);
}
-void CallImport::finalize() {
- handleUnreachableOperands(this);
-}
-
void CallIndirect::finalize() {
handleUnreachableOperands(this);
if (target->type == unreachable) {
@@ -650,14 +644,6 @@ FunctionType* Module::getFunctionType(Name name) {
return iter->second;
}
-Import* Module::getImport(Name name) {
- auto iter = importsMap.find(name);
- if (iter == importsMap.end()) {
- Fatal() << "Module::getImport: " << name << " does not exist";
- }
- return iter->second;
-}
-
Export* Module::getExport(Name name) {
auto iter = exportsMap.find(name);
if (iter == exportsMap.end()) {
@@ -690,14 +676,6 @@ FunctionType* Module::getFunctionTypeOrNull(Name name) {
return iter->second;
}
-Import* Module::getImportOrNull(Name name) {
- auto iter = importsMap.find(name);
- if (iter == importsMap.end()) {
- return nullptr;
- }
- return iter->second;
-}
-
Export* Module::getExportOrNull(Name name) {
auto iter = exportsMap.find(name);
if (iter == exportsMap.end()) {
@@ -733,17 +711,6 @@ void Module::addFunctionType(FunctionType* curr) {
functionTypesMap[curr->name] = curr;
}
-void Module::addImport(Import* curr) {
- if (!curr->name.is()) {
- Fatal() << "Module::addImport: empty name";
- }
- if (getImportOrNull(curr->name)) {
- Fatal() << "Module::addImport: " << curr->name << " already exists";
- }
- imports.push_back(std::unique_ptr<Import>(curr));
- importsMap[curr->name] = curr;
-}
-
void Module::addExport(Export* curr) {
if (!curr->name.is()) {
Fatal() << "Module::addExport: empty name";
@@ -781,14 +748,14 @@ void Module::addStart(const Name& s) {
start = s;
}
-void Module::removeImport(Name name) {
- for (size_t i = 0; i < imports.size(); i++) {
- if (imports[i]->name == name) {
- imports.erase(imports.begin() + i);
+void Module::removeFunctionType(Name name) {
+ for (size_t i = 0; i < functionTypes.size(); i++) {
+ if (functionTypes[i]->name == name) {
+ functionTypes.erase(functionTypes.begin() + i);
break;
}
}
- importsMap.erase(name);
+ functionTypesMap.erase(name);
}
void Module::removeExport(Name name) {
@@ -811,14 +778,14 @@ void Module::removeFunction(Name name) {
functionsMap.erase(name);
}
-void Module::removeFunctionType(Name name) {
- for (size_t i = 0; i < functionTypes.size(); i++) {
- if (functionTypes[i]->name == name) {
- functionTypes.erase(functionTypes.begin() + i);
+void Module::removeGlobal(Name name) {
+ for (size_t i = 0; i < globals.size(); i++) {
+ if (globals[i]->name == name) {
+ globals.erase(globals.begin() + i);
break;
}
}
- functionTypesMap.erase(name);
+ globalsMap.erase(name);
}
// TODO: remove* for other elements
@@ -832,10 +799,6 @@ void Module::updateMaps() {
for (auto& curr : functionTypes) {
functionTypesMap[curr->name] = curr.get();
}
- importsMap.clear();
- for (auto& curr : imports) {
- importsMap[curr->name] = curr.get();
- }
exportsMap.clear();
for (auto& curr : exports) {
exportsMap[curr->name] = curr.get();