Skip to content

Commit 5e374b6

Browse files
committed
DiagnoseInfiniteRecursion: refactoring, NFC
Extract isRecursiveCall() into a separate function.
1 parent 7cec26c commit 5e374b6

File tree

1 file changed

+52
-62
lines changed

1 file changed

+52
-62
lines changed

lib/SILOptimizer/Mandatory/DiagnoseInfiniteRecursion.cpp

Lines changed: 52 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -39,76 +39,66 @@ static void diagnose(ASTContext &Context, SourceLoc loc, Diag<T...> diag,
3939
diag, std::forward<U>(args)...);
4040
}
4141

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;
6546

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;
8149

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+
}
8557

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;
9372

94-
auto *F = getTargetClassMethod(M, CD, CMI);
95-
if (F == Target)
96-
return true;
73+
if (!calleesAreStaticallyKnowable(module, CMI->getMember()))
74+
return false;
9775

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;
10082

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+
}
10486

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+
}
10994

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;
112102
}
113103
return false;
114104
}

0 commit comments

Comments
 (0)