@@ -39,76 +39,66 @@ static void diagnose(ASTContext &Context, SourceLoc loc, Diag<T...> diag,
39
39
diag, std::forward<U>(args)...);
40
40
}
41
41
42
- static bool hasRecursiveCallInBlock (SILBasicBlock &Block,
43
- SILFunction *Target) {
44
- // Process all instructions in the block to find applies that reference
45
- // the parent function. Also looks through vtables for statically
46
- // dispatched (witness) methods.
47
- for (auto &I : Block) {
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
- }
57
-
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
- }
42
+ static bool isRecursiveCall (SILInstruction *inst, SILFunction *target) {
43
+ FullApplySite FAI = FullApplySite::isa (inst);
44
+ if (!FAI)
45
+ return false ;
65
46
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 ()) {
79
- continue ;
80
- }
47
+ if (SILFunction *calledFn = FAI.getReferencedFunctionOrNull ())
48
+ return calledFn == target;
81
49
82
- if (!calleesAreStaticallyKnowable (FAI.getModule (), CMI->getMember ())) {
83
- continue ;
84
- }
50
+ // Don't touch dynamic dispatch.
51
+ const auto callee = FAI.getCallee ();
52
+ if (isa<SuperMethodInst>(callee) ||
53
+ isa<ObjCSuperMethodInst>(callee) ||
54
+ isa<ObjCMethodInst>(callee)) {
55
+ return false ;
56
+ }
85
57
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 ()) {
91
- continue ;
92
- }
58
+ if (auto *CMI = dyn_cast<ClassMethodInst>(callee)) {
59
+
60
+ // FIXME: If we're not inside the module context of the method,
61
+ // we may have to deserialize vtables. If the serialized tables
62
+ // are damaged, the pass will crash.
63
+ //
64
+ // Though, this has the added bonus of not looking into vtables
65
+ // outside the current module. Because we're not doing IPA, let
66
+ // alone cross-module IPA, this is all well and good.
67
+ SILModule &module = target->getModule ();
68
+ CanType classType = CMI->getOperand ()->getType ().getASTType ();
69
+ ClassDecl *classDecl = classType.getClassOrBoundGenericClass ();
70
+ if (classDecl && classDecl->getModuleContext () != module .getSwiftModule ())
71
+ return false ;
93
72
94
- auto *F = getTargetClassMethod (M, CD, CMI);
95
- if (F == Target)
96
- return true ;
73
+ if (!calleesAreStaticallyKnowable (module , CMI->getMember ()))
74
+ return false ;
97
75
98
- continue ;
99
- }
76
+ // The "statically knowable" check just means that we have all the
77
+ // callee candidates available for analysis. We still need to check
78
+ // if the current function has a known override point.
79
+ auto *methodDecl = CMI->getMember ().getAbstractFunctionDecl ();
80
+ if (methodDecl->isOverridden ())
81
+ return false ;
100
82
101
- if ( auto *WMI = dyn_cast<WitnessMethodInst>(callee)) {
102
- SILFunction *F ;
103
- SILWitnessTable *WT;
83
+ SILFunction *method = getTargetClassMethod ( module , classDecl, CMI);
84
+ return method == target ;
85
+ }
104
86
105
- std::tie (F, WT) = M.lookUpFunctionInWitnessTable (
106
- WMI->getConformance (), WMI->getMember ());
107
- if (F == Target)
108
- return true ;
87
+ if (auto *WMI = dyn_cast<WitnessMethodInst>(callee)) {
88
+ auto funcAndTable = target->getModule ().lookUpFunctionInWitnessTable (
89
+ WMI->getConformance (), WMI->getMember ());
90
+ return funcAndTable.first == target;
91
+ }
92
+ return false ;
93
+ }
109
94
110
- continue ;
111
- }
95
+ static bool hasRecursiveCallInBlock (SILBasicBlock &block, SILFunction *target) {
96
+ // Process all instructions in the block to find applies that reference
97
+ // the parent function. Also looks through vtables for statically
98
+ // dispatched (witness) methods.
99
+ for (auto &inst : block) {
100
+ if (isRecursiveCall (&inst, target))
101
+ return true ;
112
102
}
113
103
return false ;
114
104
}
0 commit comments