Skip to content

Commit 0b84789

Browse files
committed
Refactor DI a bit to simplify it, NFC.
1 parent 8c3bcdd commit 0b84789

File tree

1 file changed

+55
-56
lines changed

1 file changed

+55
-56
lines changed

lib/SILOptimizer/Mandatory/DefiniteInitialization.cpp

Lines changed: 55 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -476,14 +476,15 @@ namespace {
476476

477477
AvailabilitySet getLivenessAtInst(SILInstruction *Inst, unsigned FirstElt,
478478
unsigned NumElts);
479+
int getAnyUninitializedMemberAtInst(SILInstruction *Inst, unsigned FirstElt,
480+
unsigned NumElts);
481+
479482
DIKind getSelfConsumedAtInst(SILInstruction *Inst);
480483

481484
bool isInitializedAtUse(const DIMemoryUse &Use,
482485
bool *SuperInitDone = nullptr,
483486
bool *FailedSelfUse = nullptr);
484487

485-
bool hasUninitializedMemberAtInst(SILInstruction *Inst, unsigned FirstElt,
486-
unsigned NumElts);
487488

488489
void handleStoreUse(unsigned UseID);
489490
void handleInOutUse(const DIMemoryUse &Use);
@@ -674,20 +675,14 @@ std::string LifetimeChecker::getUninitElementName(const DIMemoryUse &Use) {
674675
// the query, to get a bitmask of exactly which elements are uninitialized.
675676
// In a multi-element query, the first element may already be defined and
676677
// we want to point to the second one.
677-
AvailabilitySet Liveness =
678-
getLivenessAtInst(Use.Inst, Use.FirstElement, Use.NumElements);
679-
680-
unsigned FirstUndefElement = Use.FirstElement;
681-
while (Liveness.get(FirstUndefElement) == DIKind::Yes) {
682-
++FirstUndefElement;
683-
assert(FirstUndefElement != Use.FirstElement+Use.NumElements &&
684-
"No undef elements found?");
685-
}
686-
678+
unsigned firstUndefElement =
679+
getAnyUninitializedMemberAtInst(Use.Inst, Use.FirstElement,Use.NumElements);
680+
assert(firstUndefElement != ~0U && "No undef elements found?");
681+
687682
// Verify that it isn't the super.init marker that failed. The client should
688683
// handle this, not pass it down to diagnoseInitError.
689684
assert((!TheMemory.isDerivedClassSelf() ||
690-
FirstUndefElement != TheMemory.NumElements-1) &&
685+
firstUndefElement != TheMemory.NumElements-1) &&
691686
"super.init failure not handled in the right place");
692687

693688
// If the definition is a declaration, try to reconstruct a name and
@@ -698,7 +693,7 @@ std::string LifetimeChecker::getUninitElementName(const DIMemoryUse &Use) {
698693
// an error about "v" instead of "v.0" when "v" has tuple type and the whole
699694
// thing is accessed inappropriately.
700695
std::string Name;
701-
TheMemory.getPathStringToElement(FirstUndefElement, Name);
696+
TheMemory.getPathStringToElement(firstUndefElement, Name);
702697

703698
return Name;
704699
}
@@ -1331,24 +1326,14 @@ void LifetimeChecker::handleLoadUseFailure(const DIMemoryUse &Use,
13311326
(unsigned)TheMemory.isDelegatingInit());
13321327
return;
13331328
}
1334-
1335-
SILLocation Loc = Inst->getLoc();
13361329

