A while back, the method vlocJoin was responsible for updating all variable location information at the entry point into a block. However, it was split into two parts:
- vlocJoin remained to check whether a PHI on block entry could be eliminated, and that incoming DIExpressions and indirect-ness agreed,
- pickVPHILoc identifies a location (i.e.. register) where a PHI could occur.
With rG102d2a8a9905 / D114578, we started tracking variable values that are assigned in out-of-scope blocks, which is what VarLocBasedLDV does. In VarLocBasedLDV, entry to such out-of-scope blocks is ignored because there are no instructions in scope and there's an assignment in the block anyway. Unfortunately, due to the split mentioned above, this led to:
- vlocJoin not updating the live-in DIExpression of such a block, but
- pickVPHILoc could find a location for a PHI if the parent blocks have a live-out value
Which meant we would accidentally not update DIExpression information on entry to a block, dropping fragment information, and creating a bogus DBG_VALUE, leading to an assertion failure.
Simple solution: delete the filter inherited from VarLocBasedLDV. We'll do slightly more work than necessary, but not a huge amount, and it'll be correct. I've added an assertion to check that all the block live-in variable locations we create have the correct fragment information, which should make this fail in a more clear manner in the future.
The attached test is reduced from some libcxx test that was crashing; the first block is in scope, two subsequent blocks are out of scope, all blocks assign to the variable in question "_First".
Does InScopeBlocks have any other uses? Can it be removed from vlocJoin parameter list etc?