@@ -48,26 +48,33 @@ struct FuncInfo {
4848 std::unordered_set<HeapType> indirectCalledTypes;
4949};
5050
51+ /*
52+ Only funcs that are 'addressed' may be the target of an indirect call. A
53+ function is addressed if:
54+ - It appears in a ref.func expression
55+ - It appears in an `elem declare` statement (note that we already ignore `elem`
56+ statements in our IR, but we check separately for funcs that appear in
57+ `ref.func`).
58+ - It's exported, because it may flow back to us as a reference.
59+ - It's imported, which implies it is `elem declare`d.
60+
61+ If a function doesn't meet any of these criteria, it can't be the target of
62+ an indirect call and we don't need to include its effects in indirect calls.
63+ */
5164std::unordered_set<Function*> getAddressedFuncs (Module& module ) {
52- struct AddressedFuncsWalker
53- : PostWalker<AddressedFuncsWalker,
54- UnifiedExpressionVisitor<AddressedFuncsWalker>> {
55- const Module& module ;
65+ struct AddressedFuncsWalker : PostWalker<AddressedFuncsWalker> {
5666 std::unordered_set<Function*>& addressedFuncs;
5767
58- AddressedFuncsWalker (const Module& module ,
59- std::unordered_set<Function*>& addressedFuncs)
60- : module (module ), addressedFuncs(addressedFuncs) {}
68+ AddressedFuncsWalker (std::unordered_set<Function*>& addressedFuncs)
69+ : addressedFuncs(addressedFuncs) {}
6170
62- void visitExpression (Expression* curr) {
63- if (auto * refFunc = curr->dynCast <RefFunc>()) {
64- addressedFuncs.insert (module .getFunction (refFunc->func ));
65- }
71+ void visitRefFunc (RefFunc* refFunc) {
72+ addressedFuncs.insert (getModule ()->getFunction (refFunc->func ));
6673 }
6774 };
6875
6976 std::unordered_set<Function*> addressedFuncs;
70- AddressedFuncsWalker walker (module , addressedFuncs);
77+ AddressedFuncsWalker walker (addressedFuncs);
7178 walker.walkModule (&module );
7279
7380 ModuleUtils::iterImportedFunctions (
@@ -80,9 +87,6 @@ std::unordered_set<Function*> getAddressedFuncs(Module& module) {
8087 continue ;
8188 }
8289
83- // TODO: internal or external? I think internal
84- // This might be why we failed to lookup the function earlier
85- // Maybe we can use Function* after all
8690 addressedFuncs.insert (module .getFunction (*export_->getInternalName ()));
8791 }
8892
@@ -96,7 +100,6 @@ std::unordered_set<Function*> getAddressedFuncs(Module& module) {
96100
97101std::map<Function*, FuncInfo> analyzeFuncs (Module& module ,
98102 const PassOptions& passOptions) {
99- std::unordered_set<Name> addressedFuncs;
100103 ModuleUtils::ParallelFunctionAnalysis<FuncInfo> analysis (
101104 module , [&](Function* func, FuncInfo& funcInfo) {
102105 if (func->imported ()) {
@@ -127,14 +130,10 @@ std::map<Function*, FuncInfo> analyzeFuncs(Module& module,
127130 const PassOptions& options;
128131 FuncInfo& funcInfo;
129132
130- std::unordered_set<Name>& addressedFuncs;
131-
132133 CallScanner (Module& wasm,
133134 const PassOptions& options,
134- FuncInfo& funcInfo,
135- std::unordered_set<Name>& addressedFuncs)
136- : wasm(wasm), options(options), funcInfo(funcInfo),
137- addressedFuncs (addressedFuncs) {}
135+ FuncInfo& funcInfo)
136+ : wasm(wasm), options(options), funcInfo(funcInfo) {}
138137
139138 void visitExpression (Expression* curr) {
140139 ShallowEffectAnalyzer effects (options, wasm, curr);
@@ -167,7 +166,7 @@ std::map<Function*, FuncInfo> analyzeFuncs(Module& module,
167166 }
168167 }
169168 };
170- CallScanner scanner (module , passOptions, funcInfo, addressedFuncs );
169+ CallScanner scanner (module , passOptions, funcInfo);
171170 scanner.walkFunction (func);
172171 }
173172 });
@@ -199,7 +198,7 @@ using CallGraph =
199198
200199CallGraph buildCallGraph (const Module& module ,
201200 const std::map<Function*, FuncInfo>& funcInfos,
202- const std::unordered_set<Function*> addressedFuncs,
201+ const std::unordered_set<Function*>& addressedFuncs,
203202 bool closedWorld) {
204203 CallGraph callGraph;
205204 if (!closedWorld) {
@@ -398,7 +397,8 @@ void copyEffectsToFunctions(const std::map<Function*, FuncInfo>& funcInfos) {
398397
399398struct GenerateGlobalEffects : public Pass {
400399 void run (Module* module ) override {
401- auto funcInfos = analyzeFuncs (*module , getPassOptions ());
400+ std::map<Function*, FuncInfo> funcInfos =
401+ analyzeFuncs (*module , getPassOptions ());
402402
403403 auto addressedFuncs = getAddressedFuncs (*module );
404404
0 commit comments