-
Notifications
You must be signed in to change notification settings - Fork 10.5k
[DI] Fixup alloc_box borrow scope ends. #41781
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
[DI] Fixup alloc_box borrow scope ends. #41781
Conversation
@swift-ci please test |
@swift-ci please test source compatibility |
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.
I think this fix can go in as is. But I have some follow-up questions
auto *Previous = Release->getPreviousInstruction();
Does this create an implicit coupling between SILGen and DI? What guarantees that the end_borrow/destroy_value
are adjacent? How would someone working on SILGen know that, and what ensures that they stay adjacent? Normally any correctness assumption made across passes should be checked in SILVerifier. It may be reasonable to assume the end_borrow and destroy_value are in the same block, which is not much harder to handle.
ebi->moveBefore(&*B.getInsertionPoint());
}
}
}
}
This small closure now has a couple pages of comments within 5 levels of nested control flow. So I can't see at a glance what the original closure as a whole or the surrounding code does. This could all be in an adjustEndBorrow helper with the comments outside the function and no control flow nesting.
1ab460b
to
f5d4e54
Compare
@atrick Added a function
|
After swiftlang#40793, alloc_boxes all have their lifetimes protected by a lexical borrow scope. In that PR, DI had been updated to see through begin_borrow instructions from a project_box to a mark_uninitialized. It did not, however, correct the end_borrow instructions when destroy_values of mark_uninitializeds were replaced with destroy_addrs of project_boxes. That is done here. In a bit more detail, in the following context %box = alloc_box %mark_uninit = mark_uninitialized %box %lifetime = begin_borrow [lexical] %mark_uninit %proj_box = project_box %lifetime When it is not statically known whether a field is initialized, we are replacing the instruction // before destroy_value %mark_uninit // after with the following diamond // before %initialized = load cond_br %initialized, yes, no yes: destroy_addr %proj_box br bottom no: br bottom bottom: dealloc_box %box br keep_going keep_going: // after Doing so is problematic, though, because by SILGen construction the destroy_value is always preceded by an end_borrow: end_borrow %lifetime destroy_value %mark_uninit Previously, that end_borrow remained above the %initialized = load instruction in the above. That was invalid because the the newly introduced destroy_addr %proj_box was a use of the borrow scope (%proj_box is a projection of the begin_borrow) and consequently must be within the borrow scope. Note also that it would not be sufficient to simply emit the diamond before the end_borrow. The end_borrow must come before the destruction of the value whose lifetime it is protecting (%box), and the diamond contains the instruction to destroy that value (dealloc_box) in its bottom block. To resolve this issue, just move the end_borrow instruction from where it was to before the dealloc box. (This is actually done by moving it to the top of the diamond's "continue" block prior to the emission of that dealloc_box instruction.) rdar://89984216
f5d4e54
to
05e643b
Compare
@swift-ci please test |
@swift-ci please clean test linux platform |
@swift-ci please test linux platform |
@swift-ci please clean test linux platform |
After #40793,
alloc_boxes
all have their lifetimes protected by a lexical borrow scope. In that PR, DI had been updated to see throughbegin_borrow
instructions from aproject_box
to amark_uninitialized
. It did not, however, correct theend_borrow
instructions whendestroy_value
s ofmark_uninitialized
s were replaced withdestroy_addr
s ofproject_box
es. That is done here.In a bit more detail, in the following context
When it is not statically known whether a field is initialized, we arereplacing the instruction
with the following diamond
Doing so is problematic, though, because by SILGen construction the
destroy_value
is always preceded by anend_borrow
:Previously, that end_borrow remained above the
instruction in the above. That was invalid because the the newly introduced
was a use of the borrow scope (
%proj_box
is a projection of thebegin_borrow
) and consequently must be within the borrow scope.Note also that it would not be sufficient to simply emit the diamond before the
end_borrow
. Theend_borrow
must come before the destruction of the value whose lifetime it is protecting (%box
), and the diamond contains the instruction to destroy that value (dealloc_box
) in its bottom block.To resolve this issue, just move the
end_borrow
instruction from where it was to before the dealloc box. (This is actually done by moving it to the top of the diamond's "continue" block prior to the emission of thatdealloc_box
instruction.)rdar://89984216