| /* |
| * Copyright 2021 WebAssembly Community Group participants |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #include "table-utils.h" |
| #include "element-utils.h" |
| #include "find_all.h" |
| #include "module-utils.h" |
| |
| namespace wasm::TableUtils { |
| |
| std::set<Name> getFunctionsNeedingElemDeclare(Module& wasm) { |
| // Without reference types there are no ref.funcs or elem declare. |
| if (!wasm.features.hasReferenceTypes()) { |
| return {}; |
| } |
| |
| // Find all the names in the tables. |
| |
| std::unordered_set<Name> tableNames; |
| ElementUtils::iterAllElementFunctionNames( |
| &wasm, [&](Name name) { tableNames.insert(name); }); |
| |
| // Find all the names in ref.funcs. |
| using Names = std::unordered_set<Name>; |
| |
| ModuleUtils::ParallelFunctionAnalysis<Names> analysis( |
| wasm, [&](Function* func, Names& names) { |
| if (func->imported()) { |
| return; |
| } |
| for (auto* refFunc : FindAll<RefFunc>(func->body).list) { |
| names.insert(refFunc->func); |
| } |
| }); |
| |
| // Find the names that need to be declared. |
| |
| std::set<Name> ret; |
| |
| for (auto& kv : analysis.map) { |
| auto& names = kv.second; |
| for (auto name : names) { |
| if (!tableNames.count(name)) { |
| ret.insert(name); |
| } |
| } |
| } |
| |
| 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 segment has a specialized (non-MVP) type, then it must use the |
| // post-MVP form of using expressions. |
| bool hasSpecializedType = curr->type != Type(HeapType::func, Nullable); |
| |
| return !allElementsRefFunc || hasSpecializedType; |
| } |
| |
| } // namespace wasm::TableUtils |