From b0ca6fe4bd524a27423a86a7d45991a84bde9281 Mon Sep 17 00:00:00 2001 From: Dominic Chen Date: Wed, 13 Jul 2016 17:12:51 -0700 Subject: [PATCH 1/3] Add backend support for multiple tables --- src/asm2wasm.h | 4 +- src/binaryen-c.cpp | 4 +- src/passes/DuplicateFunctionElimination.cpp | 10 ++- src/passes/Print.cpp | 6 +- src/passes/RemoveUnusedFunctions.cpp | 6 +- src/passes/ReorderFunctions.cpp | 6 +- src/wasm-binary.h | 56 +++++++----- src/wasm-interpreter.h | 5 +- src/wasm-linker.cpp | 96 ++++++++++++--------- src/wasm-linker.h | 28 ++++-- src/wasm-s-parser.h | 2 +- src/wasm-traversal.h | 4 +- src/wasm.h | 36 +++++++- 13 files changed, 173 insertions(+), 90 deletions(-) diff --git a/src/asm2wasm.h b/src/asm2wasm.h index c0f13ff8f3c..f266c6b03c3 100644 --- a/src/asm2wasm.h +++ b/src/asm2wasm.h @@ -660,11 +660,11 @@ void Asm2WasmBuilder::processAsm(Ref ast) { // TODO: when not using aliasing function pointers, we could merge them by noticing that // index 0 in each table is the null func, and each other index should only have one // non-null func. However, that breaks down when function pointer casts are emulated. - functionTableStarts[name] = wasm.table.names.size(); // this table starts here + functionTableStarts[name] = wasm.getDefaultTable()->values.size(); // this table starts here Ref contents = value[1]; for (unsigned k = 0; k < contents->size(); k++) { IString curr = contents[k][1]->getIString(); - wasm.table.names.push_back(curr); + wasm.getDefaultTable()->values.push_back(curr); } } else { abort_on("invalid var element", pair); diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index b7fc4347a2c..8a1b35d3f26 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -586,7 +586,7 @@ BinaryenExpressionRef BinaryenSelect(BinaryenModuleRef module, BinaryenExpressio } BinaryenExpressionRef BinaryenReturn(BinaryenModuleRef module, BinaryenExpressionRef value) { auto* ret = Builder(*((Module*)module)).makeReturn((Expression*)value); - + if (tracing) { auto id = noteExpression(ret); std::cout << " expressions[" << id << "] = BinaryenReturn(the_module, expressions[" << expressions[value] << "]);\n"; @@ -730,7 +730,7 @@ void BinaryenSetFunctionTable(BinaryenModuleRef module, BinaryenFunctionRef* fun auto* wasm = (Module*)module; for (BinaryenIndex i = 0; i < numFuncs; i++) { - wasm->table.names.push_back(((Function*)funcs[i])->name); + wasm->getDefaultTable()->values.push_back(((Function*)funcs[i])->name); } } diff --git a/src/passes/DuplicateFunctionElimination.cpp b/src/passes/DuplicateFunctionElimination.cpp index 961d26ba5a3..af5b133cffb 100644 --- a/src/passes/DuplicateFunctionElimination.cpp +++ b/src/passes/DuplicateFunctionElimination.cpp @@ -123,10 +123,12 @@ struct DuplicateFunctionElimination : public Pass { replacerRunner.add(&replacements); replacerRunner.run(); // replace in table - for (auto& name : module->table.names) { - auto iter = replacements.find(name); - if (iter != replacements.end()) { - name = iter->second; + for (auto& curr : module->tables) { + for (auto& name : curr->values) { + auto iter = replacements.find(name); + if (iter != replacements.end()) { + name = iter->second; + } } } // replace in start diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index 47e503fa4c4..1e3161cc15f 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -576,7 +576,7 @@ struct PrintSExpression : public Visitor { } void visitTable(Table *curr) { printOpening(o, "table"); - for (auto name : curr->names) { + for (auto name : curr->values) { o << ' '; printName(name); } @@ -647,9 +647,9 @@ struct PrintSExpression : public Visitor { visitGlobal(child.get()); o << maybeNewLine; } - if (curr->table.names.size() > 0) { + for (auto& child : curr->tables) { doIndent(o, indent); - visitTable(&curr->table); + visitTable(child.get()); o << maybeNewLine; } for (auto& child : curr->functions) { diff --git a/src/passes/RemoveUnusedFunctions.cpp b/src/passes/RemoveUnusedFunctions.cpp index a2941aff662..e73b6f897d5 100644 --- a/src/passes/RemoveUnusedFunctions.cpp +++ b/src/passes/RemoveUnusedFunctions.cpp @@ -39,8 +39,10 @@ struct RemoveUnusedFunctions : public Pass { root.push_back(module->getFunction(curr->value)); } // For now, all functions that can be called indirectly are marked as roots. - for (auto& curr : module->table.names) { - root.push_back(module->getFunction(curr)); + for (auto& child : module->tables) { + for (auto& curr : child->values) { + root.push_back(module->getFunction(curr)); + } } // Compute function reachability starting from the root set. DirectCallGraphAnalyzer analyzer(module, root); diff --git a/src/passes/ReorderFunctions.cpp b/src/passes/ReorderFunctions.cpp index 38ef98afb7a..c4aeae9bd71 100644 --- a/src/passes/ReorderFunctions.cpp +++ b/src/passes/ReorderFunctions.cpp @@ -38,8 +38,10 @@ struct ReorderFunctions : public WalkerPassexports) { counts[curr->value]++; } - for (auto& curr : module->table.names) { - counts[curr]++; + for (auto& child : module->tables) { + for (auto& curr : child->values) { + counts[curr]++; + } } std::sort(module->functions.begin(), module->functions.end(), [this]( const std::unique_ptr& a, diff --git a/src/wasm-binary.h b/src/wasm-binary.h index aad142d4459..3106617622a 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -480,7 +480,7 @@ class WasmBinaryWriter : public Visitor { writeSignatures(); writeImports(); writeFunctionSignatures(); - writeFunctionTable(); + writeFunctionTables(); writeMemory(); writeGlobals(); writeExports(); @@ -556,7 +556,7 @@ class WasmBinaryWriter : public Visitor { finishSection(start); } - int32_t getFunctionTypeIndex(Name type) { + Index getFunctionTypeIndex(Name type) { // TODO: optimize for (size_t i = 0; i < wasm->functionTypes.size(); i++) { if (wasm->functionTypes[i]->name == type) return i; @@ -685,7 +685,7 @@ class WasmBinaryWriter : public Visitor { void writeExports() { if (wasm->exports.size() == 0) return; - if (debug) std::cerr << "== writeexports" << std::endl; + if (debug) std::cerr << "== writeExports" << std::endl; auto start = startSection(BinaryConsts::Section::ExportTable); o << U32LEB(wasm->exports.size()); for (auto& curr : wasm->exports) { @@ -724,8 +724,8 @@ class WasmBinaryWriter : public Visitor { assert(mappedImports.count(name)); return mappedImports[name]; } - - std::map mappedFunctions; // name of the Function => index + + std::map mappedFunctions; // name of the Function => entry index uint32_t getFunctionIndex(Name name) { if (!mappedFunctions.size()) { // Create name => index mapping. @@ -738,13 +738,18 @@ class WasmBinaryWriter : public Visitor { return mappedFunctions[name]; } - void writeFunctionTable() { - if (wasm->table.names.size() == 0) return; - if (debug) std::cerr << "== writeFunctionTable" << std::endl; + void writeFunctionTables() { + if (wasm->tables.size() == 0) return; + if (debug) std::cerr << "== writeFunctionTables" << std::endl; auto start = startSection(BinaryConsts::Section::FunctionTable); - o << U32LEB(wasm->table.names.size()); - for (auto name : wasm->table.names) { - o << U32LEB(getFunctionIndex(name)); + assert(wasm->tables.size() == 1); + // o << U32LEB(wasm->tables.size()); + for (auto& curr : wasm->tables) { + if (debug) std::cerr << "write one" << std::endl; + o << U32LEB(curr->values.size()); + for (auto name : curr->values) { + o << U32LEB(getFunctionIndex(name)); + } } finishSection(start); } @@ -1256,7 +1261,7 @@ class WasmBinaryBuilder { else if (match(BinaryConsts::Section::ExportTable)) readExports(); else if (match(BinaryConsts::Section::Globals)) readGlobals(); else if (match(BinaryConsts::Section::DataSegments)) readDataSegments(); - else if (match(BinaryConsts::Section::FunctionTable)) readFunctionTable(); + else if (match(BinaryConsts::Section::FunctionTable)) readFunctionTables(); else if (match(BinaryConsts::Section::Names)) readNames(); else { std::cerr << "unfamiliar section: "; @@ -1638,9 +1643,10 @@ class WasmBinaryBuilder { } } - for (size_t index : functionTable) { - assert(index < wasm.functions.size()); - wasm.table.names.push_back(wasm.functions[index]->name); + for (auto& pair : functionTable) { + assert(pair.first < wasm.tables.size()); + assert(pair.second < wasm.functions.size()); + wasm.tables[pair.first]->values.push_back(wasm.functions[pair.second]->name); } } @@ -1660,14 +1666,20 @@ class WasmBinaryBuilder { } } - std::vector functionTable; + std::vector> functionTable; - void readFunctionTable() { - if (debug) std::cerr << "== readFunctionTable" << std::endl; - auto num = getU32LEB(); - for (size_t i = 0; i < num; i++) { - auto index = getU32LEB(); - functionTable.push_back(index); + void readFunctionTables() { + if (debug) std::cerr << "== readFunctionTables" << std::endl; + size_t numTables = 1; // getU32LEB() + for (size_t i = 0; i < numTables; i++) { + if (debug) std::cerr << "read one" << std::endl; + auto curr = new Table; + auto size = getU32LEB(); + for (size_t j = 0; j < size; j++) { + auto index = getU32LEB(); + functionTable.push_back(std::make_pair<>(i, index)); + } + wasm.addTable(curr); } } diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index adaee0b6fca..5b21fc75680 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -666,9 +666,10 @@ class ModuleInstance { LiteralList arguments; Flow flow = generateArguments(curr->operands, arguments); if (flow.breaking()) return flow; + Table *table = instance.wasm.getDefaultTable(); size_t index = target.value.geti32(); - if (index >= instance.wasm.table.names.size()) trap("callIndirect: overflow"); - Name name = instance.wasm.table.names[index]; + if (index >= table->values.size()) trap("callIndirect: overflow"); + Name name = table->values[index]; Function *func = instance.wasm.getFunction(name); if (func->type.is() && func->type != curr->fullType) trap("callIndirect: bad type"); if (func->params.size() != arguments.size()) trap("callIndirect: bad # of arguments"); diff --git a/src/wasm-linker.cpp b/src/wasm-linker.cpp index 45615fd59c1..c17f15e807c 100644 --- a/src/wasm-linker.cpp +++ b/src/wasm-linker.cpp @@ -117,22 +117,20 @@ void Linker::layout() { // Pre-assign the function indexes for (auto& pair : out.indirectIndexes) { - if (functionIndexes.count(pair.first) != 0 || - functionNames.count(pair.second) != 0) { - Fatal() << "Function " << pair.first << " already has an index " << - functionIndexes[pair.first] << " while setting index " << pair.second; + Index tableIndex = Table::kDefault; + Table *table = out.getIndirectTable(tableIndex); + if (functionIndexes.count(pair.second) != 0) { + Fatal() << "Function " << pair.second << " already has an index " << + functionIndexes[pair.second].first << " while setting index " << pair.first; } if (debug) { - std::cerr << "pre-assigned function index: " << pair.first << ": " - << pair.second << '\n'; + std::cerr << "pre-assigned function index: " << pair.second << ": " + << pair.first << '\n'; } - functionIndexes[pair.first] = pair.second; - functionNames[pair.second] = pair.first; - } - - // Emit the pre-assigned function names in sorted order - for (const auto& P : functionNames) { - out.wasm.table.names.push_back(P.second); + assert(table->values.size() == pair.first); + table->values.push_back(pair.second); + auto indexes = std::make_pair(tableIndex, pair.first); + functionIndexes[pair.second] = indexes; } for (auto& relocation : out.relocations) { @@ -170,6 +168,15 @@ void Linker::layout() { } } } + + // Create the actual tables in the underlying module. This is delayed because + // table references may be out of order, and the underlying object is a vector. + Index counter = 0; + for (auto& pair : out.tables) { + if (pair.first != counter++) Fatal() << "Tables are nonconsecutive!" << '\n'; + out.wasm.addTable(pair.second); + } + if (!!startFunction) { if (out.symbolInfo.implementedFunctions.count(startFunction) == 0) { Fatal() << "Unknown start function: `" << startFunction << "`\n"; @@ -206,9 +213,11 @@ void Linker::layout() { } // ensure an explicit function type for indirect call targets - for (auto& name : out.wasm.table.names) { - auto* func = out.wasm.getFunction(name); - func->type = ensureFunctionType(getSig(func), &out.wasm)->name; + for (auto& table : out.wasm.tables) { + for (auto& name : table->values) { + auto* func = out.wasm.getFunction(name); + func->type = ensureFunctionType(getSig(func), &out.wasm)->name; + } } } @@ -371,14 +380,17 @@ void Linker::emscriptenGlue(std::ostream& o) { Index Linker::getFunctionIndex(Name name) { if (!functionIndexes.count(name)) { - functionIndexes[name] = out.wasm.table.names.size(); - out.wasm.table.names.push_back(name); + Index tableIndex = Table::kDefault; + Table *table = out.getIndirectTable(tableIndex); + functionIndexes[name] = std::make_pair(tableIndex, table->values.size()); + table->values.push_back(name); if (debug) { std::cerr << "function index: " << name << ": " - << functionIndexes[name] << '\n'; + << functionIndexes[name].first << " " + << functionIndexes[name].second << '\n'; } } - return functionIndexes[name]; + return functionIndexes[name].second; } bool hasI64ResultOrParam(FunctionType* ft) { @@ -390,7 +402,7 @@ bool hasI64ResultOrParam(FunctionType* ft) { } void Linker::makeDummyFunction() { - assert(out.wasm.table.names.empty()); + assert(out.wasm.tables.empty()); bool create = false; // Check if there are address-taken functions for (auto& relocation : out.relocations) { @@ -410,27 +422,29 @@ void Linker::makeDummyFunction() { void Linker::makeDynCallThunks() { std::unordered_set sigs; wasm::Builder wasmBuilder(out.wasm); - for (const auto& indirectFunc : out.wasm.table.names) { - // Skip generating thunks for the dummy function - if (indirectFunc == dummyFunction) continue; - std::string sig(getSig(out.wasm.getFunction(indirectFunc))); - auto* funcType = ensureFunctionType(sig, &out.wasm); - if (hasI64ResultOrParam(funcType)) continue; // Can't export i64s on the web. - if (!sigs.insert(sig).second) continue; // Sig is already in the set - std::vector params; - params.emplace_back("fptr", i32); // function pointer param - int p = 0; - for (const auto& ty : funcType->params) params.emplace_back(std::to_string(p++), ty); - Function* f = wasmBuilder.makeFunction(std::string("dynCall_") + sig, std::move(params), funcType->result, {}); - Expression* fptr = wasmBuilder.makeGetLocal(0, i32); - std::vector args; - for (unsigned i = 0; i < funcType->params.size(); ++i) { - args.push_back(wasmBuilder.makeGetLocal(i + 1, funcType->params[i])); + for (const auto& table : out.wasm.tables) { + for (const auto& indirectFunc : table->values) { + // Skip generating thunks for the dummy function + if (indirectFunc == dummyFunction) continue; + std::string sig(getSig(out.wasm.getFunction(indirectFunc))); + auto* funcType = ensureFunctionType(sig, &out.wasm); + if (hasI64ResultOrParam(funcType)) continue; // Can't export i64s on the web. + if (!sigs.insert(sig).second) continue; // Sig is already in the set + std::vector params; + params.emplace_back("fptr", i32); // function pointer param + int p = 0; + for (const auto& ty : funcType->params) params.emplace_back(std::to_string(p++), ty); + Function* f = wasmBuilder.makeFunction(std::string("dynCall_") + sig, std::move(params), funcType->result, {}); + Expression* fptr = wasmBuilder.makeGetLocal(0, i32); + std::vector args; + for (unsigned i = 0; i < funcType->params.size(); ++i) { + args.push_back(wasmBuilder.makeGetLocal(i + 1, funcType->params[i])); + } + Expression* call = wasmBuilder.makeCallIndirect(funcType, fptr, args); + f->body = call; + out.wasm.addFunction(f); + exportFunction(f->name, true); } - Expression* call = wasmBuilder.makeCallIndirect(funcType, fptr, args); - f->body = call; - out.wasm.addFunction(f); - exportFunction(f->name, true); } } diff --git a/src/wasm-linker.h b/src/wasm-linker.h index 3f1e8c7aca6..6a6e4a84cae 100644 --- a/src/wasm-linker.h +++ b/src/wasm-linker.h @@ -111,6 +111,24 @@ class LinkerObject { return nullptr; } + // Create a table locally, because insertion into the underlying wasm vector + // needs to be delayed until all tables have been encountered. + Table *getIndirectTable(Index index) { + if (tables.count(index)) + return tables[index]; + + // Add the first default table, if it is missing and another table is + // being requested. + if (index && !tables.count(Table::kDefault)) { + getIndirectTable(Table::kDefault); + } + + // Otherwise, proceed and create the requested table. + assert(index == Table::kDefault); + tables[index] = Table::createDefaultTable(); + return tables[index]; + } + // Add an initializer segment for the named static variable. void addSegment(Name name, const char* data, Address size) { segments[name] = wasm.memory.segments.size(); @@ -142,8 +160,8 @@ class LinkerObject { } void addIndirectIndex(Name name, Address index) { - assert(!indirectIndexes.count(name)); - indirectIndexes[name] = index; + assert(!indirectIndexes.count(index)); + indirectIndexes[index] = name; } bool isEmpty() { @@ -177,9 +195,10 @@ class LinkerObject { std::unordered_map externTypesMap; std::map segments; // name => segment index (in wasm module) + std::map tables; // index => table index (in wasm module) // preassigned indexes for functions called indirectly - std::map indirectIndexes; + std::map indirectIndexes; std::vector initializerFunctions; @@ -328,8 +347,7 @@ class Linker { std::unordered_map staticAddresses; // name => address std::unordered_map segmentsByAddress; // address => segment index - std::unordered_map functionIndexes; - std::map functionNames; + std::unordered_map> functionIndexes; // name => table, entry indexes }; diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h index 750d485fbe1..bf927b0a208 100644 --- a/src/wasm-s-parser.h +++ b/src/wasm-s-parser.h @@ -1403,7 +1403,7 @@ class SExpressionWasmBuilder { void parseTable(Element& s) { for (size_t i = 1; i < s.size(); i++) { - wasm.table.names.push_back(getFunctionName(*s[i])); + wasm.getDefaultTable()->values.push_back(getFunctionName(*s[i])); } } diff --git a/src/wasm-traversal.h b/src/wasm-traversal.h index b50ca0fb292..cddb5be899c 100644 --- a/src/wasm-traversal.h +++ b/src/wasm-traversal.h @@ -205,7 +205,9 @@ struct Walker : public VisitorType { for (auto& curr : module->functions) { self->walkFunction(curr.get()); } - self->visitTable(&module->table); + for (auto &curr : module->tables) { + self->visitTable(curr.get()); + } self->visitMemory(&module->memory); } diff --git a/src/wasm.h b/src/wasm.h index 38a030e1a26..2e25a64b038 100644 --- a/src/wasm.h +++ b/src/wasm.h @@ -1432,7 +1432,16 @@ class Export { class Table { public: - std::vector names; + Name name; + std::vector values; + + enum { kDefault = 0 }; + + static Table* createDefaultTable() { + Table *table = new Table(); + table->name = Name::fromInt(kDefault); + return table; + } }; class Memory { @@ -1475,8 +1484,8 @@ class Module { std::vector> exports; std::vector> functions; std::vector> globals; + std::vector> tables; - Table table; Memory memory; Name start; @@ -1489,6 +1498,7 @@ class Module { std::map exportsMap; std::map functionsMap; std::map globalsMap; + std::map tablesMap; public: Module() {}; @@ -1498,24 +1508,28 @@ class Module { Export* getExport(Index i) { assert(i < exports.size()); return exports[i].get(); } Function* getFunction(Index i) { assert(i < functions.size()); return functions[i].get(); } Global* getGlobal(Index i) { assert(i < globals.size()); return globals[i].get(); } + Table* getTable(Index i) { assert(i < tables.size()); return tables[i].get(); } FunctionType* getFunctionType(Name name) { assert(functionTypesMap.count(name)); return functionTypesMap[name]; } Import* getImport(Name name) { assert(importsMap.count(name)); return importsMap[name]; } Export* getExport(Name name) { assert(exportsMap.count(name)); return exportsMap[name]; } Function* getFunction(Name name) { assert(functionsMap.count(name)); return functionsMap[name]; } Global* getGlobal(Name name) { assert(globalsMap.count(name)); return globalsMap[name]; } + Table* getTable(Name name) { assert(tablesMap.count(name)); return tablesMap[name]; } FunctionType* checkFunctionType(Name name) { if (!functionTypesMap.count(name)) return nullptr; return functionTypesMap[name]; } Import* checkImport(Name name) { if (!importsMap.count(name)) return nullptr; return importsMap[name]; } Export* checkExport(Name name) { if (!exportsMap.count(name)) return nullptr; return exportsMap[name]; } Function* checkFunction(Name name) { if (!functionsMap.count(name)) return nullptr; return functionsMap[name]; } Global* checkGlobal(Name name) { if (!globalsMap.count(name)) return nullptr; return globalsMap[name]; } + Table* checkTable(Name name) { if (!tablesMap.count(name)) return nullptr; return tablesMap[name]; } FunctionType* checkFunctionType(Index i) { if (i >= functionTypes.size()) return nullptr; return functionTypes[i].get(); } Import* checkImport(Index i) { if (i >= imports.size()) return nullptr; return imports[i].get(); } Export* checkExport(Index i) { if (i >= exports.size()) return nullptr; return exports[i].get(); } Function* checkFunction(Index i) { if (i >= functions.size()) return nullptr; return functions[i].get(); } Global* checkGlobal(Index i) { if (i >= globals.size()) return nullptr; return globals[i].get(); } + Table* checkTable(Index i) { if (i >= tables.size()) return nullptr; return tables[i].get(); } void addFunctionType(FunctionType* curr) { Name numericName = Name::fromInt(functionTypes.size()); // TODO: remove all these, assert on names already existing, do numeric stuff in wasm-s-parser etc. @@ -1562,11 +1576,27 @@ class Module { globalsMap[curr->name] = curr; globalsMap[numericName] = curr; } - + void addTable(Table *curr) { + Name numericName = Name::fromInt(tables.size()); + if (curr->name.isNull()) { + curr->name = numericName; + } + tables.push_back(std::unique_ptr(curr)); + tablesMap[curr->name] = curr; + tablesMap[numericName] = curr; + } void addStart(const Name &s) { start = s; } + Table* getDefaultTable() { + Table *def = checkTable(Name::fromInt(Table::kDefault)); + if (def) return def; + def = Table::createDefaultTable(); + addTable(def); + return def; + } + void removeImport(Name name) { for (size_t i = 0; i < imports.size(); i++) { if (imports[i]->name == name) { From 04dd6a92f99794759b18b9507bad2016212374a4 Mon Sep 17 00:00:00 2001 From: Dominic Chen Date: Wed, 13 Jul 2016 17:12:51 -0700 Subject: [PATCH 2/3] Add support for multiple tables and update CFI This commits makes a number of changes to the WebAssembly format, some of which exceed the feature set desired for the MVP. (1) It adds support for updated table definitions, including the default, elementType, initial, and max attributes, plus a name. Currently, the initial and max attributes must be equal to the number of elements. The elementType attribute is interpreted as a FunctionType index, and type homogeneity is enforced on table elements, unless the specified FunctionType has name "anyfunc", which corresponds to a FunctionType with a none parameter and return type none. Format: (table [default] ) (2) It adds support for multiple tables. If tables are used, currently the first table must be default, and the remainder must not. Example: (table "foo" default (type $FUNCSIG$i) $a) (table "bla" (type $anyfunc) $b $c $d) (3) Indirect calls have an immediate argument that specifies the index of the function call table. Example: (call_indirect "foo" $FUNCSIG$i (get_local $1)) (4) Corresponding upstream LLVM changes are required to use multiple tables, but the updated format is backwards compatible. Example: i32.call_indirect $0=, $pop0 i32.call_indirect.1 $0=, $pop0, $1, $2, $3 (5) Generating WebAssembly from code built with Clang/LLVM CFI now utilizes multiple tables. This is the only enabled use case for multiple tables; all others will default to a single table, if tables are used. The value passed in the .indidx assembler directive is now interpreted as the index of the indirect call table to assign. --- src/asm2wasm.h | 1 + src/ast_utils.h | 4 +- src/passes/Print.cpp | 10 +- src/s2wasm.h | 8 +- src/wasm-binary.h | 43 +++++-- src/wasm-builder.h | 6 +- src/wasm-interpreter.h | 4 +- src/wasm-linker.cpp | 121 +++++++++++------- src/wasm-linker.h | 39 +++--- src/wasm-s-parser.h | 55 +++++++- src/wasm.h | 27 ++++ test/dot_s/alias.wast | 7 +- test/dot_s/basics.wast | 9 +- test/dot_s/bcp-1.wast | 43 ++++--- test/dot_s/dyncall.wast | 13 +- test/dot_s/indidx.s | 8 +- test/dot_s/indidx.wast | 15 ++- test/dot_s/indirect-import.wast | 15 ++- test/emcc_O2_hello_world.fromasm | 19 +-- test/emcc_O2_hello_world.fromasm.imprecise | 19 +-- ...c_O2_hello_world.fromasm.imprecise.no-opts | 19 +-- test/emcc_O2_hello_world.fromasm.no-opts | 19 +-- test/emcc_hello_world.fromasm | 19 +-- test/emcc_hello_world.fromasm.imprecise | 19 +-- ...emcc_hello_world.fromasm.imprecise.no-opts | 19 +-- test/emcc_hello_world.fromasm.no-opts | 19 +-- test/llvm_autogenerated/call.wast | 6 +- test/memorygrowth.fromasm | 19 +-- test/memorygrowth.fromasm.imprecise | 19 +-- test/memorygrowth.fromasm.imprecise.no-opts | 19 +-- test/memorygrowth.fromasm.no-opts | 19 +-- test/passes/coalesce-locals-learning.txt | 2 + test/passes/coalesce-locals.txt | 2 + test/passes/dce.txt | 3 +- test/passes/dce.wast | 2 +- .../passes/duplicate-function-elimination.txt | 22 ++-- .../duplicate-function-elimination.wast | 8 +- test/passes/remove-unused-functions.txt | 3 +- test/passes/remove-unused-functions.wast | 2 +- .../remove-unused-names_merge-blocks.txt | 7 +- .../remove-unused-names_merge-blocks.wast | 2 +- test/unit.fromasm | 9 +- test/unit.fromasm.imprecise | 9 +- test/unit.fromasm.imprecise.no-opts | 9 +- test/unit.fromasm.no-opts | 9 +- test/unit.wast | 7 +- test/unit.wast.fromBinary | 7 +- 47 files changed, 476 insertions(+), 289 deletions(-) diff --git a/src/asm2wasm.h b/src/asm2wasm.h index f266c6b03c3..123741645d1 100644 --- a/src/asm2wasm.h +++ b/src/asm2wasm.h @@ -1404,6 +1404,7 @@ Function* Asm2WasmBuilder::processFunction(Ref ast) { } // function pointers auto ret = allocator.alloc(); + ret->table = wasm.getDefaultTable()->name; Ref target = ast[1]; assert(target[0] == SUB && target[1][0] == NAME && target[2][0] == BINARY && target[2][1] == AND && target[2][3][0] == NUM); // FUNCTION_TABLE[(expr) & mask] ret->target = process(target[2]); // TODO: as an optimization, we could look through the mask diff --git a/src/ast_utils.h b/src/ast_utils.h index 3e45d0e3395..a57e07e8e49 100644 --- a/src/ast_utils.h +++ b/src/ast_utils.h @@ -267,7 +267,7 @@ struct ExpressionManipulator { return ret; } Expression* visitCallIndirect(CallIndirect *curr) { - auto* ret = builder.makeCallIndirect(curr->fullType, curr->target, {}, curr->type); + auto* ret = builder.makeCallIndirect(curr->table, curr->fullType, curr->target, {}, curr->type); for (Index i = 0; i < curr->operands.size(); i++) { ret->operands.push_back(copy(curr->operands[i])); } @@ -467,6 +467,7 @@ struct ExpressionAnalyzer { break; } case Expression::Id::CallIndirectId: { + CHECK(CallIndirect, table); PUSH(CallIndirect, target); CHECK(CallIndirect, fullType); CHECK(CallIndirect, operands.size()); @@ -678,6 +679,7 @@ struct ExpressionAnalyzer { break; } case Expression::Id::CallIndirectId: { + HASH_NAME(CallIndirect, table); PUSH(CallIndirect, target); HASH_NAME(CallIndirect, fullType); HASH(CallIndirect, operands.size()); diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index 1e3161cc15f..ccf1b49950d 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -227,7 +227,9 @@ struct PrintSExpression : public Visitor { printCallBody(curr); } void visitCallIndirect(CallIndirect *curr) { - printOpening(o, "call_indirect ") << curr->fullType; + printOpening(o, "call_indirect "); + printName(curr->table); + o << ' ' << curr->fullType; incIndent(); printFullLine(curr->target); for (auto operand : curr->operands) { @@ -575,7 +577,11 @@ struct PrintSExpression : public Visitor { decIndent(); } void visitTable(Table *curr) { - printOpening(o, "table"); + printOpening(o, "table "); + printName(curr->name) << ' '; + if (curr->isDefault) + o << "default" << ' '; + visitFunctionType(curr->elementType, true); for (auto name : curr->values) { o << ' '; printName(name); diff --git a/src/s2wasm.h b/src/s2wasm.h index b17ed070217..beee6f28c13 100644 --- a/src/s2wasm.h +++ b/src/s2wasm.h @@ -318,6 +318,11 @@ class S2WasmBuilder { return cashew::IString(str.c_str(), false); } + uint32_t getTable() { + if (!match(".")) return 0; + return getInt(); + } + std::vector getQuoted() { assert(*s == '"'); s++; @@ -863,6 +868,7 @@ class S2WasmBuilder { auto makeCall = [&](WasmType type) { if (match("_indirect")) { // indirect call + uint32_t table = getTable(); Name assign = getAssign(); int num = getNumInputs(); auto inputs = getInputs(num); @@ -871,7 +877,7 @@ class S2WasmBuilder { std::vector operands(++input, inputs.end()); auto* funcType = ensureFunctionType(getSig(type, operands), wasm); assert(type == funcType->result); - auto* indirect = builder.makeCallIndirect(funcType, target, std::move(operands)); + auto* indirect = builder.makeCallIndirect(linkerObj->getIndirectTable(table, funcType)->name, funcType, target, std::move(operands)); setOutput(indirect, assign); } else { // non-indirect call diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 3106617622a..0c660d162aa 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -564,6 +564,14 @@ class WasmBinaryWriter : public Visitor { abort(); } + Index getFunctionTableIndex(Name type) { + // TODO: optimize + for (size_t i = 0; i < wasm->tables.size(); i++) { + if (wasm->tables[i]->name == type) return i; + } + abort(); + } + void writeImports() { if (wasm->imports.size() == 0) return; if (debug) std::cerr << "== writeImports" << std::endl; @@ -742,11 +750,14 @@ class WasmBinaryWriter : public Visitor { if (wasm->tables.size() == 0) return; if (debug) std::cerr << "== writeFunctionTables" << std::endl; auto start = startSection(BinaryConsts::Section::FunctionTable); - assert(wasm->tables.size() == 1); - // o << U32LEB(wasm->tables.size()); + o << U32LEB(wasm->tables.size()); for (auto& curr : wasm->tables) { if (debug) std::cerr << "write one" << std::endl; - o << U32LEB(curr->values.size()); + o << int8_t(curr->isDefault); + o << U32LEB(getFunctionTypeIndex(curr->elementType->name)); + assert(curr->initial == curr->values.size() && curr->initial == curr->max); + o << U32LEB(curr->initial); + o << U32LEB(curr->max); for (auto name : curr->values) { o << U32LEB(getFunctionIndex(name)); } @@ -929,7 +940,7 @@ class WasmBinaryWriter : public Visitor { for (auto* operand : curr->operands) { recurse(operand); } - o << int8_t(BinaryConsts::CallIndirect) << U32LEB(curr->operands.size()) << U32LEB(getFunctionTypeIndex(curr->fullType)); + o << int8_t(BinaryConsts::CallIndirect) << U32LEB(curr->operands.size()) << U32LEB(getFunctionTypeIndex(curr->fullType)) << U32LEB(getFunctionTableIndex(curr->table)); } void visitGetLocal(GetLocal *curr) { if (debug) std::cerr << "zz node: GetLocal " << (o.size() + 1) << std::endl; @@ -1457,6 +1468,11 @@ class WasmBinaryBuilder { assert(numResults == 1); curr->result = getWasmType(); } + // TODO: Handle "anyfunc" properly. This sets the name to "anyfunc" if + // it does not already exist, and matches the expected type signature. + if (!wasm.checkFunctionType(FunctionType::kAnyFunc) && FunctionType::isAnyFuncType(curr)) { + curr->name = FunctionType::kAnyFunc; + } wasm.addFunctionType(curr); } } @@ -1471,7 +1487,7 @@ class WasmBinaryBuilder { curr->name = Name(std::string("import$") + std::to_string(i)); auto index = getU32LEB(); assert(index < wasm.functionTypes.size()); - curr->type = wasm.getFunctionType(index); + curr->type = wasm.functionTypes[index].get(); assert(curr->type->name.is()); curr->module = getInlineString(); curr->base = getInlineString(); @@ -1646,6 +1662,8 @@ class WasmBinaryBuilder { for (auto& pair : functionTable) { assert(pair.first < wasm.tables.size()); assert(pair.second < wasm.functions.size()); + assert(wasm.tables[pair.first]->values.size() <= wasm.tables[pair.first]->max); + assert(wasm.tables[pair.first]->elementType->name == FunctionType::kAnyFunc || wasm.tables[pair.first]->elementType == wasm.getFunctionType(wasm.functions[pair.second]->type)); wasm.tables[pair.first]->values.push_back(wasm.functions[pair.second]->name); } } @@ -1670,12 +1688,20 @@ class WasmBinaryBuilder { void readFunctionTables() { if (debug) std::cerr << "== readFunctionTables" << std::endl; - size_t numTables = 1; // getU32LEB() + size_t numTables = getU32LEB(); for (size_t i = 0; i < numTables; i++) { if (debug) std::cerr << "read one" << std::endl; auto curr = new Table; - auto size = getU32LEB(); - for (size_t j = 0; j < size; j++) { + auto flag = getInt8(); + assert((!i && flag) || (i && !flag)); + curr->isDefault = flag; + auto index = getU32LEB(); + assert(index < functionTypes.size()); + curr->elementType = wasm.getFunctionType(index); + curr->initial = getU32LEB(); + curr->max = getU32LEB(); + assert(curr->initial == curr->max); + for (size_t j = 0; j < curr->initial; j++) { auto index = getU32LEB(); functionTable.push_back(std::make_pair<>(i, index)); } @@ -1899,6 +1925,7 @@ class WasmBinaryBuilder { curr->fullType = fullType->name; auto num = fullType->params.size(); assert(num == arity); + curr->table = wasm.getTable(getU32LEB())->name; curr->operands.resize(num); for (size_t i = 0; i < num; i++) { curr->operands[num - i - 1] = popExpression(); diff --git a/src/wasm-builder.h b/src/wasm-builder.h index 22e1f9a007f..fa6c9c58b50 100644 --- a/src/wasm-builder.h +++ b/src/wasm-builder.h @@ -115,16 +115,18 @@ class Builder { call->operands.set(args); return call; } - CallIndirect* makeCallIndirect(FunctionType* type, Expression* target, const std::vector& args) { + CallIndirect* makeCallIndirect(Name table, FunctionType* type, Expression* target, const std::vector& args) { auto* call = allocator.alloc(); + call->table = table; call->fullType = type->name; call->type = type->result; call->target = target; call->operands.set(args); return call; } - CallIndirect* makeCallIndirect(Name fullType, Expression* target, const std::vector& args, WasmType type) { + CallIndirect* makeCallIndirect(Name table, Name fullType, Expression* target, const std::vector& args, WasmType type) { auto* call = allocator.alloc(); + call->table = table; call->fullType = fullType; call->type = type; call->target = target; diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h index 5b21fc75680..bfe02d8647c 100644 --- a/src/wasm-interpreter.h +++ b/src/wasm-interpreter.h @@ -666,12 +666,12 @@ class ModuleInstance { LiteralList arguments; Flow flow = generateArguments(curr->operands, arguments); if (flow.breaking()) return flow; - Table *table = instance.wasm.getDefaultTable(); + Table *table = instance.wasm.getTable(curr->table); + if (table->elementType->name != FunctionType::kAnyFunc && table->elementType->name != curr->fullType) trap("callIndirect: bad type"); size_t index = target.value.geti32(); if (index >= table->values.size()) trap("callIndirect: overflow"); Name name = table->values[index]; Function *func = instance.wasm.getFunction(name); - if (func->type.is() && func->type != curr->fullType) trap("callIndirect: bad type"); if (func->params.size() != arguments.size()) trap("callIndirect: bad # of arguments"); for (size_t i = 0; i < func->params.size(); i++) { if (func->params[i] != arguments[i].type) { diff --git a/src/wasm-linker.cpp b/src/wasm-linker.cpp index c17f15e807c..cb36f5b261e 100644 --- a/src/wasm-linker.cpp +++ b/src/wasm-linker.cpp @@ -112,25 +112,30 @@ void Linker::layout() { for (Name name : out.globls) exportFunction(name, false); for (Name name : out.initializerFunctions) exportFunction(name, true); - // Pad the indirect function table with a dummy function - makeDummyFunction(); - // Pre-assign the function indexes - for (auto& pair : out.indirectIndexes) { - Index tableIndex = Table::kDefault; - Table *table = out.getIndirectTable(tableIndex); - if (functionIndexes.count(pair.second) != 0) { - Fatal() << "Function " << pair.second << " already has an index " << - functionIndexes[pair.second].first << " while setting index " << pair.first; - } - if (debug) { - std::cerr << "pre-assigned function index: " << pair.second << ": " - << pair.first << '\n'; + for (auto &pair : out.indirectIndexes) { + Index tableIndex = pair.first; + for (auto &funcName : pair.second) { + Function *func = out.wasm.getFunction(funcName); + FunctionType *funcType = ensureFunctionType(getSig(func), &out.wasm); + func->type = funcType->name; + Table *table = out.getIndirectTable(tableIndex, funcType); + if (table->values.empty()) { + Name dummy = makeDummyFunction(table); + functionIndexes[dummy] = std::make_pair(tableIndex, table->values.size()); + table->values.push_back(dummy); + } + if (functionIndexes.count(funcName) != 0) { + Fatal() << "Function " << funcName << " already has an index " << + functionIndexes[funcName].first << " while setting index " << pair.first; + } + if (debug) { + std::cerr << "pre-assigned function index: " << funcName << ": " + << pair.first << '\n'; + } + functionIndexes[funcName] = std::make_pair(tableIndex, table->values.size()); + table->values.push_back(funcName); } - assert(table->values.size() == pair.first); - table->values.push_back(pair.second); - auto indexes = std::make_pair(tableIndex, pair.first); - functionIndexes[pair.second] = indexes; } for (auto& relocation : out.relocations) { @@ -169,14 +174,6 @@ void Linker::layout() { } } - // Create the actual tables in the underlying module. This is delayed because - // table references may be out of order, and the underlying object is a vector. - Index counter = 0; - for (auto& pair : out.tables) { - if (pair.first != counter++) Fatal() << "Tables are nonconsecutive!" << '\n'; - out.wasm.addTable(pair.second); - } - if (!!startFunction) { if (out.symbolInfo.implementedFunctions.count(startFunction) == 0) { Fatal() << "Unknown start function: `" << startFunction << "`\n"; @@ -212,13 +209,35 @@ void Linker::layout() { } } - // ensure an explicit function type for indirect call targets - for (auto& table : out.wasm.tables) { - for (auto& name : table->values) { - auto* func = out.wasm.getFunction(name); - func->type = ensureFunctionType(getSig(func), &out.wasm)->name; + // Create the default table if necessary + if (!out.tables.count(Table::kDefault)) { + bool create = out.tables.size(); + // Check if there are address-taken functions or non-default tables + for (auto& relocation : out.relocations) { + if (create || relocation->kind == LinkerObject::Relocation::kFunction) { + create = true; + break; + } + } + + if (create) { + Index tableIndex = Table::kDefault; + Table *table = out.getIndirectTable(tableIndex, NULL); + if (table->values.empty()) { + Name dummy = makeDummyFunction(table); + functionIndexes[dummy] = std::make_pair(tableIndex, table->values.size()); + table->values.push_back(dummy); + } } } + + // Create the actual tables in the underlying module. This is delayed because + // table references may be out of order, and the underlying object is a vector. + Index counter = 0; + for (auto& pair : out.tables) { + if (pair.first != counter++) Fatal() << "Tables are nonconsecutive!" << '\n'; + out.wasm.addTable(pair.second); + } } bool Linker::linkObject(S2WasmBuilder& builder) { @@ -380,8 +399,16 @@ void Linker::emscriptenGlue(std::ostream& o) { Index Linker::getFunctionIndex(Name name) { if (!functionIndexes.count(name)) { + Function *func = out.wasm.getFunction(name); + FunctionType *funcType = ensureFunctionType(getSig(func), &out.wasm); + func->type = funcType->name; Index tableIndex = Table::kDefault; - Table *table = out.getIndirectTable(tableIndex); + Table *table = out.getIndirectTable(tableIndex, funcType); + if (table->values.empty()) { + Name dummy = makeDummyFunction(table); + functionIndexes[dummy] = std::make_pair(tableIndex, table->values.size()); + table->values.push_back(dummy); + } functionIndexes[name] = std::make_pair(tableIndex, table->values.size()); table->values.push_back(name); if (debug) { @@ -401,22 +428,22 @@ bool hasI64ResultOrParam(FunctionType* ft) { return false; } -void Linker::makeDummyFunction() { - assert(out.wasm.tables.empty()); - bool create = false; - // Check if there are address-taken functions - for (auto& relocation : out.relocations) { - if (relocation->kind == LinkerObject::Relocation::kFunction) { - create = true; - break; +Name Linker::makeDummyFunction(Table *table) { + assert(table->values.empty()); + Name functionName = std::string(dummyFunction) + std::string(table->name.c_str()); + if (!out.wasm.checkFunction(functionName)) { + wasm::Builder wasmBuilder(out.wasm); + Expression *unreachable = wasmBuilder.makeUnreachable(); + Function *dummy = wasmBuilder.makeFunction(functionName, {}, table->elementType->result, {}, unreachable); + if (FunctionType::isAnyFuncType(table->elementType)) { + std::string sig = getSig(dummy); + dummy->type = ensureFunctionType(sig, &out.wasm)->name; + } else { + dummy->type = table->elementType->name; } + out.wasm.addFunction(dummy); } - if (!create) return; - wasm::Builder wasmBuilder(out.wasm); - Expression *unreachable = wasmBuilder.makeUnreachable(); - Function *dummy = wasmBuilder.makeFunction(Name(dummyFunction), {}, WasmType::none, {}, unreachable); - out.wasm.addFunction(dummy); - getFunctionIndex(dummy->name); + return functionName; } void Linker::makeDynCallThunks() { @@ -425,7 +452,7 @@ void Linker::makeDynCallThunks() { for (const auto& table : out.wasm.tables) { for (const auto& indirectFunc : table->values) { // Skip generating thunks for the dummy function - if (indirectFunc == dummyFunction) continue; + if (!strncmp(indirectFunc.c_str(), dummyFunction, std::min(strlen(indirectFunc.c_str()), strlen(dummyFunction)))) continue; std::string sig(getSig(out.wasm.getFunction(indirectFunc))); auto* funcType = ensureFunctionType(sig, &out.wasm); if (hasI64ResultOrParam(funcType)) continue; // Can't export i64s on the web. @@ -440,7 +467,7 @@ void Linker::makeDynCallThunks() { for (unsigned i = 0; i < funcType->params.size(); ++i) { args.push_back(wasmBuilder.makeGetLocal(i + 1, funcType->params[i])); } - Expression* call = wasmBuilder.makeCallIndirect(funcType, fptr, args); + Expression* call = wasmBuilder.makeCallIndirect(table->name, funcType, fptr, args); f->body = call; out.wasm.addFunction(f); exportFunction(f->name, true); diff --git a/src/wasm-linker.h b/src/wasm-linker.h index 6a6e4a84cae..5b99d3e0fb8 100644 --- a/src/wasm-linker.h +++ b/src/wasm-linker.h @@ -113,20 +113,25 @@ class LinkerObject { // Create a table locally, because insertion into the underlying wasm vector // needs to be delayed until all tables have been encountered. - Table *getIndirectTable(Index index) { - if (tables.count(index)) + Table *getIndirectTable(Index index, FunctionType* type) { + Table *table; + if (tables.count(index)) { return tables[index]; - - // Add the first default table, if it is missing and another table is - // being requested. - if (index && !tables.count(Table::kDefault)) { - getIndirectTable(Table::kDefault); } // Otherwise, proceed and create the requested table. - assert(index == Table::kDefault); - tables[index] = Table::createDefaultTable(); - return tables[index]; + if (index != Table::kDefault) { + table = new Table(); + table->name = Name::fromInt(index); + table->isDefault = false; + table->elementType = type; + } else { + table = Table::createDefaultTable(); + table->elementType = wasm.getAnyFuncType(); + } + tables[index] = table; + + return table; } // Add an initializer segment for the named static variable. @@ -160,8 +165,10 @@ class LinkerObject { } void addIndirectIndex(Name name, Address index) { - assert(!indirectIndexes.count(index)); - indirectIndexes[index] = name; + if (!indirectIndexes.count(index)) { + indirectIndexes[index] = std::vector(); + } + indirectIndexes[index].push_back(name); } bool isEmpty() { @@ -198,7 +205,7 @@ class LinkerObject { std::map tables; // index => table index (in wasm module) // preassigned indexes for functions called indirectly - std::map indirectIndexes; + std::map> indirectIndexes; std::vector initializerFunctions; @@ -272,7 +279,7 @@ class Linker { bool linkArchive(Archive& archive); // Name of the dummy function to prevent erroneous nullptr comparisons. - static constexpr const char* dummyFunction = "__wasm_nullptr"; + static constexpr const char* dummyFunction = "__wasm_nullptr_"; private: // Allocate a static variable and return its address in linear memory @@ -305,9 +312,9 @@ class Linker { // a given function. Index getFunctionIndex(Name name); - // Adds a dummy function in the indirect table at slot 0 to prevent NULL + // Adds a dummy function in the given indirect table to prevent NULL // pointer miscomparisons. - void makeDummyFunction(); + Name makeDummyFunction(Table *table); // Create thunks for use with emscripten Runtime.dynCall. Creates one for each // signature in the indirect function table. diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h index bf927b0a208..8f4357103b8 100644 --- a/src/wasm-s-parser.h +++ b/src/wasm-s-parser.h @@ -265,11 +265,13 @@ class SExpressionWasmBuilder { int functionCounter; int importCounter; int globalCounter; + int tableCounter; std::map functionTypes; // we need to know function return types before we parse their contents + std::map functionFullTypes; // we need to know function full types before we parse their contents for tables public: // Assumes control of and modifies the input. - SExpressionWasmBuilder(Module& wasm, Element& module) : wasm(wasm), allocator(wasm.allocator), importCounter(0), globalCounter(0) { + SExpressionWasmBuilder(Module& wasm, Element& module) : wasm(wasm), allocator(wasm.allocator), importCounter(0), globalCounter(0), tableCounter(0) { assert(module[0]->str() == MODULE); if (module.size() > 1 && module[1]->isStr()) { // these s-expressions contain a binary module, actually @@ -324,6 +326,7 @@ class SExpressionWasmBuilder { Name typeName = curr[1]->str(); if (!wasm.checkFunctionType(typeName)) throw ParseException("unknown function"); type = wasm.getFunctionType(typeName); + functionFullTypes[name] = type; functionTypes[name] = type->result; } else if (id == PARAM && curr.size() > 1) { Index j = 1; @@ -354,6 +357,7 @@ class SExpressionWasmBuilder { if (need) { wasm.addFunctionType(functionType.release()); } + functionFullTypes[name] = functionType.get(); } } @@ -1186,13 +1190,16 @@ class SExpressionWasmBuilder { Expression* makeCallIndirect(Element& s) { auto ret = allocator.alloc(); - IString type = s[1]->str(); + size_t i = 1; + ret->table = wasm.getDefaultTable()->name; + if (wasm.checkTable(s[i]->str())) ret->table = wasm.getTable(s[i++]->str())->name; + IString type = s[i++]->str(); auto* fullType = wasm.checkFunctionType(type); if (!fullType) throw ParseException("invalid call_indirect type", s.line, s.col); ret->fullType = fullType->name; ret->type = fullType->result; - ret->target = parseExpression(s[2]); - parseCallOperands(s, 3, ret); + ret->target = parseExpression(s[i++]); + parseCallOperands(s, i++, ret); return ret; } @@ -1402,9 +1409,42 @@ class SExpressionWasmBuilder { } void parseTable(Element& s) { - for (size_t i = 1; i < s.size(); i++) { - wasm.getDefaultTable()->values.push_back(getFunctionName(*s[i])); + std::unique_ptr
tab = make_unique
(); + size_t i = 1; + if (s.size() > i && s[i]->isStr()) { + tab->name = s[i++]->str(); + } else { + tab->name = Name::fromInt(tableCounter); + } + tab->isDefault = !tableCounter; + if (s.size() > i && s[i]->isStr() && s[i]->str() == "default") { + tab->isDefault = true; + i++; + } + if (tableCounter && tab->isDefault) throw ParseException("only the first table can be default"); + tableCounter++; + if (s.size() > i && s[i]->isList()) { + Element& params = *s[i++]; + IString id = params[0]->str(); + if (id == TYPE) { + IString name = params[1]->str(); + if (!wasm.checkFunctionType(name)) throw ParseException("bad function type for table"); + tab->elementType = wasm.getFunctionType(name); + } else { + throw ParseException("bad table element"); + } + } else { + tab->elementType = wasm.getAnyFuncType(); + } + while (i < s.size()) { + Name func = getFunctionName(*s[i++]); + if (!functionFullTypes.count(func)) throw ParseException("unknown function"); + if (tab->elementType->name != FunctionType::kAnyFunc && tab->elementType != functionFullTypes[func]) throw ParseException("bad element type for table"); + tab->values.push_back(func); } + tab->initial = tab->values.size(); + tab->max = tab->values.size(); + wasm.addTable(tab.release()); } void parseType(Element& s) { @@ -1420,12 +1460,13 @@ class SExpressionWasmBuilder { Element& curr = *func[i]; if (curr[0]->str() == PARAM) { for (size_t j = 1; j < curr.size(); j++) { - type->params.push_back(stringToWasmType(curr[j]->str())); + type->params.push_back(stringToWasmType(curr[j]->str(), type->name == FunctionType::kAnyFunc)); } } else if (curr[0]->str() == RESULT) { type->result = stringToWasmType(curr[1]->str()); } } + if (type->name == FunctionType::kAnyFunc && !FunctionType::isAnyFuncType(type.get())) throw ParseException("reserved type keyword"); wasm.addFunctionType(type.release()); } }; diff --git a/src/wasm.h b/src/wasm.h index 2e25a64b038..8897830cd02 100644 --- a/src/wasm.h +++ b/src/wasm.h @@ -1065,6 +1065,8 @@ class FunctionType { FunctionType() : result(none) {} + static constexpr const char* kAnyFunc = "anyfunc"; + bool structuralComparison(FunctionType& b) { if (result != b.result) return false; if (params.size() != b.params.size()) return false; @@ -1081,12 +1083,24 @@ class FunctionType { bool operator!=(FunctionType& b) { return !(*this == b); } + + static FunctionType* createAnyFuncType() { + FunctionType *anyFunc = new FunctionType; + anyFunc->name = FunctionType::kAnyFunc; + anyFunc->params.push_back(none); + return anyFunc; + } + + static bool isAnyFuncType(FunctionType *curr) { + return curr->params.size() == 1 && curr->params[0] == none && curr->result == none; + } }; class CallIndirect : public SpecificExpression { public: CallIndirect(MixedArena& allocator) : operands(allocator) {} + Name table; ExpressionList operands; Name fullType; Expression *target; @@ -1433,12 +1447,16 @@ class Export { class Table { public: Name name; + bool isDefault; + FunctionType* elementType; + Address initial, max; std::vector values; enum { kDefault = 0 }; static Table* createDefaultTable() { Table *table = new Table(); + table->isDefault = true; table->name = Name::fromInt(kDefault); return table; } @@ -1589,10 +1607,19 @@ class Module { start = s; } + FunctionType* getAnyFuncType() { + FunctionType *anyFunc = checkFunctionType(FunctionType::kAnyFunc); + if (anyFunc) return anyFunc; + anyFunc = FunctionType::createAnyFuncType(); + addFunctionType(anyFunc); + return anyFunc; + } + Table* getDefaultTable() { Table *def = checkTable(Name::fromInt(Table::kDefault)); if (def) return def; def = Table::createDefaultTable(); + def->elementType = getAnyFuncType(); addTable(def); return def; } diff --git a/test/dot_s/alias.wast b/test/dot_s/alias.wast index 5744f8e8ade..90ad6a159ee 100644 --- a/test/dot_s/alias.wast +++ b/test/dot_s/alias.wast @@ -4,10 +4,11 @@ ) (export "memory" memory) (type $FUNCSIG$v (func)) + (type $anyfunc (func (param none))) (export "__exit" $__exit) (export "__needs_exit" $__needs_exit) (export "dynCall_v" $dynCall_v) - (table $__wasm_nullptr $__exit) + (table $0 default (type $anyfunc (func (param none))) $__wasm_nullptr_0 $__exit) (func $__exit (type $FUNCSIG$v) (return (i32.add @@ -26,11 +27,11 @@ (i32.const 1) ) ) - (func $__wasm_nullptr (type $FUNCSIG$v) + (func $__wasm_nullptr_0 (type $FUNCSIG$v) (unreachable) ) (func $dynCall_v (param $fptr i32) - (call_indirect $FUNCSIG$v + (call_indirect $0 $FUNCSIG$v (get_local $fptr) ) ) diff --git a/test/dot_s/basics.wast b/test/dot_s/basics.wast index b93bcd5cc2f..c6d4313c504 100644 --- a/test/dot_s/basics.wast +++ b/test/dot_s/basics.wast @@ -6,12 +6,13 @@ ) (export "memory" memory) (type $FUNCSIG$vi (func (param i32))) - (type $FUNCSIG$v (func)) (type $FUNCSIG$iii (func (param i32 i32) (result i32))) + (type $anyfunc (func (param none))) + (type $FUNCSIG$v (func)) (import $puts "env" "puts" (param i32)) (export "main" $main) (export "dynCall_iii" $dynCall_iii) - (table $__wasm_nullptr $main) + (table $0 default (type $anyfunc (func (param none))) $__wasm_nullptr_0 $main) (func $main (type $FUNCSIG$iii) (param $0 i32) (param $1 i32) (result i32) (call_import $puts (i32.const 16) @@ -91,11 +92,11 @@ ) (get_local $0) ) - (func $__wasm_nullptr (type $FUNCSIG$v) + (func $__wasm_nullptr_0 (type $FUNCSIG$v) (unreachable) ) (func $dynCall_iii (param $fptr i32) (param $0 i32) (param $1 i32) (result i32) - (call_indirect $FUNCSIG$iii + (call_indirect $0 $FUNCSIG$iii (get_local $fptr) (get_local $0) (get_local $1) diff --git a/test/dot_s/bcp-1.wast b/test/dot_s/bcp-1.wast index fcbe3b81e3c..4bdad3f7ef5 100644 --- a/test/dot_s/bcp-1.wast +++ b/test/dot_s/bcp-1.wast @@ -10,6 +10,7 @@ ) (export "memory" memory) (type $FUNCSIG$i (func (result i32))) + (type $anyfunc (func (param none))) (type $FUNCSIG$ii (func (param i32) (result i32))) (type $FUNCSIG$v (func)) (type $FUNCSIG$vi (func (param i32))) @@ -35,7 +36,7 @@ (export "main" $main) (export "dynCall_i" $dynCall_i) (export "dynCall_ii" $dynCall_ii) - (table $__wasm_nullptr $bad0 $bad1 $bad5 $bad7 $bad8 $bad10 $bad2 $bad3 $bad6 $bad4 $bad9 $good0 $good1 $good2 $opt0 $opt1 $opt2) + (table $0 default (type $anyfunc (func (param none))) $__wasm_nullptr_0 $bad0 $bad1 $bad5 $bad7 $bad8 $bad10 $bad2 $bad3 $bad6 $bad4 $bad9 $good0 $good1 $good2 $opt0 $opt1 $opt2) (func $bad0 (type $FUNCSIG$i) (result i32) (return (i32.const 0) @@ -130,42 +131,42 @@ ) (block $label$0 (br_if $label$0 - (call_indirect $FUNCSIG$i + (call_indirect $0 $FUNCSIG$i (i32.load offset=16 (get_local $0) ) ) ) (br_if $label$0 - (call_indirect $FUNCSIG$i + (call_indirect $0 $FUNCSIG$i (i32.load offset=20 (get_local $0) ) ) ) (br_if $label$0 - (call_indirect $FUNCSIG$i + (call_indirect $0 $FUNCSIG$i (i32.load offset=24 (get_local $0) ) ) ) (br_if $label$0 - (call_indirect $FUNCSIG$i + (call_indirect $0 $FUNCSIG$i (i32.load offset=28 (get_local $0) ) ) ) (br_if $label$0 - (call_indirect $FUNCSIG$i + (call_indirect $0 $FUNCSIG$i (i32.load offset=32 (get_local $0) ) ) ) (br_if $label$0 - (call_indirect $FUNCSIG$i + (call_indirect $0 $FUNCSIG$i (i32.load offset=36 (get_local $0) ) @@ -181,13 +182,13 @@ ) (block $label$1 (br_if $label$1 - (call_indirect $FUNCSIG$ii + (call_indirect $0 $FUNCSIG$ii (get_local $1) (get_local $2) ) ) (br_if $label$1 - (call_indirect $FUNCSIG$ii + (call_indirect $0 $FUNCSIG$ii (i32.load offset=44 (get_local $0) ) @@ -195,7 +196,7 @@ ) ) (br_if $label$1 - (call_indirect $FUNCSIG$ii + (call_indirect $0 $FUNCSIG$ii (i32.load offset=48 (get_local $0) ) @@ -212,13 +213,13 @@ ) (block $label$2 (br_if $label$2 - (call_indirect $FUNCSIG$ii + (call_indirect $0 $FUNCSIG$ii (get_local $1) (get_local $2) ) ) (br_if $label$2 - (call_indirect $FUNCSIG$ii + (call_indirect $0 $FUNCSIG$ii (i32.load offset=56 (get_local $0) ) @@ -228,7 +229,7 @@ (block $label$3 (br_if $label$3 (i32.eq - (call_indirect $FUNCSIG$i + (call_indirect $0 $FUNCSIG$i (i32.load offset=60 (get_local $0) ) @@ -238,7 +239,7 @@ ) (br_if $label$3 (i32.eq - (call_indirect $FUNCSIG$i + (call_indirect $0 $FUNCSIG$i (i32.load offset=64 (get_local $0) ) @@ -248,7 +249,7 @@ ) (br_if $label$3 (i32.eq - (call_indirect $FUNCSIG$i + (call_indirect $0 $FUNCSIG$i (i32.load offset=68 (get_local $0) ) @@ -259,7 +260,7 @@ (block $label$4 (br_if $label$4 (i32.eq - (call_indirect $FUNCSIG$i + (call_indirect $0 $FUNCSIG$i (i32.load offset=72 (get_local $0) ) @@ -269,7 +270,7 @@ ) (br_if $label$4 (i32.eq - (call_indirect $FUNCSIG$i + (call_indirect $0 $FUNCSIG$i (i32.load offset=76 (get_local $0) ) @@ -279,7 +280,7 @@ ) (br_if $label$4 (i32.eq - (call_indirect $FUNCSIG$i + (call_indirect $0 $FUNCSIG$i (i32.load offset=80 (get_local $0) ) @@ -307,16 +308,16 @@ (call_import $abort) (unreachable) ) - (func $__wasm_nullptr (type $FUNCSIG$v) + (func $__wasm_nullptr_0 (type $FUNCSIG$v) (unreachable) ) (func $dynCall_i (param $fptr i32) (result i32) - (call_indirect $FUNCSIG$i + (call_indirect $0 $FUNCSIG$i (get_local $fptr) ) ) (func $dynCall_ii (param $fptr i32) (param $0 i32) (result i32) - (call_indirect $FUNCSIG$ii + (call_indirect $0 $FUNCSIG$ii (get_local $fptr) (get_local $0) ) diff --git a/test/dot_s/dyncall.wast b/test/dot_s/dyncall.wast index e284c838de3..8872ca82a40 100644 --- a/test/dot_s/dyncall.wast +++ b/test/dot_s/dyncall.wast @@ -1,8 +1,9 @@ (module (memory 1) (export "memory" memory) - (type $FUNCSIG$v (func)) (type $FUNCSIG$i (func (result i32))) + (type $anyfunc (func (param none))) + (type $FUNCSIG$v (func)) (type $FUNCSIG$if (func (param f32) (result i32))) (type $FUNCSIG$vd (func (param f64))) (type $FUNCSIG$ffjjdi (func (param f32 i64 i64 f64 i32) (result f32))) @@ -15,7 +16,7 @@ (export "dynCall_i" $dynCall_i) (export "dynCall_if" $dynCall_if) (export "dynCall_vd" $dynCall_vd) - (table $__wasm_nullptr $i $i_f $vd $ffjjdi $vd2) + (table $0 default (type $anyfunc (func (param none))) $__wasm_nullptr_0 $i $i_f $vd $ffjjdi $vd2) (func $i (type $FUNCSIG$i) (result i32) (i32.const 0) ) @@ -37,22 +38,22 @@ (i32.const 5) (i32.const 0) ) - (func $__wasm_nullptr (type $FUNCSIG$v) + (func $__wasm_nullptr_0 (type $FUNCSIG$v) (unreachable) ) (func $dynCall_i (param $fptr i32) (result i32) - (call_indirect $FUNCSIG$i + (call_indirect $0 $FUNCSIG$i (get_local $fptr) ) ) (func $dynCall_if (param $fptr i32) (param $0 f32) (result i32) - (call_indirect $FUNCSIG$if + (call_indirect $0 $FUNCSIG$if (get_local $fptr) (get_local $0) ) ) (func $dynCall_vd (param $fptr i32) (param $0 f64) - (call_indirect $FUNCSIG$vd + (call_indirect $0 $FUNCSIG$vd (get_local $fptr) (get_local $0) ) diff --git a/test/dot_s/indidx.s b/test/dot_s/indidx.s index 68d8f5b774f..29b9ab223f7 100644 --- a/test/dot_s/indidx.s +++ b/test/dot_s/indidx.s @@ -2,7 +2,7 @@ .file "cfi-wasm.bs.bc" .type a,@function a: # @a - .indidx 4 + .indidx 1 .result i32 # BB#0: # %entry i32.const $push0=, 0 @@ -13,7 +13,7 @@ a: # @a .type b,@function b: # @b - .indidx 2 + .indidx 1 .result i32 # BB#0: # %entry i32.const $push0=, 1 @@ -35,7 +35,7 @@ c: # @c .type d,@function d: # @d - .indidx 3 + .indidx 1 .result i32 # BB#0: # %entry i32.const $push0=, 3 @@ -64,7 +64,7 @@ main: # @main i32.ge_u $push6=, $pop8, $pop5 br_if 0, $pop6 # 0: down to label0 # BB#1: # %cont - i32.call_indirect $push7=, $2 + i32.call_indirect.1 $push7=, $2 return $pop7 .LBB4_2: # %trap end_block # label0: diff --git a/test/dot_s/indidx.wast b/test/dot_s/indidx.wast index 2a5224d00d0..bd7206324de 100644 --- a/test/dot_s/indidx.wast +++ b/test/dot_s/indidx.wast @@ -1,14 +1,16 @@ (module (memory 1 - (segment 16 "\04\00\00\00\02\00\00\00\01\00\00\00\03\00\00\00") + (segment 16 "\01\00\00\00\02\00\00\00\03\00\00\00\04\00\00\00") ) (export "memory" memory) (type $FUNCSIG$i (func (result i32))) + (type $anyfunc (func (param none))) (type $FUNCSIG$v (func)) (import $getchar "env" "getchar" (result i32)) (export "main" $main) (export "dynCall_i" $dynCall_i) - (table $__wasm_nullptr $c $b $d $a) + (table $0 default (type $anyfunc (func (param none))) $__wasm_nullptr_0) + (table $1 (type $FUNCSIG$i (func (result i32))) $__wasm_nullptr_1 $a $b $c $d) (func $a (type $FUNCSIG$i) (result i32) (i32.const 0) ) @@ -41,7 +43,7 @@ ) ) (return - (call_indirect $FUNCSIG$i + (call_indirect $1 $FUNCSIG$i (get_local $2) ) ) @@ -49,11 +51,14 @@ (unreachable) (unreachable) ) - (func $__wasm_nullptr (type $FUNCSIG$v) + (func $__wasm_nullptr_1 (type $FUNCSIG$i) (result i32) + (unreachable) + ) + (func $__wasm_nullptr_0 (type $FUNCSIG$v) (unreachable) ) (func $dynCall_i (param $fptr i32) (result i32) - (call_indirect $FUNCSIG$i + (call_indirect $1 $FUNCSIG$i (get_local $fptr) ) ) diff --git a/test/dot_s/indirect-import.wast b/test/dot_s/indirect-import.wast index 22821a4e0c4..5aee0f377cb 100644 --- a/test/dot_s/indirect-import.wast +++ b/test/dot_s/indirect-import.wast @@ -6,6 +6,7 @@ (type $FUNCSIG$v (func)) (type $FUNCSIG$ijidf (func (param i64 i32 f64 f32) (result i32))) (type $FUNCSIG$vi (func (param i32))) + (type $anyfunc (func (param none))) (import $extern_ijidf "env" "extern_ijidf" (param i64 i32 f64 f32) (result i32)) (import $extern_v "env" "extern_v") (import $extern_vj "env" "extern_vj" (param i64)) @@ -17,7 +18,7 @@ (export "dynCall_fd" $dynCall_fd) (export "dynCall_v" $dynCall_v) (export "dynCall_vi" $dynCall_vi) - (table $__wasm_nullptr $__importThunk_extern_fd $__importThunk_extern_vj $__importThunk_extern_v $__importThunk_extern_ijidf $__importThunk_extern_struct $__importThunk_extern_sret) + (table $0 default (type $anyfunc (func (param none))) $__wasm_nullptr_0 $__importThunk_extern_fd $__importThunk_extern_vj $__importThunk_extern_v $__importThunk_extern_ijidf $__importThunk_extern_struct $__importThunk_extern_sret) (func $bar (result i32) (local $0 i32) (local $1 i32) @@ -82,14 +83,14 @@ (func $baz (result i32) (i32.const 3) ) - (func $__wasm_nullptr (type $FUNCSIG$v) - (unreachable) - ) (func $__importThunk_extern_fd (type $FUNCSIG$fd) (param $0 f64) (result f32) (call_import $extern_fd (get_local $0) ) ) + (func $__wasm_nullptr_0 (type $FUNCSIG$v) + (unreachable) + ) (func $__importThunk_extern_vj (type $FUNCSIG$vj) (param $0 i64) (call_import $extern_vj (get_local $0) @@ -117,18 +118,18 @@ ) ) (func $dynCall_fd (param $fptr i32) (param $0 f64) (result f32) - (call_indirect $FUNCSIG$fd + (call_indirect $0 $FUNCSIG$fd (get_local $fptr) (get_local $0) ) ) (func $dynCall_v (param $fptr i32) - (call_indirect $FUNCSIG$v + (call_indirect $0 $FUNCSIG$v (get_local $fptr) ) ) (func $dynCall_vi (param $fptr i32) (param $0 i32) - (call_indirect $FUNCSIG$vi + (call_indirect $0 $FUNCSIG$vi (get_local $fptr) (get_local $0) ) diff --git a/test/emcc_O2_hello_world.fromasm b/test/emcc_O2_hello_world.fromasm index 8289055612a..9523da805d2 100644 --- a/test/emcc_O2_hello_world.fromasm +++ b/test/emcc_O2_hello_world.fromasm @@ -1,6 +1,7 @@ (module (memory 256 256) (export "memory" memory) + (type $anyfunc (func (param none))) (type $FUNCSIG$iiii (func (param i32 i32 i32) (result i32))) (type $FUNCSIG$iii (func (param i32 i32) (result i32))) (type $FUNCSIG$ii (func (param i32) (result i32))) @@ -42,7 +43,7 @@ (export "dynCall_ii" $dynCall_ii) (export "dynCall_iiii" $dynCall_iiii) (export "dynCall_vi" $dynCall_vi) - (table $b0 $___stdio_close $b1 $b1 $___stdout_write $___stdio_seek $b1 $___stdio_write $b1 $b1 $b2 $b2 $b2 $b2 $_cleanup_418 $b2 $b2 $b2) + (table $0 default (type $anyfunc (func (param none))) $b0 $___stdio_close $b1 $b1 $___stdout_write $___stdio_seek $b1 $___stdio_write $b1 $b1 $b2 $b2 $b2 $b2 $_cleanup_418 $b2 $b2 $b2) (func $_malloc (param $0 i32) (result i32) (local $1 i32) (local $2 i32) @@ -8255,7 +8256,7 @@ ) (block (set_local $4 - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load offset=36 @@ -8332,7 +8333,7 @@ ) (if (i32.lt_u - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load offset=36 @@ -8827,7 +8828,7 @@ (set_local $4 (if (i32.eq - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load offset=36 @@ -8886,7 +8887,7 @@ ) ) (block - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load offset=36 @@ -8934,7 +8935,7 @@ ) ) ) - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load offset=40 @@ -9809,7 +9810,7 @@ ) ) (func $dynCall_iiii (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (result i32) - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (get_local $0) @@ -9896,7 +9897,7 @@ ) ) (func $dynCall_ii (param $0 i32) (param $1 i32) (result i32) - (call_indirect $FUNCSIG$ii + (call_indirect $0 $FUNCSIG$ii (i32.add (i32.and (get_local $0) @@ -9930,7 +9931,7 @@ ) ) (func $dynCall_vi (param $0 i32) (param $1 i32) - (call_indirect $FUNCSIG$vi + (call_indirect $0 $FUNCSIG$vi (i32.add (i32.and (get_local $0) diff --git a/test/emcc_O2_hello_world.fromasm.imprecise b/test/emcc_O2_hello_world.fromasm.imprecise index ede6c05d4a0..1224568e0b8 100644 --- a/test/emcc_O2_hello_world.fromasm.imprecise +++ b/test/emcc_O2_hello_world.fromasm.imprecise @@ -1,6 +1,7 @@ (module (memory 256 256) (export "memory" memory) + (type $anyfunc (func (param none))) (type $FUNCSIG$iiii (func (param i32 i32 i32) (result i32))) (type $FUNCSIG$ii (func (param i32) (result i32))) (type $FUNCSIG$vi (func (param i32))) @@ -41,7 +42,7 @@ (export "dynCall_ii" $dynCall_ii) (export "dynCall_iiii" $dynCall_iiii) (export "dynCall_vi" $dynCall_vi) - (table $b0 $___stdio_close $b1 $b1 $___stdout_write $___stdio_seek $b1 $___stdio_write $b1 $b1 $b2 $b2 $b2 $b2 $_cleanup_418 $b2 $b2 $b2) + (table $0 default (type $anyfunc (func (param none))) $b0 $___stdio_close $b1 $b1 $___stdout_write $___stdio_seek $b1 $___stdio_write $b1 $b1 $b2 $b2 $b2 $b2 $_cleanup_418 $b2 $b2 $b2) (func $_malloc (param $0 i32) (result i32) (local $1 i32) (local $2 i32) @@ -8254,7 +8255,7 @@ ) (block (set_local $4 - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load offset=36 @@ -8331,7 +8332,7 @@ ) (if (i32.lt_u - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load offset=36 @@ -8826,7 +8827,7 @@ (set_local $4 (if (i32.eq - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load offset=36 @@ -8885,7 +8886,7 @@ ) ) (block - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load offset=36 @@ -8933,7 +8934,7 @@ ) ) ) - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load offset=40 @@ -9808,7 +9809,7 @@ ) ) (func $dynCall_iiii (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (result i32) - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (get_local $0) @@ -9895,7 +9896,7 @@ ) ) (func $dynCall_ii (param $0 i32) (param $1 i32) (result i32) - (call_indirect $FUNCSIG$ii + (call_indirect $0 $FUNCSIG$ii (i32.add (i32.and (get_local $0) @@ -9929,7 +9930,7 @@ ) ) (func $dynCall_vi (param $0 i32) (param $1 i32) - (call_indirect $FUNCSIG$vi + (call_indirect $0 $FUNCSIG$vi (i32.add (i32.and (get_local $0) diff --git a/test/emcc_O2_hello_world.fromasm.imprecise.no-opts b/test/emcc_O2_hello_world.fromasm.imprecise.no-opts index d34022a9e39..19897ef8fda 100644 --- a/test/emcc_O2_hello_world.fromasm.imprecise.no-opts +++ b/test/emcc_O2_hello_world.fromasm.imprecise.no-opts @@ -1,6 +1,7 @@ (module (memory 256 256) (export "memory" memory) + (type $anyfunc (func (param none))) (type $FUNCSIG$iiii (func (param i32 i32 i32) (result i32))) (type $FUNCSIG$ii (func (param i32) (result i32))) (type $FUNCSIG$vi (func (param i32))) @@ -41,7 +42,7 @@ (export "dynCall_ii" $dynCall_ii) (export "dynCall_iiii" $dynCall_iiii) (export "dynCall_vi" $dynCall_vi) - (table $b0 $___stdio_close $b1 $b1 $___stdout_write $___stdio_seek $b1 $___stdio_write $b1 $b1 $b2 $b2 $b2 $b2 $_cleanup_418 $b2 $b2 $b2) + (table $0 default (type $anyfunc (func (param none))) $b0 $___stdio_close $b1 $b1 $___stdout_write $___stdio_seek $b1 $___stdio_write $b1 $b1 $b2 $b2 $b2 $b2 $_cleanup_418 $b2 $b2 $b2) (func $_malloc (param $i1 i32) (result i32) (local $i2 i32) (local $i3 i32) @@ -9722,7 +9723,7 @@ ) (block (set_local $i8 - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load @@ -9809,7 +9810,7 @@ ) (if (i32.lt_u - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load @@ -10427,7 +10428,7 @@ ) (if (i32.eq - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load @@ -10497,7 +10498,7 @@ ) ) (block - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load @@ -10554,7 +10555,7 @@ (get_local $i6) (get_local $i8) ) - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load @@ -11672,7 +11673,7 @@ ) (func $dynCall_iiii (param $i1 i32) (param $i2 i32) (param $i3 i32) (param $i4 i32) (result i32) (return - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (get_local $i1) @@ -11778,7 +11779,7 @@ ) (func $dynCall_ii (param $i1 i32) (param $i2 i32) (result i32) (return - (call_indirect $FUNCSIG$ii + (call_indirect $0 $FUNCSIG$ii (i32.add (i32.and (get_local $i1) @@ -11817,7 +11818,7 @@ ) ) (func $dynCall_vi (param $i1 i32) (param $i2 i32) - (call_indirect $FUNCSIG$vi + (call_indirect $0 $FUNCSIG$vi (i32.add (i32.and (get_local $i1) diff --git a/test/emcc_O2_hello_world.fromasm.no-opts b/test/emcc_O2_hello_world.fromasm.no-opts index f850b8306c7..4cc6dc7fadf 100644 --- a/test/emcc_O2_hello_world.fromasm.no-opts +++ b/test/emcc_O2_hello_world.fromasm.no-opts @@ -1,6 +1,7 @@ (module (memory 256 256) (export "memory" memory) + (type $anyfunc (func (param none))) (type $FUNCSIG$iiii (func (param i32 i32 i32) (result i32))) (type $FUNCSIG$iii (func (param i32 i32) (result i32))) (type $FUNCSIG$ii (func (param i32) (result i32))) @@ -42,7 +43,7 @@ (export "dynCall_ii" $dynCall_ii) (export "dynCall_iiii" $dynCall_iiii) (export "dynCall_vi" $dynCall_vi) - (table $b0 $___stdio_close $b1 $b1 $___stdout_write $___stdio_seek $b1 $___stdio_write $b1 $b1 $b2 $b2 $b2 $b2 $_cleanup_418 $b2 $b2 $b2) + (table $0 default (type $anyfunc (func (param none))) $b0 $___stdio_close $b1 $b1 $___stdout_write $___stdio_seek $b1 $___stdio_write $b1 $b1 $b2 $b2 $b2 $b2 $_cleanup_418 $b2 $b2 $b2) (func $_malloc (param $i1 i32) (result i32) (local $i2 i32) (local $i3 i32) @@ -9723,7 +9724,7 @@ ) (block (set_local $i8 - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load @@ -9810,7 +9811,7 @@ ) (if (i32.lt_u - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load @@ -10428,7 +10429,7 @@ ) (if (i32.eq - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load @@ -10498,7 +10499,7 @@ ) ) (block - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load @@ -10555,7 +10556,7 @@ (get_local $i6) (get_local $i8) ) - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load @@ -11673,7 +11674,7 @@ ) (func $dynCall_iiii (param $i1 i32) (param $i2 i32) (param $i3 i32) (param $i4 i32) (result i32) (return - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (get_local $i1) @@ -11779,7 +11780,7 @@ ) (func $dynCall_ii (param $i1 i32) (param $i2 i32) (result i32) (return - (call_indirect $FUNCSIG$ii + (call_indirect $0 $FUNCSIG$ii (i32.add (i32.and (get_local $i1) @@ -11818,7 +11819,7 @@ ) ) (func $dynCall_vi (param $i1 i32) (param $i2 i32) - (call_indirect $FUNCSIG$vi + (call_indirect $0 $FUNCSIG$vi (i32.add (i32.and (get_local $i1) diff --git a/test/emcc_hello_world.fromasm b/test/emcc_hello_world.fromasm index c99290ba837..7e0680c6d64 100644 --- a/test/emcc_hello_world.fromasm +++ b/test/emcc_hello_world.fromasm @@ -1,6 +1,7 @@ (module (memory 256 256) (export "memory" memory) + (type $anyfunc (func (param none))) (type $FUNCSIG$iiii (func (param i32 i32 i32) (result i32))) (type $FUNCSIG$id (func (param f64) (result i32))) (type $FUNCSIG$iii (func (param i32 i32) (result i32))) @@ -55,7 +56,7 @@ (export "dynCall_iiii" $dynCall_iiii) (export "dynCall_vi" $dynCall_vi) (export "___udivmoddi4" $___udivmoddi4) - (table $b0 $___stdio_close $b1 $b1 $___stdout_write $___stdio_seek $___stdio_write $b1 $b1 $b1 $b2 $b2 $b2 $b2 $b2 $_cleanup $b2 $b2) + (table $0 default (type $anyfunc (func (param none))) $b0 $___stdio_close $b1 $b1 $___stdout_write $___stdio_seek $___stdio_write $b1 $b1 $b1 $b2 $b2 $b2 $b2 $b2 $_cleanup $b2 $b2) (func $stackAlloc (param $0 i32) (result i32) (local $1 i32) (set_local $1 @@ -1653,7 +1654,7 @@ ) (get_local $1) (block - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load offset=36 @@ -1833,7 +1834,7 @@ (get_local $3) (block (set_local $4 - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load offset=36 @@ -1915,7 +1916,7 @@ ) (if (i32.lt_u - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load offset=36 @@ -2783,7 +2784,7 @@ ) ) (block - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load offset=36 @@ -2845,7 +2846,7 @@ ) ) ) - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load offset=40 @@ -19491,7 +19492,7 @@ ) ) (func $dynCall_ii (param $0 i32) (param $1 i32) (result i32) - (call_indirect $FUNCSIG$ii + (call_indirect $0 $FUNCSIG$ii (i32.add (i32.and (get_local $0) @@ -19503,7 +19504,7 @@ ) ) (func $dynCall_iiii (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (result i32) - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (get_local $0) @@ -19517,7 +19518,7 @@ ) ) (func $dynCall_vi (param $0 i32) (param $1 i32) - (call_indirect $FUNCSIG$vi + (call_indirect $0 $FUNCSIG$vi (i32.add (i32.and (get_local $0) diff --git a/test/emcc_hello_world.fromasm.imprecise b/test/emcc_hello_world.fromasm.imprecise index ee84765a141..c6147c08a4f 100644 --- a/test/emcc_hello_world.fromasm.imprecise +++ b/test/emcc_hello_world.fromasm.imprecise @@ -1,6 +1,7 @@ (module (memory 256 256) (export "memory" memory) + (type $anyfunc (func (param none))) (type $FUNCSIG$iiii (func (param i32 i32 i32) (result i32))) (type $FUNCSIG$ii (func (param i32) (result i32))) (type $FUNCSIG$vi (func (param i32))) @@ -49,7 +50,7 @@ (export "dynCall_iiii" $dynCall_iiii) (export "dynCall_vi" $dynCall_vi) (export "___udivmoddi4" $___udivmoddi4) - (table $b0 $___stdio_close $b1 $b1 $___stdout_write $___stdio_seek $___stdio_write $b1 $b1 $b1 $b2 $b2 $b2 $b2 $b2 $_cleanup $b2 $b2) + (table $0 default (type $anyfunc (func (param none))) $b0 $___stdio_close $b1 $b1 $___stdout_write $___stdio_seek $___stdio_write $b1 $b1 $b1 $b2 $b2 $b2 $b2 $b2 $_cleanup $b2 $b2) (func $stackAlloc (param $0 i32) (result i32) (local $1 i32) (set_local $1 @@ -1647,7 +1648,7 @@ ) (get_local $1) (block - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load offset=36 @@ -1827,7 +1828,7 @@ (get_local $3) (block (set_local $4 - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load offset=36 @@ -1909,7 +1910,7 @@ ) (if (i32.lt_u - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load offset=36 @@ -2777,7 +2778,7 @@ ) ) (block - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load offset=36 @@ -2839,7 +2840,7 @@ ) ) ) - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load offset=40 @@ -19476,7 +19477,7 @@ ) ) (func $dynCall_ii (param $0 i32) (param $1 i32) (result i32) - (call_indirect $FUNCSIG$ii + (call_indirect $0 $FUNCSIG$ii (i32.add (i32.and (get_local $0) @@ -19488,7 +19489,7 @@ ) ) (func $dynCall_iiii (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (result i32) - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (get_local $0) @@ -19502,7 +19503,7 @@ ) ) (func $dynCall_vi (param $0 i32) (param $1 i32) - (call_indirect $FUNCSIG$vi + (call_indirect $0 $FUNCSIG$vi (i32.add (i32.and (get_local $0) diff --git a/test/emcc_hello_world.fromasm.imprecise.no-opts b/test/emcc_hello_world.fromasm.imprecise.no-opts index 32761816931..937a5c763c9 100644 --- a/test/emcc_hello_world.fromasm.imprecise.no-opts +++ b/test/emcc_hello_world.fromasm.imprecise.no-opts @@ -1,6 +1,7 @@ (module (memory 256 256) (export "memory" memory) + (type $anyfunc (func (param none))) (type $FUNCSIG$iiii (func (param i32 i32 i32) (result i32))) (type $FUNCSIG$ii (func (param i32) (result i32))) (type $FUNCSIG$vi (func (param i32))) @@ -49,7 +50,7 @@ (export "dynCall_iiii" $dynCall_iiii) (export "dynCall_vi" $dynCall_vi) (export "___udivmoddi4" $___udivmoddi4) - (table $b0 $___stdio_close $b1 $b1 $___stdout_write $___stdio_seek $___stdio_write $b1 $b1 $b1 $b2 $b2 $b2 $b2 $b2 $_cleanup $b2 $b2) + (table $0 default (type $anyfunc (func (param none))) $b0 $___stdio_close $b1 $b1 $___stdout_write $___stdio_seek $___stdio_write $b1 $b1 $b1 $b2 $b2 $b2 $b2 $b2 $_cleanup $b2 $b2) (func $stackAlloc (param $size i32) (result i32) (local $ret i32) (set_local $ret @@ -2641,7 +2642,7 @@ (get_local $$write) ) ) - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (get_local $$5) @@ -2933,7 +2934,7 @@ ) ) (set_local $$call4 - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (get_local $$5) @@ -3062,7 +3063,7 @@ ) ) (set_local $$call16 - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (get_local $$8) @@ -4544,7 +4545,7 @@ (get_local $$write) ) ) - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (get_local $$2) @@ -4641,7 +4642,7 @@ (get_local $$sub$ptr$rhs$cast) ) ) - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (get_local $$6) @@ -32692,7 +32693,7 @@ ) (func $dynCall_ii (param $index i32) (param $a1 i32) (result i32) (return - (call_indirect $FUNCSIG$ii + (call_indirect $0 $FUNCSIG$ii (i32.add (i32.and (get_local $index) @@ -32706,7 +32707,7 @@ ) (func $dynCall_iiii (param $index i32) (param $a1 i32) (param $a2 i32) (param $a3 i32) (result i32) (return - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (get_local $index) @@ -32721,7 +32722,7 @@ ) ) (func $dynCall_vi (param $index i32) (param $a1 i32) - (call_indirect $FUNCSIG$vi + (call_indirect $0 $FUNCSIG$vi (i32.add (i32.and (get_local $index) diff --git a/test/emcc_hello_world.fromasm.no-opts b/test/emcc_hello_world.fromasm.no-opts index 41e3e9e26e2..f7da2a1e6de 100644 --- a/test/emcc_hello_world.fromasm.no-opts +++ b/test/emcc_hello_world.fromasm.no-opts @@ -1,6 +1,7 @@ (module (memory 256 256) (export "memory" memory) + (type $anyfunc (func (param none))) (type $FUNCSIG$iiii (func (param i32 i32 i32) (result i32))) (type $FUNCSIG$id (func (param f64) (result i32))) (type $FUNCSIG$iii (func (param i32 i32) (result i32))) @@ -55,7 +56,7 @@ (export "dynCall_iiii" $dynCall_iiii) (export "dynCall_vi" $dynCall_vi) (export "___udivmoddi4" $___udivmoddi4) - (table $b0 $___stdio_close $b1 $b1 $___stdout_write $___stdio_seek $___stdio_write $b1 $b1 $b1 $b2 $b2 $b2 $b2 $b2 $_cleanup $b2 $b2) + (table $0 default (type $anyfunc (func (param none))) $b0 $___stdio_close $b1 $b1 $___stdout_write $___stdio_seek $___stdio_write $b1 $b1 $b1 $b2 $b2 $b2 $b2 $b2 $_cleanup $b2 $b2) (func $stackAlloc (param $size i32) (result i32) (local $ret i32) (set_local $ret @@ -2647,7 +2648,7 @@ (get_local $$write) ) ) - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (get_local $$5) @@ -2939,7 +2940,7 @@ ) ) (set_local $$call4 - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (get_local $$5) @@ -3068,7 +3069,7 @@ ) ) (set_local $$call16 - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (get_local $$8) @@ -4550,7 +4551,7 @@ (get_local $$write) ) ) - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (get_local $$2) @@ -4647,7 +4648,7 @@ (get_local $$sub$ptr$rhs$cast) ) ) - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (get_local $$6) @@ -32698,7 +32699,7 @@ ) (func $dynCall_ii (param $index i32) (param $a1 i32) (result i32) (return - (call_indirect $FUNCSIG$ii + (call_indirect $0 $FUNCSIG$ii (i32.add (i32.and (get_local $index) @@ -32712,7 +32713,7 @@ ) (func $dynCall_iiii (param $index i32) (param $a1 i32) (param $a2 i32) (param $a3 i32) (result i32) (return - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (get_local $index) @@ -32727,7 +32728,7 @@ ) ) (func $dynCall_vi (param $index i32) (param $a1 i32) - (call_indirect $FUNCSIG$vi + (call_indirect $0 $FUNCSIG$vi (i32.add (i32.and (get_local $index) diff --git a/test/llvm_autogenerated/call.wast b/test/llvm_autogenerated/call.wast index 812667aec91..dd22242d565 100644 --- a/test/llvm_autogenerated/call.wast +++ b/test/llvm_autogenerated/call.wast @@ -4,6 +4,7 @@ ) (export "memory" memory) (type $FUNCSIG$v (func)) + (type $anyfunc (func (param none))) (type $FUNCSIG$i (func (result i32))) (type $FUNCSIG$d (func (result f64))) (type $FUNCSIG$f (func (result f32))) @@ -29,6 +30,7 @@ (export "tail_call_void_nullary" $tail_call_void_nullary) (export "fastcc_tail_call_void_nullary" $fastcc_tail_call_void_nullary) (export "coldcc_tail_call_void_nullary" $coldcc_tail_call_void_nullary) + (table $0 default (type $anyfunc (func (param none)))) (func $call_i32_nullary (result i32) (return (call_import $i32_nullary) @@ -69,14 +71,14 @@ ) ) (func $call_indirect_void (param $0 i32) - (call_indirect $FUNCSIG$v + (call_indirect $0 $FUNCSIG$v (get_local $0) ) (return) ) (func $call_indirect_i32 (param $0 i32) (result i32) (return - (call_indirect $FUNCSIG$i + (call_indirect $0 $FUNCSIG$i (get_local $0) ) ) diff --git a/test/memorygrowth.fromasm b/test/memorygrowth.fromasm index 5c005ba9993..2eed5247a90 100644 --- a/test/memorygrowth.fromasm +++ b/test/memorygrowth.fromasm @@ -1,6 +1,7 @@ (module (memory 256 256) (export "memory" memory) + (type $anyfunc (func (param none))) (type $FUNCSIG$iiii (func (param i32 i32 i32) (result i32))) (type $FUNCSIG$iii (func (param i32 i32) (result i32))) (type $FUNCSIG$ii (func (param i32) (result i32))) @@ -40,7 +41,7 @@ (export "dynCall_iiii" $lb) (export "dynCall_vi" $mb) (export "__growWasmMemory" $__growWasmMemory) - (table $nb $Oa $ob $Va $Ua $Ra $pb $Sa) + (table $0 default (type $anyfunc (func (param none))) $nb $Oa $ob $Va $Ua $Ra $pb $Sa) (func $eb (param $0 i32) (result i32) (local $1 i32) (local $2 i32) @@ -8338,7 +8339,7 @@ ) (block (set_local $4 - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load offset=36 @@ -8415,7 +8416,7 @@ ) (if (i32.lt_u - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load offset=36 @@ -8905,7 +8906,7 @@ (set_local $4 (if (i32.eq - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load offset=36 @@ -8963,7 +8964,7 @@ ) ) (block - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load offset=36 @@ -9022,7 +9023,7 @@ ) ) ) - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load offset=40 @@ -9904,7 +9905,7 @@ ) ) (func $lb (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (result i32) - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (get_local $0) @@ -9986,7 +9987,7 @@ ) ) (func $kb (param $0 i32) (param $1 i32) (result i32) - (call_indirect $FUNCSIG$ii + (call_indirect $0 $FUNCSIG$ii (i32.add (i32.and (get_local $0) @@ -10010,7 +10011,7 @@ ) ) (func $mb (param $0 i32) (param $1 i32) - (call_indirect $FUNCSIG$vi + (call_indirect $0 $FUNCSIG$vi (i32.add (i32.and (get_local $0) diff --git a/test/memorygrowth.fromasm.imprecise b/test/memorygrowth.fromasm.imprecise index b70bc7c9e27..2187fb9b064 100644 --- a/test/memorygrowth.fromasm.imprecise +++ b/test/memorygrowth.fromasm.imprecise @@ -1,6 +1,7 @@ (module (memory 256 256) (export "memory" memory) + (type $anyfunc (func (param none))) (type $FUNCSIG$iiii (func (param i32 i32 i32) (result i32))) (type $FUNCSIG$ii (func (param i32) (result i32))) (type $FUNCSIG$vi (func (param i32))) @@ -39,7 +40,7 @@ (export "dynCall_iiii" $lb) (export "dynCall_vi" $mb) (export "__growWasmMemory" $__growWasmMemory) - (table $nb $Oa $ob $Va $Ua $Ra $pb $Sa) + (table $0 default (type $anyfunc (func (param none))) $nb $Oa $ob $Va $Ua $Ra $pb $Sa) (func $eb (param $0 i32) (result i32) (local $1 i32) (local $2 i32) @@ -8337,7 +8338,7 @@ ) (block (set_local $4 - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load offset=36 @@ -8414,7 +8415,7 @@ ) (if (i32.lt_u - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load offset=36 @@ -8904,7 +8905,7 @@ (set_local $4 (if (i32.eq - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load offset=36 @@ -8962,7 +8963,7 @@ ) ) (block - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load offset=36 @@ -9021,7 +9022,7 @@ ) ) ) - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load offset=40 @@ -9903,7 +9904,7 @@ ) ) (func $lb (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (result i32) - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (get_local $0) @@ -9985,7 +9986,7 @@ ) ) (func $kb (param $0 i32) (param $1 i32) (result i32) - (call_indirect $FUNCSIG$ii + (call_indirect $0 $FUNCSIG$ii (i32.add (i32.and (get_local $0) @@ -10009,7 +10010,7 @@ ) ) (func $mb (param $0 i32) (param $1 i32) - (call_indirect $FUNCSIG$vi + (call_indirect $0 $FUNCSIG$vi (i32.add (i32.and (get_local $0) diff --git a/test/memorygrowth.fromasm.imprecise.no-opts b/test/memorygrowth.fromasm.imprecise.no-opts index dd03e651e9c..8014c2dd456 100644 --- a/test/memorygrowth.fromasm.imprecise.no-opts +++ b/test/memorygrowth.fromasm.imprecise.no-opts @@ -1,6 +1,7 @@ (module (memory 256 256) (export "memory" memory) + (type $anyfunc (func (param none))) (type $FUNCSIG$iiii (func (param i32 i32 i32) (result i32))) (type $FUNCSIG$ii (func (param i32) (result i32))) (type $FUNCSIG$vi (func (param i32))) @@ -39,7 +40,7 @@ (export "dynCall_iiii" $lb) (export "dynCall_vi" $mb) (export "__growWasmMemory" $__growWasmMemory) - (table $nb $Oa $ob $Va $Ua $Ra $pb $Sa) + (table $0 default (type $anyfunc (func (param none))) $nb $Oa $ob $Va $Ua $Ra $pb $Sa) (func $eb (param $a i32) (result i32) (local $b i32) (local $c i32) @@ -9781,7 +9782,7 @@ ) (block (set_local $h - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load @@ -9868,7 +9869,7 @@ ) (if (i32.lt_u - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load @@ -10487,7 +10488,7 @@ ) (if (i32.eq - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load @@ -10556,7 +10557,7 @@ ) ) (block - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load @@ -10624,7 +10625,7 @@ (get_local $f) (get_local $h) ) - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load @@ -11764,7 +11765,7 @@ ) (func $lb (param $a i32) (param $b i32) (param $c i32) (param $d i32) (result i32) (return - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (get_local $a) @@ -11854,7 +11855,7 @@ ) (func $kb (param $a i32) (param $b i32) (result i32) (return - (call_indirect $FUNCSIG$ii + (call_indirect $0 $FUNCSIG$ii (i32.add (i32.and (get_local $a) @@ -11883,7 +11884,7 @@ (return) ) (func $mb (param $a i32) (param $b i32) - (call_indirect $FUNCSIG$vi + (call_indirect $0 $FUNCSIG$vi (i32.add (i32.and (get_local $a) diff --git a/test/memorygrowth.fromasm.no-opts b/test/memorygrowth.fromasm.no-opts index 29aa4aa3099..0cc0a430689 100644 --- a/test/memorygrowth.fromasm.no-opts +++ b/test/memorygrowth.fromasm.no-opts @@ -1,6 +1,7 @@ (module (memory 256 256) (export "memory" memory) + (type $anyfunc (func (param none))) (type $FUNCSIG$iiii (func (param i32 i32 i32) (result i32))) (type $FUNCSIG$iii (func (param i32 i32) (result i32))) (type $FUNCSIG$ii (func (param i32) (result i32))) @@ -40,7 +41,7 @@ (export "dynCall_iiii" $lb) (export "dynCall_vi" $mb) (export "__growWasmMemory" $__growWasmMemory) - (table $nb $Oa $ob $Va $Ua $Ra $pb $Sa) + (table $0 default (type $anyfunc (func (param none))) $nb $Oa $ob $Va $Ua $Ra $pb $Sa) (func $eb (param $a i32) (result i32) (local $b i32) (local $c i32) @@ -9782,7 +9783,7 @@ ) (block (set_local $h - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load @@ -9869,7 +9870,7 @@ ) (if (i32.lt_u - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load @@ -10488,7 +10489,7 @@ ) (if (i32.eq - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load @@ -10557,7 +10558,7 @@ ) ) (block - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load @@ -10625,7 +10626,7 @@ (get_local $f) (get_local $h) ) - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (i32.load @@ -11765,7 +11766,7 @@ ) (func $lb (param $a i32) (param $b i32) (param $c i32) (param $d i32) (result i32) (return - (call_indirect $FUNCSIG$iiii + (call_indirect $0 $FUNCSIG$iiii (i32.add (i32.and (get_local $a) @@ -11855,7 +11856,7 @@ ) (func $kb (param $a i32) (param $b i32) (result i32) (return - (call_indirect $FUNCSIG$ii + (call_indirect $0 $FUNCSIG$ii (i32.add (i32.and (get_local $a) @@ -11884,7 +11885,7 @@ (return) ) (func $mb (param $a i32) (param $b i32) - (call_indirect $FUNCSIG$vi + (call_indirect $0 $FUNCSIG$vi (i32.add (i32.and (get_local $a) diff --git a/test/passes/coalesce-locals-learning.txt b/test/passes/coalesce-locals-learning.txt index 44ad12f5394..412cde19498 100644 --- a/test/passes/coalesce-locals-learning.txt +++ b/test/passes/coalesce-locals-learning.txt @@ -5,7 +5,9 @@ (type $2 (func)) (type $3 (func (param i32 f32))) (type $4 (func (param i32))) + (type $anyfunc (func (param none))) (import $_emscripten_autodebug_i32 "env" "_emscripten_autodebug_i32" (param i32 i32) (result i32)) + (table $0 default (type $anyfunc (func (param none)))) (func $nothing-to-do (type $2) (local $0 i32) (nop) diff --git a/test/passes/coalesce-locals.txt b/test/passes/coalesce-locals.txt index c24cf34e9cf..f9530d0710d 100644 --- a/test/passes/coalesce-locals.txt +++ b/test/passes/coalesce-locals.txt @@ -5,7 +5,9 @@ (type $2 (func)) (type $3 (func (param i32 f32))) (type $4 (func (param i32))) + (type $anyfunc (func (param none))) (import $_emscripten_autodebug_i32 "env" "_emscripten_autodebug_i32" (param i32 i32) (result i32)) + (table $0 default (type $anyfunc (func (param none)))) (func $nothing-to-do (type $2) (local $0 i32) (nop) diff --git a/test/passes/dce.txt b/test/passes/dce.txt index 692a5005e85..ca29e425808 100644 --- a/test/passes/dce.txt +++ b/test/passes/dce.txt @@ -2,7 +2,8 @@ (memory 10) (type $ii (func (param i32 i32))) (type $1 (func)) - (table $call-me) + (type $anyfunc (func (param none))) + (table $0 default (type $anyfunc (func (param none))) $call-me) (func $call-me (type $ii) (param $0 i32) (param $1 i32) (nop) ) diff --git a/test/passes/dce.wast b/test/passes/dce.wast index dcec20cc1fe..50fbeb6c91e 100644 --- a/test/passes/dce.wast +++ b/test/passes/dce.wast @@ -1,7 +1,7 @@ (module (memory 10) (type $ii (func (param i32) (param i32))) - (table $call-me) + (table $0 $call-me) (func $call-me (param i32) (param i32) ) (func $code-to-kill diff --git a/test/passes/duplicate-function-elimination.txt b/test/passes/duplicate-function-elimination.txt index 3671ce24b44..a8d3fa911b6 100644 --- a/test/passes/duplicate-function-elimination.txt +++ b/test/passes/duplicate-function-elimination.txt @@ -36,9 +36,10 @@ (memory 0) (start $keep2) (type $0 (func)) + (type $anyfunc (func (param none))) (export "keep2" $keep2) (export "other" $keep2) - (table $keep2 $keep2 $caller) + (table $0 default (type $anyfunc (func (param none))) $keep2 $keep2 $caller) (func $keep2 (type $0) (nop) ) @@ -363,9 +364,10 @@ (module (memory 0) (type $T (func)) - (table $erase $erase) + (type $anyfunc (func (param none))) + (table $0 default (type $anyfunc (func (param none))) $erase $erase) (func $erase (type $T) - (call_indirect $T + (call_indirect $0 $T (i32.const 0) ) ) @@ -373,14 +375,15 @@ (module (memory 0) (type $T (func)) - (table $keep2 $other) + (type $anyfunc (func (param none))) + (table $0 default (type $anyfunc (func (param none))) $keep2 $other) (func $keep2 (type $T) - (call_indirect $T + (call_indirect $0 $T (i32.const 0) ) ) (func $other (type $T) - (call_indirect $T + (call_indirect $0 $T (i32.const 1) ) ) @@ -389,14 +392,15 @@ (memory 0) (type $T (func)) (type $S (func)) - (table $keep2 $other) + (type $anyfunc (func (param none))) + (table $0 default (type $anyfunc (func (param none))) $keep2 $other) (func $keep2 (type $T) - (call_indirect $T + (call_indirect $0 $T (i32.const 0) ) ) (func $other (type $T) - (call_indirect $S + (call_indirect $0 $S (i32.const 0) ) ) diff --git a/test/passes/duplicate-function-elimination.wast b/test/passes/duplicate-function-elimination.wast index 8d1a85cd58d..45a8edd17ce 100644 --- a/test/passes/duplicate-function-elimination.wast +++ b/test/passes/duplicate-function-elimination.wast @@ -34,7 +34,7 @@ (export "keep2" $keep2) (export "other" $other) (start $other) - (table $keep2 $other $caller) + (table $0 $keep2 $other $caller) (func $keep2 (nop) ) @@ -315,7 +315,7 @@ ) (module (type T (func)) - (table $erase $other) + (table $0 $erase $other) (func $erase (call_indirect $T (i32.const 0)) ) @@ -325,7 +325,7 @@ ) (module (type T (func)) - (table $keep2 $other) + (table $0 $keep2 $other) (func $keep2 (call_indirect $T (i32.const 0)) ) @@ -336,7 +336,7 @@ (module (type T (func)) (type S (func)) - (table $keep2 $other) + (table $0 $keep2 $other) (func $keep2 (call_indirect $T (i32.const 0)) ) diff --git a/test/passes/remove-unused-functions.txt b/test/passes/remove-unused-functions.txt index b6f7cf3e1ce..10bde36fae2 100644 --- a/test/passes/remove-unused-functions.txt +++ b/test/passes/remove-unused-functions.txt @@ -2,8 +2,9 @@ (memory 0) (start $start) (type $0 (func)) + (type $anyfunc (func (param none))) (export "exported" $exported) - (table $called_indirect) + (table $0 default (type $anyfunc (func (param none))) $called_indirect) (func $start (type $0) (call $called0) ) diff --git a/test/passes/remove-unused-functions.wast b/test/passes/remove-unused-functions.wast index 4c89804bf59..29c95f27883 100644 --- a/test/passes/remove-unused-functions.wast +++ b/test/passes/remove-unused-functions.wast @@ -1,7 +1,7 @@ (module (start $start) (export "exported" $exported) - (table $called_indirect) + (table $0 $called_indirect) (func $start (call $called0) ) diff --git a/test/passes/remove-unused-names_merge-blocks.txt b/test/passes/remove-unused-names_merge-blocks.txt index fe5bd5cf8ed..6cacf62be9d 100644 --- a/test/passes/remove-unused-names_merge-blocks.txt +++ b/test/passes/remove-unused-names_merge-blocks.txt @@ -4,7 +4,8 @@ (type $ii (func (param i32 i32))) (type $iii (func (param i32 i32 i32))) (type $3 (func)) - (table $call-i) + (type $anyfunc (func (param none))) + (table $0 default (type $anyfunc (func (param none))) $call-i) (func $call-i (type $i) (param $0 i32) (nop) ) @@ -405,12 +406,12 @@ (i32.const 10) (i32.const 30) (i32.const 50) - (call_indirect $ii + (call_indirect $0 $ii (i32.const 20) (i32.const 40) (i32.const 60) ) - (call_indirect $ii + (call_indirect $0 $ii (unreachable) (block (i32.const 30) diff --git a/test/passes/remove-unused-names_merge-blocks.wast b/test/passes/remove-unused-names_merge-blocks.wast index 85bb11da62d..99932673265 100644 --- a/test/passes/remove-unused-names_merge-blocks.wast +++ b/test/passes/remove-unused-names_merge-blocks.wast @@ -3,7 +3,7 @@ (type $i (func (param i32))) (type $ii (func (param i32) (param i32))) (type $iii (func (param i32) (param i32) (param i32))) - (table $call-i) + (table $0 $call-i) (func $call-i (param i32) ) (func $call-ii (param i32) (param i32) diff --git a/test/unit.fromasm b/test/unit.fromasm index f939782e73f..b383ac0095b 100644 --- a/test/unit.fromasm +++ b/test/unit.fromasm @@ -4,6 +4,7 @@ (type $FUNCSIG$id (func (param f64) (result i32))) (type $FUNCSIG$ddd (func (param f64 f64) (result f64))) (type $FUNCSIG$iii (func (param i32 i32) (result i32))) + (type $anyfunc (func (param none))) (type $FUNCSIG$vf (func (param f32))) (type $FUNCSIG$vi (func (param i32))) (type $FUNCSIG$vd (func (param f64))) @@ -15,7 +16,7 @@ (import $i32u-div "asm2wasm" "i32u-div" (param i32 i32) (result i32)) (export "big_negative" $big_negative) (export "pick" $big_negative) - (table $big_negative $big_negative $big_negative $big_negative $big_negative $big_negative $importedDoubles $big_negative $big_negative $cneg) + (table $0 default (type $anyfunc (func (param none))) $big_negative $big_negative $big_negative $big_negative $big_negative $big_negative $importedDoubles $big_negative $big_negative $cneg) (func $big_negative (nop) ) @@ -221,7 +222,7 @@ ) (func $neg (local $0 f32) - (call_indirect $FUNCSIG$vf + (call_indirect $0 $FUNCSIG$vf (i32.add (i32.const 1) (i32.const 8) @@ -232,7 +233,7 @@ ) ) (func $cneg (param $0 f32) - (call_indirect $FUNCSIG$vf + (call_indirect $0 $FUNCSIG$vf (i32.add (i32.const 1) (i32.const 8) @@ -270,7 +271,7 @@ (get_local $0) ) (func $cneg_nosemicolon - (call_indirect $FUNCSIG$vi + (call_indirect $0 $FUNCSIG$vi (i32.add (i32.const 1) (i32.const 8) diff --git a/test/unit.fromasm.imprecise b/test/unit.fromasm.imprecise index f80f4ce6c74..dbc5d6943fb 100644 --- a/test/unit.fromasm.imprecise +++ b/test/unit.fromasm.imprecise @@ -2,6 +2,7 @@ (memory 256 256) (export "memory" memory) (type $FUNCSIG$ddd (func (param f64 f64) (result f64))) + (type $anyfunc (func (param none))) (type $FUNCSIG$vf (func (param f32))) (type $FUNCSIG$vi (func (param i32))) (type $FUNCSIG$vd (func (param f64))) @@ -11,7 +12,7 @@ (import $f64-rem "asm2wasm" "f64-rem" (param f64 f64) (result f64)) (export "big_negative" $big_negative) (export "pick" $big_negative) - (table $big_negative $big_negative $big_negative $big_negative $big_negative $big_negative $importedDoubles $big_negative $big_negative $cneg) + (table $0 default (type $anyfunc (func (param none))) $big_negative $big_negative $big_negative $big_negative $big_negative $big_negative $importedDoubles $big_negative $big_negative $cneg) (func $big_negative (nop) ) @@ -205,7 +206,7 @@ ) (func $neg (local $0 f32) - (call_indirect $FUNCSIG$vf + (call_indirect $0 $FUNCSIG$vf (i32.add (i32.const 1) (i32.const 8) @@ -216,7 +217,7 @@ ) ) (func $cneg (param $0 f32) - (call_indirect $FUNCSIG$vf + (call_indirect $0 $FUNCSIG$vf (i32.add (i32.const 1) (i32.const 8) @@ -254,7 +255,7 @@ (get_local $0) ) (func $cneg_nosemicolon - (call_indirect $FUNCSIG$vi + (call_indirect $0 $FUNCSIG$vi (i32.add (i32.const 1) (i32.const 8) diff --git a/test/unit.fromasm.imprecise.no-opts b/test/unit.fromasm.imprecise.no-opts index 4fa627938f1..227bdb5f33b 100644 --- a/test/unit.fromasm.imprecise.no-opts +++ b/test/unit.fromasm.imprecise.no-opts @@ -2,6 +2,7 @@ (memory 256 256) (export "memory" memory) (type $FUNCSIG$ddd (func (param f64 f64) (result f64))) + (type $anyfunc (func (param none))) (type $FUNCSIG$vf (func (param f32))) (type $FUNCSIG$vi (func (param i32))) (type $FUNCSIG$vd (func (param f64))) @@ -11,7 +12,7 @@ (import $f64-rem "asm2wasm" "f64-rem" (param f64 f64) (result f64)) (export "big_negative" $big_negative) (export "pick" $exportMe) - (table $z $big_negative $z $z $w $w $importedDoubles $w $z $cneg) + (table $0 default (type $anyfunc (func (param none))) $z $big_negative $z $z $w $w $importedDoubles $w $z $cneg) (func $big_negative (local $temp f64) (set_local $temp @@ -394,7 +395,7 @@ (get_local $x) ) ) - (call_indirect $FUNCSIG$vf + (call_indirect $0 $FUNCSIG$vf (i32.add (i32.and (i32.const 1) @@ -406,7 +407,7 @@ ) ) (func $cneg (param $x f32) - (call_indirect $FUNCSIG$vf + (call_indirect $0 $FUNCSIG$vf (i32.add (i32.and (i32.const 1) @@ -456,7 +457,7 @@ ) ) (func $cneg_nosemicolon - (call_indirect $FUNCSIG$vi + (call_indirect $0 $FUNCSIG$vi (i32.add (i32.and (i32.const 1) diff --git a/test/unit.fromasm.no-opts b/test/unit.fromasm.no-opts index c10bd3dff25..8e92645fd87 100644 --- a/test/unit.fromasm.no-opts +++ b/test/unit.fromasm.no-opts @@ -4,6 +4,7 @@ (type $FUNCSIG$id (func (param f64) (result i32))) (type $FUNCSIG$ddd (func (param f64 f64) (result f64))) (type $FUNCSIG$iii (func (param i32 i32) (result i32))) + (type $anyfunc (func (param none))) (type $FUNCSIG$vf (func (param f32))) (type $FUNCSIG$vi (func (param i32))) (type $FUNCSIG$vd (func (param f64))) @@ -15,7 +16,7 @@ (import $i32u-div "asm2wasm" "i32u-div" (param i32 i32) (result i32)) (export "big_negative" $big_negative) (export "pick" $exportMe) - (table $z $big_negative $z $z $w $w $importedDoubles $w $z $cneg) + (table $0 default (type $anyfunc (func (param none))) $z $big_negative $z $z $w $w $importedDoubles $w $z $cneg) (func $big_negative (local $temp f64) (set_local $temp @@ -400,7 +401,7 @@ (get_local $x) ) ) - (call_indirect $FUNCSIG$vf + (call_indirect $0 $FUNCSIG$vf (i32.add (i32.and (i32.const 1) @@ -412,7 +413,7 @@ ) ) (func $cneg (param $x f32) - (call_indirect $FUNCSIG$vf + (call_indirect $0 $FUNCSIG$vf (i32.add (i32.and (i32.const 1) @@ -462,7 +463,7 @@ ) ) (func $cneg_nosemicolon - (call_indirect $FUNCSIG$vi + (call_indirect $0 $FUNCSIG$vi (i32.add (i32.and (i32.const 1) diff --git a/test/unit.wast b/test/unit.wast index 301ba719c46..d5b12634f7a 100644 --- a/test/unit.wast +++ b/test/unit.wast @@ -10,11 +10,12 @@ (type $5 (func (result i32))) (type $6 (func (param i32) (result i32))) (type $7 (func (param f64) (result f64))) + (type $anyfunc (func (param none))) (import $_emscripten_asm_const_vi "env" "_emscripten_asm_const_vi") (import $f64-to-int "asm2wasm" "f64-to-int" (param f64) (result i32)) (import $f64-rem "asm2wasm" "f64-rem" (param f64 f64) (result f64)) (export "big_negative" $big_negative) - (table $z $big_negative $z $z $w $w $importedDoubles $w $z $cneg) + (table $0 default (type $anyfunc (func (param none))) $z $big_negative $z $z $w $w $importedDoubles $w $z $cneg) (func $big_negative (type $FUNCSIG$v) (local $temp f64) (block $block0 @@ -359,7 +360,7 @@ (get_local $x) ) ) - (call_indirect $FUNCSIG$vf + (call_indirect $0 $FUNCSIG$vf (i32.add (i32.and (i32.const 1) @@ -372,7 +373,7 @@ ) ) (func $cneg (type $FUNCSIG$vf) (param $x f32) - (call_indirect $FUNCSIG$vf + (call_indirect $0 $FUNCSIG$vf (i32.add (i32.and (i32.const 1) diff --git a/test/unit.wast.fromBinary b/test/unit.wast.fromBinary index c9ba4528b31..46a33f998d2 100644 --- a/test/unit.wast.fromBinary +++ b/test/unit.wast.fromBinary @@ -10,11 +10,12 @@ (type $5 (func (result i32))) (type $6 (func (param i32) (result i32))) (type $7 (func (param f64) (result f64))) + (type $anyfunc (func (param none))) (import $import$0 "env" "_emscripten_asm_const_vi") (import $import$1 "asm2wasm" "f64-to-int" (param f64) (result i32)) (import $import$2 "asm2wasm" "f64-rem" (param f64 f64) (result f64)) (export "big_negative" $big_negative) - (table $z $big_negative $z $z $w $w $importedDoubles $w $z $cneg) + (table $0 default (type $anyfunc (func (param none))) $z $big_negative $z $z $w $w $importedDoubles $w $z $cneg) (func $big_negative (type $1) (local $var$0 f64) (block $label$0 @@ -367,7 +368,7 @@ (get_local $var$0) ) ) - (call_indirect $0 + (call_indirect $0 $0 (i32.add (i32.and (i32.const 1) @@ -380,7 +381,7 @@ ) ) (func $cneg (type $0) (param $var$0 f32) - (call_indirect $0 + (call_indirect $0 $0 (i32.add (i32.and (i32.const 1) From 89a66d2b3f51a2e3b2aea2533e231833c4094536 Mon Sep 17 00:00:00 2001 From: Dominic Chen Date: Fri, 19 Aug 2016 12:36:00 -0700 Subject: [PATCH 3/3] Silence binaryen JS output --- src/js/wasm.js-post.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/js/wasm.js-post.js b/src/js/wasm.js-post.js index ae42ef17596..10eb69739c3 100644 --- a/src/js/wasm.js-post.js +++ b/src/js/wasm.js-post.js @@ -301,8 +301,6 @@ function integrateWasmJS(Module) { for (var i = 0; i < methods.length; i++) { var curr = methods[i]; - Module['printErr']('trying binaryen method: ' + curr); - if (curr === 'native-wasm') { if (exports = doNativeWasm(global, env, providedBuffer)) break; } else if (curr === 'asmjs') { @@ -316,8 +314,6 @@ function integrateWasmJS(Module) { if (!exports) throw 'no binaryen method succeeded'; - Module['printErr']('binaryen method succeeded.'); - return exports; };