@@ -39,72 +39,75 @@ static void diagnose(ASTContext &Context, SourceLoc loc, Diag<T...> diag,
39
39
diag, std::forward<U>(args)...);
40
40
}
41
41
42
- static bool hasRecursiveCallInPath (SILBasicBlock &Block,
43
- SILFunction *Target,
44
- ModuleDecl *TargetModule) {
42
+ static bool hasRecursiveCallInBlock (SILBasicBlock &Block,
43
+ SILFunction *Target) {
45
44
// Process all instructions in the block to find applies that reference
46
45
// the parent function. Also looks through vtables for statically
47
46
// dispatched (witness) methods.
48
47
for (auto &I : Block) {
49
- auto *AI = dyn_cast<ApplyInst>(&I);
50
- if (AI && AI->getCalleeFunction () && AI->getCalleeFunction () == Target)
51
- return true ;
48
+ FullApplySite FAI = FullApplySite::isa (&I);
49
+ if (!FAI)
50
+ continue ;
51
+
52
+ if (SILFunction *calledFn = FAI.getReferencedFunctionOrNull ()) {
53
+ if (calledFn == Target)
54
+ return true ;
55
+ continue ;
56
+ }
52
57
53
- if (FullApplySite FAI = FullApplySite::isa (&I)) {
54
- // Don't touch dynamic dispatch.
55
- const auto callee = FAI.getCallee ();
56
- if (isa<SuperMethodInst>(callee) ||
57
- isa<ObjCSuperMethodInst>(callee) ||
58
- isa<ObjCMethodInst>(callee)) {
58
+ // Don't touch dynamic dispatch.
59
+ const auto callee = FAI.getCallee ();
60
+ if (isa<SuperMethodInst>(callee) ||
61
+ isa<ObjCSuperMethodInst>(callee) ||
62
+ isa<ObjCMethodInst>(callee)) {
63
+ continue ;
64
+ }
65
+
66
+ auto &M = FAI.getModule ();
67
+ if (auto *CMI = dyn_cast<ClassMethodInst>(callee)) {
68
+ auto ClassType = CMI->getOperand ()->getType ().getASTType ();
69
+
70
+ // FIXME: If we're not inside the module context of the method,
71
+ // we may have to deserialize vtables. If the serialized tables
72
+ // are damaged, the pass will crash.
73
+ //
74
+ // Though, this has the added bonus of not looking into vtables
75
+ // outside the current module. Because we're not doing IPA, let
76
+ // alone cross-module IPA, this is all well and good.
77
+ auto *CD = ClassType.getClassOrBoundGenericClass ();
78
+ if (CD && CD->getModuleContext () != Target->getModule ().getSwiftModule ()) {
59
79
continue ;
60
80
}
61
81
62
- auto &M = FAI.getModule ();
63
- if (auto *CMI = dyn_cast<ClassMethodInst>(callee)) {
64
- auto ClassType = CMI->getOperand ()->getType ().getASTType ();
65
-
66
- // FIXME: If we're not inside the module context of the method,
67
- // we may have to deserialize vtables. If the serialized tables
68
- // are damaged, the pass will crash.
69
- //
70
- // Though, this has the added bonus of not looking into vtables
71
- // outside the current module. Because we're not doing IPA, let
72
- // alone cross-module IPA, this is all well and good.
73
- auto *CD = ClassType.getClassOrBoundGenericClass ();
74
- if (CD && CD->getModuleContext () != TargetModule) {
75
- continue ;
76
- }
77
-
78
- if (!calleesAreStaticallyKnowable (FAI.getModule (), CMI->getMember ())) {
79
- continue ;
80
- }
81
-
82
- // The "statically knowable" check just means that we have all the
83
- // callee candidates available for analysis. We still need to check
84
- // if the current function has a known override point.
85
- auto *method = CMI->getMember ().getAbstractFunctionDecl ();
86
- if (method->isOverridden ()) {
87
- continue ;
88
- }
89
-
90
- auto *F = getTargetClassMethod (M, CD, CMI);
91
- if (F == Target)
92
- return true ;
82
+ if (!calleesAreStaticallyKnowable (FAI.getModule (), CMI->getMember ())) {
83
+ continue ;
84
+ }
93
85
86
+ // The "statically knowable" check just means that we have all the
87
+ // callee candidates available for analysis. We still need to check
88
+ // if the current function has a known override point.
89
+ auto *method = CMI->getMember ().getAbstractFunctionDecl ();
90
+ if (method->isOverridden ()) {
94
91
continue ;
95
92
}
96
93
97
- if ( auto *WMI = dyn_cast<WitnessMethodInst>(callee)) {
98
- SILFunction *F;
99
- SILWitnessTable *WT ;
94
+ auto *F = getTargetClassMethod (M, CD, CMI);
95
+ if (F == Target)
96
+ return true ;
100
97
101
- std::tie (F, WT) = M.lookUpFunctionInWitnessTable (
102
- WMI->getConformance (), WMI->getMember ());
103
- if (F == Target)
104
- return true ;
98
+ continue ;
99
+ }
105
100
106
- continue ;
107
- }
101
+ if (auto *WMI = dyn_cast<WitnessMethodInst>(callee)) {
102
+ SILFunction *F;
103
+ SILWitnessTable *WT;
104
+
105
+ std::tie (F, WT) = M.lookUpFunctionInWitnessTable (
106
+ WMI->getConformance (), WMI->getMember ());
107
+ if (F == Target)
108
+ return true ;
109
+
110
+ continue ;
108
111
}
109
112
}
110
113
return false ;
@@ -138,7 +141,6 @@ static bool hasInfinitelyRecursiveApply(SILFunction *targetFn) {
138
141
// We return true if we found any recursion and did not find any
139
142
// non-recursive, function-exiting blocks.
140
143
bool foundRecursion = false ;
141
- auto *targetModule = targetFn->getModule ().getSwiftModule ();
142
144
143
145
while (!workList.empty ()) {
144
146
SILBasicBlock *curBlock = workList.pop_back_val ();
@@ -153,7 +155,7 @@ static bool hasInfinitelyRecursiveApply(SILFunction *targetFn) {
153
155
// We're looking for functions that are recursive on _all_ paths. If this
154
156
// block is recursive, mark that we found recursion and check the next
155
157
// block in the work list.
156
- if (hasRecursiveCallInPath (*curBlock, targetFn, targetModule )) {
158
+ if (hasRecursiveCallInBlock (*curBlock, targetFn)) {
157
159
foundRecursion = true ;
158
160
continue ;
159
161
}
0 commit comments