This is necessary since our func may want to emit conditional code with an early
exit, emitting unused cleanups from the current scope via the function
emitBranchAndCleanups(). If we have not yet created those cleanups, we will
introduce a leak along that path.
rdar://49990484
Today SILGenPattern maintains the following invariants:
1. All values passed into a switch must be either TakeAlways or BorrowAlways and
loadable input values will be loaded.
2. Loadable types passed to a subtree must be loaded.
3. TakeOnSuccess can only occur with address only types and only in subtrees.
4. A TakeOnSuccess value must go through "fake borrowing"
(i.e. forward/unforwarding) to ensure that along failing cases, we properly
re-enable the cleanup on the aggregate. This means that TakeOnSuccess can
never be handled as a loadable value with ownership enabled and that any
take_on_success value since the original cleanup on the parent value was
disabled must be at +1.
5. We use BorrowAlways instead of TakeOnSuccess for objects to express the
notion that the object is not owned by the sub-tree.
The bug in this tuple code occured at the a place in the code where we go from
an address only parent type to a loadable subtype via TakeOnSuccess. I was
trying to follow (5) and thus I converted the subvalue to use a {load_borrow,
BorrowAlways}. The problem with this is that I lost the cleanup from the tuple
subvalue since take_on_success is just simulating +0 and thus entails having a
cleanup for each of the underlying tuple values.
The fix here was to:
* Create a cleanup for the loadable subvalue leaving it in memory. This address
version of the subvalue we use for the purposes of unforwarding. This avoids
(4).
* load_borrow the subvalue and pass that off to the subtree. This ensures that
we respect (2), (3), (4).
* Unforward in the failure case the in memory subvalue.
This gives us both characteristics as well as in the future the possibility of
enforcing via the ownership verifier that the borrow ends before the
destroy_addr.
I also sprinkled some assertions liberally to maintain invariants.
rdar://47034816
Implement switch statements with simple value comparison to get the drudge work of parsing and generating switches in place. Cases are checked using a '=~' operator to compare the subject of the switch to the value in the case. Unlike a C switch, cases each have their own scope and don't fall through. 'break' and 'continue' apply to an outer loop rather to the switch itself. Multiple case values can be specified in a comma-separated list, as in 'case 1, 2, 3, 4:'. Currently no effort is made to check for duplicate cases or to rank cases by match strength; cases are just checked in source order, and the first one wins (aside from 'default', which is branched to if all cases fail).
Swift SVN r4359