diff options
Diffstat (limited to 'src')
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 { |