Skip to content

[Serialization] Use stable hash functions #96136

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion clang/lib/AST/ODRHash.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ unsigned ODRHash::CalculateHash() {

assert(I == Bools.rend());
Bools.clear();
return ID.ComputeHash();
return ID.computeStableHash();
}

namespace {
Expand Down
10 changes: 6 additions & 4 deletions clang/lib/Serialization/ASTReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1197,7 +1197,7 @@ unsigned DeclarationNameKey::getHash() const {
break;
}

return ID.ComputeHash();
return ID.computeStableHash();
}

ModuleFile *
Expand Down Expand Up @@ -2029,7 +2029,10 @@ const FileEntry *HeaderFileInfoTrait::getFile(const internal_key_type &Key) {
}

unsigned HeaderFileInfoTrait::ComputeHash(internal_key_ref ikey) {
return llvm::hash_combine(ikey.Size, ikey.ModTime);
uint8_t buf[sizeof(ikey.Size) + sizeof(ikey.ModTime)];
memcpy(buf, &ikey.Size, sizeof(ikey.Size));
memcpy(buf + sizeof(ikey.Size), &ikey.ModTime, sizeof(ikey.ModTime));
return llvm::xxh3_64bits(buf);
}

HeaderFileInfoTrait::internal_key_type
Expand Down Expand Up @@ -2636,8 +2639,7 @@ InputFile ASTReader::getInputFile(ModuleFile &F, unsigned ID, bool Complain) {
return OriginalChange;
}

// FIXME: hash_value is not guaranteed to be stable!
auto ContentHash = hash_value(MemBuffOrError.get()->getBuffer());
auto ContentHash = xxh3_64bits(MemBuffOrError.get()->getBuffer());
if (StoredContentHash == static_cast<uint64_t>(ContentHash))
return Change{Change::None};

Expand Down
7 changes: 5 additions & 2 deletions clang/lib/Serialization/ASTWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1782,7 +1782,7 @@ void ASTWriter::WriteInputFiles(SourceManager &SourceMgr,
.ValidateASTInputFilesContent) {
auto MemBuff = Cache->getBufferIfLoaded();
if (MemBuff)
ContentHash = hash_value(MemBuff->getBuffer());
ContentHash = xxh3_64bits(MemBuff->getBuffer());
else
PP->Diag(SourceLocation(), diag::err_module_unable_to_hash_content)
<< Entry.File.getName();
Expand Down Expand Up @@ -1987,7 +1987,10 @@ namespace {
// The hash is based only on size/time of the file, so that the reader can
// match even when symlinking or excess path elements ("foo/../", "../")
// change the form of the name. However, complete path is still the key.
return llvm::hash_combine(key.Size, key.ModTime);
uint8_t buf[sizeof(key.Size) + sizeof(key.ModTime)];
memcpy(buf, &key.Size, sizeof(key.Size));
memcpy(buf + sizeof(key.Size), &key.ModTime, sizeof(key.ModTime));
return llvm::xxh3_64bits(buf);
}

std::pair<unsigned, unsigned>
Expand Down
23 changes: 19 additions & 4 deletions llvm/include/llvm/ADT/FoldingSet.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/iterator.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/xxhash.h"
#include <cassert>
#include <cstddef>
#include <cstdint>
Expand Down Expand Up @@ -294,12 +295,19 @@ class FoldingSetNodeIDRef {
FoldingSetNodeIDRef() = default;
FoldingSetNodeIDRef(const unsigned *D, size_t S) : Data(D), Size(S) {}

/// ComputeHash - Compute a strong hash value for this FoldingSetNodeIDRef,
/// used to lookup the node in the FoldingSetBase.
// Compute a strong hash value used to lookup the node in the FoldingSetBase.
// The hash value is not guaranteed to be deterministic across processes.
unsigned ComputeHash() const {
return static_cast<unsigned>(hash_combine_range(Data, Data + Size));
}

// Compute a deterministic hash value across processes that is suitable for
// on-disk serialization.
unsigned computeStableHash() const {
return static_cast<unsigned>(xxh3_64bits(ArrayRef(
reinterpret_cast<const uint8_t *>(Data), sizeof(unsigned) * Size)));
}

bool operator==(FoldingSetNodeIDRef) const;

bool operator!=(FoldingSetNodeIDRef RHS) const { return !(*this == RHS); }
Expand Down Expand Up @@ -366,12 +374,19 @@ class FoldingSetNodeID {
/// object to be used to compute a new profile.
inline void clear() { Bits.clear(); }

/// ComputeHash - Compute a strong hash value for this FoldingSetNodeID, used
/// to lookup the node in the FoldingSetBase.
// Compute a strong hash value for this FoldingSetNodeID, used to lookup the
// node in the FoldingSetBase. The hash value is not guaranteed to be
// deterministic across processes.
unsigned ComputeHash() const {
return FoldingSetNodeIDRef(Bits.data(), Bits.size()).ComputeHash();
}

// Compute a deterministic hash value across processes that is suitable for
// on-disk serialization.
unsigned computeStableHash() const {
return FoldingSetNodeIDRef(Bits.data(), Bits.size()).computeStableHash();
}

/// operator== - Used to compare two nodes to each other.
bool operator==(const FoldingSetNodeID &RHS) const;
bool operator==(const FoldingSetNodeIDRef RHS) const;
Expand Down
Loading