diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/binaryen-c.cpp | 4 | ||||
-rw-r--r-- | src/binaryen-c.h | 4 | ||||
-rw-r--r-- | src/ir/table-utils.cpp | 19 | ||||
-rw-r--r-- | src/ir/table-utils.h | 5 | ||||
-rw-r--r-- | src/passes/Print.cpp | 13 | ||||
-rw-r--r-- | src/wasm-binary.h | 4 | ||||
-rw-r--r-- | src/wasm/wasm-binary.cpp | 13 | ||||
-rw-r--r-- | src/wasm/wasm-s-parser.cpp | 47 |
8 files changed, 70 insertions, 39 deletions
diff --git a/src/binaryen-c.cpp b/src/binaryen-c.cpp index 15c4cb90e..68b0f86c2 100644 --- a/src/binaryen-c.cpp +++ b/src/binaryen-c.cpp @@ -3775,6 +3775,10 @@ void BinaryenModuleOptimize(BinaryenModuleRef module) { passRunner.run(); } +void BinaryenModuleUpdateMaps(BinaryenModuleRef module) { + ((Module*)module)->updateMaps(); +} + int BinaryenGetOptimizeLevel(void) { return globalPassOptions.optimizeLevel; } void BinaryenSetOptimizeLevel(int level) { diff --git a/src/binaryen-c.h b/src/binaryen-c.h index dc8bb890f..b2c4351b1 100644 --- a/src/binaryen-c.h +++ b/src/binaryen-c.h @@ -2253,6 +2253,10 @@ BINARYEN_API bool BinaryenModuleValidate(BinaryenModuleRef module); // global optimize and shrink level. BINARYEN_API void BinaryenModuleOptimize(BinaryenModuleRef module); +// Updates the internal name mapping logic in a module. This must be called +// after renaming module elements. +BINARYEN_API void BinaryenModuleUpdateMaps(BinaryenModuleRef module); + // Gets the currently set optimize level. Applies to all modules, globally. // 0, 1, 2 correspond to -O0, -O1, -O2 (default), etc. BINARYEN_API int BinaryenGetOptimizeLevel(void); diff --git a/src/ir/table-utils.cpp b/src/ir/table-utils.cpp index 80ef885f9..79b90d249 100644 --- a/src/ir/table-utils.cpp +++ b/src/ir/table-utils.cpp @@ -64,6 +64,25 @@ std::set<Name> getFunctionsNeedingElemDeclare(Module& wasm) { return ret; } +bool usesExpressions(ElementSegment* curr, Module* module) { + // Binaryen IR always has ref.funcs for functions in tables for uniformity, + // so that by itself does not indicate if expressions should be used when + // emitting the table or not. But definitely anything that is not a ref.func + // implies we are post-MVP and must use expressions. + bool allElementsRefFunc = + std::all_of(curr->data.begin(), curr->data.end(), [](Expression* entry) { + return entry->is<RefFunc>(); + }); + + // If the table has a specialized (non-MVP) type, then the segment must + // declare a type that is a subtype of that, so it must use the post-MVP form + // of using expressions. + bool hasTableOfSpecializedType = + curr->table.is() && module->getTable(curr->table)->type != Type::funcref; + + return !allElementsRefFunc || hasTableOfSpecializedType; +} + } // namespace TableUtils } // namespace wasm diff --git a/src/ir/table-utils.h b/src/ir/table-utils.h index 99a5bbf5b..e4cf409c1 100644 --- a/src/ir/table-utils.h +++ b/src/ir/table-utils.h @@ -110,6 +110,11 @@ inline Index getOrAppend(Table& table, Name name, Module& wasm) { // "elem declare" mention in the text and binary formats. std::set<Name> getFunctionsNeedingElemDeclare(Module& wasm); +// Returns whether a segment uses arbitrary wasm expressions, as opposed to the +// original tables from the MVP that use function indices. (Some post-MVP tables +// do so, and some do not, depending on their type and use.) +bool usesExpressions(ElementSegment* curr, Module* module); + } // namespace TableUtils } // namespace wasm diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index 4fa38442c..616ce9759 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -2735,12 +2735,9 @@ struct PrintSExpression : public UnifiedExpressionVisitor<PrintSExpression> { } } void visitElementSegment(ElementSegment* curr) { - bool allElementsRefFunc = - std::all_of(curr->data.begin(), curr->data.end(), [](Expression* entry) { - return entry->is<RefFunc>(); - }); + bool usesExpressions = TableUtils::usesExpressions(curr, currModule); auto printElemType = [&]() { - if (allElementsRefFunc) { + if (!usesExpressions) { o << "func"; } else { printType(o, curr->type, currModule); @@ -2758,7 +2755,7 @@ struct PrintSExpression : public UnifiedExpressionVisitor<PrintSExpression> { } if (curr->table.is()) { - if (!allElementsRefFunc || currModule->tables.size() > 1) { + if (usesExpressions || currModule->tables.size() > 1) { // tableuse o << " (table "; printName(curr->table, o); @@ -2768,7 +2765,7 @@ struct PrintSExpression : public UnifiedExpressionVisitor<PrintSExpression> { o << ' '; visit(curr->offset); - if (!allElementsRefFunc || currModule->tables.size() > 1) { + if (usesExpressions || currModule->tables.size() > 1) { o << ' '; printElemType(); } @@ -2777,7 +2774,7 @@ struct PrintSExpression : public UnifiedExpressionVisitor<PrintSExpression> { printElemType(); } - if (allElementsRefFunc) { + if (!usesExpressions) { for (auto* entry : curr->data) { auto* refFunc = entry->cast<RefFunc>(); o << ' '; diff --git a/src/wasm-binary.h b/src/wasm-binary.h index 260bacecf..13925f5e1 100644 --- a/src/wasm-binary.h +++ b/src/wasm-binary.h @@ -346,8 +346,8 @@ enum SegmentFlag { // Bit 1 if active: 0 = index 0, 1 = index given HasIndex = 1 << 1, // Table element segments only: - // Bit 2: 0 = elemType is funcref and vector of func indexes given - // 1 = elemType is given and vector of ref expressions is given + // Bit 2: 0 = elemType is funcref and a vector of func indexes given + // 1 = elemType is given and a vector of ref expressions is given UsesExpressions = 1 << 2 }; diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index ab229f111..ee3c1a6fa 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -584,11 +584,8 @@ void WasmBinaryWriter::writeElementSegments() { Index tableIdx = 0; bool isPassive = segment->table.isNull(); - // if all items are ref.func, we can use the shorter form. - bool usesExpressions = - std::any_of(segment->data.begin(), - segment->data.end(), - [](Expression* curr) { return !curr->is<RefFunc>(); }); + // If the segment is MVP, we can use the shorter form. + bool usesExpressions = TableUtils::usesExpressions(segment.get(), wasm); bool hasTableIndex = false; if (!isPassive) { @@ -620,7 +617,7 @@ void WasmBinaryWriter::writeElementSegments() { // elemType writeType(segment->type); } else { - // elemKind funcref + // MVP elemKind of funcref o << U32LEB(0); } } @@ -2864,12 +2861,12 @@ void WasmBinaryBuilder::readElementSegments() { if (usesExpressions) { segment->type = getType(); if (!segment->type.isFunction()) { - throwError("Invalid type for an element segment"); + throwError("Invalid type for a usesExpressions element segment"); } } else { auto elemKind = getU32LEB(); if (elemKind != 0x0) { - throwError("Only funcref elem kinds are valid."); + throwError("Invalid kind (!= funcref(0)) since !usesExpressions."); } } } diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp index c9c8235e2..c9ca71a6d 100644 --- a/src/wasm/wasm-s-parser.cpp +++ b/src/wasm/wasm-s-parser.cpp @@ -21,6 +21,7 @@ #include <limits> #include "ir/branch-utils.h" +#include "ir/table-utils.h" #include "shared-constants.h" #include "support/string.h" #include "wasm-binary.h" @@ -3368,6 +3369,11 @@ void SExpressionWasmBuilder::parseElem(Element& s, Table* table) { segment->table = table->name; } + // We may be post-MVP also due to type reasons or otherwise, as detected by + // the utility function for Binaryen IR. + usesExpressions = + usesExpressions || TableUtils::usesExpressions(segment.get(), &wasm); + parseElemFinish(s, segment, i, usesExpressions); } @@ -3377,30 +3383,29 @@ ElementSegment* SExpressionWasmBuilder::parseElemFinish( Index i, bool usesExpressions) { - if (usesExpressions) { - for (; i < s.size(); i++) { - if (!s[i]->isList()) { - throw ParseException("expected a ref.* expression."); - } - auto& inner = *s[i]; - if (elementStartsWith(inner, ITEM)) { - if (inner[1]->isList()) { - // (item (ref.func $f)) - segment->data.push_back(parseExpression(inner[1])); - } else { - // (item ref.func $f) - inner.list().removeAt(0); - segment->data.push_back(parseExpression(inner)); - } - } else { - segment->data.push_back(parseExpression(inner)); - } - } - } else { - for (; i < s.size(); i++) { + for (; i < s.size(); i++) { + if (!s[i]->isList()) { + // An MVP-style declaration: just a function name. auto func = getFunctionName(*s[i]); segment->data.push_back( Builder(wasm).makeRefFunc(func, functionTypes[func])); + continue; + } + if (!usesExpressions) { + throw ParseException("expected an MVP-style $funcname in elem."); + } + auto& inner = *s[i]; + if (elementStartsWith(inner, ITEM)) { + if (inner[1]->isList()) { + // (item (ref.func $f)) + segment->data.push_back(parseExpression(inner[1])); + } else { + // (item ref.func $f) + inner.list().removeAt(0); + segment->data.push_back(parseExpression(inner)); + } + } else { + segment->data.push_back(parseExpression(inner)); } } return wasm.addElementSegment(std::move(segment)); |