1337-
// Try to find the return location
1338-
auto TermLoc = Inst->getParent()->getTerminator()->getLoc();
1339-
if (TermLoc.getKind() == SILLocation::ReturnKind) {
1340-
Loc = TermLoc;
1341-
}
1342-
13431330
// If this is a load with a single user that is a return (and optionally a
13441331
// retain_value for non-trivial structs/enums), then this is a return in the
13451332
// enum/struct init case, and we haven't stored to self. Emit a specific
13461333
// diagnostic.
13471334
if (auto *LI = dyn_cast<LoadInst>(Inst)) {
13481335
bool hasReturnUse = false, hasUnknownUses = false;
13491336

1350-
auto *LoadBB = LI->getParent();
1351-
13521337
for (auto LoadUse : LI->getUses()) {
13531338
auto *User = LoadUse->getUser();
13541339

@@ -1362,18 +1347,6 @@ void LifetimeChecker::handleLoadUseFailure(const DIMemoryUse &Use,
13621347

13631348
if (auto *EI = dyn_cast<EnumInst>(User))
13641349
if (isFailableInitReturnUseOfEnum(EI)) {
1365-
// Try to find the return location
1366-
for (auto Pred : LoadBB->getPreds()) {
1367-
auto *TI = Pred->getTerminator();
1368-
auto TermLoc = TI->getLoc();
1369-
1370-
// Check if this is an early return with uninitialized members
1371-
if (TermLoc.getKind() == SILLocation::ReturnKind &&
1372-
hasUninitializedMemberAtInst(TI, Use.FirstElement,
1373-
Use.NumElements))
1374-
Loc = TermLoc;
1375-
}
1376-
13771350
hasReturnUse = true;
13781351
continue;
13791352
}
@@ -1382,16 +1355,41 @@ void LifetimeChecker::handleLoadUseFailure(const DIMemoryUse &Use,
13821355
break;
13831356
}
13841357

1358+
// Okay, this load is part of a return sequence, diagnose it specially.
13851359
if (hasReturnUse && !hasUnknownUses) {
1360+
// The load is probably part of the common epilog for the function, try to
1361+
// find a more useful source location than the syntactic end of the
1362+
// function.
1363+
SILLocation returnLoc = Inst->getLoc();
1364+
auto TermLoc = Inst->getParent()->getTerminator()->getLoc();
1365+
if (TermLoc.getKind() == SILLocation::ReturnKind) {
1366+
// Function has a single return that got merged into the epilog block.
1367+
returnLoc = TermLoc;
1368+
} else {
1369+
// Otherwise, there are multiple paths to the epilog block, scan its
1370+
// predecessors to see if there are any where the value is unavailable.
1371+
// If so, we can use its location information for more precision.
1372+
for (auto pred : LI->getParent()->getPreds()) {
1373+
auto *TI = pred->getTerminator();
1374+
// Check if this is an early return with uninitialized members.
1375+
if (TI->getLoc().getKind() == SILLocation::ReturnKind &&
1376+
getAnyUninitializedMemberAtInst(TI, Use.FirstElement,
1377+
Use.NumElements) != -1)
1378+
returnLoc = TI->getLoc();
1379+
}
1380+
}
1381+
13861382
if (TheMemory.isEnumInitSelf()) {
13871383
if (!shouldEmitError(Inst)) return;
1388-
diagnose(Module, Loc,
1384+
diagnose(Module, returnLoc,
13891385
diag::return_from_init_without_initing_self);
13901386
return;
1391-
} else if (TheMemory.isAnyInitSelf() && !TheMemory.isClassInitSelf() &&
1387+
}
1388+
1389+
if (TheMemory.isAnyInitSelf() && !TheMemory.isClassInitSelf() &&
13921390
!TheMemory.isDelegatingInit()) {
13931391
if (!shouldEmitError(Inst)) return;
1394-
diagnose(Module, Loc,
1392+
diagnose(Module, returnLoc,
13951393
diag::return_from_init_without_initing_stored_properties);
13961394
noteUninitializedMembers(Use);
13971395
return;
@@ -1746,8 +1744,7 @@ void LifetimeChecker::processNonTrivialRelease(unsigned ReleaseID) {
17461744
// destruction.
17471745
assert(isa<StrongReleaseInst>(Release) || isa<DestroyAddrInst>(Release));
17481746

1749-
AvailabilitySet Availability =
1750-
getLivenessAtInst(Release, 0, TheMemory.NumElements);
1747+
auto Availability = getLivenessAtInst(Release, 0, TheMemory.NumElements);
17511748
DIKind SelfConsumed =
17521749
getSelfConsumedAtInst(Release);
17531750

@@ -2407,6 +2404,23 @@ getLivenessAtInst(SILInstruction *Inst, unsigned FirstElt, unsigned NumElts) {
24072404
return Result;
24082405
}
24092406

2407+
/// If any of the elements in the specified range are uninitialized at the
2408+
/// specified instruction, return the first element that is uninitialized. If
2409+
/// they are all initialized, return -1.
2410+
int LifetimeChecker::getAnyUninitializedMemberAtInst(SILInstruction *Inst,
2411+
unsigned FirstElt,
2412+
unsigned NumElts) {
2413+
// Determine the liveness states of the elements that we care about.
2414+
auto Liveness = getLivenessAtInst(Inst, FirstElt, NumElts);
2415+
2416+
// Find unintialized member.
2417+
for (unsigned i = FirstElt, e = i+NumElts; i != e; ++i)
2418+
if (Liveness.get(i) != DIKind::Yes)
2419+
return i;
2420+
2421+
return -1;
2422+
}
2423+
24102424
/// getSelfConsumedAtInst - Compute the liveness state for any number of tuple
24112425
/// elements at the specified instruction. The elements are returned as an
24122426
/// AvailabilitySet. Elements outside of the range specified may not be
@@ -2471,21 +2485,6 @@ bool LifetimeChecker::isInitializedAtUse(const DIMemoryUse &Use,
24712485
return true;
24722486
}
24732487

2474-
bool LifetimeChecker::hasUninitializedMemberAtInst(SILInstruction *Inst,
2475-
unsigned FirstElt,
2476-
unsigned NumElts) {
2477-
// Determine the liveness states of the elements that we care about.
2478-
AvailabilitySet Liveness =
2479-
getLivenessAtInst(Inst, FirstElt, NumElts);
2480-
2481-
// Find unintialized member
2482-
for (unsigned i = FirstElt, e = i+NumElts;
2483-
i != e; ++i)
2484-
if (Liveness.get(i) != DIKind::Yes)
2485-
return true;
2486-
2487-
return false;
2488-
}
24892488

24902489

24912490

0 commit comments

Comments
 (0)