mirror of
https://github.com/RPCS3/llvm.git
synced 2025-05-23 22:06:19 +00:00

Summary: This removes the CVTypeVisitor updater and verifier classes. They were made dead by the minimal type dumping refactoring. Replace them with a single function that takes a type record and produces a hash. Call this from the minimal type dumper and compare the hash. I also noticed that the microsoft-pdb reference repository uses a basic CRC32 for records that aren't special. We already have an implementation of that CRC ready to use, because it's used in COFF for ICF. I'll make LLD call this hashing utility in a follow-up change. We might also consider using this same hash in type stream merging, so that we don't have to hash our records twice. Reviewers: inglorion, ruiu Subscribers: llvm-commits, hiraditya Differential Revision: https://reviews.llvm.org/D35515 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@308240 91177308-0d34-0410-b5e6-96231b3b80d8
90 lines
2.9 KiB
C++
90 lines
2.9 KiB
C++
//===- TpiHashing.cpp -----------------------------------------------------===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include "llvm/DebugInfo/PDB/Native/TpiHashing.h"
|
|
|
|
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
|
|
#include "llvm/DebugInfo/PDB/Native/Hash.h"
|
|
#include "llvm/Support/JamCRC.h"
|
|
|
|
using namespace llvm;
|
|
using namespace llvm::codeview;
|
|
using namespace llvm::pdb;
|
|
|
|
// Corresponds to `fUDTAnon`.
|
|
static bool isAnonymous(StringRef Name) {
|
|
return Name == "<unnamed-tag>" || Name == "__unnamed" ||
|
|
Name.endswith("::<unnamed-tag>") || Name.endswith("::__unnamed");
|
|
}
|
|
|
|
// Computes the hash for a user-defined type record. This could be a struct,
|
|
// class, union, or enum.
|
|
static uint32_t getHashForUdt(const TagRecord &Rec,
|
|
ArrayRef<uint8_t> FullRecord) {
|
|
ClassOptions Opts = Rec.getOptions();
|
|
bool ForwardRef = bool(Opts & ClassOptions::ForwardReference);
|
|
bool Scoped = bool(Opts & ClassOptions::Scoped);
|
|
bool HasUniqueName = bool(Opts & ClassOptions::HasUniqueName);
|
|
bool IsAnon = HasUniqueName && isAnonymous(Rec.getName());
|
|
|
|
if (!ForwardRef && !Scoped && !IsAnon)
|
|
return hashStringV1(Rec.getName());
|
|
if (!ForwardRef && HasUniqueName && !IsAnon)
|
|
return hashStringV1(Rec.getUniqueName());
|
|
return hashBufferV8(FullRecord);
|
|
}
|
|
|
|
template <typename T>
|
|
static Expected<uint32_t> getHashForUdt(const CVType &Rec) {
|
|
T Deserialized;
|
|
if (auto E = TypeDeserializer::deserializeAs(const_cast<CVType &>(Rec),
|
|
Deserialized))
|
|
return std::move(E);
|
|
return getHashForUdt(Deserialized, Rec.data());
|
|
}
|
|
|
|
template <typename T>
|
|
static Expected<uint32_t> getSourceLineHash(const CVType &Rec) {
|
|
T Deserialized;
|
|
if (auto E = TypeDeserializer::deserializeAs(const_cast<CVType &>(Rec),
|
|
Deserialized))
|
|
return std::move(E);
|
|
char Buf[4];
|
|
support::endian::write32le(Buf, Deserialized.getUDT().getIndex());
|
|
return hashStringV1(StringRef(Buf, 4));
|
|
}
|
|
|
|
Expected<uint32_t> llvm::pdb::hashTypeRecord(const CVType &Rec) {
|
|
switch (Rec.kind()) {
|
|
case LF_CLASS:
|
|
case LF_STRUCTURE:
|
|
case LF_INTERFACE:
|
|
return getHashForUdt<ClassRecord>(Rec);
|
|
case LF_UNION:
|
|
return getHashForUdt<UnionRecord>(Rec);
|
|
case LF_ENUM:
|
|
return getHashForUdt<EnumRecord>(Rec);
|
|
|
|
case LF_UDT_SRC_LINE:
|
|
return getSourceLineHash<UdtSourceLineRecord>(Rec);
|
|
case LF_UDT_MOD_SRC_LINE:
|
|
return getSourceLineHash<UdtModSourceLineRecord>(Rec);
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
// Run CRC32 over the bytes. This corresponds to `hashBufv8`.
|
|
JamCRC JC(/*Init=*/0U);
|
|
ArrayRef<char> Bytes(reinterpret_cast<const char *>(Rec.data().data()),
|
|
Rec.data().size());
|
|
JC.update(Bytes);
|
|
return JC.getCRC();
|
|
}
|