Skip to content

Commit 64c709c

Browse files
committed
[gardening] Refactor load handling code from collectDelegatingClassInitSelfUses into its own function.
The new function is called collectDelegatingClassInitSelfLoadUses. This is just a classical loop function extraction refactor.
1 parent 784d5d1 commit 64c709c

File tree

1 file changed

+91
-85
lines changed

1 file changed

+91
-85
lines changed

lib/SILOptimizer/Mandatory/DIMemoryUseCollector.cpp

Lines changed: 91 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,8 @@ namespace {
497497
unsigned BaseEltNo);
498498
void collectStructElementUses(StructElementAddrInst *SEAI,
499499
unsigned BaseEltNo);
500+
void collectDelegatingClassInitSelfLoadUses(MarkUninitializedInst *MUI,
501+
LoadInst *LI);
500502
};
501503
} // end anonymous namespace
502504

@@ -1287,6 +1289,89 @@ collectClassSelfUses(SILValue ClassPointer, SILType MemorySILType,
12871289
}
12881290
}
12891291

1292+
void ElementUseCollector::collectDelegatingClassInitSelfLoadUses(
1293+
MarkUninitializedInst *MUI, LoadInst *LI) {
1294+
1295+
// If we have a load, then this is a use of the box. Look at the uses of
1296+
// the load to find out more information.
1297+
for (auto UI : LI->getUses()) {
1298+
auto *User = UI->getUser();
1299+
1300+
// super_method always looks at the metatype for the class, not at any of
1301+
// its stored properties, so it doesn't have any DI requirements.
1302+
if (isa<SuperMethodInst>(User))
1303+
continue;
1304+
1305+
// We ignore retains of self.
1306+
if (isa<StrongRetainInst>(User))
1307+
continue;
1308+
1309+
// A release of a load from the self box in a class delegating
1310+
// initializer might be releasing an uninitialized self, which requires
1311+
// special processing.
1312+
if (isa<StrongReleaseInst>(User)) {
1313+
Releases.push_back(User);
1314+
continue;
1315+
}
1316+
1317+
if (auto *Method = dyn_cast<ClassMethodInst>(User)) {
1318+
// class_method that refers to an initializing constructor is a method
1319+
// lookup for delegation, which is ignored.
1320+
if (Method->getMember().kind == SILDeclRef::Kind::Initializer)
1321+
continue;
1322+
1323+
/// Returns true if \p Method used by an apply in a way that we know
1324+
/// will cause us to emit a better error.
1325+
if (shouldIgnoreClassMethodUseError(Method, LI))
1326+
continue;
1327+
}
1328+
1329+
// If this is an upcast instruction, it is a conversion of self to the
1330+
// base. This is either part of a super.init sequence, or a general
1331+
// superclass access. We special case super.init calls since they are
1332+
// part of the object lifecycle.
1333+
if (auto *UCI = dyn_cast<UpcastInst>(User)) {
1334+
if (auto *subAI = isSuperInitUse(UCI)) {
1335+
Uses.push_back(DIMemoryUse(subAI, DIUseKind::SuperInit, 0, 1));
1336+
recordFailableInitCall(subAI);
1337+
continue;
1338+
}
1339+
}
1340+
1341+
// We only track two kinds of uses for delegating initializers:
1342+
// calls to self.init, and "other", which we choose to model as escapes.
1343+
// This intentionally ignores all stores, which (if they got emitted as
1344+
// copyaddr or assigns) will eventually get rewritten as assignments
1345+
// (not initializations), which is the right thing to do.
1346+
DIUseKind Kind = DIUseKind::Escape;
1347+
1348+
// If this is an ApplyInst, check to see if this is part of a self.init
1349+
// call in a delegating initializer.
1350+
if (isa<FullApplySite>(User) && isSelfInitUse(User)) {
1351+
Kind = DIUseKind::SelfInit;
1352+
recordFailableInitCall(User);
1353+
}
1354+
1355+
// If this load's value is being stored back into the delegating
1356+
// mark_uninitialized buffer and it is a self init use, skip the
1357+
// use. This is to handle situations where due to usage of a metatype to
1358+
// allocate, we do not actually consume self.
1359+
if (auto *SI = dyn_cast<StoreInst>(User)) {
1360+
if (SI->getDest() == MUI && isSelfInitUse(User)) {
1361+
continue;
1362+
}
1363+
}
1364+
1365+
// A simple reference to "type(of:)" is always fine,
1366+
// even if self is uninitialized.
1367+
if (isa<ValueMetatypeInst>(User)) {
1368+
continue;
1369+
}
1370+
1371+
Uses.push_back(DIMemoryUse(User, Kind, 0, 1));
1372+
}
1373+
}
1374+
12901375
/// collectDelegatingClassInitSelfUses - Collect uses of the self argument in a
12911376
/// delegating-constructor-for-a-class case.
12921377
void ElementUseCollector::collectDelegatingClassInitSelfUses() {
@@ -1314,21 +1399,20 @@ void ElementUseCollector::collectDelegatingClassInitSelfUses() {
13141399

13151400
// For class initializers, the assign into the self box may be
13161401
// captured as SelfInit or SuperInit elsewhere.
1317-
if (TheMemory.isClassInitSelf() &&
1318-
isa<AssignInst>(User) && UI->getOperandNumber() == 1) {
1402+
if (TheMemory.isClassInitSelf() && isa<AssignInst>(User) &&
1403+
UI->getOperandNumber() == 1) {
13191404
// If the source of the assignment is an application of a C
13201405
// function, there is no metatype argument, so treat the
13211406
// assignment to the self box as the initialization.
13221407
if (auto apply = dyn_cast<ApplyInst>(cast<AssignInst>(User)->getSrc())) {
13231408
if (auto fn = apply->getCalleeFunction()) {
1324-
if (fn->getRepresentation()
1325-
== SILFunctionTypeRepresentation::CFunctionPointer) {
1409+
if (fn->getRepresentation() ==
1410+
SILFunctionTypeRepresentation::CFunctionPointer) {
13261411
Uses.push_back(DIMemoryUse(User, DIUseKind::SelfInit, 0, 1));
13271412
continue;
13281413
}
13291414
}
13301415
}
1331-
13321416
}
13331417

13341418
// Stores *to* the allocation are writes. If the value being stored is a
@@ -1346,7 +1430,7 @@ void ElementUseCollector::collectDelegatingClassInitSelfUses() {
13461430
continue;
13471431
}
13481432
}
1349-
1433+
13501434
if (auto *CAI = dyn_cast<CopyAddrInst>(User)) {
13511435
if (isSelfInitUse(CAI)) {
13521436
Uses.push_back(DIMemoryUse(User, DIUseKind::SelfInit, 0, 1));
@@ -1356,85 +1440,7 @@ void ElementUseCollector::collectDelegatingClassInitSelfUses() {
13561440

13571441
// Loads of the box produce self, so collect uses from them.
13581442
if (auto *LI = dyn_cast<LoadInst>(User)) {
1359-
1360-
// If we have a load, then this is a use of the box. Look at the uses of
1361-
// the load to find out more information.
1362-
for (auto UI : LI->getUses()) {
1363-
auto *User = UI->getUser();
1364-
1365-
// super_method always looks at the metatype for the class, not at any of
1366-
// its stored properties, so it doesn't have any DI requirements.
1367-
if (isa<SuperMethodInst>(User))
1368-
continue;
1369-
1370-
// We ignore retains of self.
1371-
if (isa<StrongRetainInst>(User))
1372-
continue;
1373-
1374-
// A release of a load from the self box in a class delegating
1375-
// initializer might be releasing an uninitialized self, which requires
1376-
// special processing.
1377-
if (isa<StrongReleaseInst>(User)) {
1378-
Releases.push_back(User);
1379-
continue;
1380-
}
1381-
1382-
if (auto *Method = dyn_cast<ClassMethodInst>(User)) {
1383-
// class_method that refers to an initializing constructor is a method
1384-
// lookup for delegation, which is ignored.
1385-
if (Method->getMember().kind == SILDeclRef::Kind::Initializer)
1386-
continue;
1387-
1388-
/// Returns true if \p Method used by an apply in a way that we know
1389-
/// will cause us to emit a better error.
1390-
if (shouldIgnoreClassMethodUseError(Method, LI))
1391-
continue;
1392-
}
1393-
1394-
// If this is an upcast instruction, it is a conversion of self to the
1395-
// base. This is either part of a super.init sequence, or a general
1396-
// superclass access. We special case super.init calls since they are
1397-
// part of the object lifecycle.
1398-
if (auto *UCI = dyn_cast<UpcastInst>(User)) {
1399-
if (auto *subAI = isSuperInitUse(UCI)) {
1400-
Uses.push_back(DIMemoryUse(subAI, DIUseKind::SuperInit, 0, 1));
1401-
recordFailableInitCall(subAI);
1402-
continue;
1403-
}
1404-
}
1405-
1406-
// We only track two kinds of uses for delegating initializers:
1407-
// calls to self.init, and "other", which we choose to model as escapes.
1408-
// This intentionally ignores all stores, which (if they got emitted as
1409-
// copyaddr or assigns) will eventually get rewritten as assignments
1410-
// (not initializations), which is the right thing to do.
1411-
DIUseKind Kind = DIUseKind::Escape;
1412-
1413-
// If this is an ApplyInst, check to see if this is part of a self.init
1414-
// call in a delegating initializer.
1415-
if (isa<FullApplySite>(User) && isSelfInitUse(User)) {
1416-
Kind = DIUseKind::SelfInit;
1417-
recordFailableInitCall(User);
1418-
}
1419-
1420-
// If this load's value is being stored back into the delegating
1421-
// mark_uninitialized buffer and it is a self init use, skip the
1422-
// use. This is to handle situations where due to usage of a metatype to
1423-
// allocate, we do not actually consume self.
1424-
if (auto *SI = dyn_cast<StoreInst>(User)) {
1425-
if (SI->getDest() == MUI && isSelfInitUse(User)) {
1426-
continue;
1427-
}
1428-
}
1429-
1430-
// A simple reference to "type(of:)" is always fine,
1431-
// even if self is uninitialized.
1432-
if (isa<ValueMetatypeInst>(User)) {
1433-
continue;
1434-
}
1435-
1436-
Uses.push_back(DIMemoryUse(User, Kind, 0, 1));
1437-
}
1443+
collectDelegatingClassInitSelfLoadUses(MUI, LI);
14381444
continue;
14391445
}
14401446

0 commit comments

Comments
 (0)