summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/abi/js.h5
-rw-r--r--src/binaryen-c.cpp16
-rw-r--r--src/ir/ExpressionAnalyzer.cpp2
-rw-r--r--src/ir/ReFinalize.cpp2
-rw-r--r--src/ir/function-utils.h4
-rw-r--r--src/ir/hashed.h3
-rw-r--r--src/ir/module-splitting.cpp29
-rw-r--r--src/ir/module-utils.h4
-rw-r--r--src/ir/table-utils.h2
-rw-r--r--src/ir/utils.h2
-rw-r--r--src/passes/Asyncify.cpp10
-rw-r--r--src/passes/CodeFolding.cpp2
-rw-r--r--src/passes/DeNaN.cpp6
-rw-r--r--src/passes/DeadArgumentElimination.cpp9
-rw-r--r--src/passes/Directize.cpp2
-rw-r--r--src/passes/DuplicateImportElimination.cpp2
-rw-r--r--src/passes/FuncCastEmulation.cpp4
-rw-r--r--src/passes/GenerateDynCalls.cpp31
-rw-r--r--src/passes/I64ToI32Lowering.cpp8
-rw-r--r--src/passes/Inlining.cpp8
-rw-r--r--src/passes/InstrumentLocals.cpp6
-rw-r--r--src/passes/InstrumentMemory.cpp6
-rw-r--r--src/passes/LegalizeJSInterface.cpp37
-rw-r--r--src/passes/LogExecution.cpp7
-rw-r--r--src/passes/Print.cpp10
-rw-r--r--src/passes/ReReloop.cpp4
-rw-r--r--src/passes/RemoveImports.cpp2
-rw-r--r--src/passes/ReorderLocals.cpp2
-rw-r--r--src/passes/SafeHeap.cpp44
-rw-r--r--src/passes/StackCheck.cpp6
-rw-r--r--src/passes/TrapMode.cpp18
-rw-r--r--src/passes/Vacuum.cpp4
-rw-r--r--src/shell-interface.h8
-rw-r--r--src/tools/execution-results.h6
-rw-r--r--src/tools/fuzzing.h72
-rw-r--r--src/tools/js-wrapper.h10
-rw-r--r--src/tools/spec-wrapper.h4
-rw-r--r--src/tools/wasm-ctor-eval.cpp2
-rw-r--r--src/tools/wasm-reduce.cpp8
-rw-r--r--src/tools/wasm2c-wrapper.h10
-rw-r--r--src/tools/wasm2js.cpp10
-rw-r--r--src/wasm-builder.h29
-rw-r--r--src/wasm-interpreter.h23
-rw-r--r--src/wasm.h8
-rw-r--r--src/wasm/wasm-binary.cpp16
-rw-r--r--src/wasm/wasm-s-parser.cpp20
-rw-r--r--src/wasm/wasm-validator.cpp28
-rw-r--r--src/wasm/wasm.cpp12
48 files changed, 278 insertions, 285 deletions
diff --git a/src/abi/js.h b/src/abi/js.h
index 118a2c981..970f7ffa7 100644
--- a/src/abi/js.h
+++ b/src/abi/js.h
@@ -18,6 +18,7 @@
#define wasm_abi_abi_h
#include "asmjs/shared-constants.h"
+#include "wasm-builder.h"
#include "wasm.h"
namespace wasm {
@@ -64,9 +65,7 @@ inline void ensureHelpers(Module* wasm,
if (specific.is() && name != specific) {
return;
}
- auto func = make_unique<Function>();
- func->name = name;
- func->sig = Signature(params, results);
+ auto func = Builder::makeFunction(name, Signature(params, results), {});
func->module = ENV;
func->base = name;
wasm->addFunction(std::move(func));
diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp
index 66c4341e3..d7f23e259 100644
--- a/src/binaryen-c.cpp
+++ b/src/binaryen-c.cpp
@@ -3280,7 +3280,8 @@ BinaryenFunctionRef BinaryenAddFunction(BinaryenModuleRef module,
BinaryenExpressionRef body) {
auto* ret = new Function;
ret->setExplicitName(name);
- ret->sig = Signature(Type(params), Type(results));
+ // TODO: Take a HeapType rather than params and results.
+ ret->type = Signature(Type(params), Type(results));
for (BinaryenIndex i = 0; i < numVarTypes; i++) {
ret->vars.push_back(Type(varTypes[i]));
}
@@ -3380,7 +3381,8 @@ void BinaryenAddFunctionImport(BinaryenModuleRef module,
ret->name = internalName;
ret->module = externalModuleName;
ret->base = externalBaseName;
- ret->sig = Signature(Type(params), Type(results));
+ // TODO: Take a HeapType rather than params and results.
+ ret->type = Signature(Type(params), Type(results));
((Module*)module)->addFunction(ret);
}
void BinaryenAddTableImport(BinaryenModuleRef module,
@@ -3547,7 +3549,7 @@ BinaryenAddActiveElementSegment(BinaryenModuleRef module,
Fatal() << "invalid function '" << funcNames[i] << "'.";
}
segment->data.push_back(
- Builder(*(Module*)module).makeRefFunc(funcNames[i], func->sig));
+ Builder(*(Module*)module).makeRefFunc(funcNames[i], func->type));
}
return ((Module*)module)->addElementSegment(std::move(segment));
}
@@ -3564,7 +3566,7 @@ BinaryenAddPassiveElementSegment(BinaryenModuleRef module,
Fatal() << "invalid function '" << funcNames[i] << "'.";
}
segment->data.push_back(
- Builder(*(Module*)module).makeRefFunc(funcNames[i], func->sig));
+ Builder(*(Module*)module).makeRefFunc(funcNames[i], func->type));
}
return ((Module*)module)->addElementSegment(std::move(segment));
}
@@ -4006,14 +4008,16 @@ const char* BinaryenModuleGetDebugInfoFileName(BinaryenModuleRef module,
// ========== Function Operations ==========
//
+// TODO: add BinaryenFunctionGetType
+
const char* BinaryenFunctionGetName(BinaryenFunctionRef func) {
return ((Function*)func)->name.c_str();
}
BinaryenType BinaryenFunctionGetParams(BinaryenFunctionRef func) {
- return ((Function*)func)->sig.params.getID();
+ return ((Function*)func)->getParams().getID();
}
BinaryenType BinaryenFunctionGetResults(BinaryenFunctionRef func) {
- return ((Function*)func)->sig.results.getID();
+ return ((Function*)func)->getResults().getID();
}
BinaryenIndex BinaryenFunctionGetNumVars(BinaryenFunctionRef func) {
return ((Function*)func)->vars.size();
diff --git a/src/ir/ExpressionAnalyzer.cpp b/src/ir/ExpressionAnalyzer.cpp
index 0c6081b03..260a9a6c4 100644
--- a/src/ir/ExpressionAnalyzer.cpp
+++ b/src/ir/ExpressionAnalyzer.cpp
@@ -60,7 +60,7 @@ bool ExpressionAnalyzer::isResultUsed(ExpressionStack& stack, Function* func) {
}
}
// The value might be used, so it depends on if the function returns
- return func->sig.results != Type::none;
+ return func->getResults() != Type::none;
}
// Checks if a value is dropped.
diff --git a/src/ir/ReFinalize.cpp b/src/ir/ReFinalize.cpp
index 6f1a22095..419b83cc2 100644
--- a/src/ir/ReFinalize.cpp
+++ b/src/ir/ReFinalize.cpp
@@ -171,7 +171,7 @@ void ReFinalize::visitRefAs(RefAs* curr) { curr->finalize(); }
void ReFinalize::visitFunction(Function* curr) {
// we may have changed the body from unreachable to none, which might be bad
// if the function has a return value
- if (curr->sig.results != Type::none && curr->body->type == Type::none) {
+ if (curr->getResults() != Type::none && curr->body->type == Type::none) {
Builder builder(*getModule());
curr->body = builder.blockify(curr->body, builder.makeUnreachable());
}
diff --git a/src/ir/function-utils.h b/src/ir/function-utils.h
index f172240e2..b1654d965 100644
--- a/src/ir/function-utils.h
+++ b/src/ir/function-utils.h
@@ -28,13 +28,13 @@ namespace FunctionUtils {
// everything but their name (which can't be the same, in the same
// module!) - same params, vars, body, result, etc.
inline bool equal(Function* left, Function* right) {
- if (left->sig != right->sig) {
+ if (left->type != right->type) {
return false;
}
if (left->getNumVars() != right->getNumVars()) {
return false;
}
- for (Index i = left->sig.params.size(); i < left->getNumLocals(); i++) {
+ for (Index i = left->getParams().size(); i < left->getNumLocals(); i++) {
if (left->getLocalType(i) != right->getLocalType(i)) {
return false;
}
diff --git a/src/ir/hashed.h b/src/ir/hashed.h
index fe959936a..4a6e1647e 100644
--- a/src/ir/hashed.h
+++ b/src/ir/hashed.h
@@ -64,8 +64,7 @@ struct FunctionHasher : public WalkerPass<PostWalker<FunctionHasher>> {
void doWalkFunction(Function* func) { output->at(func) = hashFunction(func); }
static size_t hashFunction(Function* func) {
- auto digest = hash(func->sig.params.getID());
- rehash(digest, func->sig.results.getID());
+ auto digest = hash(func->type);
for (auto type : func->vars) {
rehash(digest, type.getID());
}
diff --git a/src/ir/module-splitting.cpp b/src/ir/module-splitting.cpp
index 62c10222a..2ef9f505d 100644
--- a/src/ir/module-splitting.cpp
+++ b/src/ir/module-splitting.cpp
@@ -122,7 +122,7 @@ struct TableSlotManager {
ElementSegment* makeElementSegment();
// Returns the table index for `func`, allocating a new index if necessary.
- Slot getSlot(Name func, Signature sig);
+ Slot getSlot(Name func, HeapType type);
void addSlot(Name func, Slot slot);
};
@@ -209,7 +209,7 @@ ElementSegment* TableSlotManager::makeElementSegment() {
Builder(module).makeConst(int32_t(0))));
}
-TableSlotManager::Slot TableSlotManager::getSlot(Name func, Signature sig) {
+TableSlotManager::Slot TableSlotManager::getSlot(Name func, HeapType type) {
auto slotIt = funcIndices.find(func);
if (slotIt != funcIndices.end()) {
return slotIt->second;
@@ -237,7 +237,7 @@ TableSlotManager::Slot TableSlotManager::getSlot(Name func, Signature sig) {
activeBase.index + Index(activeSegment->data.size())};
Builder builder(module);
- activeSegment->data.push_back(builder.makeRefFunc(func, sig));
+ activeSegment->data.push_back(builder.makeRefFunc(func, type));
addSlot(func, newSlot);
if (activeTable->initial <= newSlot.index) {
@@ -365,7 +365,7 @@ void ModuleSplitter::exportImportFunction(Name funcName) {
// module.
if (secondary.getFunctionOrNull(funcName) == nullptr) {
auto func =
- Builder::makeFunction(funcName, primary.getFunction(funcName)->sig, {});
+ Builder::makeFunction(funcName, primary.getFunction(funcName)->type, {});
func->module = config.importNamespace;
func->base = exportName;
secondary.addFunction(std::move(func));
@@ -399,14 +399,15 @@ void ModuleSplitter::thunkExportedSecondaryFunctions() {
continue;
}
auto* func = primary.addFunction(Builder::makeFunction(
- secondaryFunc, secondary.getFunction(secondaryFunc)->sig, {}));
+ secondaryFunc, secondary.getFunction(secondaryFunc)->type, {}));
std::vector<Expression*> args;
- for (size_t i = 0, size = func->sig.params.size(); i < size; ++i) {
- args.push_back(builder.makeLocalGet(i, func->sig.params[i]));
+ Type params = func->getParams();
+ for (size_t i = 0, size = params.size(); i < size; ++i) {
+ args.push_back(builder.makeLocalGet(i, params[i]));
}
- auto tableSlot = tableManager.getSlot(secondaryFunc, func->sig);
+ auto tableSlot = tableManager.getSlot(secondaryFunc, func->type);
func->body = builder.makeCallIndirect(
- tableSlot.tableName, tableSlot.makeExpr(primary), args, func->sig);
+ tableSlot.tableName, tableSlot.makeExpr(primary), args, func->getSig());
}
}
@@ -425,12 +426,12 @@ void ModuleSplitter::indirectCallsToSecondaryFunctions() {
return;
}
auto* func = parent.secondary.getFunction(curr->target);
- auto tableSlot = parent.tableManager.getSlot(curr->target, func->sig);
+ auto tableSlot = parent.tableManager.getSlot(curr->target, func->type);
replaceCurrent(
builder.makeCallIndirect(tableSlot.tableName,
tableSlot.makeExpr(parent.primary),
curr->operands,
- func->sig,
+ func->getSig(),
curr->isReturn));
}
void visitRefFunc(RefFunc* curr) {
@@ -496,7 +497,7 @@ void ModuleSplitter::setupTablePatching() {
primary,
std::string("placeholder_") + std::string(placeholder->base.c_str()));
placeholder->hasExplicitName = false;
- placeholder->sig = secondaryFunc->sig;
+ placeholder->type = secondaryFunc->type;
elem = placeholder->name;
primary.addFunction(std::move(placeholder));
}
@@ -535,7 +536,7 @@ void ModuleSplitter::setupTablePatching() {
if (replacement->first == i) {
// primarySeg->data[i] is a placeholder, so use the secondary function.
auto* func = replacement->second;
- auto* ref = Builder(secondary).makeRefFunc(func->name, func->sig);
+ auto* ref = Builder(secondary).makeRefFunc(func->name, func->type);
secondaryElems.push_back(ref);
++replacement;
} else if (auto* get = primarySeg->data[i]->dynCast<RefFunc>()) {
@@ -574,7 +575,7 @@ void ModuleSplitter::setupTablePatching() {
currData.clear();
}
auto* func = curr->second;
- currData.push_back(Builder(secondary).makeRefFunc(func->name, func->sig));
+ currData.push_back(Builder(secondary).makeRefFunc(func->name, func->type));
}
if (currData.size()) {
finishSegment();
diff --git a/src/ir/module-utils.h b/src/ir/module-utils.h
index 9c9f5cbfb..2cbab414b 100644
--- a/src/ir/module-utils.h
+++ b/src/ir/module-utils.h
@@ -33,7 +33,7 @@ namespace ModuleUtils {
inline Function* copyFunction(Function* func, Module& out) {
auto* ret = new Function();
ret->name = func->name;
- ret->sig = func->sig;
+ ret->type = func->type;
ret->vars = func->vars;
ret->localNames = func->localNames;
ret->localIndices = func->localIndices;
@@ -526,7 +526,7 @@ inline void collectHeapTypes(Module& wasm,
// Collect info from functions in parallel.
ModuleUtils::ParallelFunctionAnalysis<Counts, InsertOrderedMap> analysis(
wasm, [&](Function* func, Counts& counts) {
- counts.note(func->sig);
+ counts.note(func->type);
for (auto type : func->vars) {
counts.note(type);
}
diff --git a/src/ir/table-utils.h b/src/ir/table-utils.h
index 59d7cc3df..99a5bbf5b 100644
--- a/src/ir/table-utils.h
+++ b/src/ir/table-utils.h
@@ -87,7 +87,7 @@ inline Index append(Table& table, Name name, Module& wasm) {
auto* func = wasm.getFunctionOrNull(name);
assert(func != nullptr && "Cannot append non-existing function to a table.");
- segment->data.push_back(Builder(wasm).makeRefFunc(name, func->sig));
+ segment->data.push_back(Builder(wasm).makeRefFunc(name, func->type));
table.initial++;
return tableIndex;
}
diff --git a/src/ir/utils.h b/src/ir/utils.h
index 78b546962..157293e31 100644
--- a/src/ir/utils.h
+++ b/src/ir/utils.h
@@ -237,7 +237,7 @@ struct AutoDrop : public WalkerPass<ExpressionStackWalker<AutoDrop>> {
void doWalkFunction(Function* curr) {
ReFinalize().walkFunctionInModule(curr, getModule());
walk(curr->body);
- if (curr->sig.results == Type::none && curr->body->type.isConcrete()) {
+ if (curr->getResults() == Type::none && curr->body->type.isConcrete()) {
curr->body = Builder(*getModule()).makeDrop(curr->body);
}
ReFinalize().walkFunctionInModule(curr, getModule());
diff --git a/src/passes/Asyncify.cpp b/src/passes/Asyncify.cpp
index 4bd9dee61..d0d03c9d1 100644
--- a/src/passes/Asyncify.cpp
+++ b/src/passes/Asyncify.cpp
@@ -862,7 +862,7 @@ struct AsyncifyFlow : public Pass {
State::Rewinding), // TODO: such checks can be !normal
makeCallIndexPop()),
process(func->body)});
- if (func->sig.results != Type::none) {
+ if (func->getResults() != Type::none) {
// Rewriting control flow may alter things; make sure the function ends in
// something valid (which the optimizer can remove later).
block->list.push_back(builder->makeUnreachable());
@@ -1204,7 +1204,7 @@ struct AsyncifyLocals : public WalkerPass<PostWalker<AsyncifyLocals>> {
walk(func->body);
// After the normal function body, emit a barrier before the postamble.
Expression* barrier;
- if (func->sig.results == Type::none) {
+ if (func->getResults() == Type::none) {
// The function may have ended without a return; ensure one.
barrier = builder->makeReturn();
} else {
@@ -1222,12 +1222,12 @@ struct AsyncifyLocals : public WalkerPass<PostWalker<AsyncifyLocals>> {
builder->makeSequence(func->body, barrier))),
makeCallIndexPush(unwindIndex),
makeLocalSaving()});
- if (func->sig.results != Type::none) {
+ if (func->getResults() != Type::none) {
// If we unwind, we must still "return" a value, even if it will be
// ignored on the outside.
newBody->list.push_back(
- LiteralUtils::makeZero(func->sig.results, *getModule()));
- newBody->finalize(func->sig.results);
+ LiteralUtils::makeZero(func->getResults(), *getModule()));
+ newBody->finalize(func->getResults());
}
func->body = newBody;
// Making things like returns conditional may alter types.
diff --git a/src/passes/CodeFolding.cpp b/src/passes/CodeFolding.cpp
index 5362e310d..5b7c88024 100644
--- a/src/passes/CodeFolding.cpp
+++ b/src/passes/CodeFolding.cpp
@@ -742,7 +742,7 @@ private:
mergeable.pop_back();
}
// ensure the replacement has the same type, so the outside is not surprised
- outer->finalize(getFunction()->sig.results);
+ outer->finalize(getFunction()->getResults());
getFunction()->body = outer;
return true;
}
diff --git a/src/passes/DeNaN.cpp b/src/passes/DeNaN.cpp
index 8dadb90de..44dd0bf15 100644
--- a/src/passes/DeNaN.cpp
+++ b/src/passes/DeNaN.cpp
@@ -120,9 +120,7 @@ struct DeNaN : public WalkerPass<
// Add helper functions after the walk, so they are not instrumented.
Builder builder(*module);
auto add = [&](Name name, Type type, Literal literal, BinaryOp op) {
- auto* func = new Function;
- func->name = name;
- func->sig = Signature(type, type);
+ auto func = Builder::makeFunction(name, Signature(type, type), {});
// Compare the value to itself to check if it is a NaN, and return 0 if
// so:
//
@@ -139,7 +137,7 @@ struct DeNaN : public WalkerPass<
op, builder.makeLocalGet(0, type), builder.makeLocalGet(0, type)),
builder.makeLocalGet(0, type),
builder.makeConst(literal));
- module->addFunction(func);
+ module->addFunction(std::move(func));
};
add(deNan32, Type::f32, Literal(float(0)), EqFloat32);
add(deNan64, Type::f64, Literal(double(0)), EqFloat64);
diff --git a/src/passes/DeadArgumentElimination.cpp b/src/passes/DeadArgumentElimination.cpp
index 33ca81dc7..a95d4f91a 100644
--- a/src/passes/DeadArgumentElimination.cpp
+++ b/src/passes/DeadArgumentElimination.cpp
@@ -405,7 +405,7 @@ struct DAE : public Pass {
// once to remove a param, once to drop the return value).
if (changed.empty()) {
for (auto& func : module->functions) {
- if (func->sig.results == Type::none) {
+ if (func->getResults() == Type::none) {
continue;
}
auto name = func->name;
@@ -451,10 +451,11 @@ private:
// Remove the parameter from the function. We must add a new local
// for uses of the parameter, but cannot make it use the same index
// (in general).
- std::vector<Type> params(func->sig.params.begin(), func->sig.params.end());
+ auto paramsType = func->getParams();
+ std::vector<Type> params(paramsType.begin(), paramsType.end());
auto type = params[i];
params.erase(params.begin() + i);
- func->sig.params = Type(params);
+ func->setParams(Type(params));
Index newIndex = Builder::addVar(func, type);
// Update local operations.
struct LocalUpdater : public PostWalker<LocalUpdater> {
@@ -482,7 +483,7 @@ private:
void
removeReturnValue(Function* func, std::vector<Call*>& calls, Module* module) {
- func->sig.results = Type::none;
+ func->setResults(Type::none);
Builder builder(*module);
// Remove any return values.
struct ReturnUpdater : public PostWalker<ReturnUpdater> {
diff --git a/src/passes/Directize.cpp b/src/passes/Directize.cpp
index 3a7ef1024..086cc88a5 100644
--- a/src/passes/Directize.cpp
+++ b/src/passes/Directize.cpp
@@ -66,7 +66,7 @@ struct FunctionDirectizer : public WalkerPass<PostWalker<FunctionDirectizer>> {
return;
}
auto* func = getModule()->getFunction(name);
- if (curr->sig != func->sig) {
+ if (curr->sig != func->getSig()) {
replaceWithUnreachable(curr);
return;
}
diff --git a/src/passes/DuplicateImportElimination.cpp b/src/passes/DuplicateImportElimination.cpp
index b917c5fe8..a4d9065c5 100644
--- a/src/passes/DuplicateImportElimination.cpp
+++ b/src/passes/DuplicateImportElimination.cpp
@@ -41,7 +41,7 @@ struct DuplicateImportElimination : public Pass {
auto previousFunc = module->getFunction(previousName);
// It is ok to import the same thing with multiple types; we can only
// merge if the types match, of course.
- if (previousFunc->sig == func->sig) {
+ if (previousFunc->type == func->type) {
replacements[func->name] = previousName;
toRemove.push_back(func->name);
continue;
diff --git a/src/passes/FuncCastEmulation.cpp b/src/passes/FuncCastEmulation.cpp
index e63375f2b..d8b9f9b1d 100644
--- a/src/passes/FuncCastEmulation.cpp
+++ b/src/passes/FuncCastEmulation.cpp
@@ -199,11 +199,11 @@ private:
}
// The item in the table may be a function or a function import.
auto* func = module->getFunction(name);
- Type type = func->sig.results;
+ Type type = func->getResults();
Builder builder(*module);
std::vector<Expression*> callOperands;
Index i = 0;
- for (const auto& param : func->sig.params) {
+ for (const auto& param : func->getParams()) {
callOperands.push_back(
fromABI(builder.makeLocalGet(i++, Type::i64), param, module));
}
diff --git a/src/passes/GenerateDynCalls.cpp b/src/passes/GenerateDynCalls.cpp
index 0f4934c06..2487085c0 100644
--- a/src/passes/GenerateDynCalls.cpp
+++ b/src/passes/GenerateDynCalls.cpp
@@ -40,8 +40,8 @@ struct GenerateDynCalls : public WalkerPass<PostWalker<GenerateDynCalls>> {
void doWalkModule(Module* wasm) {
PostWalker<GenerateDynCalls>::doWalkModule(wasm);
- for (auto& sig : invokeSigs) {
- generateDynCallThunk(sig);
+ for (auto& type : invokeTypes) {
+ generateDynCallThunk(type);
}
}
@@ -61,7 +61,7 @@ struct GenerateDynCalls : public WalkerPass<PostWalker<GenerateDynCalls>> {
std::vector<Name> tableSegmentData;
ElementUtils::iterElementSegmentFunctionNames(
it->get(), [&](Name name, Index) {
- generateDynCallThunk(wasm->getFunction(name)->sig);
+ generateDynCallThunk(wasm->getFunction(name)->type);
});
}
}
@@ -70,19 +70,19 @@ struct GenerateDynCalls : public WalkerPass<PostWalker<GenerateDynCalls>> {
// Generate dynCalls for invokes
if (func->imported() && func->module == ENV &&
func->base.startsWith("invoke_")) {
- Signature sig = func->sig;
+ Signature sig = func->type.getSignature();
// The first parameter is a pointer to the original function that's called
// by the invoke, so skip it
std::vector<Type> newParams(sig.params.begin() + 1, sig.params.end());
- invokeSigs.insert(Signature(Type(newParams), sig.results));
+ invokeTypes.insert(Signature(Type(newParams), sig.results));
}
}
- void generateDynCallThunk(Signature sig);
+ void generateDynCallThunk(HeapType funcType);
bool onlyI64;
- // The set of all invokes' signatures
- InsertOrderedSet<Signature> invokeSigs;
+ // The set of all invokes' signature types.
+ InsertOrderedSet<HeapType> invokeTypes;
};
static bool hasI64(Signature sig) {
@@ -116,7 +116,8 @@ static void exportFunction(Module& wasm, Name name, bool must_export) {
wasm.addExport(exp);
}
-void GenerateDynCalls::generateDynCallThunk(Signature sig) {
+void GenerateDynCalls::generateDynCallThunk(HeapType funcType) {
+ Signature sig = funcType.getSignature();
if (onlyI64 && !hasI64(sig)) {
return;
}
@@ -127,13 +128,17 @@ void GenerateDynCalls::generateDynCallThunk(Signature sig) {
if (wasm->getFunctionOrNull(name) || wasm->getExportOrNull(name)) {
return; // module already contains this dyncall
}
- std::vector<NameType> params;
- params.emplace_back("fptr", Type::i32); // function pointer param
+ std::vector<NameType> namedParams;
+ std::vector<Type> params;
+ namedParams.emplace_back("fptr", Type::i32); // function pointer param
+ params.push_back(Type::i32);
int p = 0;
for (const auto& param : sig.params) {
- params.emplace_back(std::to_string(p++), param);
+ namedParams.emplace_back(std::to_string(p++), param);
+ params.push_back(param);
}
- auto f = builder.makeFunction(name, std::move(params), sig.results, {});
+ auto f = builder.makeFunction(
+ name, std::move(namedParams), Signature(Type(params), sig.results), {});
Expression* fptr = builder.makeLocalGet(0, Type::i32);
std::vector<Expression*> args;
Index i = 0;
diff --git a/src/passes/I64ToI32Lowering.cpp b/src/passes/I64ToI32Lowering.cpp
index 36d0ce8f9..9b516342d 100644
--- a/src/passes/I64ToI32Lowering.cpp
+++ b/src/passes/I64ToI32Lowering.cpp
@@ -158,7 +158,7 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
freeTemps.clear();
Module temp;
auto* oldFunc = ModuleUtils::copyFunction(func, temp);
- func->sig.params = Type::none;
+ func->setParams(Type::none);
func->vars.clear();
func->localNames.clear();
func->localIndices.clear();
@@ -191,8 +191,8 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
if (func->imported()) {
return;
}
- if (func->sig.results == Type::i64) {
- func->sig.results = Type::i32;
+ if (func->getResults() == Type::i64) {
+ func->setResults(Type::i32);
// body may not have out param if it ends with control flow
if (hasOutParam(func->body)) {
TempVar highBits = fetchOutParam(func->body);
@@ -250,7 +250,7 @@ struct I64ToI32Lowering : public WalkerPass<PostWalker<I64ToI32Lowering>> {
}
void visitCall(Call* curr) {
if (curr->isReturn &&
- getModule()->getFunction(curr->target)->sig.results == Type::i64) {
+ getModule()->getFunction(curr->target)->getResults() == Type::i64) {
Fatal()
<< "i64 to i32 lowering of return_call values not yet implemented";
}
diff --git a/src/passes/Inlining.cpp b/src/passes/Inlining.cpp
index 8601b3409..1a84918bb 100644
--- a/src/passes/Inlining.cpp
+++ b/src/passes/Inlining.cpp
@@ -143,7 +143,7 @@ struct FunctionInfoScanner
// We cannot inline a function if we cannot handle placing it in a local, as
// all params become locals.
- for (auto param : curr->sig.params) {
+ for (auto param : curr->getParams()) {
if (!TypeUpdating::canHandleAsLocal(param)) {
info.uninlineable = true;
}
@@ -233,7 +233,7 @@ struct Updater : public PostWalker<Updater> {
}
void visitCall(Call* curr) {
if (curr->isReturn) {
- handleReturnCall(curr, module->getFunction(curr->target)->sig.results);
+ handleReturnCall(curr, module->getFunction(curr->target)->getResults());
}
}
void visitCallIndirect(CallIndirect* curr) {
@@ -262,7 +262,7 @@ doInlining(Module* module, Function* into, const InliningAction& action) {
Function* from = action.contents;
auto* call = (*action.callSite)->cast<Call>();
// Works for return_call, too
- Type retType = module->getFunction(call->target)->sig.results;
+ Type retType = module->getFunction(call->target)->getResults();
Builder builder(*module);
auto* block = builder.makeBlock();
block->name = Name(std::string("__inlined_func$") + from->name.str);
@@ -285,7 +285,7 @@ doInlining(Module* module, Function* into, const InliningAction& action) {
updater.localMapping[i] = builder.addVar(into, from->getLocalType(i));
}
// Assign the operands into the params
- for (Index i = 0; i < from->sig.params.size(); i++) {
+ for (Index i = 0; i < from->getParams().size(); i++) {
block->list.push_back(
builder.makeLocalSet(updater.localMapping[i], call->operands[i]));
}
diff --git a/src/passes/InstrumentLocals.cpp b/src/passes/InstrumentLocals.cpp
index 85da3bd9b..aab0ee3fe 100644
--- a/src/passes/InstrumentLocals.cpp
+++ b/src/passes/InstrumentLocals.cpp
@@ -245,12 +245,10 @@ private:
Index id = 0;
void addImport(Module* wasm, Name name, Type params, Type results) {
- auto import = new Function;
- import->name = name;
+ auto import = Builder::makeFunction(name, Signature(params, results), {});
import->module = ENV;
import->base = name;
- import->sig = Signature(params, results);
- wasm->addFunction(import);
+ wasm->addFunction(std::move(import));
}
};
diff --git a/src/passes/InstrumentMemory.cpp b/src/passes/InstrumentMemory.cpp
index 6c81f8588..38a23a658 100644
--- a/src/passes/InstrumentMemory.cpp
+++ b/src/passes/InstrumentMemory.cpp
@@ -158,12 +158,10 @@ private:
Index id;
void addImport(Module* curr, Name name, Type params, Type results) {
- auto import = new Function;
- import->name = name;
+ auto import = Builder::makeFunction(name, Signature(params, results), {});
import->module = ENV;
import->base = name;
- import->sig = Signature(params, results);
- curr->addFunction(import);
+ curr->addFunction(std::move(import));
}
};
diff --git a/src/passes/LegalizeJSInterface.cpp b/src/passes/LegalizeJSInterface.cpp
index 10e751701..e7a5f9220 100644
--- a/src/passes/LegalizeJSInterface.cpp
+++ b/src/passes/LegalizeJSInterface.cpp
@@ -157,12 +157,12 @@ private:
std::map<Name, Name> illegalImportsToLegal;
template<typename T> bool isIllegal(T* t) {
- for (const auto& param : t->sig.params) {
+ for (const auto& param : t->getParams()) {
if (param == Type::i64) {
return true;
}
}
- return t->sig.results == Type::i64;
+ return t->getResults() == Type::i64;
}
bool isDynCall(Name name) { return name.startsWith("dynCall_"); }
@@ -201,10 +201,10 @@ private:
auto* call = module->allocator.alloc<Call>();
call->target = func->name;
- call->type = func->sig.results;
+ call->type = func->getResults();
std::vector<Type> legalParams;
- for (const auto& param : func->sig.params) {
+ for (const auto& param : func->getParams()) {
if (param == Type::i64) {
call->operands.push_back(I64Utilities::recreateI64(
builder, legalParams.size(), legalParams.size() + 1));
@@ -216,12 +216,12 @@ private:
legalParams.push_back(param);
}
}
- legal->sig.params = Type(legalParams);
-
- if (func->sig.results == Type::i64) {
+ Type resultsType =
+ func->getResults() == Type::i64 ? Type::i32 : func->getResults();
+ legal->type = Signature(Type(legalParams), resultsType);
+ if (func->getResults() == Type::i64) {
Function* f =
getFunctionOrImport(module, SET_TEMP_RET0, Type::i32, Type::none);
- legal->sig.results = Type::i32;
auto index = Builder::addVar(legal, Name(), Type::i64);
auto* block = builder.makeBlock();
block->list.push_back(builder.makeLocalSet(index, call));
@@ -231,10 +231,8 @@ private:
block->finalize();
legal->body = block;
} else {
- legal->sig.results = func->sig.results;
legal->body = call;
}
-
return module->addFunction(legal)->name;
}
@@ -248,14 +246,14 @@ private:
legalIm->base = im->base;
auto stub = make_unique<Function>();
stub->name = Name(std::string("legalfunc$") + im->name.str);
- stub->sig = im->sig;
+ stub->type = im->type;
auto* call = module->allocator.alloc<Call>();
call->target = legalIm->name;
std::vector<Type> params;
Index i = 0;
- for (const auto& param : im->sig.params) {
+ for (const auto& param : im->getParams()) {
if (param == Type::i64) {
call->operands.push_back(I64Utilities::getI64Low(builder, i));
call->operands.push_back(I64Utilities::getI64High(builder, i));
@@ -268,17 +266,17 @@ private:
++i;
}
- if (im->sig.results == Type::i64) {
+ if (im->getResults() == Type::i64) {
Function* f =
getFunctionOrImport(module, GET_TEMP_RET0, Type::none, Type::i32);
call->type = Type::i32;
Expression* get = builder.makeCall(f->name, {}, call->type);
stub->body = I64Utilities::recreateI64(builder, call, get);
} else {
- call->type = im->sig.results;
+ call->type = im->getResults();
stub->body = call;
}
- legalIm->sig = Signature(Type(params), call->type);
+ legalIm->type = Signature(Type(params), call->type);
const auto& stubName = stub->name;
if (!module->getFunctionOrNull(stubName)) {
@@ -302,13 +300,12 @@ private:
return f;
}
// Failing that create a new function import.
- auto import = new Function;
- import->name = name;
+ auto import = Builder::makeFunction(name, Signature(params, results), {});
import->module = ENV;
import->base = name;
- import->sig = Signature(params, results);
- module->addFunction(import);
- return import;
+ auto* ret = import.get();
+ module->addFunction(std::move(import));
+ return ret;
}
};
diff --git a/src/passes/LogExecution.cpp b/src/passes/LogExecution.cpp
index b9b203d0b..5978ecc72 100644
--- a/src/passes/LogExecution.cpp
+++ b/src/passes/LogExecution.cpp
@@ -57,12 +57,11 @@ struct LogExecution : public WalkerPass<PostWalker<LogExecution>> {
void visitModule(Module* curr) {
// Add the import
- auto import = new Function;
- import->name = LOGGER;
+ auto import =
+ Builder::makeFunction(LOGGER, Signature(Type::i32, Type::none), {});
import->module = ENV;
import->base = LOGGER;
- import->sig = Signature(Type::i32, Type::none);
- curr->addFunction(import);
+ curr->addFunction(std::move(import));
}
private:
diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp
index c6bf13f42..491e44ca2 100644
--- a/src/passes/Print.cpp
+++ b/src/passes/Print.cpp
@@ -2596,7 +2596,7 @@ struct PrintSExpression : public UnifiedExpressionVisitor<PrintSExpression> {
lastPrintedLocation = {0, 0, 0};
o << '(';
emitImportHeader(curr);
- handleSignature(curr->sig, curr->name);
+ handleSignature(curr->getSig(), curr->name);
o << ')';
o << maybeNewLine;
}
@@ -2613,9 +2613,9 @@ struct PrintSExpression : public UnifiedExpressionVisitor<PrintSExpression> {
if (!stackIR && curr->stackIR && !minify) {
o << " (; has Stack IR ;)";
}
- if (curr->sig.params.size() > 0) {
+ if (curr->getParams().size() > 0) {
Index i = 0;
- for (const auto& param : curr->sig.params) {
+ for (const auto& param : curr->getParams()) {
o << maybeSpace;
o << '(';
printMinor(o, "param ");
@@ -2625,9 +2625,9 @@ struct PrintSExpression : public UnifiedExpressionVisitor<PrintSExpression> {
++i;
}
}
- if (curr->sig.results != Type::none) {
+ if (curr->getResults() != Type::none) {
o << maybeSpace;
- printResultType(o, curr->sig.results, currModule);
+ printResultType(o, curr->getResults(), currModule);
}
incIndent();
for (size_t i = curr->getVarIndexBase(); i < curr->getNumLocals(); i++) {
diff --git a/src/passes/ReReloop.cpp b/src/passes/ReReloop.cpp
index 9a82d8b44..0559343d4 100644
--- a/src/passes/ReReloop.cpp
+++ b/src/passes/ReReloop.cpp
@@ -318,7 +318,7 @@ struct ReReloop final : public Pass {
for (auto& cfgBlock : relooper->Blocks) {
auto* block = cfgBlock->Code->cast<Block>();
if (cfgBlock->BranchesOut.empty() && block->type != Type::unreachable) {
- block->list.push_back(function->sig.results == Type::none
+ block->list.push_back(function->getResults() == Type::none
? (Expression*)builder->makeReturn()
: (Expression*)builder->makeUnreachable());
block->finalize();
@@ -351,7 +351,7 @@ struct ReReloop final : public Pass {
// because of the relooper's boilerplate switch-handling
// code, for example, which could be optimized out later
// but isn't yet), then make sure it has a proper type
- if (function->sig.results != Type::none &&
+ if (function->getResults() != Type::none &&
function->body->type == Type::none) {
function->body =
builder.makeSequence(function->body, builder.makeUnreachable());
diff --git a/src/passes/RemoveImports.cpp b/src/passes/RemoveImports.cpp
index 2a1c119fd..af216ecbd 100644
--- a/src/passes/RemoveImports.cpp
+++ b/src/passes/RemoveImports.cpp
@@ -35,7 +35,7 @@ struct RemoveImports : public WalkerPass<PostWalker<RemoveImports>> {
if (!func->imported()) {
return;
}
- Type type = func->sig.results;
+ Type type = func->getResults();
if (type == Type::none) {
replaceCurrent(getModule()->allocator.alloc<Nop>());
} else {
diff --git a/src/passes/ReorderLocals.cpp b/src/passes/ReorderLocals.cpp
index 8d7c0f1d9..b34eeb3bf 100644
--- a/src/passes/ReorderLocals.cpp
+++ b/src/passes/ReorderLocals.cpp
@@ -82,7 +82,7 @@ struct ReorderLocals : public WalkerPass<PostWalker<ReorderLocals>> {
return counts[a] > counts[b];
});
// sorting left params in front, perhaps slightly reordered. verify and fix.
- size_t numParams = curr->sig.params.size();
+ size_t numParams = curr->getParams().size();
for (size_t i = 0; i < numParams; i++) {
assert(newToOld[i] < numParams);
newToOld[i] = i;
diff --git a/src/passes/SafeHeap.cpp b/src/passes/SafeHeap.cpp
index 2eed23256..a3416afaf 100644
--- a/src/passes/SafeHeap.cpp
+++ b/src/passes/SafeHeap.cpp
@@ -134,32 +134,33 @@ struct SafeHeap : public Pass {
} else if (auto* existing = info.getImportedFunction(ENV, SBRK)) {
sbrk = existing->name;
} else {
- auto* import = new Function;
- import->name = getSbrkPtr = GET_SBRK_PTR;
+ auto import = Builder::makeFunction(
+ GET_SBRK_PTR, Signature(Type::none, indexType), {});
+ getSbrkPtr = GET_SBRK_PTR;
import->module = ENV;
import->base = GET_SBRK_PTR;
- import->sig = Signature(Type::none, indexType);
- module->addFunction(import);
+ module->addFunction(std::move(import));
}
if (auto* existing = info.getImportedFunction(ENV, SEGFAULT_IMPORT)) {
segfault = existing->name;
} else {
- auto* import = new Function;
- import->name = segfault = SEGFAULT_IMPORT;
+ auto import = Builder::makeFunction(
+ SEGFAULT_IMPORT, Signature(Type::none, Type::none), {});
+ segfault = SEGFAULT_IMPORT;
import->module = ENV;
import->base = SEGFAULT_IMPORT;
- import->sig = Signature(Type::none, Type::none);
- module->addFunction(import);
+ module->addFunction(std::move(import));
}
if (auto* existing = info.getImportedFunction(ENV, ALIGNFAULT_IMPORT)) {
alignfault = existing->name;
} else {
- auto* import = new Function;
- import->name = alignfault = ALIGNFAULT_IMPORT;
+ auto import = Builder::makeFunction(
+ ALIGNFAULT_IMPORT, Signature(Type::none, Type::none), {});
+
+ alignfault = ALIGNFAULT_IMPORT;
import->module = ENV;
import->base = ALIGNFAULT_IMPORT;
- import->sig = Signature(Type::none, Type::none);
- module->addFunction(import);
+ module->addFunction(std::move(import));
}
}
@@ -246,12 +247,10 @@ struct SafeHeap : public Pass {
if (module->getFunctionOrNull(name)) {
return;
}
- auto* func = new Function;
- func->name = name;
// pointer, offset
auto indexType = module->memory.indexType;
- func->sig = Signature({indexType, indexType}, style.type);
- func->vars.push_back(indexType); // pointer + offset
+ auto funcSig = Signature({indexType, indexType}, style.type);
+ auto func = Builder::makeFunction(name, funcSig, {indexType});
Builder builder(*module);
auto* block = builder.makeBlock();
block->list.push_back(builder.makeLocalSet(
@@ -279,7 +278,7 @@ struct SafeHeap : public Pass {
block->list.push_back(last);
block->finalize(style.type);
func->body = block;
- module->addFunction(func);
+ module->addFunction(std::move(func));
}
// creates a function for a particular type of store
@@ -288,12 +287,11 @@ struct SafeHeap : public Pass {
if (module->getFunctionOrNull(name)) {
return;
}
- auto* func = new Function;
- func->name = name;
- // pointer, offset, value
auto indexType = module->memory.indexType;
- func->sig = Signature({indexType, indexType, style.valueType}, Type::none);
- func->vars.push_back(indexType); // pointer + offset
+ // pointer, offset, value
+ auto funcSig =
+ Signature({indexType, indexType, style.valueType}, Type::none);
+ auto func = Builder::makeFunction(name, funcSig, {indexType});
Builder builder(*module);
auto* block = builder.makeBlock();
block->list.push_back(builder.makeLocalSet(
@@ -316,7 +314,7 @@ struct SafeHeap : public Pass {
block->list.push_back(store);
block->finalize(Type::none);
func->body = block;
- module->addFunction(func);
+ module->addFunction(std::move(func));
}
Expression*
diff --git a/src/passes/StackCheck.cpp b/src/passes/StackCheck.cpp
index 23fd5be3d..e7fc3c6b3 100644
--- a/src/passes/StackCheck.cpp
+++ b/src/passes/StackCheck.cpp
@@ -39,12 +39,10 @@ static void importStackOverflowHandler(Module& module, Name name) {
ImportInfo info(module);
if (!info.getImportedFunction(ENV, name)) {
- auto* import = new Function;
- import->name = name;
+ auto import = Builder::makeFunction(name, Signature(), {});
import->module = ENV;
import->base = name;
- import->sig = Signature(Type::none, Type::none);
- module.addFunction(import);
+ module.addFunction(std::move(import));
}
}
diff --git a/src/passes/TrapMode.cpp b/src/passes/TrapMode.cpp
index 9c9dee9ca..ee245af88 100644
--- a/src/passes/TrapMode.cpp
+++ b/src/passes/TrapMode.cpp
@@ -132,14 +132,14 @@ Function* generateBinaryFunc(Module& wasm, Binary* curr) {
builder.makeConst(zeroLit),
result);
}
- auto func = new Function;
- func->name = getBinaryFuncName(curr);
- func->sig = Signature({type, type}, type);
+ auto funcSig = Signature({type, type}, type);
+ auto func = Builder::makeFunction(getBinaryFuncName(curr), funcSig, {});
func->body =
builder.makeIf(builder.makeUnary(eqZOp, builder.makeLocalGet(1, type)),
builder.makeConst(zeroLit),
result);
- return func;
+ // TODO: use unique_ptr properly and do not release ownership.
+ return func.release();
}
template<typename IntType, typename FloatType>
@@ -193,9 +193,8 @@ Function* generateUnaryFunc(Module& wasm, Unary* curr) {
WASM_UNREACHABLE("unexpected op");
}
- auto func = new Function;
- func->name = getUnaryFuncName(curr);
- func->sig = Signature(type, retType);
+ auto func =
+ Builder::makeFunction(getUnaryFuncName(curr), Signature(type, retType), {});
func->body = builder.makeUnary(truncOp, builder.makeLocalGet(0, type));
// too small XXX this is different than asm.js, which does frem. here we
// clamp, which is much simpler/faster, and similar to native builds
@@ -218,7 +217,8 @@ Function* generateUnaryFunc(Module& wasm, Unary* curr) {
// NB: min here as well. anything invalid => to the min
builder.makeConst(iMin),
func->body);
- return func;
+ // TODO: use unique_ptr properly and do not release ownership.
+ return func.release();
}
void ensureBinaryFunc(Binary* curr,
@@ -251,7 +251,7 @@ void ensureF64ToI64JSImport(TrappingFunctionContainer& trappingFunctions) {
import->name = F64_TO_INT;
import->module = ASM2WASM;
import->base = F64_TO_INT;
- import->sig = Signature(Type::f64, Type::i32);
+ import->type = Signature(Type::f64, Type::i32);
trappingFunctions.addImport(import);
}
diff --git a/src/passes/Vacuum.cpp b/src/passes/Vacuum.cpp
index 506eee5e6..25b0116b3 100644
--- a/src/passes/Vacuum.cpp
+++ b/src/passes/Vacuum.cpp
@@ -355,13 +355,13 @@ struct Vacuum : public WalkerPass<ExpressionStackWalker<Vacuum>> {
void visitFunction(Function* curr) {
auto* optimized =
- optimize(curr->body, curr->sig.results != Type::none, true);
+ optimize(curr->body, curr->getResults() != Type::none, true);
if (optimized) {
curr->body = optimized;
} else {
ExpressionManipulator::nop(curr->body);
}
- if (curr->sig.results == Type::none &&
+ if (curr->getResults() == Type::none &&
!EffectAnalyzer(getPassOptions(), getModule()->features, curr->body)
.hasSideEffects()) {
ExpressionManipulator::nop(curr->body);
diff --git a/src/shell-interface.h b/src/shell-interface.h
index 494722ab1..96b96cf15 100644
--- a/src/shell-interface.h
+++ b/src/shell-interface.h
@@ -174,19 +174,19 @@ struct ShellExternalInterface : ModuleInstance::ExternalInterface {
if (!func) {
trap("uninitialized table element");
}
- if (sig != func->sig) {
+ if (sig != func->getSig()) {
trap("callIndirect: function signatures don't match");
}
- if (func->sig.params.size() != arguments.size()) {
+ if (func->getParams().size() != arguments.size()) {
trap("callIndirect: bad # of arguments");
}
size_t i = 0;
- for (const auto& param : func->sig.params) {
+ for (const auto& param : func->getParams()) {
if (!Type::isSubType(arguments[i++].type, param)) {
trap("callIndirect: bad argument type");
}
}
- if (func->sig.results != results) {
+ if (func->getResults() != results) {
trap("callIndirect: bad result type");
}
if (func->imported()) {
diff --git a/src/tools/execution-results.h b/src/tools/execution-results.h
index 50f627baf..aabbb4819 100644
--- a/src/tools/execution-results.h
+++ b/src/tools/execution-results.h
@@ -106,14 +106,14 @@ struct ExecutionResults {
}
std::cout << "[fuzz-exec] calling " << exp->name << "\n";
auto* func = wasm.getFunction(exp->value);
- if (func->sig.results != Type::none) {
+ if (func->getResults() != Type::none) {
// this has a result
Literals ret = run(func, wasm, instance);
results[exp->name] = ret;
// ignore the result if we hit an unreachable and returned no value
if (ret.size() > 0) {
std::cout << "[fuzz-exec] note result: " << exp->name << " => ";
- auto resultType = func->sig.results;
+ auto resultType = func->getResults();
if (resultType.isRef()) {
// Don't print reference values, as funcref(N) contains an index
// for example, which is not guaranteed to remain identical after
@@ -227,7 +227,7 @@ struct ExecutionResults {
instance.callFunction(ex->value, arguments);
}
// call the method
- for (const auto& param : func->sig.params) {
+ for (const auto& param : func->getParams()) {
// zeros in arguments TODO: more?
if (!param.isDefaultable()) {
std::cout << "[trap fuzzer can only send defaultable parameters to "
diff --git a/src/tools/fuzzing.h b/src/tools/fuzzing.h
index 03efd8134..dcdfd391f 100644
--- a/src/tools/fuzzing.h
+++ b/src/tools/fuzzing.h
@@ -592,7 +592,7 @@ private:
auto funcName = Names::getValidFunctionName(wasm, exportName);
auto* func = new Function;
func->name = funcName;
- func->sig = Signature(Type::none, Type::none);
+ func->type = Signature(Type::none, Type::none);
func->body = builder.makeGlobalSet(HANG_LIMIT_GLOBAL,
builder.makeConst(int32_t(HANG_LIMIT)));
wasm.addFunction(func);
@@ -616,7 +616,7 @@ private:
func->name = name;
func->module = "fuzzing-support";
func->base = name;
- func->sig = Signature(type, Type::none);
+ func->type = Signature(type, Type::none);
wasm.addFunction(func);
}
}
@@ -684,7 +684,7 @@ private:
funcContext->typeLocals[type].push_back(params.size());
params.push_back(type);
}
- func->sig = Signature(Type(params), getControlFlowType());
+ func->type = Signature(Type(params), getControlFlowType());
Index numVars = upToSquared(MAX_VARS);
for (Index i = 0; i < numVars; i++) {
auto type = getConcreteType();
@@ -698,7 +698,7 @@ private:
func->vars.push_back(type);
}
// with small chance, make the body unreachable
- auto bodyType = func->sig.results;
+ auto bodyType = func->getResults();
if (oneIn(10)) {
bodyType = Type::unreachable;
}
@@ -737,7 +737,7 @@ private:
}
// add some to an elem segment
while (oneIn(3) && !finishedInput) {
- auto type = Type(HeapType(func->sig), NonNullable);
+ auto type = Type(func->type, NonNullable);
std::vector<ElementSegment*> compatibleSegments;
ModuleUtils::iterActiveElementSegments(
wasm, [&](ElementSegment* segment) {
@@ -746,7 +746,7 @@ private:
}
});
auto& randomElem = compatibleSegments[upTo(compatibleSegments.size())];
- randomElem->data.push_back(builder.makeRefFunc(func->name, func->sig));
+ randomElem->data.push_back(builder.makeRefFunc(func->name, func->type));
}
numAddedFunctions++;
return func;
@@ -760,8 +760,8 @@ private:
builder.makeSequence(makeHangLimitCheck(), loop->body, loop->type);
}
// recursion limit
- func->body =
- builder.makeSequence(makeHangLimitCheck(), func->body, func->sig.results);
+ func->body = builder.makeSequence(
+ makeHangLimitCheck(), func->body, func->getResults());
}
// Recombination and mutation can replace a node with another node of the same
@@ -967,7 +967,7 @@ private:
// We can't allow extra imports, as the fuzzing infrastructure wouldn't
// know what to provide.
func->module = func->base = Name();
- func->body = make(func->sig.results);
+ func->body = make(func->getResults());
}
// Optionally, fuzz the function contents.
if (upTo(RESOLUTION) >= chance) {
@@ -1033,12 +1033,12 @@ private:
std::vector<Expression*> invocations;
while (oneIn(2) && !finishedInput) {
std::vector<Expression*> args;
- for (const auto& type : func->sig.params) {
+ for (const auto& type : func->getParams()) {
args.push_back(makeConst(type));
}
Expression* invoke =
- builder.makeCall(func->name, args, func->sig.results);
- if (func->sig.results.isConcrete()) {
+ builder.makeCall(func->name, args, func->getResults());
+ if (func->getResults().isConcrete()) {
invoke = builder.makeDrop(invoke);
}
invocations.push_back(invoke);
@@ -1052,7 +1052,7 @@ private:
}
auto* invoker = new Function;
invoker->name = name;
- invoker->sig = Signature(Type::none, Type::none);
+ invoker->type = Signature(Type::none, Type::none);
invoker->body = builder.makeBlock(invocations);
wasm.addFunction(invoker);
auto* export_ = new Export;
@@ -1236,8 +1236,8 @@ private:
}
assert(type == Type::unreachable);
Expression* ret = nullptr;
- if (funcContext->func->sig.results.isConcrete()) {
- ret = makeTrivial(funcContext->func->sig.results);
+ if (funcContext->func->getResults().isConcrete()) {
+ ret = makeTrivial(funcContext->func->getResults());
}
return builder.makeReturn(ret);
}
@@ -1437,13 +1437,13 @@ private:
target = pick(wasm.functions).get();
}
isReturn = type == Type::unreachable && wasm.features.hasTailCall() &&
- funcContext->func->sig.results == target->sig.results;
- if (target->sig.results != type && !isReturn) {
+ funcContext->func->getResults() == target->getResults();
+ if (target->getResults() != type && !isReturn) {
continue;
}
// we found one!
std::vector<Expression*> args;
- for (const auto& argType : target->sig.params) {
+ for (const auto& argType : target->getParams()) {
args.push_back(make(argType));
}
return builder.makeCall(target->name, args, type, isReturn);
@@ -1468,8 +1468,8 @@ private:
if (auto* get = data[i]->dynCast<RefFunc>()) {
targetFn = wasm.getFunction(get->func);
isReturn = type == Type::unreachable && wasm.features.hasTailCall() &&
- funcContext->func->sig.results == targetFn->sig.results;
- if (targetFn->sig.results == type || isReturn) {
+ funcContext->func->getResults() == targetFn->getResults();
+ if (targetFn->getResults() == type || isReturn) {
break;
}
}
@@ -1490,12 +1490,12 @@ private:
target = make(Type::i32);
}
std::vector<Expression*> args;
- for (const auto& type : targetFn->sig.params) {
+ for (const auto& type : targetFn->getParams()) {
args.push_back(make(type));
}
// TODO: use a random table
return builder.makeCallIndirect(
- funcrefTableName, target, args, targetFn->sig, isReturn);
+ funcrefTableName, target, args, targetFn->getSig(), isReturn);
}
Expression* makeCallRef(Type type) {
@@ -1511,19 +1511,19 @@ private:
// TODO: handle unreachable
target = wasm.functions[upTo(wasm.functions.size())].get();
isReturn = type == Type::unreachable && wasm.features.hasTailCall() &&
- funcContext->func->sig.results == target->sig.results;
- if (target->sig.results == type || isReturn) {
+ funcContext->func->getResults() == target->getResults();
+ if (target->getResults() == type || isReturn) {
break;
}
i++;
}
std::vector<Expression*> args;
- for (const auto& type : target->sig.params) {
+ for (const auto& type : target->getParams()) {
args.push_back(make(type));
}
// TODO: half the time make a completely random item with that type.
return builder.makeCallRef(
- builder.makeRefFunc(target->name, target->sig), args, type, isReturn);
+ builder.makeRefFunc(target->name, target->type), args, type, isReturn);
}
Expression* makeLocalGet(Type type) {
@@ -2112,7 +2112,7 @@ private:
if (!wasm.functions.empty() && !oneIn(wasm.functions.size())) {
target = pick(wasm.functions).get();
}
- return builder.makeRefFunc(target->name, target->sig);
+ return builder.makeRefFunc(target->name, target->type);
}
if (type == Type::i31ref) {
return builder.makeI31New(makeConst(Type::i32));
@@ -2133,8 +2133,8 @@ private:
}
// TODO: randomize the order
for (auto& func : wasm.functions) {
- if (type == Type(HeapType(func->sig), NonNullable)) {
- return builder.makeRefFunc(func->name, func->sig);
+ if (type == Type(func->type, NonNullable)) {
+ return builder.makeRefFunc(func->name, func->type);
}
}
// We failed to find a function, so create a null reference if we can.
@@ -2143,17 +2143,13 @@ private:
}
// Last resort: create a function.
auto heapType = type.getHeapType();
- Signature sig;
- if (heapType.isSignature()) {
- sig = heapType.getSignature();
- } else {
- assert(heapType == HeapType::func);
+ if (heapType == HeapType::func) {
// The specific signature does not matter.
- sig = Signature(Type::none, Type::none);
+ heapType = Signature(Type::none, Type::none);
}
auto* func = wasm.addFunction(builder.makeFunction(
Names::getValidFunctionName(wasm, "ref_func_target"),
- sig,
+ heapType,
{},
builder.makeUnreachable()));
return builder.makeRefFunc(func->name, heapType);
@@ -2681,8 +2677,8 @@ private:
}
Expression* makeReturn(Type type) {
- return builder.makeReturn(funcContext->func->sig.results.isConcrete()
- ? make(funcContext->func->sig.results)
+ return builder.makeReturn(funcContext->func->getResults().isConcrete()
+ ? make(funcContext->func->getResults())
: nullptr);
}
diff --git a/src/tools/js-wrapper.h b/src/tools/js-wrapper.h
index e6f553124..b93948e74 100644
--- a/src/tools/js-wrapper.h
+++ b/src/tools/js-wrapper.h
@@ -25,7 +25,7 @@
namespace wasm {
-static std::string generateJSWrapper(Module& wasm) {
+inline std::string generateJSWrapper(Module& wasm) {
std::string ret;
ret += "if (typeof console === 'undefined') {\n"
" console = { log: print };\n"
@@ -96,7 +96,7 @@ static std::string generateJSWrapper(Module& wasm) {
ret += "try {\n";
ret += std::string(" console.log('[fuzz-exec] calling ") + exp->name.str +
"');\n";
- if (func->sig.results != Type::none) {
+ if (func->getResults() != Type::none) {
ret += std::string(" console.log('[fuzz-exec] note result: ") +
exp->name.str + " => ' + literal(";
} else {
@@ -104,7 +104,7 @@ static std::string generateJSWrapper(Module& wasm) {
}
ret += std::string("instance.exports.") + exp->name.str + "(";
bool first = true;
- for (auto param : func->sig.params) {
+ for (auto param : func->getParams()) {
// zeros in arguments TODO more?
if (first) {
first = false;
@@ -121,8 +121,8 @@ static std::string generateJSWrapper(Module& wasm) {
}
}
ret += ")";
- if (func->sig.results != Type::none) {
- ret += ", '" + func->sig.results.toString() + "'))";
+ if (func->getResults() != Type::none) {
+ ret += ", '" + func->getResults().toString() + "'))";
// TODO: getTempRet
}
ret += ";\n";
diff --git a/src/tools/spec-wrapper.h b/src/tools/spec-wrapper.h
index 32e547f1b..3a490c954 100644
--- a/src/tools/spec-wrapper.h
+++ b/src/tools/spec-wrapper.h
@@ -24,7 +24,7 @@
namespace wasm {
-static std::string generateSpecWrapper(Module& wasm) {
+inline std::string generateSpecWrapper(Module& wasm) {
std::string ret;
for (auto& exp : wasm.exports) {
auto* func = wasm.getFunctionOrNull(exp->value);
@@ -33,7 +33,7 @@ static std::string generateSpecWrapper(Module& wasm) {
}
ret += std::string("(invoke \"hangLimitInitializer\") (invoke \"") +
exp->name.str + "\" ";
- for (const auto& param : func->sig.params) {
+ for (const auto& param : func->getParams()) {
// zeros in arguments TODO more?
TODO_SINGLE_COMPOUND(param);
switch (param.getBasic()) {
diff --git a/src/tools/wasm-ctor-eval.cpp b/src/tools/wasm-ctor-eval.cpp
index 5bede4444..bd370a58a 100644
--- a/src/tools/wasm-ctor-eval.cpp
+++ b/src/tools/wasm-ctor-eval.cpp
@@ -322,7 +322,7 @@ struct CtorEvalExternalInterface : EvallingModuleInstance::ExternalInterface {
// if this is one of our functions, we can call it; if it was
// imported, fail
auto* func = wasm->getFunction(name);
- if (func->sig != sig) {
+ if (func->getSig() != sig) {
throw FailToEvalException(
std::string("callTable signature mismatch: ") + name.str);
}
diff --git a/src/tools/wasm-reduce.cpp b/src/tools/wasm-reduce.cpp
index 48435fac0..ed2b9b564 100644
--- a/src/tools/wasm-reduce.cpp
+++ b/src/tools/wasm-reduce.cpp
@@ -483,7 +483,7 @@ struct Reducer
auto* save = curr;
Unreachable un;
Nop nop;
- bool useUnreachable = getFunction()->sig.results != Type::none;
+ bool useUnreachable = getFunction()->getResults() != Type::none;
if (useUnreachable) {
replaceCurrent(&un);
} else {
@@ -977,7 +977,7 @@ struct Reducer
auto* func = module->functions[0].get();
// We can't remove something that might have breaks to it.
if (!func->imported() && !Properties::isNamedControlFlow(func->body)) {
- auto funcSig = func->sig;
+ auto funcType = func->type;
auto* funcBody = func->body;
for (auto* child : ChildIterator(func->body)) {
if (!(child->type.isConcrete() || child->type == Type::none)) {
@@ -985,7 +985,7 @@ struct Reducer
}
// Try to replace the body with the child, fixing up the function
// to accept it.
- func->sig.results = child->type;
+ func->type = Signature(funcType.getSignature().params, child->type);
func->body = child;
if (writeAndTestReduction()) {
// great, we succeeded!
@@ -994,7 +994,7 @@ struct Reducer
break;
}
// Undo.
- func->sig = funcSig;
+ func->type = funcType;
func->body = funcBody;
}
}
diff --git a/src/tools/wasm2c-wrapper.h b/src/tools/wasm2c-wrapper.h
index de235c35e..ae32ec744 100644
--- a/src/tools/wasm2c-wrapper.h
+++ b/src/tools/wasm2c-wrapper.h
@@ -27,7 +27,7 @@
namespace wasm {
// Mangle a name in (hopefully) exactly the same way wasm2c does.
-static std::string wasm2cMangle(Name name, Signature sig) {
+inline std::string wasm2cMangle(Name name, Signature sig) {
const char escapePrefix = 'Z';
std::string mangled = "Z_";
const char* original = name.str;
@@ -78,7 +78,7 @@ static std::string wasm2cMangle(Name name, Signature sig) {
return mangled;
}
-static std::string generateWasm2CWrapper(Module& wasm) {
+inline std::string generateWasm2CWrapper(Module& wasm) {
// First, emit implementations of the wasm's imports so that the wasm2c code
// can call them. The names use wasm2c's name mangling.
std::string ret = R"(
@@ -169,7 +169,7 @@ int main(int argc, char** argv) {
ret += std::string(" puts(\"[fuzz-exec] calling ") +
exp->name.str + "\");\n";
- auto result = func->sig.results;
+ auto result = func->getResults();
// Emit the call itself.
ret += " ";
@@ -199,13 +199,13 @@ int main(int argc, char** argv) {
ret += "(*";
// Emit the callee's name with wasm2c name mangling.
- ret += wasm2cMangle(exp->name, func->sig);
+ ret += wasm2cMangle(exp->name, func->getSig());
ret += ")(";
// Emit the parameters (all 0s, like the other wrappers).
bool first = true;
- for (const auto& param : func->sig.params) {
+ for (const auto& param : func->getParams()) {
WASM_UNUSED(param);
if (!first) {
ret += ", ";
diff --git a/src/tools/wasm2js.cpp b/src/tools/wasm2js.cpp
index 06b24ea26..4736dee08 100644
--- a/src/tools/wasm2js.cpp
+++ b/src/tools/wasm2js.cpp
@@ -604,7 +604,7 @@ Expression* AssertionEmitter::parseInvoke(Builder& wasmBuilder,
for (size_t i = 2; i < e.size(); ++i) {
args.push_back(sexpBuilder.parseExpression(e[i]));
}
- Type type = module.getFunction(module.getExport(target)->value)->sig.results;
+ Type type = module.getFunction(module.getExport(target)->value)->getResults();
return wasmBuilder.makeCall(target, args, type);
}
@@ -658,7 +658,7 @@ Ref AssertionEmitter::emitAssertReturnFunc(Builder& wasmBuilder,
std::unique_ptr<Function> testFunc(
wasmBuilder.makeFunction(testFuncName,
std::vector<NameType>{},
- body->type,
+ Signature(Type::none, body->type),
std::vector<NameType>{},
body));
Ref jsFunc = processFunction(testFunc.get());
@@ -676,7 +676,7 @@ Ref AssertionEmitter::emitAssertReturnNanFunc(Builder& wasmBuilder,
std::unique_ptr<Function> testFunc(
wasmBuilder.makeFunction(testFuncName,
std::vector<NameType>{},
- body->type,
+ Signature(Type::none, body->type),
std::vector<NameType>{},
body));
Ref jsFunc = processFunction(testFunc.get());
@@ -695,7 +695,7 @@ Ref AssertionEmitter::emitAssertTrapFunc(Builder& wasmBuilder,
std::unique_ptr<Function> exprFunc(
wasmBuilder.makeFunction(innerFuncName,
std::vector<NameType>{},
- expr->type,
+ Signature(Type::none, expr->type),
std::vector<NameType>{},
expr));
IString expectedErr = e[2]->str();
@@ -729,7 +729,7 @@ Ref AssertionEmitter::emitInvokeFunc(Builder& wasmBuilder,
std::unique_ptr<Function> testFunc(
wasmBuilder.makeFunction(testFuncName,
std::vector<NameType>{},
- body->type,
+ Signature(Type::none, body->type),
std::vector<NameType>{},
body));
Ref jsFunc = processFunction(testFunc.get());
diff --git a/src/wasm-builder.h b/src/wasm-builder.h
index a3b0febaa..876474223 100644
--- a/src/wasm-builder.h
+++ b/src/wasm-builder.h
@@ -43,12 +43,13 @@ public:
// make* functions create an expression instance.
static std::unique_ptr<Function> makeFunction(Name name,
- Signature sig,
+ HeapType type,
std::vector<Type>&& vars,
Expression* body = nullptr) {
+ assert(type.isSignature());
auto func = std::make_unique<Function>();
func->name = name;
- func->sig = sig;
+ func->type = type;
func->body = body;
func->vars.swap(vars);
return func;
@@ -56,20 +57,21 @@ public:
static std::unique_ptr<Function> makeFunction(Name name,
std::vector<NameType>&& params,
- Type resultType,
+ HeapType type,
std::vector<NameType>&& vars,
Expression* body = nullptr) {
+ assert(type.isSignature());
auto func = std::make_unique<Function>();
func->name = name;
+ func->type = type;
func->body = body;
- std::vector<Type> paramVec;
- for (auto& param : params) {
- paramVec.push_back(param.type);
+ for (size_t i = 0; i < params.size(); ++i) {
+ NameType& param = params[i];
+ assert(func->getParams()[i] == param.type);
Index index = func->localNames.size();
func->localIndices[param.name] = index;
func->localNames[index] = param.name;
}
- func->sig = Signature(Type(paramVec), resultType);
for (auto& var : vars) {
func->vars.push_back(var.type);
Index index = func->localNames.size();
@@ -948,11 +950,12 @@ public:
static Index addParam(Function* func, Name name, Type type) {
// only ok to add a param if no vars, otherwise indices are invalidated
- assert(func->localIndices.size() == func->sig.params.size());
+ assert(func->localIndices.size() == func->getParams().size());
assert(name.is());
- std::vector<Type> params(func->sig.params.begin(), func->sig.params.end());
+ Signature sig = func->getSig();
+ std::vector<Type> params(sig.params.begin(), sig.params.end());
params.push_back(type);
- func->sig.params = Type(params);
+ func->type = Signature(Type(params), sig.results);
Index index = func->localNames.size();
func->localIndices[name] = index;
func->localNames[index] = name;
@@ -980,12 +983,6 @@ public:
func->localIndices.clear();
}
- static void clearLocals(Function* func) {
- func->sig.params = Type::none;
- func->vars.clear();
- clearLocalNames(func);
- }
-
// ensure a node is a block, if it isn't already, and optionally append to the
// block
Block* blockify(Expression* any, Expression* append = nullptr) {
diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h
index 2ffb542c7..77b055fd1 100644
--- a/src/wasm-interpreter.h
+++ b/src/wasm-interpreter.h
@@ -1452,7 +1452,7 @@ public:
cast.breaking = NONCONSTANT_FLOW;
return cast;
}
- seenRtt = Literal(Type(Rtt(0, func->sig)));
+ seenRtt = Literal(Type(Rtt(0, func->type)));
if (!seenRtt.isSubRtt(intendedRtt)) {
cast.outcome = cast.Failure;
return cast;
@@ -2019,7 +2019,7 @@ public:
if ((flags & FlagValues::TRAVERSE_CALLS) != 0 && this->module != nullptr) {
auto* func = this->module->getFunction(curr->target);
if (!func->imported()) {
- if (func->sig.results.isConcrete()) {
+ if (func->getResults().isConcrete()) {
auto numOperands = curr->operands.size();
assert(numOperands == func->getNumParams());
auto prevLocalValues = localValues;
@@ -2425,6 +2425,7 @@ private:
void initializeTableContents() {
ModuleUtils::iterActiveElementSegments(wasm, [&](ElementSegment* segment) {
Function dummyFunc;
+ dummyFunc.type = Signature(Type::none, Type::none);
FunctionScope dummyScope(&dummyFunc, {});
RuntimeExpressionRunner runner(*this, dummyScope, maxDepth);
@@ -2476,6 +2477,7 @@ private:
// we don't actually have a function, but we need one in order to visit
// the memory.init and data.drop instructions.
Function dummyFunc;
+ dummyFunc.type = Signature(Type::none, Type::none);
FunctionScope dummyScope(&dummyFunc, {});
RuntimeExpressionRunner runner(*this, dummyScope, maxDepth);
runner.visit(&init);
@@ -2490,19 +2492,20 @@ private:
FunctionScope(Function* function, const LiteralList& arguments)
: function(function) {
- if (function->sig.params.size() != arguments.size()) {
+ if (function->getParams().size() != arguments.size()) {
std::cerr << "Function `" << function->name << "` expects "
- << function->sig.params.size() << " parameters, got "
+ << function->getParams().size() << " parameters, got "
<< arguments.size() << " arguments." << std::endl;
WASM_UNREACHABLE("invalid param count");
}
locals.resize(function->getNumLocals());
+ Type params = function->getParams();
for (size_t i = 0; i < function->getNumLocals(); i++) {
if (i < arguments.size()) {
- if (!Type::isSubType(arguments[i].type, function->sig.params[i])) {
+ if (!Type::isSubType(arguments[i].type, params[i])) {
std::cerr << "Function `" << function->name << "` expects type "
- << function->sig.params[i] << " for parameter " << i
- << ", got " << arguments[i].type << "." << std::endl;
+ << params[i] << " for parameter " << i << ", got "
+ << arguments[i].type << "." << std::endl;
WASM_UNREACHABLE("invalid param count");
}
locals[i] = {arguments[i]};
@@ -2590,7 +2593,7 @@ private:
}
Index index = target.getSingleValue().geti32();
- Type type = curr->isReturn ? scope.function->sig.results : curr->type;
+ Type type = curr->isReturn ? scope.function->getResults() : curr->type;
Flow ret;
auto* table = instance.wasm.getTable(curr->table);
@@ -3345,9 +3348,9 @@ public:
// cannot still be breaking, it means we missed our stop
assert(!flow.breaking() || flow.breakTo == RETURN_FLOW);
auto type = flow.getType();
- if (!Type::isSubType(type, function->sig.results)) {
+ if (!Type::isSubType(type, function->getResults())) {
std::cerr << "calling " << function->name << " resulted in " << type
- << " but the function type is " << function->sig.results
+ << " but the function type is " << function->getResults()
<< '\n';
WASM_UNREACHABLE("unexpected result type");
}
diff --git a/src/wasm.h b/src/wasm.h
index d02d9a1a7..268611f34 100644
--- a/src/wasm.h
+++ b/src/wasm.h
@@ -1609,7 +1609,7 @@ using StackIR = std::vector<StackInst*>;
class Function : public Importable {
public:
- Signature sig; // parameters and return value
+ HeapType type = HeapType(Signature()); // parameters and return value
IRProfile profile = IRProfile::Normal;
std::vector<Type> vars; // non-param locals
@@ -1658,6 +1658,12 @@ public:
delimiterLocations;
BinaryLocations::FunctionLocations funcLocation;
+ Signature getSig() { return type.getSignature(); }
+ Type getParams() { return getSig().params; }
+ Type getResults() { return getSig().results; }
+ void setParams(Type params) { type = Signature(params, getResults()); }
+ void setResults(Type results) { type = Signature(getParams(), results); }
+
size_t getNumParams();
size_t getNumVars();
size_t getNumLocals();
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp
index 779df5c65..31fe1bc6e 100644
--- a/src/wasm/wasm-binary.cpp
+++ b/src/wasm/wasm-binary.cpp
@@ -269,7 +269,7 @@ void WasmBinaryWriter::writeImports() {
BYN_TRACE("write one function\n");
writeImportHeader(func);
o << U32LEB(int32_t(ExternalKind::Function));
- o << U32LEB(getTypeIndex(func->sig));
+ o << U32LEB(getTypeIndex(func->type));
});
ModuleUtils::iterImportedGlobals(*wasm, [&](Global* global) {
BYN_TRACE("write one global\n");
@@ -318,7 +318,7 @@ void WasmBinaryWriter::writeFunctionSignatures() {
o << U32LEB(importInfo->getNumDefinedFunctions());
ModuleUtils::iterDefinedFunctions(*wasm, [&](Function* func) {
BYN_TRACE("write one\n");
- o << U32LEB(getTypeIndex(func->sig));
+ o << U32LEB(getTypeIndex(func->type));
});
finishSection(start);
}
@@ -2008,8 +2008,7 @@ void WasmBinaryBuilder::readImports() {
Name name(std::string("fimport$") + std::to_string(functionCounter++));
auto index = getU32LEB();
functionTypes.push_back(getTypeByIndex(index));
- auto curr =
- builder.makeFunction(name, getSignatureByTypeIndex(index), {});
+ auto curr = builder.makeFunction(name, getTypeByIndex(index), {});
curr->module = module;
curr->base = base;
functionImports.push_back(curr.get());
@@ -2158,7 +2157,7 @@ void WasmBinaryBuilder::readFunctions() {
auto* func = new Function;
func->name = Name::fromInt(i);
- func->sig = getSignatureByFunctionIndex(functionImports.size() + i);
+ func->type = getTypeByFunctionIndex(functionImports.size() + i);
currFunction = func;
if (DWARF) {
@@ -2197,7 +2196,7 @@ void WasmBinaryBuilder::readFunctions() {
auto currFunctionIndex = functionImports.size() + functions.size();
bool isStart = startIndex == currFunctionIndex;
if (!skipFunctionBodies || isStart) {
- func->body = getBlockOrSingleton(func->sig.results);
+ func->body = getBlockOrSingleton(func->getResults());
} else {
// When skipping the function body we need to put something valid in
// their place so we validate. An unreachable is always acceptable
@@ -6004,8 +6003,9 @@ void WasmBinaryBuilder::visitSelect(Select* curr, uint8_t code) {
void WasmBinaryBuilder::visitReturn(Return* curr) {
BYN_TRACE("zz node: Return\n");
requireFunctionContext("return");
- if (currFunction->sig.results.isConcrete()) {
- curr->value = popTypedExpression(currFunction->sig.results);
+ Type type = currFunction->getResults();
+ if (type.isConcrete()) {
+ curr->value = popTypedExpression(type);
}
curr->finalize();
}
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp
index bda94dec5..25be13f58 100644
--- a/src/wasm/wasm-s-parser.cpp
+++ b/src/wasm/wasm-s-parser.cpp
@@ -914,9 +914,7 @@ void SExpressionWasmBuilder::preParseFunctionType(Element& s) {
}
functionNames.push_back(name);
functionCounter++;
- HeapType type;
- parseTypeUse(s, i, type);
- functionTypes[name] = type;
+ parseTypeUse(s, i, functionTypes[name]);
}
size_t SExpressionWasmBuilder::parseFunctionNames(Element& s,
@@ -1007,12 +1005,12 @@ void SExpressionWasmBuilder::parseFunction(Element& s, bool preParseImport) {
im->setName(name, hasExplicitName);
im->module = importModule;
im->base = importBase;
- im->sig = type.getSignature();
+ im->type = type;
functionTypes[name] = type;
if (wasm.getFunctionOrNull(im->name)) {
throw ParseException("duplicate import", s.line, s.col);
}
- wasm.addFunction(im.release());
+ wasm.addFunction(std::move(im));
if (currFunction) {
throw ParseException("import module inside function dec", s.line, s.col);
}
@@ -1034,8 +1032,8 @@ void SExpressionWasmBuilder::parseFunction(Element& s, bool preParseImport) {
}
// make a new function
- currFunction = std::unique_ptr<Function>(Builder(wasm).makeFunction(
- name, std::move(params), type.getSignature().results, std::move(vars)));
+ currFunction = std::unique_ptr<Function>(
+ Builder(wasm).makeFunction(name, std::move(params), type, std::move(vars)));
currFunction->profile = profile;
// parse body
@@ -3045,13 +3043,11 @@ void SExpressionWasmBuilder::parseImport(Element& s) {
if (kind == ExternalKind::Function) {
auto func = make_unique<Function>();
- HeapType funcType;
- j = parseTypeUse(inner, j, funcType);
- func->sig = funcType.getSignature();
+ j = parseTypeUse(inner, j, func->type);
func->setName(name, hasExplicitName);
func->module = module;
func->base = base;
- functionTypes[name] = funcType;
+ functionTypes[name] = func->type;
wasm.addFunction(func.release());
} else if (kind == ExternalKind::Global) {
Type type;
@@ -3403,7 +3399,7 @@ ElementSegment* SExpressionWasmBuilder::parseElemFinish(
for (; i < s.size(); i++) {
auto func = getFunctionName(*s[i]);
segment->data.push_back(
- Builder(wasm).makeRefFunc(func, functionTypes[func].getSignature()));
+ Builder(wasm).makeRefFunc(func, functionTypes[func]));
}
}
return wasm.addElementSegment(std::move(segment));
diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp
index bed04b92b..f492c7110 100644
--- a/src/wasm/wasm-validator.cpp
+++ b/src/wasm/wasm-validator.cpp
@@ -461,7 +461,7 @@ private:
curr,
"return_call* should have unreachable type");
shouldBeEqual(
- getFunction()->sig.results,
+ getFunction()->getResults(),
sig.results,
curr,
"return_call* callee return type must match caller return type");
@@ -785,7 +785,7 @@ void FunctionValidator::visitCall(Call* curr) {
if (!shouldBeTrue(!!target, curr, "call target must exist")) {
return;
}
- validateCallParamsAndResult(curr, target->sig);
+ validateCallParamsAndResult(curr, target->getSig());
}
void FunctionValidator::visitCallIndirect(CallIndirect* curr) {
@@ -2481,17 +2481,17 @@ void FunctionValidator::visitArrayCopy(ArrayCopy* curr) {
}
void FunctionValidator::visitFunction(Function* curr) {
- if (curr->sig.results.isTuple()) {
+ if (curr->getResults().isTuple()) {
shouldBeTrue(getModule()->features.hasMultivalue(),
curr->body,
"Multivalue function results (multivalue is not enabled)");
}
FeatureSet features;
- for (const auto& param : curr->sig.params) {
+ for (const auto& param : curr->getParams()) {
features |= param.getFeatures();
shouldBeTrue(param.isConcrete(), curr, "params must be concretely typed");
}
- for (const auto& result : curr->sig.results) {
+ for (const auto& result : curr->getResults()) {
features |= result.getFeatures();
shouldBeTrue(result.isConcrete(), curr, "results must be concretely typed");
}
@@ -2512,12 +2512,12 @@ void FunctionValidator::visitFunction(Function* curr) {
// if function has no result, it is ignored
// if body is unreachable, it might be e.g. a return
shouldBeSubType(curr->body->type,
- curr->sig.results,
+ curr->getResults(),
curr->body,
"function body type must match, if function returns");
for (Type returnType : returnTypes) {
shouldBeSubType(returnType,
- curr->sig.results,
+ curr->getResults(),
curr->body,
"function result must match, if function has returns");
}
@@ -2657,20 +2657,20 @@ static void validateBinaryenIR(Module& wasm, ValidationInfo& info) {
static void validateImports(Module& module, ValidationInfo& info) {
ModuleUtils::iterImportedFunctions(module, [&](Function* curr) {
- if (curr->sig.results.isTuple()) {
+ if (curr->getResults().isTuple()) {
info.shouldBeTrue(module.features.hasMultivalue(),
curr->name,
"Imported multivalue function "
"(multivalue is not enabled)");
}
if (info.validateWeb) {
- for (const auto& param : curr->sig.params) {
+ for (const auto& param : curr->getParams()) {
info.shouldBeUnequal(param,
Type(Type::i64),
curr->name,
"Imported function must not have i64 parameters");
}
- for (const auto& result : curr->sig.results) {
+ for (const auto& result : curr->getResults()) {
info.shouldBeUnequal(result,
Type(Type::i64),
curr->name,
@@ -2693,14 +2693,14 @@ static void validateExports(Module& module, ValidationInfo& info) {
if (curr->kind == ExternalKind::Function) {
if (info.validateWeb) {
Function* f = module.getFunction(curr->value);
- for (const auto& param : f->sig.params) {
+ for (const auto& param : f->getParams()) {
info.shouldBeUnequal(
param,
Type(Type::i64),
f->name,
"Exported function must not have i64 parameters");
}
- for (const auto& result : f->sig.results) {
+ for (const auto& result : f->getResults()) {
info.shouldBeUnequal(result,
Type(Type::i64),
f->name,
@@ -3007,10 +3007,10 @@ static void validateModule(Module& module, ValidationInfo& info) {
auto func = module.getFunctionOrNull(module.start);
if (info.shouldBeTrue(
func != nullptr, module.start, "start must be found")) {
- info.shouldBeTrue(func->sig.params == Type::none,
+ info.shouldBeTrue(func->getParams() == Type::none,
module.start,
"start must have 0 params");
- info.shouldBeTrue(func->sig.results == Type::none,
+ info.shouldBeTrue(func->getResults() == Type::none,
module.start,
"start must not return a value");
}
diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp
index 54c82159f..5b1163ae0 100644
--- a/src/wasm/wasm.cpp
+++ b/src/wasm/wasm.cpp
@@ -1087,14 +1087,14 @@ void RefAs::finalize() {
}
}
-size_t Function::getNumParams() { return sig.params.size(); }
+size_t Function::getNumParams() { return getParams().size(); }
size_t Function::getNumVars() { return vars.size(); }
-size_t Function::getNumLocals() { return sig.params.size() + vars.size(); }
+size_t Function::getNumLocals() { return getParams().size() + vars.size(); }
bool Function::isParam(Index index) {
- size_t size = sig.params.size();
+ size_t size = getParams().size();
assert(index < size + vars.size());
return index < size;
}
@@ -1141,12 +1141,12 @@ Index Function::getLocalIndex(Name name) {
return iter->second;
}
-Index Function::getVarIndexBase() { return sig.params.size(); }
+Index Function::getVarIndexBase() { return getParams().size(); }
Type Function::getLocalType(Index index) {
- auto numParams = sig.params.size();
+ auto numParams = getParams().size();
if (index < numParams) {
- return sig.params[index];
+ return getParams()[index];
} else if (isVar(index)) {
return vars[index - numParams];
} else {