@@ -80,7 +80,12 @@ struct LinearExecutionWalker : public PostWalker<SubType, VisitorType> {
8080 static void scan (SubType* self, Expression** currp) {
8181 Expression* curr = *currp;
8282
83- auto handleCall = [&](bool mayThrow, bool isReturn) {
83+ auto handleCall = [&](bool isReturn, const EffectAnalyzer* effects) {
84+ bool refutesThrowEffect = effects && !effects->throws ();
85+ bool mayThrow = !self->getModule () ||
86+ self->getModule ()->features .hasExceptionHandling ();
87+ mayThrow = mayThrow && !refutesThrowEffect;
88+
8489 if (!self->connectAdjacentBlocks ) {
8590 // Control is nonlinear if we return or throw. Traps don't need to be
8691 // taken into account since they don't break control flow in a way
@@ -156,40 +161,39 @@ struct LinearExecutionWalker : public PostWalker<SubType, VisitorType> {
156161 case Expression::Id::CallId: {
157162 auto * call = curr->cast <Call>();
158163
159- bool mayThrow = !self->getModule () ||
160- self->getModule ()->features .hasExceptionHandling ();
161- if (mayThrow && self->getModule ()) {
162- auto * effects =
163- self->getModule ()->getFunction (call->target )->effects .get ();
164-
165- if (effects && !effects->throws_ ) {
166- mayThrow = false ;
167- }
168- }
169-
170- handleCall (mayThrow, call->isReturn );
164+ const EffectAnalyzer* effects =
165+ self->getModule ()
166+ ? self->getModule ()->getFunction (call->target )->effects .get ()
167+ : nullptr ;
168+ handleCall (call->isReturn , effects);
171169 break ;
172170 }
173171 case Expression::Id::CallRefId: {
174172 auto * callRef = curr->cast <CallRef>();
175173
176- // TODO: Effect analysis for indirect calls isn't implemented yet.
177- // Assume any indirect call may throw for now.
178- bool mayThrow = !self->getModule () ||
179- self->getModule ()->features .hasExceptionHandling ();
180-
181- handleCall (mayThrow, callRef->isReturn );
174+ const EffectAnalyzer* effects = nullptr ;
175+ if (self->getModule ()) {
176+ if (const auto & effects_ptr =
177+ find_or_null (self->getModule ()->indirectCallEffects ,
178+ callRef->target ->type .getHeapType ())) {
179+ effects = effects_ptr->get ();
180+ }
181+ }
182+ handleCall (callRef->isReturn , effects);
182183 break ;
183184 }
184185 case Expression::Id::CallIndirectId: {
185186 auto * callIndirect = curr->cast <CallIndirect>();
186187
187- // TODO: Effect analysis for indirect calls isn't implemented yet.
188- // Assume any indirect call may throw for now.
189- bool mayThrow = !self->getModule () ||
190- self->getModule ()->features .hasExceptionHandling ();
191-
192- handleCall (mayThrow, callIndirect->isReturn );
188+ const EffectAnalyzer* effects = nullptr ;
189+ if (self->getModule ()) {
190+ if (const auto & effects_ptr =
191+ find_or_null (self->getModule ()->indirectCallEffects ,
192+ callIndirect->heapType )) {
193+ effects = effects_ptr->get ();
194+ }
195+ }
196+ handleCall (callIndirect->isReturn , effects);
193197 break ;
194198 }
195199 case Expression::Id::TryId: {
0 commit comments