| //===- Hash.cpp - PDB Hash Functions --------------------------------------===// | |
| // | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |
| // See https://llvm.org/LICENSE.txt for license information. | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |
| // | |
| //===----------------------------------------------------------------------===// | |
| #include "llvm/DebugInfo/PDB/Native/Hash.h" | |
| #include "llvm/ADT/ArrayRef.h" | |
| #include "llvm/Support/CRC.h" | |
| #include "llvm/Support/Endian.h" | |
| #include <cstdint> | |
| using namespace llvm; | |
| using namespace llvm::support; | |
| // Corresponds to `Hasher::lhashPbCb` in PDB/include/misc.h. | |
| // Used for name hash table and TPI/IPI hashes. | |
| uint32_t pdb::hashStringV1(StringRef Str) { | |
| uint32_t Result = 0; | |
| uint32_t Size = Str.size(); | |
| ArrayRef<ulittle32_t> Longs(reinterpret_cast<const ulittle32_t *>(Str.data()), | |
| Size / 4); | |
| for (auto Value : Longs) | |
| Result ^= Value; | |
| const uint8_t *Remainder = reinterpret_cast<const uint8_t *>(Longs.end()); | |
| uint32_t RemainderSize = 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<const ulittle16_t *>(Remainder); | |
| Result ^= static_cast<uint32_t>(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. | |
| // Used for name hash table. | |
| uint32_t pdb::hashStringV2(StringRef Str) { | |
| uint32_t Hash = 0xb170a1bf; | |
| ArrayRef<char> Buffer(Str.begin(), Str.end()); | |
| ArrayRef<ulittle32_t> Items( | |
| reinterpret_cast<const ulittle32_t *>(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 * 1664525U + 1013904223U; | |
| } | |
| // Corresponds to `SigForPbCb` in langapi/shared/crc32.h. | |
| uint32_t pdb::hashBufferV8(ArrayRef<uint8_t> Buf) { | |
| JamCRC JC(/*Init=*/0U); | |
| JC.update(Buf); | |
| return JC.getCRC(); | |
| } |