When type streams with forward references were merged using GHashes, cycles were introduced in the debug info. This was caused by GlobalTypeTableBuilder::insertRecordAs() not inserting the record on the second pass, thus yielding an empty ArrayRef at that record slot. Later on, upon PDB emission, TpiStreamBuilder::commit() would skip that empty record, thus offseting all indices that came after in the stream.
The solution comes in two steps:
- Fix the hash calculation, by doing a multiple-step resolution, iff there are forward references in the input stream.
- Fix merge by resolving with multiple passes, therefore moving records with forward references at the end of the stream.
I had to make some esthetic changes, such as to support GHashes in llvm-readoj - I could commit that separately.
There's also a bugfix for dumpCodeViewMergedTypes() which previously could reference deleted memory (see comment in llvm-readobj.cpp).
Fixes PR40221
I think this would have to go to fix point, not just two passes. Consider the case where each record in the type stream refers to the next, i.e. a pointer to a pointer to a pointer ... to void, and everything is backwards. =(