Index: include/llvm/DebugInfo/PDB/Raw/Hash.h =================================================================== --- /dev/null +++ include/llvm/DebugInfo/PDB/Raw/Hash.h @@ -0,0 +1,22 @@ +//===- Hash.h - PDB hash functions ------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_DEBUGINFO_PDB_RAW_HASH_H +#define LLVM_DEBUGINFO_PDB_RAW_HASH_H + +#include "llvm/ADT/StringRef.h" + +namespace llvm { +namespace pdb { +uint32_t HashStringV1(StringRef Str); +uint32_t HashStringV2(StringRef Str); +} +} + +#endif Index: lib/DebugInfo/PDB/CMakeLists.txt =================================================================== --- lib/DebugInfo/PDB/CMakeLists.txt +++ lib/DebugInfo/PDB/CMakeLists.txt @@ -30,6 +30,7 @@ add_pdb_impl_folder(Raw Raw/DbiStream.cpp Raw/EnumTables.cpp + Raw/Hash.cpp Raw/IndexedStreamData.cpp Raw/InfoStream.cpp Raw/MappedBlockStream.cpp Index: lib/DebugInfo/PDB/Raw/Hash.cpp =================================================================== --- /dev/null +++ lib/DebugInfo/PDB/Raw/Hash.cpp @@ -0,0 +1,75 @@ +//===- Hash.cpp - PDB Hash Functions --------------------------------------===// +// +// 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/Raw/Hash.h" + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/Support/Endian.h" + +using namespace llvm; +using namespace llvm::support; + +// Corresponds to `Hasher::lhashPbCb` in PDB/include/misc.h. +uint32_t pdb::HashStringV1(StringRef Str) { + uint32_t Result = 0; + uint32_t Size = Str.size(); + + ArrayRef Longs(reinterpret_cast(Str.data()), + Size / 4); + + for (auto Value : Longs) + Result ^= Value; + + const uint8_t *Remainder = reinterpret_cast(Longs.end()); + uint32_t RemainderSize = Size - Longs.size() * 4; + + // Maximum of 3 bytes left. Hash a 2 byte word if possible, then hash the + // possibly remaining 1 byte. + if (RemainderSize >= 2) { + uint16_t Value = *reinterpret_cast(Remainder); + Result ^= static_cast(Value); + Remainder += 2; + RemainderSize -= 2; + } + + // hash possible odd byte + if (RemainderSize == 1) { + Result ^= *(Remainder++); + } + + const uint32_t toLowerMask = 0x20202020; + Result |= toLowerMask; + Result ^= (Result >> 11); + + return Result ^ (Result >> 16); +} + +// Corresponds to `HasherV2::HashULONG` in PDB/include/misc.h. +uint32_t pdb::HashStringV2(StringRef Str) { + uint32_t Hash = 0xb170a1bf; + + ArrayRef Buffer(Str.begin(), Str.end()); + + ArrayRef Items( + reinterpret_cast(Buffer.data()), + Buffer.size() / sizeof(ulittle32_t)); + for (ulittle32_t Item : Items) { + Hash += Item; + Hash += (Hash << 10); + Hash ^= (Hash >> 6); + } + Buffer = Buffer.slice(Items.size() * sizeof(ulittle32_t)); + for (uint8_t Item : Buffer) { + Hash += Item; + Hash += (Hash << 10); + Hash ^= (Hash >> 6); + } + + return Hash * 1664525L + 1013904223L; +} Index: lib/DebugInfo/PDB/Raw/NameHashTable.cpp =================================================================== --- lib/DebugInfo/PDB/Raw/NameHashTable.cpp +++ lib/DebugInfo/PDB/Raw/NameHashTable.cpp @@ -11,6 +11,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/DebugInfo/CodeView/StreamReader.h" +#include "llvm/DebugInfo/PDB/Raw/Hash.h" #include "llvm/DebugInfo/PDB/Raw/RawError.h" #include "llvm/Support/Endian.h" @@ -18,65 +19,6 @@ using namespace llvm::support; using namespace llvm::pdb; -// Corresponds to `Hasher::lhashPbCb` in PDB/include/misc.h. -static inline uint32_t HashStringV1(StringRef Str) { - uint32_t Result = 0; - uint32_t Size = Str.size(); - - ArrayRef Longs(reinterpret_cast(Str.data()), - Size / 4); - - for (auto Value : Longs) - Result ^= Value; - - const uint8_t *Remainder = reinterpret_cast(Longs.end()); - uint32_t RemainderSize = Size - Longs.size() * 4; - - // Maximum of 3 bytes left. Hash a 2 byte word if possible, then hash the - // possibly remaining 1 byte. - if (RemainderSize >= 2) { - uint16_t Value = *reinterpret_cast(Remainder); - Result ^= static_cast(Value); - Remainder += 2; - RemainderSize -= 2; - } - - // hash possible odd byte - if (RemainderSize == 1) { - Result ^= *(Remainder++); - } - - const uint32_t toLowerMask = 0x20202020; - Result |= toLowerMask; - Result ^= (Result >> 11); - - return Result ^ (Result >> 16); -} - -// Corresponds to `HasherV2::HashULONG` in PDB/include/misc.h. -static inline uint32_t HashStringV2(StringRef Str) { - uint32_t Hash = 0xb170a1bf; - - ArrayRef Buffer(Str.begin(), Str.end()); - - ArrayRef Items( - reinterpret_cast(Buffer.data()), - Buffer.size() / sizeof(ulittle32_t)); - for (ulittle32_t Item : Items) { - Hash += Item; - Hash += (Hash << 10); - Hash ^= (Hash >> 6); - } - Buffer = Buffer.slice(Items.size() * sizeof(ulittle32_t)); - for (uint8_t Item : Buffer) { - Hash += Item; - Hash += (Hash << 10); - Hash ^= (Hash >> 6); - } - - return Hash * 1664525L + 1013904223L; -} - NameHashTable::NameHashTable() : Signature(0), HashVersion(0), NameCount(0) {} Error NameHashTable::load(codeview::StreamReader &Stream) {