diff options
Diffstat (limited to 'lib/DebugInfo/PDB/Native/TpiStream.cpp')
| -rw-r--r-- | lib/DebugInfo/PDB/Native/TpiStream.cpp | 85 | 
1 files changed, 85 insertions, 0 deletions
diff --git a/lib/DebugInfo/PDB/Native/TpiStream.cpp b/lib/DebugInfo/PDB/Native/TpiStream.cpp index 0680b673380a6..f234d446e6a09 100644 --- a/lib/DebugInfo/PDB/Native/TpiStream.cpp +++ b/lib/DebugInfo/PDB/Native/TpiStream.cpp @@ -11,8 +11,11 @@  #include "llvm/ADT/iterator_range.h"  #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" +#include "llvm/DebugInfo/CodeView/RecordName.h"  #include "llvm/DebugInfo/CodeView/TypeRecord.h" +#include "llvm/DebugInfo/CodeView/TypeRecordHelpers.h"  #include "llvm/DebugInfo/MSF/MappedBlockStream.h" +#include "llvm/DebugInfo/PDB/Native/Hash.h"  #include "llvm/DebugInfo/PDB/Native/PDBFile.h"  #include "llvm/DebugInfo/PDB/Native/RawConstants.h"  #include "llvm/DebugInfo/PDB/Native/RawError.h" @@ -140,6 +143,88 @@ uint16_t TpiStream::getTypeHashStreamAuxIndex() const {  uint32_t TpiStream::getNumHashBuckets() const { return Header->NumHashBuckets; }  uint32_t TpiStream::getHashKeySize() const { return Header->HashKeySize; } +void TpiStream::buildHashMap() { +  if (!HashMap.empty()) +    return; +  if (HashValues.empty()) +    return; + +  HashMap.resize(Header->NumHashBuckets); + +  TypeIndex TIB{Header->TypeIndexBegin}; +  TypeIndex TIE{Header->TypeIndexEnd}; +  while (TIB < TIE) { +    uint32_t HV = HashValues[TIB.toArrayIndex()]; +    HashMap[HV].push_back(TIB++); +  } +} + +std::vector<TypeIndex> TpiStream::findRecordsByName(StringRef Name) const { +  if (!supportsTypeLookup()) +    const_cast<TpiStream*>(this)->buildHashMap(); + +  uint32_t Bucket = hashStringV1(Name) % Header->NumHashBuckets; +  if (Bucket > HashMap.size()) +    return {}; + +  std::vector<TypeIndex> Result; +  for (TypeIndex TI : HashMap[Bucket]) { +    std::string ThisName = computeTypeName(*Types, TI); +    if (ThisName == Name) +      Result.push_back(TI); +  } +  return Result; +} + +bool TpiStream::supportsTypeLookup() const { return !HashMap.empty(); } + +Expected<TypeIndex> +TpiStream::findFullDeclForForwardRef(TypeIndex ForwardRefTI) const { +  if (!supportsTypeLookup()) +    const_cast<TpiStream*>(this)->buildHashMap(); + +  CVType F = Types->getType(ForwardRefTI); +  if (!isUdtForwardRef(F)) +    return ForwardRefTI; + +  Expected<TagRecordHash> ForwardTRH = hashTagRecord(F); +  if (!ForwardTRH) +    return ForwardTRH.takeError(); + +  uint32_t BucketIdx = ForwardTRH->FullRecordHash % Header->NumHashBuckets; + +  for (TypeIndex TI : HashMap[BucketIdx]) { +    CVType CVT = Types->getType(TI); +    if (CVT.kind() != F.kind()) +      continue; + +    Expected<TagRecordHash> FullTRH = hashTagRecord(CVT); +    if (!FullTRH) +      return FullTRH.takeError(); +    if (ForwardTRH->FullRecordHash != FullTRH->FullRecordHash) +      continue; +    TagRecord &ForwardTR = ForwardTRH->getRecord(); +    TagRecord &FullTR = FullTRH->getRecord(); + +    if (!ForwardTR.hasUniqueName()) { +      if (ForwardTR.getName() == FullTR.getName()) +        return TI; +      continue; +    } + +    if (!FullTR.hasUniqueName()) +      continue; +    if (ForwardTR.getUniqueName() == FullTR.getUniqueName()) +      return TI; +  } +  return ForwardRefTI; +} + +codeview::CVType TpiStream::getType(codeview::TypeIndex Index) { +  assert(!Index.isSimple()); +  return Types->getType(Index); +} +  BinarySubstreamRef TpiStream::getTypeRecordsSubstream() const {    return TypeRecordsSubstream;  }  | 
