-
Notifications
You must be signed in to change notification settings - Fork 10.5k
OSSA: Rewrite address cloning code to fix issues and fix an infinite loop in the ownership verifier. #36152
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
OSSA: Rewrite address cloning code to fix issues and fix an infinite loop in the ownership verifier. #36152
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -1283,7 +1283,9 @@ inline Operand *getAccessProjectionOperand(SingleValueInstruction *svi) { | |
/// address must be at operand(0). | ||
/// | ||
/// Some of these casts, such as address_to_pointer, may also occur inside of a | ||
/// formal access. TODO: Add stricter structural guarantee such that these never | ||
/// formal access. | ||
/// | ||
/// TODO: Add stricter structural guarantee such that these never | ||
/// occur within an access. It's important to be able to get the accessed | ||
/// address without looking though type casts or pointer_to_address [strict], | ||
/// which we can't do if those operations are behind access projections. | ||
|
@@ -1497,35 +1499,54 @@ Result AccessUseDefChainVisitor<Impl, Result>::visit(SILValue sourceAddr) { | |
|
||
namespace swift { | ||
|
||
/// Clone all projections and casts on the access use-def chain until either the | ||
/// specified predicate is true or the access base is reached. | ||
/// Clone all projections and casts on the access use-def chain until the | ||
/// checkBase predicate returns a valid base. | ||
/// | ||
/// This will not clone ref_element_addr or ref_tail_addr because those aren't | ||
/// part of the access chain. | ||
template <typename UnaryPredicate> | ||
/// See comments on the cloneUseDefChain() API. | ||
template <typename CheckBase> | ||
class AccessUseDefChainCloner | ||
: public AccessUseDefChainVisitor<AccessUseDefChainCloner<UnaryPredicate>, | ||
: public AccessUseDefChainVisitor<AccessUseDefChainCloner<CheckBase>, | ||
SILValue> { | ||
UnaryPredicate predicate; | ||
CheckBase checkBase; | ||
SILInstruction *insertionPoint; | ||
SILValue placeHolder = SILValue(); | ||
|
||
public: | ||
AccessUseDefChainCloner(UnaryPredicate predicate, | ||
SILInstruction *insertionPoint) | ||
: predicate(predicate), insertionPoint(insertionPoint) {} | ||
AccessUseDefChainCloner(CheckBase checkBase, SILInstruction *insertionPoint) | ||
: checkBase(checkBase), insertionPoint(insertionPoint) {} | ||
|
||
// Recursive main entry point | ||
// Main entry point | ||
SILValue cloneUseDefChain(SILValue addr) { | ||
if (!predicate(addr)) | ||
return addr; | ||
placeHolder = SILValue(); | ||
return cloneRecursive(addr); | ||
} | ||
|
||
// Secondary entry point to check that cloning will succeed. | ||
bool canCloneUseDefChain(SILValue addr) { | ||
// Use any valid address as a placeholder. It is innaccessible. | ||
placeHolder = addr; | ||
return cloneRecursive(addr); | ||
} | ||
|
||
SILValue cloneRecursive(SILValue addr) { | ||
if (SILValue base = checkBase(addr)) | ||
return base; | ||
|
||
return this->visit(addr); | ||
} | ||
|
||
// Recursively clone an address on the use-def chain. | ||
SingleValueInstruction *cloneProjection(SingleValueInstruction *projectedAddr, | ||
Operand *sourceOper) { | ||
SILValue projectedSource = cloneUseDefChain(sourceOper->get()); | ||
// | ||
// Helper for cloneUseDefChain. | ||
SILValue cloneProjection(SingleValueInstruction *projectedAddr, | ||
Operand *sourceOper) { | ||
SILValue projectedSource = cloneRecursive(sourceOper->get()); | ||
if (!projectedSource) | ||
return nullptr; | ||
|
||
if (placeHolder) | ||
return placeHolder; | ||
|
||
SILInstruction *clone = projectedAddr->clone(insertionPoint); | ||
clone->setOperand(sourceOper->getOperandNumber(), projectedSource); | ||
return cast<SingleValueInstruction>(clone); | ||
|
@@ -1549,6 +1570,11 @@ class AccessUseDefChainCloner | |
} | ||
|
||
SILValue visitStorageCast(SingleValueInstruction *cast, Operand *sourceOper) { | ||
// The cloner does not currently know how to create compensating | ||
// end_borrows or fix mark_dependence operands. | ||
if (isa<BeginBorrowInst>(cast) || isa<MarkDependenceInst>(cast)) | ||
return SILValue(); | ||
|
||
return cloneProjection(cast, sourceOper); | ||
} | ||
|
||
|
@@ -1558,14 +1584,37 @@ class AccessUseDefChainCloner | |
} | ||
}; | ||
|
||
template <typename UnaryPredicate> | ||
/// Clone all projections and casts on the access use-def chain until the | ||
/// checkBase predicate returns a valid base. | ||
/// | ||
/// This will not clone ref_element_addr or ref_tail_addr because those aren't | ||
/// part of the access chain. | ||
/// | ||
/// CheckBase is a unary predicate that takes the next source address and either | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is the comment on CheckBase that I wanted above. Maybe add a note above to point here for more information about CheckBase? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I had all these comments duplicated, decided the was a bad idea, so added |
||
/// returns a valid SILValue to use as the base of the cloned access path, or an | ||
/// invalid SILValue to continue cloning. | ||
/// | ||
/// CheckBase must return a valid SILValue either before attempting to clone the | ||
/// access base. The most basic valid predicate is: | ||
/// | ||
/// auto checkBase = [&](SILValue srcAddr) { | ||
/// return (srcAddr == accessBase) ? srcAddr : SILValue(); | ||
/// } | ||
template <typename CheckBase> | ||
SILValue cloneUseDefChain(SILValue addr, SILInstruction *insertionPoint, | ||
UnaryPredicate shouldFollowUse) { | ||
return AccessUseDefChainCloner<UnaryPredicate>(shouldFollowUse, | ||
insertionPoint) | ||
CheckBase checkBase) { | ||
return AccessUseDefChainCloner<CheckBase>(checkBase, insertionPoint) | ||
.cloneUseDefChain(addr); | ||
} | ||
|
||
/// Analog to cloneUseDefChain to check validity. begin_borrow and | ||
/// mark_dependence currently cannot be cloned. | ||
template <typename CheckBase> | ||
bool canCloneUseDefChain(SILValue addr, CheckBase checkBase) { | ||
return AccessUseDefChainCloner<CheckBase>(checkBase, nullptr) | ||
.canCloneUseDefChain(addr); | ||
} | ||
|
||
} // end namespace swift | ||
|
||
//===----------------------------------------------------------------------===// | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -768,7 +768,7 @@ bool InteriorPointerOperand::findTransitiveUsesForAddress( | |
} | ||
|
||
// If we are the value use, look through it. | ||
llvm::copy(mdi->getValue()->getUses(), std::back_inserter(worklist)); | ||
llvm::copy(mdi->getUses(), std::back_inserter(worklist)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am guessing this was the infinite loop? Such a thinko = /. |
||
continue; | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In a subsequent commit, can you describe the function signature of checkBase here and specify what it means to return a "valid" base. Without that I don't know what that means. I would maybe do something like this:
Clone all projections and cases on the access use-def chain until the checkBase predicate returns a valid SILValue as a base.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The next line below says "See comments on the cloneUseDefChain() API."