| /* |
| * Copyright 2022 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. |
| */ |
| |
| // |
| // Handle the computation of global effects. The effects are stored on the |
| // PassOptions structure; see more details there. |
| // |
| |
| #include "ir/effects.h" |
| #include "ir/module-utils.h" |
| #include "pass.h" |
| #include "wasm.h" |
| |
| namespace wasm { |
| |
| struct GenerateGlobalEffects : public Pass { |
| void run(Module* module) override { |
| // TODO: Full transitive closure of effects. For now, we just look at each |
| // function by itself. |
| |
| auto& funcEffectsMap = getPassOptions().funcEffectsMap; |
| |
| // First, clear any previous effects. |
| funcEffectsMap.reset(); |
| |
| // When we find useful effects, we'll save them. If we can't find anything, |
| // the final map we emit will not have an entry there at all. |
| using PossibleEffects = std::unique_ptr<EffectAnalyzer>; |
| |
| ModuleUtils::ParallelFunctionAnalysis<PossibleEffects> analysis( |
| *module, [&](Function* func, PossibleEffects& storedEffects) { |
| if (func->imported()) { |
| // Imports can do anything, so we need to assume the worst anyhow, |
| // which is the same as not specifying any effects for them in the |
| // map. |
| return; |
| } |
| |
| // Gather the effects. |
| auto effects = |
| std::make_unique<EffectAnalyzer>(getPassOptions(), *module, func); |
| |
| // If the body has a call, give up - that means we can't infer a more |
| // specific set of effects than the pessimistic case of just assuming |
| // any call to here is an arbitrary call. (See the TODO above for |
| // improvements.) |
| if (effects->calls) { |
| return; |
| } |
| |
| // Save the useful effects we found. |
| storedEffects = std::move(effects); |
| }); |
| |
| // Generate the final data structure. |
| for (auto& [func, possibleEffects] : analysis.map) { |
| if (possibleEffects) { |
| // Only allocate a new funcEffectsMap if we actually have data for it |
| // (which might make later effect computation slightly faster, to |
| // quickly skip the funcEffectsMap code path). |
| if (!funcEffectsMap) { |
| funcEffectsMap = std::make_shared<FuncEffectsMap>(); |
| } |
| funcEffectsMap->emplace(func->name, *possibleEffects); |
| } |
| } |
| } |
| }; |
| |
| struct DiscardGlobalEffects : public Pass { |
| void run(Module* module) override { getPassOptions().funcEffectsMap.reset(); } |
| }; |
| |
| Pass* createGenerateGlobalEffectsPass() { return new GenerateGlobalEffects(); } |
| |
| Pass* createDiscardGlobalEffectsPass() { return new DiscardGlobalEffects(); } |
| |
| } // namespace wasm |