[llvm-dev] ilist/iplist are broken (maybe I'll fix them?)

Duncan P. N. Exon Smith via llvm-dev llvm-dev at lists.llvm.org
Thu Oct 8 14:15:47 PDT 2015


> On 2015-Oct-08, at 13:56, escha <escha at apple.com> wrote:
> 
> 
>> On Oct 8, 2015, at 11:00 AM, Justin Bogner via llvm-dev <llvm-dev at lists.llvm.org> wrote:
>> 
>> "Duncan P. N. Exon Smith" <dexonsmith at apple.com> writes:
>>> I don't feel totally comfortable just going ahead and fixing this
>>> without buy-in, since it'll touch some things.  Here's my basic plan:
>>> 
>>> - Fix `getNextNode()` and `getPrevNode()` by taking in the parent list
>>>   and checking against `end()` instead of checking for `nullptr`.
>>> - Change the lists to be normal circular linked lists (possibly I'll
>>>   stick an "is-sentinel" bit in the prev pointer in asserts builds so
>>>   we can have assertions instead of infinite loops).  I'll layer our
>>>   weird partial ownership semantics on top to keep this part NFC.
>>> - Re-layer the external state hooks so that they're on top of the
>>>   basic list instead of inside of it (so that someone in the future
>>>   can understand the code with far less studying).
>>> 
>>> Anyone want to back me on this before I dive in?  Even better, did I
>>> miss something fundamental?
>> 
>> +1
>> 
>> Other than having to update pretty well the entire code base, I don't
>> see any drawbacks to replacing ilist/iplist with something sane. The
>> current thing is complicated, tries to do too many things (and not many
>> of them well), and broken in several ways. In addition to the UB and
>> re-capitation you mention, I've also heard of issues using the reverse
>> iterators.
> 
> Specifically, I discovered (the hard and painful way) last night that if you reverse-iterator over a MachineBasicBlock, removing/moving instructions as you go — even pre-incrementing the iterator at the start of the loop isn’t enough to prevent the list from being corrupted in unexpected ways. A regular iterator, used backwards (-- instead of ++) works correctly, nothing else different.

This is because instead of ilist/iplist implementing a list-specific
reverse iterator, they use std::reverse_iterator, which is wholly
inappropriate for a list.  std::reverse_iterator is designed for
places where you can't increment past-the-begin.  Dereferencing works
like this:
--
T &operator*() const {
  return *std::prev(I);
}
--
and it holds a iterator to the "next" node from the one you expect it
to.  Basically, iteration works, but the iterator isn't valid when
you modify the list.

I can write a proper list reverse_iterator while I'm in there.


More information about the llvm-dev mailing list