From 330268ba346b679af786879d8f696c8c412a40eb Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Mon, 4 Apr 2022 16:48:30 -0700 Subject: [PATCH] [Support/Hash functions] Change the `final()` and `result()` of the hashing functions to return an array of bytes Returning `std::array` is better ergonomics for the hashing functions usage, instead of a `StringRef`: * When returning `StringRef`, client code is "jumping through hoops" to do string manipulations instead of dealing with fixed array of bytes directly, which is more natural * Returning `std::array` avoids the need for the hasher classes to keep a field just for the purpose of wrapping it and returning it as a `StringRef` As part of this patch also: * Introduce `TruncatedBLAKE3` which is useful for using BLAKE3 as the hasher type for `HashBuilder` with non-default hash sizes. * Make `MD5Result` inherit from `std::array` which improves & simplifies its API. Differential Revision: https://reviews.llvm.org/D123100 --- bolt/lib/Core/DebugData.cpp | 3 +- clang/include/clang/Basic/Module.h | 4 +-- clang/lib/Serialization/ASTWriter.cpp | 6 ++-- lld/MachO/SyntheticSections.cpp | 2 +- llvm/include/llvm/Support/BLAKE3.h | 39 +++++++++++++++++++++++- llvm/include/llvm/Support/HashBuilder.h | 7 +++-- llvm/include/llvm/Support/MD5.h | 29 +++++------------- llvm/include/llvm/Support/SHA1.h | 13 ++++---- llvm/include/llvm/Support/SHA256.h | 13 ++++---- llvm/include/llvm/Support/raw_sha1_ostream.h | 2 +- llvm/lib/Bitcode/Reader/BitcodeAnalyzer.cpp | 6 ++-- llvm/lib/Bitcode/Writer/BitcodeWriter.cpp | 2 +- llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp | 2 +- llvm/lib/DebugInfo/CodeView/TypeHashing.cpp | 3 +- llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp | 2 +- llvm/lib/MC/MCDwarf.cpp | 3 +- llvm/lib/MC/MCParser/AsmParser.cpp | 4 +-- llvm/lib/MC/MCParser/MasmParser.cpp | 4 +-- llvm/lib/ObjCopy/MachO/MachOWriter.cpp | 2 +- llvm/lib/Support/BLAKE3/README.md | 2 +- llvm/lib/Support/MD5.cpp | 14 ++++----- llvm/lib/Support/SHA1.cpp | 21 +++++++------ llvm/lib/Support/SHA256.cpp | 21 +++++++------ llvm/unittests/Support/BLAKE3Test.cpp | 17 +++++++++++ llvm/unittests/Support/HashBuilderTest.cpp | 12 +++++--- llvm/unittests/Support/MD5Test.cpp | 12 ++------ llvm/unittests/Support/SHA256.cpp | 2 +- llvm/unittests/Support/raw_sha1_ostream_test.cpp | 4 +-- mlir/lib/Pass/IRPrinting.cpp | 2 +- 29 files changed, 148 insertions(+), 105 deletions(-) diff --git a/bolt/lib/Core/DebugData.cpp b/bolt/lib/Core/DebugData.cpp index ba6a653..2ebd2c0 100644 --- a/bolt/lib/Core/DebugData.cpp +++ b/bolt/lib/Core/DebugData.cpp @@ -820,7 +820,8 @@ void DebugAbbrevWriter::addUnitAbbreviations(DWARFUnit &Unit) { auto hashAndAddAbbrev = [&](StringRef AbbrevData) -> bool { llvm::SHA1 Hasher; Hasher.update(AbbrevData); - StringRef Key = Hasher.final(); + std::array Hash = Hasher.final(); + StringRef Key((const char *)Hash.data(), Hash.size()); auto Iter = AbbrevDataCache.find(Key); if (Iter != AbbrevDataCache.end()) { UnitsAbbrevData[&Unit] = Iter->second.get(); diff --git a/clang/include/clang/Basic/Module.h b/clang/include/clang/Basic/Module.h index af96038b..45c23d5 100644 --- a/clang/include/clang/Basic/Module.h +++ b/clang/include/clang/Basic/Module.h @@ -71,8 +71,8 @@ struct ASTFileSignature : std::array { return Value; } - static ASTFileSignature create(StringRef Bytes) { - return create(Bytes.bytes_begin(), Bytes.bytes_end()); + static ASTFileSignature create(std::array Bytes) { + return ASTFileSignature(std::move(Bytes)); } static ASTFileSignature createDISentinel() { diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index b686061..5fd4e8f 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -1117,8 +1117,7 @@ std::pair ASTWriter::createSignature(StringRef AllBytes, StringRef ASTBlockBytes) { llvm::SHA1 Hasher; Hasher.update(ASTBlockBytes); - auto Hash = Hasher.result(); - ASTFileSignature ASTBlockHash = ASTFileSignature::create(Hash); + ASTFileSignature ASTBlockHash = ASTFileSignature::create(Hasher.result()); // Add the remaining bytes (i.e. bytes before the unhashed control block that // are not part of the AST block). @@ -1126,8 +1125,7 @@ ASTWriter::createSignature(StringRef AllBytes, StringRef ASTBlockBytes) { AllBytes.take_front(ASTBlockBytes.bytes_end() - AllBytes.bytes_begin())); Hasher.update( AllBytes.take_back(AllBytes.bytes_end() - ASTBlockBytes.bytes_end())); - Hash = Hasher.result(); - ASTFileSignature Signature = ASTFileSignature::create(Hash); + ASTFileSignature Signature = ASTFileSignature::create(Hasher.result()); return std::make_pair(ASTBlockHash, Signature); } diff --git a/lld/MachO/SyntheticSections.cpp b/lld/MachO/SyntheticSections.cpp index e47c7e3..a4de385 100644 --- a/lld/MachO/SyntheticSections.cpp +++ b/lld/MachO/SyntheticSections.cpp @@ -1202,7 +1202,7 @@ void CodeSignatureSection::writeHashes(uint8_t *buf) const { std::min(codeEnd - code, static_cast(blockSize))); SHA256 hasher; hasher.update(block); - StringRef hash = hasher.final(); + std::array hash = hasher.final(); assert(hash.size() == hashSize); memcpy(hashes, hash.data(), hashSize); code += blockSize; diff --git a/llvm/include/llvm/Support/BLAKE3.h b/llvm/include/llvm/Support/BLAKE3.h index ade5201..7b30dbc 100644 --- a/llvm/include/llvm/Support/BLAKE3.h +++ b/llvm/include/llvm/Support/BLAKE3.h @@ -34,7 +34,7 @@ namespace llvm { template using BLAKE3Result = std::array; -/// A class that wrap the BLAKE3 algorithm. +/// A class that wraps the BLAKE3 algorithm. class BLAKE3 { public: BLAKE3() { init(); } @@ -70,6 +70,17 @@ public: return Result; } + /// Return the current output for the digested data since the last call to + /// init(). + /// + /// Other hash functions distinguish between \p result() and \p final(), with + /// \p result() allowing more calls into \p update(), but there's no + // difference for the BLAKE3 hash function. + template + BLAKE3Result result() { + return final(); + } + /// Returns a BLAKE3 hash for the given data. template static BLAKE3Result hash(ArrayRef Data) { @@ -82,6 +93,32 @@ private: llvm_blake3_hasher Hasher; }; +/// Like \p BLAKE3 but using a class-level template parameter for specifying the +/// hash size of the \p final() and \p result() functions. +/// +/// This is useful for using BLAKE3 as the hasher type for \p HashBuilder with +/// non-default hash sizes. +template class TruncatedBLAKE3 : public BLAKE3 { +public: + /// Finalize the hasher and put the result in \p Result. + /// This doesn't modify the hasher itself, and it's possible to finalize again + /// after adding more input. + void final(BLAKE3Result &Result) { return BLAKE3::final(Result); } + + /// Finalize the hasher and return an output of any length, given in bytes. + /// This doesn't modify the hasher itself, and it's possible to finalize again + /// after adding more input. + BLAKE3Result final() { return BLAKE3::final(); } + + /// Return the current output for the digested data since the last call to + /// init(). + /// + /// Other hash functions distinguish between \p result() and \p final(), with + /// \p result() allowing more calls into \p update(), but there's no + // difference for the BLAKE3 hash function. + BLAKE3Result result() { return BLAKE3::result(); } +}; + } // namespace llvm #endif diff --git a/llvm/include/llvm/Support/HashBuilder.h b/llvm/include/llvm/Support/HashBuilder.h index bf93a0d..9d7680d 100644 --- a/llvm/include/llvm/Support/HashBuilder.h +++ b/llvm/include/llvm/Support/HashBuilder.h @@ -39,6 +39,9 @@ struct IsHashableData /// Declares the hasher member, and functions forwarding directly to the hasher. template class HashBuilderBase { public: + template + using HashResultTy = decltype(std::declval().final()); + HasherT &getHasher() { return Hasher; } /// Forward to `HasherT::update(ArrayRef)`. @@ -59,12 +62,12 @@ public: } /// Forward to `HasherT::final()` if available. - template StringRef final() { + template HashResultTy final() { return this->getHasher().final(); } /// Forward to `HasherT::result()` if available. - template StringRef result() { + template HashResultTy result() { return this->getHasher().result(); } diff --git a/llvm/include/llvm/Support/MD5.h b/llvm/include/llvm/Support/MD5.h index 70d0466..fa2f477 100644 --- a/llvm/include/llvm/Support/MD5.h +++ b/llvm/include/llvm/Support/MD5.h @@ -40,26 +40,19 @@ template class ArrayRef; class MD5 { public: - struct MD5Result { - std::array Bytes; - - operator std::array() const { return Bytes; } - - const uint8_t &operator[](size_t I) const { return Bytes[I]; } - uint8_t &operator[](size_t I) { return Bytes[I]; } - + struct MD5Result : public std::array { SmallString<32> digest() const; uint64_t low() const { // Our MD5 implementation returns the result in little endian, so the low // word is first. using namespace support; - return endian::read(Bytes.data()); + return endian::read(data()); } uint64_t high() const { using namespace support; - return endian::read(Bytes.data() + 8); + return endian::read(data() + 8); } std::pair words() const { using namespace support; @@ -78,20 +71,20 @@ public: /// Finishes off the hash and puts the result in result. void final(MD5Result &Result); - /// Finishes off the hash, and returns a reference to the 16-byte hash data. - StringRef final(); + /// Finishes off the hash, and returns the 16-byte hash data. + MD5Result final(); - /// Finishes off the hash, and returns a reference to the 16-byte hash data. + /// Finishes off the hash, and returns the 16-byte hash data. /// This is suitable for getting the MD5 at any time without invalidating the /// internal state, so that more calls can be made into `update`. - StringRef result(); + MD5Result result(); /// Translates the bytes in \p Res to a hex string that is /// deposited into \p Str. The result will be of length 32. static void stringifyResult(MD5Result &Result, SmallVectorImpl &Str); /// Computes the hash for a given bytes. - static std::array hash(ArrayRef Data); + static MD5Result hash(ArrayRef Data); private: // Any 32-bit or wider unsigned integer data type will do. @@ -109,15 +102,9 @@ private: MD5_u32plus block[16]; } InternalState; - MD5Result Result; - const uint8_t *body(ArrayRef Data); }; -inline bool operator==(const MD5::MD5Result &LHS, const MD5::MD5Result &RHS) { - return LHS.Bytes == RHS.Bytes; -} - /// Helper to compute and return lower 64 bits of the given string's MD5 hash. inline uint64_t MD5Hash(StringRef Str) { using namespace support; diff --git a/llvm/include/llvm/Support/SHA1.h b/llvm/include/llvm/Support/SHA1.h index efd8513..ae6d62a 100644 --- a/llvm/include/llvm/Support/SHA1.h +++ b/llvm/include/llvm/Support/SHA1.h @@ -36,17 +36,17 @@ public: /// Digest more data. void update(StringRef Str); - /// Return a reference to the current raw 160-bits SHA1 for the digested data + /// Return the current raw 160-bits SHA1 for the digested data /// since the last call to init(). This call will add data to the internal /// state and as such is not suited for getting an intermediate result /// (see result()). - StringRef final(); + std::array final(); - /// Return a reference to the current raw 160-bits SHA1 for the digested data + /// Return the current raw 160-bits SHA1 for the digested data /// since the last call to init(). This is suitable for getting the SHA1 at /// any time without invalidating the internal state so that more calls can be /// made into update. - StringRef result(); + std::array result(); /// Returns a raw 160-bit SHA1 hash for the given data. static std::array hash(ArrayRef Data); @@ -68,14 +68,13 @@ private: uint8_t BufferOffset; } InternalState; - // Internal copy of the hash, populated and accessed on calls to result() - uint32_t HashResult[HASH_LENGTH / 4]; - // Helper void writebyte(uint8_t data); void hashBlock(); void addUncounted(uint8_t data); void pad(); + + void final(std::array &HashResult); }; } // end llvm namespace diff --git a/llvm/include/llvm/Support/SHA256.h b/llvm/include/llvm/Support/SHA256.h index 9e295b0..68b32c7 100644 --- a/llvm/include/llvm/Support/SHA256.h +++ b/llvm/include/llvm/Support/SHA256.h @@ -43,17 +43,17 @@ public: /// Digest more data. void update(StringRef Str); - /// Return a reference to the current raw 256-bits SHA256 for the digested + /// Return the current raw 256-bits SHA256 for the digested /// data since the last call to init(). This call will add data to the /// internal state and as such is not suited for getting an intermediate /// result (see result()). - StringRef final(); + std::array final(); - /// Return a reference to the current raw 256-bits SHA256 for the digested + /// Return the current raw 256-bits SHA256 for the digested /// data since the last call to init(). This is suitable for getting the /// SHA256 at any time without invalidating the internal state so that more /// calls can be made into update. - StringRef result(); + std::array result(); /// Returns a raw 256-bit SHA256 hash for the given data. static std::array hash(ArrayRef Data); @@ -75,14 +75,13 @@ private: uint8_t BufferOffset; } InternalState; - // Internal copy of the hash, populated and accessed on calls to result() - uint32_t HashResult[HASH_LENGTH / 4]; - // Helper void writebyte(uint8_t data); void hashBlock(); void addUncounted(uint8_t data); void pad(); + + void final(std::array &HashResult); }; } // namespace llvm diff --git a/llvm/include/llvm/Support/raw_sha1_ostream.h b/llvm/include/llvm/Support/raw_sha1_ostream.h index 3991691..299f6e6 100644 --- a/llvm/include/llvm/Support/raw_sha1_ostream.h +++ b/llvm/include/llvm/Support/raw_sha1_ostream.h @@ -30,7 +30,7 @@ class raw_sha1_ostream : public raw_ostream { public: /// Return the current SHA1 hash for the content of the stream - StringRef sha1() { + std::array sha1() { flush(); return State.result(); } diff --git a/llvm/lib/Bitcode/Reader/BitcodeAnalyzer.cpp b/llvm/lib/Bitcode/Reader/BitcodeAnalyzer.cpp index fdb07cf..f291827 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeAnalyzer.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeAnalyzer.cpp @@ -903,7 +903,7 @@ Error BitcodeAnalyzer::parseBlock(unsigned BlockID, unsigned IndentLevel, else { // Recompute the hash and compare it to the one in the bitcode SHA1 Hasher; - StringRef Hash; + std::array Hash; Hasher.update(*CheckHash); { int BlockSize = (CurrentRecordPos / 8) - BlockEntryPos; @@ -911,14 +911,14 @@ Error BitcodeAnalyzer::parseBlock(unsigned BlockID, unsigned IndentLevel, Hasher.update(ArrayRef(Ptr, BlockSize)); Hash = Hasher.result(); } - std::array RecordedHash; + std::array RecordedHash; int Pos = 0; for (auto &Val : Record) { assert(!(Val >> 32) && "Unexpected high bits set"); support::endian::write32be(&RecordedHash[Pos], Val); Pos += 4; } - if (Hash == StringRef(RecordedHash.data(), RecordedHash.size())) + if (Hash == RecordedHash) O->OS << " (match)"; else O->OS << " (!mismatch!)"; diff --git a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp index 8a16524..c76294d 100644 --- a/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp +++ b/llvm/lib/Bitcode/Writer/BitcodeWriter.cpp @@ -4387,7 +4387,7 @@ void ModuleBitcodeWriter::writeModuleHash(size_t BlockStartPos) { uint32_t Vals[5]; Hasher.update(ArrayRef((const uint8_t *)&(Buffer)[BlockStartPos], Buffer.size() - BlockStartPos)); - StringRef Hash = Hasher.result(); + std::array Hash = Hasher.result(); for (int Pos = 0; Pos < 20; Pos += 4) { Vals[Pos / 4] = support::endian::read32be(Hash.data() + Pos); } diff --git a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp index 850a5e1..37ae84a 100644 --- a/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/DwarfDebug.cpp @@ -3536,6 +3536,6 @@ Optional DwarfDebug::getMD5AsBytes(const DIFile *File) const { // An MD5 checksum is 16 bytes. std::string ChecksumString = fromHex(Checksum->Value); MD5::MD5Result CKMem; - std::copy(ChecksumString.begin(), ChecksumString.end(), CKMem.Bytes.data()); + std::copy(ChecksumString.begin(), ChecksumString.end(), CKMem.data()); return CKMem; } diff --git a/llvm/lib/DebugInfo/CodeView/TypeHashing.cpp b/llvm/lib/DebugInfo/CodeView/TypeHashing.cpp index 2dbc11a..fc85d81 100644 --- a/llvm/lib/DebugInfo/CodeView/TypeHashing.cpp +++ b/llvm/lib/DebugInfo/CodeView/TypeHashing.cpp @@ -76,5 +76,6 @@ GloballyHashedType::hashType(ArrayRef RecordData, auto TrailingBytes = RecordData.drop_front(Off); S.update(TrailingBytes); - return {S.final().take_back(8)}; + std::array Hash = S.final(); + return {ArrayRef(Hash).take_back(8)}; } diff --git a/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp b/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp index 3df22c0..81394e2 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFDebugLine.cpp @@ -341,7 +341,7 @@ parseV5DirFileTables(const DWARFDataExtractor &DebugLineData, errc::invalid_argument, "failed to parse file entry because the MD5 hash is invalid"); std::uninitialized_copy_n(Value.getAsBlock().getValue().begin(), 16, - FileEntry.Checksum.Bytes.begin()); + FileEntry.Checksum.begin()); break; default: break; diff --git a/llvm/lib/MC/MCDwarf.cpp b/llvm/lib/MC/MCDwarf.cpp index 2cb5a00..f2e92fe 100644 --- a/llvm/lib/MC/MCDwarf.cpp +++ b/llvm/lib/MC/MCDwarf.cpp @@ -387,8 +387,7 @@ static void emitOneV5FileEntry(MCStreamer *MCOS, const MCDwarfFile &DwarfFile, if (EmitMD5) { const MD5::MD5Result &Cksum = *DwarfFile.Checksum; MCOS->emitBinaryData( - StringRef(reinterpret_cast(Cksum.Bytes.data()), - Cksum.Bytes.size())); + StringRef(reinterpret_cast(Cksum.data()), Cksum.size())); } if (HasSource) { if (LineStr) diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp index 9632f00..defc86e 100644 --- a/llvm/lib/MC/MCParser/AsmParser.cpp +++ b/llvm/lib/MC/MCParser/AsmParser.cpp @@ -3573,8 +3573,8 @@ bool AsmParser::parseDirectiveFile(SMLoc DirectiveLoc) { if (HasMD5) { MD5::MD5Result Sum; for (unsigned i = 0; i != 8; ++i) { - Sum.Bytes[i] = uint8_t(MD5Hi >> ((7 - i) * 8)); - Sum.Bytes[i + 8] = uint8_t(MD5Lo >> ((7 - i) * 8)); + Sum[i] = uint8_t(MD5Hi >> ((7 - i) * 8)); + Sum[i + 8] = uint8_t(MD5Lo >> ((7 - i) * 8)); } CKMem = Sum; } diff --git a/llvm/lib/MC/MCParser/MasmParser.cpp b/llvm/lib/MC/MCParser/MasmParser.cpp index aa4cc02..be478e2 100644 --- a/llvm/lib/MC/MCParser/MasmParser.cpp +++ b/llvm/lib/MC/MCParser/MasmParser.cpp @@ -4907,8 +4907,8 @@ bool MasmParser::parseDirectiveFile(SMLoc DirectiveLoc) { if (HasMD5) { MD5::MD5Result Sum; for (unsigned i = 0; i != 8; ++i) { - Sum.Bytes[i] = uint8_t(MD5Hi >> ((7 - i) * 8)); - Sum.Bytes[i + 8] = uint8_t(MD5Lo >> ((7 - i) * 8)); + Sum[i] = uint8_t(MD5Hi >> ((7 - i) * 8)); + Sum[i + 8] = uint8_t(MD5Lo >> ((7 - i) * 8)); } CKMem = Sum; } diff --git a/llvm/lib/ObjCopy/MachO/MachOWriter.cpp b/llvm/lib/ObjCopy/MachO/MachOWriter.cpp index 2a2eda4..d5d7c02 100644 --- a/llvm/lib/ObjCopy/MachO/MachOWriter.cpp +++ b/llvm/lib/ObjCopy/MachO/MachOWriter.cpp @@ -570,7 +570,7 @@ void MachOWriter::writeCodeSignatureData() { static_cast(CodeSignature.BlockSize))); SHA256 Hasher; Hasher.update(Block); - StringRef Hash = Hasher.final(); + std::array Hash = Hasher.final(); assert(Hash.size() == CodeSignature.HashSize); memcpy(CurrHashWritePosition, Hash.data(), CodeSignature.HashSize); CurrHashReadPosition += CodeSignature.BlockSize; diff --git a/llvm/lib/Support/BLAKE3/README.md b/llvm/lib/Support/BLAKE3/README.md index c4a87c7..319a751 100644 --- a/llvm/lib/Support/BLAKE3/README.md +++ b/llvm/lib/Support/BLAKE3/README.md @@ -152,7 +152,7 @@ template void BLAKE3::final(BLAKE3Result &Result); template -BLAKE3Result final(); +BLAKE3Result BLAKE3::final(); ``` ```c void llvm_blake3_hasher_finalize( diff --git a/llvm/lib/Support/MD5.cpp b/llvm/lib/Support/MD5.cpp index caadde3..fdcf34d 100644 --- a/llvm/lib/Support/MD5.cpp +++ b/llvm/lib/Support/MD5.cpp @@ -261,13 +261,13 @@ void MD5::final(MD5Result &Result) { support::endian::write32le(&Result[12], InternalState.d); } -StringRef MD5::final() { +MD5::MD5Result MD5::final() { + MD5Result Result; final(Result); - return StringRef(reinterpret_cast(Result.Bytes.data()), - Result.Bytes.size()); + return Result; } -StringRef MD5::result() { +MD5::MD5Result MD5::result() { auto StateToRestore = InternalState; auto Hash = final(); @@ -280,15 +280,15 @@ StringRef MD5::result() { SmallString<32> MD5::MD5Result::digest() const { SmallString<32> Str; - toHex(Bytes, /*LowerCase*/ true, Str); + toHex(*this, /*LowerCase*/ true, Str); return Str; } void MD5::stringifyResult(MD5Result &Result, SmallVectorImpl &Str) { - toHex(Result.Bytes, /*LowerCase*/ true, Str); + toHex(Result, /*LowerCase*/ true, Str); } -std::array MD5::hash(ArrayRef Data) { +MD5::MD5Result MD5::hash(ArrayRef Data) { MD5 Hash; Hash.update(Data); MD5::MD5Result Res; diff --git a/llvm/lib/Support/SHA1.cpp b/llvm/lib/Support/SHA1.cpp index 5dce44a..52bae70 100644 --- a/llvm/lib/Support/SHA1.cpp +++ b/llvm/lib/Support/SHA1.cpp @@ -263,7 +263,7 @@ void SHA1::pad() { addUncounted(InternalState.ByteCount << 3); } -StringRef SHA1::final() { +void SHA1::final(std::array &HashResult) { // Pad to complete the last block pad(); @@ -281,12 +281,19 @@ StringRef SHA1::final() { (((InternalState.State[i]) >> 24) & 0x000000ff); } #endif +} - // Return pointer to hash (20 characters) - return StringRef((char *)HashResult, HASH_LENGTH); +std::array SHA1::final() { + union { + std::array HashResult; + std::array ReturnResult; + }; + static_assert(sizeof(HashResult) == sizeof(ReturnResult), ""); + final(HashResult); + return ReturnResult; } -StringRef SHA1::result() { +std::array SHA1::result() { auto StateToRestore = InternalState; auto Hash = final(); @@ -301,9 +308,5 @@ StringRef SHA1::result() { std::array SHA1::hash(ArrayRef Data) { SHA1 Hash; Hash.update(Data); - StringRef S = Hash.final(); - - std::array Arr; - memcpy(Arr.data(), S.data(), S.size()); - return Arr; + return Hash.final(); } diff --git a/llvm/lib/Support/SHA256.cpp b/llvm/lib/Support/SHA256.cpp index 3b81506..81d897f 100644 --- a/llvm/lib/Support/SHA256.cpp +++ b/llvm/lib/Support/SHA256.cpp @@ -243,7 +243,7 @@ void SHA256::pad() { addUncounted(len); } -StringRef SHA256::final() { +void SHA256::final(std::array &HashResult) { // Pad to complete the last block pad(); @@ -261,12 +261,19 @@ StringRef SHA256::final() { (((InternalState.State[i]) >> 24) & 0x000000ff); } #endif +} - // Return pointer to hash (32 characters) - return StringRef((char *)HashResult, HASH_LENGTH); +std::array SHA256::final() { + union { + std::array HashResult; + std::array ReturnResult; + }; + static_assert(sizeof(HashResult) == sizeof(ReturnResult), ""); + final(HashResult); + return ReturnResult; } -StringRef SHA256::result() { +std::array SHA256::result() { auto StateToRestore = InternalState; auto Hash = final(); @@ -281,11 +288,7 @@ StringRef SHA256::result() { std::array SHA256::hash(ArrayRef Data) { SHA256 Hash; Hash.update(Data); - StringRef S = Hash.final(); - - std::array Arr; - memcpy(Arr.data(), S.data(), S.size()); - return Arr; + return Hash.final(); } } // namespace llvm diff --git a/llvm/unittests/Support/BLAKE3Test.cpp b/llvm/unittests/Support/BLAKE3Test.cpp index 197271a..a7295241 100644 --- a/llvm/unittests/Support/BLAKE3Test.cpp +++ b/llvm/unittests/Support/BLAKE3Test.cpp @@ -12,6 +12,7 @@ #include "llvm/Support/BLAKE3.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/Support/HashBuilder.h" #include "gtest/gtest.h" using namespace llvm; @@ -59,6 +60,14 @@ TEST(BLAKE3Test, BLAKE3) { auto hashStr = toHex(hash); EXPECT_EQ(hashStr, "616F575A1B58D4C9797D4217B9730AE5E6EB319D76EDEF6549B46F4EFE31FF8B"); + + // Using generic HashBuilder. + HashBuilder HashBuilder; + HashBuilder.update(std::get<0>(testvectors[2])); + BLAKE3Result<> HBHash1 = HashBuilder.final(); + BLAKE3Result<> HBHash2 = HashBuilder.result(); + EXPECT_EQ(std::get<1>(testvectors[2]), toHex(HBHash1)); + EXPECT_EQ(std::get<1>(testvectors[2]), toHex(HBHash2)); } TEST(BLAKE3Test, SmallerHashSize) { @@ -73,6 +82,14 @@ TEST(BLAKE3Test, SmallerHashSize) { auto hashStr2 = toHex(hash2); EXPECT_EQ(hashStr1, hashStr2); EXPECT_EQ(hashStr1, "6437B3AC38465133FFB63B75273A8DB5"); + + // Using generic HashBuilder. + HashBuilder, support::endianness::native> HashBuilder; + HashBuilder.update(Input); + BLAKE3Result<16> hash3 = HashBuilder.final(); + BLAKE3Result<16> hash4 = HashBuilder.result(); + EXPECT_EQ(hashStr1, toHex(hash3)); + EXPECT_EQ(hashStr1, toHex(hash4)); } } // namespace diff --git a/llvm/unittests/Support/HashBuilderTest.cpp b/llvm/unittests/Support/HashBuilderTest.cpp index d644107..2600744 100644 --- a/llvm/unittests/Support/HashBuilderTest.cpp +++ b/llvm/unittests/Support/HashBuilderTest.cpp @@ -44,13 +44,15 @@ using HashBuilder = llvm::HashBuilder; template -static std::string hashWithBuilder(const Ts &...Args) { - return HashBuilder().add(Args...).final().str(); +static typename HashBuilder::template HashResultTy<> +hashWithBuilder(const Ts &...Args) { + return HashBuilder().add(Args...).final(); } template -static std::string hashRangeWithBuilder(const Ts &...Args) { - return HashBuilder().addRange(Args...).final().str(); +static typename HashBuilder::template HashResultTy<> +hashRangeWithBuilder(const Ts &...Args) { + return HashBuilder().addRange(Args...).final(); } // All the test infrastructure relies on the variadic helpers. Test them first. @@ -102,7 +104,7 @@ TYPED_TEST(HashBuilderTest, AddHashableData) { auto SwappedData = llvm::support::endian::byte_swap(Data, E); Hasher.update(llvm::makeArrayRef( reinterpret_cast(&SwappedData), sizeof(Data))); - return static_cast(Hasher.final()); + return Hasher.final(); }; char C = 'c'; diff --git a/llvm/unittests/Support/MD5Test.cpp b/llvm/unittests/Support/MD5Test.cpp index 8eb4d34..83c556c 100644 --- a/llvm/unittests/Support/MD5Test.cpp +++ b/llvm/unittests/Support/MD5Test.cpp @@ -62,7 +62,7 @@ TEST(MD5HashTest, MD5) { std::array Vec = MD5::hash(Input); MD5::MD5Result MD5Res; SmallString<32> Res; - memcpy(MD5Res.Bytes.data(), Vec.data(), Vec.size()); + memcpy(MD5Res.data(), Vec.data(), Vec.size()); MD5::stringifyResult(MD5Res, Res); EXPECT_EQ(Res, "c3fcd3d76192e4007dfb496cca67e13b"); EXPECT_EQ(0x3be167ca6c49fb7dULL, MD5Res.high()); @@ -79,10 +79,7 @@ TEST(MD5Test, FinalAndResultHelpers) { ReferenceHash.update("abcd"); MD5::MD5Result ReferenceResult; ReferenceHash.final(ReferenceResult); - StringRef ExpectedResult = - StringRef(reinterpret_cast(ReferenceResult.Bytes.data()), - ReferenceResult.Bytes.size()); - EXPECT_EQ(Hash.result(), ExpectedResult); + EXPECT_EQ(Hash.result(), ReferenceResult); } Hash.update("xyz"); @@ -93,10 +90,7 @@ TEST(MD5Test, FinalAndResultHelpers) { ReferenceHash.update("xyz"); MD5::MD5Result ReferenceResult; ReferenceHash.final(ReferenceResult); - StringRef ExpectedResult = - StringRef(reinterpret_cast(ReferenceResult.Bytes.data()), - ReferenceResult.Bytes.size()); - EXPECT_EQ(Hash.final(), ExpectedResult); + EXPECT_EQ(Hash.final(), ReferenceResult); } } } // namespace diff --git a/llvm/unittests/Support/SHA256.cpp b/llvm/unittests/Support/SHA256.cpp index 82359a71..a50ce7b 100644 --- a/llvm/unittests/Support/SHA256.cpp +++ b/llvm/unittests/Support/SHA256.cpp @@ -20,7 +20,7 @@ using namespace llvm; namespace { -static std::string toHex(StringRef Input) { +static std::string toHex(ArrayRef Input) { static const char *const LUT = "0123456789abcdef"; size_t Length = Input.size(); diff --git a/llvm/unittests/Support/raw_sha1_ostream_test.cpp b/llvm/unittests/Support/raw_sha1_ostream_test.cpp index 3238d0d..a3cb6f5 100644 --- a/llvm/unittests/Support/raw_sha1_ostream_test.cpp +++ b/llvm/unittests/Support/raw_sha1_ostream_test.cpp @@ -14,7 +14,7 @@ using namespace llvm; -static std::string toHex(StringRef Input) { +static std::string toHex(ArrayRef Input) { static const char *const LUT = "0123456789ABCDEF"; size_t Length = Input.size(); @@ -39,7 +39,7 @@ TEST(raw_sha1_ostreamTest, Basic) { TEST(sha1_hash_test, Basic) { ArrayRef Input((const uint8_t *)"Hello World!", 12); std::array Vec = SHA1::hash(Input); - std::string Hash = toHex({(const char *)Vec.data(), 20}); + std::string Hash = toHex(Vec); ASSERT_EQ("2EF7BDE608CE5404E97D5F042F95F89F1C232871", Hash); } diff --git a/mlir/lib/Pass/IRPrinting.cpp b/mlir/lib/Pass/IRPrinting.cpp index 30d5a8e..c6bfa94 100644 --- a/mlir/lib/Pass/IRPrinting.cpp +++ b/mlir/lib/Pass/IRPrinting.cpp @@ -66,7 +66,7 @@ private: ArrayRef(reinterpret_cast(&data), sizeof(T))); } - SmallString<20> hash; + std::array hash; }; //===----------------------------------------------------------------------===// -- 2.7.4