1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
/*
* Copyright 2023 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.
*/
#ifndef wasm_passes_pass_utils_h
#define wasm_passes_pass_utils_h
#include <unordered_set>
#include <pass.h>
#include <wasm.h>
namespace wasm::PassUtils {
using FuncSet = std::unordered_set<Function*>;
// A wrapper around a parallel pass that filters it to run run only on select
// functions.
struct FilteredPass : public Pass {
std::unique_ptr<Pass> create() override {
// Function-parallel passes get a new instance per function. Create a copy
// of the wrapped pass along with ourselves.
return std::make_unique<FilteredPass>(pass->create(), relevantFuncs);
}
FilteredPass(std::unique_ptr<Pass>&& pass, const FuncSet& relevantFuncs)
: pass(std::move(pass)), relevantFuncs(relevantFuncs) {}
bool isFunctionParallel() override {
assert(pass->isFunctionParallel());
return true;
}
void runOnFunction(Module* module, Function* func) override {
if (!relevantFuncs.count(func)) {
return;
}
// The pass runner calling us set our pass runner, which we must do for the
// wrapped pass.
pass->setPassRunner(getPassRunner());
pass->runOnFunction(module, func);
}
bool modifiesBinaryenIR() override { return pass->modifiesBinaryenIR(); }
bool invalidatesDWARF() override { return pass->invalidatesDWARF(); }
bool addsEffects() override { return pass->addsEffects(); }
bool requiresNonNullableLocalFixups() override {
return pass->requiresNonNullableLocalFixups();
}
private:
std::unique_ptr<Pass> pass;
const FuncSet& relevantFuncs;
};
// A pass runner that wraps all passes, filtering so that they only run on
// select functions.
struct FilteredPassRunner : public PassRunner {
FilteredPassRunner(Module* wasm, const FuncSet& relevantFuncs)
: PassRunner(wasm), relevantFuncs(relevantFuncs) {}
FilteredPassRunner(Module* wasm,
const FuncSet& relevantFuncs,
const PassOptions& options)
: PassRunner(wasm, options), relevantFuncs(relevantFuncs) {}
protected:
void doAdd(std::unique_ptr<Pass> pass) override {
PassRunner::doAdd(
std::make_unique<FilteredPass>(std::move(pass), relevantFuncs));
}
private:
const FuncSet& relevantFuncs;
};
} // namespace wasm::PassUtils
#endif // wasm_passes_pass_utils_h
|