summaryrefslogtreecommitdiff
path: root/src/tools
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools')
-rw-r--r--src/tools/execution-results.h3
-rw-r--r--src/tools/wasm-ctor-eval.cpp37
-rw-r--r--src/tools/wasm-merge.cpp168
-rw-r--r--src/tools/wasm-metadce.cpp87
-rw-r--r--src/tools/wasm-shell.cpp27
5 files changed, 176 insertions, 146 deletions
diff --git a/src/tools/execution-results.h b/src/tools/execution-results.h
index 1e8fba4ff..ca4b819d9 100644
--- a/src/tools/execution-results.h
+++ b/src/tools/execution-results.h
@@ -20,6 +20,7 @@
#include "wasm.h"
#include "shell-interface.h"
+#include "ir/import-utils.h"
namespace wasm {
@@ -32,7 +33,7 @@ struct ExecutionResults {
// get results of execution
void get(Module& wasm) {
- if (wasm.imports.size() > 0) {
+ if (ImportInfo(wasm).getNumImports() > 0) {
std::cout << "[fuzz-exec] imports, so quitting\n";
return;
}
diff --git a/src/tools/wasm-ctor-eval.cpp b/src/tools/wasm-ctor-eval.cpp
index e11454b04..4272c5dba 100644
--- a/src/tools/wasm-ctor-eval.cpp
+++ b/src/tools/wasm-ctor-eval.cpp
@@ -36,6 +36,7 @@
#include "ir/global-utils.h"
#include "ir/import-utils.h"
#include "ir/literal-utils.h"
+#include "ir/module-utils.h"
using namespace wasm;
@@ -124,23 +125,23 @@ public:
EvallingModuleInstance(Module& wasm, ExternalInterface* externalInterface) : ModuleInstanceBase(wasm, externalInterface) {
// if any global in the module has a non-const constructor, it is using a global import,
// which we don't have, and is illegal to use
- for (auto& global : wasm.globals) {
+ ModuleUtils::iterDefinedGlobals(wasm, [&](Global* global) {
if (!global->init->is<Const>()) {
// some constants are ok to use
if (auto* get = global->init->dynCast<GetGlobal>()) {
auto name = get->name;
- auto* import = wasm.getImport(name);
+ auto* import = wasm.getGlobal(name);
if (import->module == Name("env") && (
import->base == Name("STACKTOP") || // stack constants are special, we handle them
import->base == Name("STACK_MAX")
)) {
- continue; // this is fine
+ return; // this is fine
}
}
// this global is dangerously initialized by an import, so if it is used, we must fail
globals.addDangerous(global->name);
}
- }
+ });
}
std::vector<char> stack;
@@ -173,34 +174,33 @@ struct CtorEvalExternalInterface : EvallingModuleInstance::ExternalInterface {
void importGlobals(EvallingGlobalManager& globals, Module& wasm_) override {
// fill usable values for stack imports, and globals initialized to them
- if (auto* stackTop = ImportUtils::getImport(wasm_, "env", "STACKTOP")) {
+ ImportInfo imports(wasm_);
+ if (auto* stackTop = imports.getImportedGlobal("env", "STACKTOP")) {
globals[stackTop->name] = Literal(int32_t(STACK_START));
if (auto* stackTop = GlobalUtils::getGlobalInitializedToImport(wasm_, "env", "STACKTOP")) {
globals[stackTop->name] = Literal(int32_t(STACK_START));
}
}
- if (auto* stackMax = ImportUtils::getImport(wasm_, "env", "STACK_MAX")) {
+ if (auto* stackMax = imports.getImportedGlobal("env", "STACK_MAX")) {
globals[stackMax->name] = Literal(int32_t(STACK_START));
if (auto* stackMax = GlobalUtils::getGlobalInitializedToImport(wasm_, "env", "STACK_MAX")) {
globals[stackMax->name] = Literal(int32_t(STACK_START));
}
}
// fill in fake values for everything else, which is dangerous to use
- for (auto& global : wasm_.globals) {
- if (globals.find(global->name) == globals.end()) {
- globals[global->name] = LiteralUtils::makeLiteralZero(global->type);
+ ModuleUtils::iterDefinedGlobals(wasm_, [&](Global* defined) {
+ if (globals.find(defined->name) == globals.end()) {
+ globals[defined->name] = LiteralUtils::makeLiteralZero(defined->type);
}
- }
- for (auto& import : wasm_.imports) {
- if (import->kind == ExternalKind::Global) {
- if (globals.find(import->name) == globals.end()) {
- globals[import->name] = LiteralUtils::makeLiteralZero(import->globalType);
- }
+ });
+ ModuleUtils::iterImportedGlobals(wasm_, [&](Global* import) {
+ if (globals.find(import->name) == globals.end()) {
+ globals[import->name] = LiteralUtils::makeLiteralZero(import->type);
}
- }
+ });
}
- Literal callImport(Import *import, LiteralList& arguments) override {
+ Literal callImport(Function* import, LiteralList& arguments) override {
std::string extra;
if (import->module == "env" && import->base == "___cxa_atexit") {
extra = "\nrecommendation: build with -s NO_EXIT_RUNTIME=1 so that calls to atexit are not emitted";
@@ -227,7 +227,8 @@ struct CtorEvalExternalInterface : EvallingModuleInstance::ExternalInterface {
if (start <= index && index < end) {
auto name = segment.data[index - start];
// if this is one of our functions, we can call it; if it was imported, fail
- if (wasm->getFunctionOrNull(name)) {
+ auto* func = wasm->getFunction(name);
+ if (!func->imported()) {
return instance.callFunctionInternal(name, arguments);
} else {
throw FailToEvalException(std::string("callTable on imported function: ") + name.str);
diff --git a/src/tools/wasm-merge.cpp b/src/tools/wasm-merge.cpp
index e8910860e..70611e269 100644
--- a/src/tools/wasm-merge.cpp
+++ b/src/tools/wasm-merge.cpp
@@ -34,20 +34,10 @@
#include "wasm-binary.h"
#include "wasm-builder.h"
#include "wasm-validator.h"
+#include "ir/module-utils.h"
using namespace wasm;
-// Calls note() on every import that has form "env".(base)
-static void findImportsByBase(Module& wasm, Name base, std::function<void (Name)> note) {
- for (auto& curr : wasm.imports) {
- if (curr->module == ENV) {
- if (curr->base == base) {
- note(curr->name);
- }
- }
- }
-}
-
// Ensure a memory or table is of at least a size
template<typename T>
static void ensureSize(T& what, Index size) {
@@ -119,31 +109,33 @@ struct Mergeable {
}
void findImports() {
- findImportsByBase(wasm, MEMORY_BASE, [&](Name name) {
- memoryBaseGlobals.insert(name);
+ ModuleUtils::iterImportedGlobals(wasm, [&](Global* import) {
+ if (import->module == ENV && import->base == MEMORY_BASE) {
+ memoryBaseGlobals.insert(import->name);
+ }
});
if (memoryBaseGlobals.size() == 0) {
// add one
- auto* import = new Import;
+ auto* import = new Global;
import->name = MEMORY_BASE;
import->module = ENV;
import->base = MEMORY_BASE;
- import->kind = ExternalKind::Global;
- import->globalType = i32;
- wasm.addImport(import);
+ import->type = i32;
+ wasm.addGlobal(import);
memoryBaseGlobals.insert(import->name);
}
- findImportsByBase(wasm, TABLE_BASE, [&](Name name) {
- tableBaseGlobals.insert(name);
+ ModuleUtils::iterImportedGlobals(wasm, [&](Global* import) {
+ if (import->module == ENV && import->base == TABLE_BASE) {
+ tableBaseGlobals.insert(import->name);
+ }
});
if (tableBaseGlobals.size() == 0) {
- auto* import = new Import;
+ auto* import = new Global;
import->name = TABLE_BASE;
import->module = ENV;
import->base = TABLE_BASE;
- import->kind = ExternalKind::Global;
- import->globalType = i32;
- wasm.addImport(import);
+ import->type = i32;
+ wasm.addGlobal(import);
tableBaseGlobals.insert(import->name);
}
}
@@ -244,7 +236,7 @@ struct Mergeable {
struct OutputMergeable : public PostWalker<OutputMergeable, Visitor<OutputMergeable>>, public Mergeable {
OutputMergeable(Module& wasm) : Mergeable(wasm) {}
- void visitCallImport(CallImport* curr) {
+ void visitCall(Call* curr) {
auto iter = implementedFunctionImports.find(curr->target);
if (iter != implementedFunctionImports.end()) {
// this import is now in the module - call it
@@ -264,10 +256,10 @@ struct OutputMergeable : public PostWalker<OutputMergeable, Visitor<OutputMergea
void visitModule(Module* curr) {
// remove imports that are being implemented
for (auto& pair : implementedFunctionImports) {
- curr->removeImport(pair.first);
+ curr->removeFunction(pair.first);
}
for (auto& pair : implementedGlobalImports) {
- curr->removeImport(pair.first);
+ curr->removeGlobal(pair.first);
}
}
};
@@ -288,11 +280,6 @@ struct InputMergeable : public ExpressionStackWalker<InputMergeable, Visitor<Inp
std::map<Name, Name> gNames; // globals
void visitCall(Call* curr) {
- curr->target = fNames[curr->target];
- assert(curr->target.is());
- }
-
- void visitCallImport(CallImport* curr) {
auto iter = implementedFunctionImports.find(curr->target);
if (iter != implementedFunctionImports.end()) {
// this import is now in the module - call it
@@ -333,29 +320,38 @@ struct InputMergeable : public ExpressionStackWalker<InputMergeable, Visitor<Inp
void merge() {
// find function imports in us that are implemented in the output
// TODO make maps, avoid N^2
- for (auto& imp : wasm.imports) {
+ ModuleUtils::iterImportedFunctions(wasm, [&](Function* import) {
// per wasm dynamic library rules, we expect to see exports on 'env'
- if ((imp->kind == ExternalKind::Function || imp->kind == ExternalKind::Global) && imp->module == ENV) {
+ if (import->module == ENV) {
// seek an export on the other side that matches
for (auto& exp : outputMergeable.wasm.exports) {
- if (exp->kind == imp->kind && exp->name == imp->base) {
+ if (exp->name == import->base) {
// fits!
- if (imp->kind == ExternalKind::Function) {
- implementedFunctionImports[imp->name] = exp->value;
- } else {
- implementedGlobalImports[imp->name] = exp->value;
- }
+ implementedFunctionImports[import->name] = exp->value;
break;
}
}
}
- }
+ });
+ ModuleUtils::iterImportedGlobals(wasm, [&](Global* import) {
+ // per wasm dynamic library rules, we expect to see exports on 'env'
+ if (import->module == ENV) {
+ // seek an export on the other side that matches
+ for (auto& exp : outputMergeable.wasm.exports) {
+ if (exp->name == import->base) {
+ // fits!
+ implementedGlobalImports[import->name] = exp->value;
+ break;
+ }
+ }
+ }
+ });
// remove the unneeded ones
for (auto& pair : implementedFunctionImports) {
- wasm.removeImport(pair.first);
+ wasm.removeFunction(pair.first);
}
for (auto& pair : implementedGlobalImports) {
- wasm.removeImport(pair.first);
+ wasm.removeGlobal(pair.first);
}
// find new names
@@ -364,27 +360,26 @@ struct InputMergeable : public ExpressionStackWalker<InputMergeable, Visitor<Inp
return outputMergeable.wasm.getFunctionTypeOrNull(name);
});
}
- for (auto& curr : wasm.imports) {
- if (curr->kind == ExternalKind::Function) {
- curr->name = fNames[curr->name] = getNonColliding(curr->name, [&](Name name) -> bool {
- return !!outputMergeable.wasm.getImportOrNull(name) || !!outputMergeable.wasm.getFunctionOrNull(name);
- });
- } else if (curr->kind == ExternalKind::Global) {
- curr->name = gNames[curr->name] = getNonColliding(curr->name, [&](Name name) -> bool {
- return !!outputMergeable.wasm.getImportOrNull(name) || !!outputMergeable.wasm.getGlobalOrNull(name);
- });
- }
- }
- for (auto& curr : wasm.functions) {
+ ModuleUtils::iterImportedFunctions(wasm, [&](Function* curr) {
+ curr->name = fNames[curr->name] = getNonColliding(curr->name, [&](Name name) -> bool {
+ return !!outputMergeable.wasm.getFunctionOrNull(name);
+ });
+ });
+ ModuleUtils::iterImportedGlobals(wasm, [&](Global* curr) {
+ curr->name = gNames[curr->name] = getNonColliding(curr->name, [&](Name name) -> bool {
+ return !!outputMergeable.wasm.getGlobalOrNull(name);
+ });
+ });
+ ModuleUtils::iterDefinedFunctions(wasm, [&](Function* curr) {
curr->name = fNames[curr->name] = getNonColliding(curr->name, [&](Name name) -> bool {
return outputMergeable.wasm.getFunctionOrNull(name);
});
- }
- for (auto& curr : wasm.globals) {
+ });
+ ModuleUtils::iterDefinedGlobals(wasm, [&](Global* curr) {
curr->name = gNames[curr->name] = getNonColliding(curr->name, [&](Name name) -> bool {
return outputMergeable.wasm.getGlobalOrNull(name);
});
- }
+ });
// update global names in input
{
@@ -403,20 +398,26 @@ struct InputMergeable : public ExpressionStackWalker<InputMergeable, Visitor<Inp
}
// find function imports in output that are implemented in the input
- for (auto& imp : outputMergeable.wasm.imports) {
- if ((imp->kind == ExternalKind::Function || imp->kind == ExternalKind::Global) && imp->module == ENV) {
+ ModuleUtils::iterImportedFunctions(outputMergeable.wasm, [&](Function* import) {
+ if (import->module == ENV) {
for (auto& exp : wasm.exports) {
- if (exp->kind == imp->kind && exp->name == imp->base) {
- if (imp->kind == ExternalKind::Function) {
- outputMergeable.implementedFunctionImports[imp->name] = fNames[exp->value];
- } else {
- outputMergeable.implementedGlobalImports[imp->name] = gNames[exp->value];
- }
+ if (exp->name == import->base) {
+ outputMergeable.implementedFunctionImports[import->name] = fNames[exp->value];
break;
}
}
}
- }
+ });
+ ModuleUtils::iterImportedGlobals(outputMergeable.wasm, [&](Global* import) {
+ if (import->module == ENV) {
+ for (auto& exp : wasm.exports) {
+ if (exp->name == import->base) {
+ outputMergeable.implementedGlobalImports[import->name] = gNames[exp->value];
+ break;
+ }
+ }
+ }
+ });
// update the output before bringing anything in. avoid doing so when possible, as in the
// common case the output module is very large.
@@ -448,16 +449,19 @@ struct InputMergeable : public ExpressionStackWalker<InputMergeable, Visitor<Inp
for (auto& curr : wasm.functionTypes) {
outputMergeable.wasm.addFunctionType(curr.release());
}
- for (auto& curr : wasm.imports) {
- if (curr->kind == ExternalKind::Memory || curr->kind == ExternalKind::Table) {
- continue; // wasm has just 1 of each, they must match
+ for (auto& curr : wasm.globals) {
+ if (curr->imported()) {
+ outputMergeable.wasm.addGlobal(curr.release());
}
- // update and add
- if (curr->functionType.is()) {
- curr->functionType = ftNames[curr->functionType];
- assert(curr->functionType.is());
+ }
+ for (auto& curr : wasm.functions) {
+ if (curr->imported()) {
+ if (curr->type.is()) {
+ curr->type = ftNames[curr->type];
+ assert(curr->type.is());
+ }
+ outputMergeable.wasm.addFunction(curr.release());
}
- outputMergeable.wasm.addImport(curr.release());
}
for (auto& curr : wasm.exports) {
if (curr->kind == ExternalKind::Memory || curr->kind == ExternalKind::Table) {
@@ -477,13 +481,21 @@ struct InputMergeable : public ExpressionStackWalker<InputMergeable, Visitor<Inp
}
}
}
+ // Copy over the remaining non-imports (we have already transferred
+ // the imports, and they are nullptrs).
for (auto& curr : wasm.functions) {
- curr->type = ftNames[curr->type];
- assert(curr->type.is());
- outputMergeable.wasm.addFunction(curr.release());
+ if (curr) {
+ assert(!curr->imported());
+ curr->type = ftNames[curr->type];
+ assert(curr->type.is());
+ outputMergeable.wasm.addFunction(curr.release());
+ }
}
for (auto& curr : wasm.globals) {
- outputMergeable.wasm.addGlobal(curr.release());
+ if (curr) {
+ assert(!curr->imported());
+ outputMergeable.wasm.addGlobal(curr.release());
+ }
}
}
diff --git a/src/tools/wasm-metadce.cpp b/src/tools/wasm-metadce.cpp
index 4f90ee612..5caf8fea7 100644
--- a/src/tools/wasm-metadce.cpp
+++ b/src/tools/wasm-metadce.cpp
@@ -33,7 +33,7 @@
#include "support/colors.h"
#include "wasm-io.h"
#include "wasm-builder.h"
-#include "ir/import-utils.h"
+#include "ir/module-utils.h"
using namespace wasm;
@@ -69,8 +69,13 @@ struct MetaDCEGraph {
return std::string(module.str) + " (*) " + std::string(base.str);
}
- ImportId getImportId(Name name) {
- auto* imp = wasm.getImport(name);
+ ImportId getFunctionImportId(Name name) {
+ auto* imp = wasm.getFunction(name);
+ return getImportId(imp->module, imp->base);
+ }
+
+ ImportId getGlobalImportId(Name name) {
+ auto* imp = wasm.getGlobal(name);
return getImportId(imp->module, imp->base);
}
@@ -86,28 +91,33 @@ struct MetaDCEGraph {
// Add an entry for everything we might need ahead of time, so parallel work
// does not alter parent state, just adds to things pointed by it, independently
// (each thread will add for one function, etc.)
- for (auto& func : wasm.functions) {
+ ModuleUtils::iterDefinedFunctions(wasm, [&](Function* func) {
auto dceName = getName("func", func->name.str);
DCENodeToFunction[dceName] = func->name;
functionToDCENode[func->name] = dceName;
nodes[dceName] = DCENode(dceName);
- }
- for (auto& global : wasm.globals) {
+ });
+ ModuleUtils::iterDefinedGlobals(wasm, [&](Global* global) {
auto dceName = getName("global", global->name.str);
DCENodeToGlobal[dceName] = global->name;
globalToDCENode[global->name] = dceName;
nodes[dceName] = DCENode(dceName);
- }
- for (auto& imp : wasm.imports) {
- // only process function and global imports - the table and memory are always there
- if (imp->kind == ExternalKind::Function || imp->kind == ExternalKind::Global) {
- auto id = getImportId(imp->module, imp->base);
- if (importIdToDCENode.find(id) == importIdToDCENode.end()) {
- auto dceName = getName("importId", imp->name.str);
- importIdToDCENode[id] = dceName;
- }
+ });
+ // only process function and global imports - the table and memory are always there
+ ModuleUtils::iterImportedFunctions(wasm, [&](Function* import) {
+ auto id = getImportId(import->module, import->base);
+ if (importIdToDCENode.find(id) == importIdToDCENode.end()) {
+ auto dceName = getName("importId", import->name.str);
+ importIdToDCENode[id] = dceName;
}
- }
+ });
+ ModuleUtils::iterImportedGlobals(wasm, [&](Global* import) {
+ auto id = getImportId(import->module, import->base);
+ if (importIdToDCENode.find(id) == importIdToDCENode.end()) {
+ auto dceName = getName("importId", import->name.str);
+ importIdToDCENode[id] = dceName;
+ }
+ });
for (auto& exp : wasm.exports) {
if (exportToDCENode.find(exp->name) == exportToDCENode.end()) {
auto dceName = getName("export", exp->name.str);
@@ -118,16 +128,16 @@ struct MetaDCEGraph {
// we can also link the export to the thing being exported
auto& node = nodes[exportToDCENode[exp->name]];
if (exp->kind == ExternalKind::Function) {
- if (wasm.getFunctionOrNull(exp->value)) {
+ if (!wasm.getFunction(exp->value)->imported()) {
node.reaches.push_back(functionToDCENode[exp->value]);
} else {
- node.reaches.push_back(importIdToDCENode[getImportId(exp->value)]);
+ node.reaches.push_back(importIdToDCENode[getFunctionImportId(exp->value)]);
}
} else if (exp->kind == ExternalKind::Global) {
- if (wasm.getGlobalOrNull(exp->value)) {
+ if (!wasm.getGlobal(exp->value)->imported()) {
node.reaches.push_back(globalToDCENode[exp->value]);
} else {
- node.reaches.push_back(importIdToDCENode[getImportId(exp->value)]);
+ node.reaches.push_back(importIdToDCENode[getGlobalImportId(exp->value)]);
}
}
}
@@ -150,12 +160,12 @@ struct MetaDCEGraph {
void handleGlobal(Name name) {
Name dceName;
- if (getModule()->getGlobalOrNull(name)) {
- // its a global
+ if (!getModule()->getGlobal(name)->imported()) {
+ // its a defined global
dceName = parent->globalToDCENode[name];
} else {
// it's an import.
- dceName = parent->importIdToDCENode[parent->getImportId(name)];
+ dceName = parent->importIdToDCENode[parent->getGlobalImportId(name)];
}
if (parentDceName.isNull()) {
parent->roots.insert(parentDceName);
@@ -164,11 +174,11 @@ struct MetaDCEGraph {
}
}
};
- for (auto& global : wasm.globals) {
+ ModuleUtils::iterDefinedGlobals(wasm, [&](Global* global) {
InitScanner scanner(this, globalToDCENode[global->name]);
scanner.setModule(&wasm);
scanner.walk(global->init);
- }
+ });
// we can't remove segments, so root what they need
InitScanner rooter(this, Name());
rooter.setModule(&wasm);
@@ -176,10 +186,10 @@ struct MetaDCEGraph {
// TODO: currently, all functions in the table are roots, but we
// should add an option to refine that
for (auto& name : segment.data) {
- if (wasm.getFunctionOrNull(name)) {
+ if (!wasm.getFunction(name)->imported()) {
roots.insert(functionToDCENode[name]);
} else {
- roots.insert(importIdToDCENode[getImportId(name)]);
+ roots.insert(importIdToDCENode[getFunctionImportId(name)]);
}
}
rooter.walk(segment.offset);
@@ -199,15 +209,16 @@ struct MetaDCEGraph {
}
void visitCall(Call* curr) {
- parent->nodes[parent->functionToDCENode[getFunction()->name]].reaches.push_back(
- parent->functionToDCENode[curr->target]
- );
- }
- void visitCallImport(CallImport* curr) {
- assert(parent->functionToDCENode.count(getFunction()->name) > 0);
- parent->nodes[parent->functionToDCENode[getFunction()->name]].reaches.push_back(
- parent->importIdToDCENode[parent->getImportId(curr->target)]
- );
+ if (!getModule()->getFunction(curr->target)->imported()) {
+ parent->nodes[parent->functionToDCENode[getFunction()->name]].reaches.push_back(
+ parent->functionToDCENode[curr->target]
+ );
+ } else {
+ assert(parent->functionToDCENode.count(getFunction()->name) > 0);
+ parent->nodes[parent->functionToDCENode[getFunction()->name]].reaches.push_back(
+ parent->importIdToDCENode[parent->getFunctionImportId(curr->target)]
+ );
+ }
}
void visitGetGlobal(GetGlobal* curr) {
handleGlobal(curr->name);
@@ -222,12 +233,12 @@ struct MetaDCEGraph {
void handleGlobal(Name name) {
if (!getFunction()) return; // non-function stuff (initializers) are handled separately
Name dceName;
- if (getModule()->getGlobalOrNull(name)) {
+ if (!getModule()->getGlobal(name)->imported()) {
// its a global
dceName = parent->globalToDCENode[name];
} else {
// it's an import.
- dceName = parent->importIdToDCENode[parent->getImportId(name)];
+ dceName = parent->importIdToDCENode[parent->getGlobalImportId(name)];
}
parent->nodes[parent->functionToDCENode[getFunction()->name]].reaches.push_back(dceName);
}
diff --git a/src/tools/wasm-shell.cpp b/src/tools/wasm-shell.cpp
index 2a59be167..9ad1fa799 100644
--- a/src/tools/wasm-shell.cpp
+++ b/src/tools/wasm-shell.cpp
@@ -146,24 +146,29 @@ static void run_asserts(Name moduleName, size_t* i, bool* checked, Module* wasm,
}
if (!invalid && id == ASSERT_UNLINKABLE) {
// validate "instantiating" the mdoule
- for (auto& import : wasm.imports) {
+ auto reportUnknownImport = [&](Importable* import) {
+ std::cerr << "unknown import: " << import->module << '.' << import->base << '\n';
+ invalid = true;
+ };
+ ModuleUtils::iterImportedGlobals(wasm, reportUnknownImport);
+ ModuleUtils::iterImportedFunctions(wasm, [&](Importable* import) {
if (import->module == SPECTEST && import->base == PRINT) {
- if (import->kind != ExternalKind::Function) {
- std::cerr << "spectest.print should be a function, but is " << int32_t(import->kind) << '\n';
- invalid = true;
- break;
- }
+ // We can handle it.
} else {
- std::cerr << "unknown import: " << import->module << '.' << import->base << '\n';
- invalid = true;
- break;
+ reportUnknownImport(import);
}
+ });
+ if (wasm.memory.imported()) {
+ reportUnknownImport(&wasm.memory);
+ }
+ if (wasm.table.imported()) {
+ reportUnknownImport(&wasm.table);
}
for (auto& segment : wasm.table.segments) {
for (auto name : segment.data) {
// spec tests consider it illegal to use spectest.print in a table
- if (auto* import = wasm.getImportOrNull(name)) {
- if (import->module == SPECTEST && import->base == PRINT) {
+ if (auto* import = wasm.getFunction(name)) {
+ if (import->imported() && import->module == SPECTEST && import->base == PRINT) {
std::cerr << "cannot put spectest.print in table\n";
invalid = true;
}