| /* |
| * Copyright 2026 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. |
| */ |
| |
| // |
| // Users should mark JS-called functions using @binaryen.js.called. This pass |
| // helps by auto-marking them where possible. The main thing this does is to |
| // find any configureAll calls and mark the functions referred to there. |
| // |
| // We do automatically handle configureAll in the start function (in |
| // intrinsics.cpp), so this pass is only needed for other uses of configureAll, |
| // like from an export. |
| // |
| |
| #include "ir/find_all.h" |
| #include "ir/intrinsics.h" |
| #include "ir/module-utils.h" |
| #include "pass.h" |
| #include "wasm.h" |
| |
| namespace wasm { |
| |
| struct MarkJSCalled : public Pass { |
| void run(Module* module) override { |
| Intrinsics intrinsics(*module); |
| |
| // See if there even is a configureAll. |
| auto hasConfigureAll = false; |
| for (auto& func : module->functions) { |
| if (intrinsics.isConfigureAll(func.get())) { |
| hasConfigureAll = true; |
| break; |
| } |
| } |
| if (!hasConfigureAll) { |
| return; |
| } |
| |
| using JSCalledSet = std::unordered_set<Name>; |
| |
| ModuleUtils::ParallelFunctionAnalysis<JSCalledSet> analysis( |
| *module, [&](Function* func, JSCalledSet& jsCalled) { |
| if (func->imported()) { |
| return; |
| } |
| |
| FindAll<Call> calls(func->body); |
| for (auto* call : calls.list) { |
| if (intrinsics.isConfigureAll(call)) { |
| for (auto name : intrinsics.getConfigureAllFunctions(call)) { |
| jsCalled.insert(name); |
| } |
| } |
| } |
| }); |
| |
| for (auto& [_, jsCalled] : analysis.map) { |
| for (auto name : jsCalled) { |
| module->getFunction(name)->funcAnnotations.jsCalled = true; |
| } |
| } |
| } |
| }; |
| |
| Pass* createMarkJSCalledPass() { return new MarkJSCalled(); } |
| |
| } // namespace wasm |