From 4a6a534c0cfcdaf93c7b7b281dd8491615262bba Mon Sep 17 00:00:00 2001 From: George Rimar Date: Tue, 17 Jan 2017 13:20:17 +0000 Subject: [PATCH] [Support/Compression] - Change zlib API to return Error instead of custom status. Previously API returned custom enum values. Patch changes it to return Error with string description. That should help users to report errors in universal way. Differential revision: https://reviews.llvm.org/D28684 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@292214 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Support/Compression.h | 24 +++----- lib/MC/ELFObjectWriter.cpp | 9 +-- lib/Object/Decompressor.cpp | 5 +- lib/ProfileData/InstrProf.cpp | 17 +++--- lib/Support/Compression.cpp | 83 +++++++++++++++------------ unittests/Support/CompressionTest.cpp | 17 ++++-- 6 files changed, 83 insertions(+), 72 deletions(-) diff --git a/include/llvm/Support/Compression.h b/include/llvm/Support/Compression.h index 5bf7031fe9f..2d191abe4b1 100644 --- a/include/llvm/Support/Compression.h +++ b/include/llvm/Support/Compression.h @@ -18,6 +18,7 @@ namespace llvm { template class SmallVectorImpl; +class Error; class StringRef; namespace zlib { @@ -29,26 +30,17 @@ enum CompressionLevel { BestSizeCompression }; -enum Status { - StatusOK, - StatusUnsupported, // zlib is unavailable - StatusOutOfMemory, // there was not enough memory - StatusBufferTooShort, // there was not enough room in the output buffer - StatusInvalidArg, // invalid input parameter - StatusInvalidData // data was corrupted or incomplete -}; - bool isAvailable(); -Status compress(StringRef InputBuffer, SmallVectorImpl &CompressedBuffer, - CompressionLevel Level = DefaultCompression); +Error compress(StringRef InputBuffer, SmallVectorImpl &CompressedBuffer, + CompressionLevel Level = DefaultCompression); -Status uncompress(StringRef InputBuffer, char *UncompressedBuffer, - size_t &UncompressedSize); +Error uncompress(StringRef InputBuffer, char *UncompressedBuffer, + size_t &UncompressedSize); -Status uncompress(StringRef InputBuffer, - SmallVectorImpl &UncompressedBuffer, - size_t UncompressedSize); +Error uncompress(StringRef InputBuffer, + SmallVectorImpl &UncompressedBuffer, + size_t UncompressedSize); uint32_t crc32(StringRef Buffer); diff --git a/lib/MC/ELFObjectWriter.cpp b/lib/MC/ELFObjectWriter.cpp index a8c88dda693..0e02cdb4ca0 100644 --- a/lib/MC/ELFObjectWriter.cpp +++ b/lib/MC/ELFObjectWriter.cpp @@ -32,6 +32,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/ELF.h" #include "llvm/Support/Endian.h" +#include "llvm/Support/Error.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/StringSaver.h" #include @@ -1037,10 +1038,10 @@ void ELFObjectWriter::writeSectionData(const MCAssembler &Asm, MCSection &Sec, setStream(OldStream); SmallVector CompressedContents; - zlib::Status Success = zlib::compress( - StringRef(UncompressedData.data(), UncompressedData.size()), - CompressedContents); - if (Success != zlib::StatusOK) { + if (Error E = zlib::compress( + StringRef(UncompressedData.data(), UncompressedData.size()), + CompressedContents)) { + consumeError(std::move(E)); getStream() << UncompressedData; return; } diff --git a/lib/Object/Decompressor.cpp b/lib/Object/Decompressor.cpp index bca41fd9f48..0be602b1fc1 100644 --- a/lib/Object/Decompressor.cpp +++ b/lib/Object/Decompressor.cpp @@ -95,8 +95,5 @@ Error Decompressor::decompress(SmallString<32> &Out) { Error Decompressor::decompress(MutableArrayRef Buffer) { size_t Size = Buffer.size(); - zlib::Status Status = zlib::uncompress(SectionData, Buffer.data(), Size); - if (Status != zlib::StatusOK) - return createError("decompression failed"); - return Error::success(); + return zlib::uncompress(SectionData, Buffer.data(), Size); } diff --git a/lib/ProfileData/InstrProf.cpp b/lib/ProfileData/InstrProf.cpp index 74acd9e5e20..eb676602632 100644 --- a/lib/ProfileData/InstrProf.cpp +++ b/lib/ProfileData/InstrProf.cpp @@ -271,12 +271,12 @@ Error collectPGOFuncNameStrings(const std::vector &NameStrs, } SmallString<128> CompressedNameStrings; - zlib::Status Success = - zlib::compress(StringRef(UncompressedNameStrings), CompressedNameStrings, - zlib::BestSizeCompression); - - if (Success != zlib::StatusOK) + Error E = zlib::compress(StringRef(UncompressedNameStrings), + CompressedNameStrings, zlib::BestSizeCompression); + if (E) { + consumeError(std::move(E)); return make_error(instrprof_error::compress_failed); + } return WriteStringToResult(CompressedNameStrings.size(), CompressedNameStrings); @@ -315,9 +315,12 @@ Error readPGOFuncNameStrings(StringRef NameStrings, InstrProfSymtab &Symtab) { if (isCompressed) { StringRef CompressedNameStrings(reinterpret_cast(P), CompressedSize); - if (zlib::uncompress(CompressedNameStrings, UncompressedNameStrings, - UncompressedSize) != zlib::StatusOK) + if (Error E = + zlib::uncompress(CompressedNameStrings, UncompressedNameStrings, + UncompressedSize)) { + consumeError(std::move(E)); return make_error(instrprof_error::uncompress_failed); + } P += CompressedSize; NameStrings = StringRef(UncompressedNameStrings.data(), UncompressedNameStrings.size()); diff --git a/lib/Support/Compression.cpp b/lib/Support/Compression.cpp index 5d556462e89..c279d10f6c6 100644 --- a/lib/Support/Compression.cpp +++ b/lib/Support/Compression.cpp @@ -16,6 +16,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Config/config.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/Error.h" #include "llvm/Support/ErrorHandling.h" #if LLVM_ENABLE_ZLIB == 1 && HAVE_ZLIB_H #include @@ -24,6 +25,10 @@ using namespace llvm; #if LLVM_ENABLE_ZLIB == 1 && HAVE_LIBZ +static Error createError(StringRef Err) { + return make_error(Err, inconvertibleErrorCode()); +} + static int encodeZlibCompressionLevel(zlib::CompressionLevel Level) { switch (Level) { case zlib::NoCompression: return 0; @@ -34,53 +39,59 @@ static int encodeZlibCompressionLevel(zlib::CompressionLevel Level) { llvm_unreachable("Invalid zlib::CompressionLevel!"); } -static zlib::Status encodeZlibReturnValue(int ReturnValue) { - switch (ReturnValue) { - case Z_OK: return zlib::StatusOK; - case Z_MEM_ERROR: return zlib::StatusOutOfMemory; - case Z_BUF_ERROR: return zlib::StatusBufferTooShort; - case Z_STREAM_ERROR: return zlib::StatusInvalidArg; - case Z_DATA_ERROR: return zlib::StatusInvalidData; - default: llvm_unreachable("unknown zlib return status!"); +static StringRef convertZlibCodeToString(int Code) { + switch (Code) { + case Z_MEM_ERROR: + return "zlib error: Z_MEM_ERROR"; + case Z_BUF_ERROR: + return "zlib error: Z_BUF_ERROR"; + case Z_STREAM_ERROR: + return "zlib error: Z_STREAM_ERROR"; + case Z_DATA_ERROR: + return "zlib error: Z_DATA_ERROR"; + case Z_OK: + default: + llvm_unreachable("unknown or unexpected zlib status code"); } } bool zlib::isAvailable() { return true; } -zlib::Status zlib::compress(StringRef InputBuffer, - SmallVectorImpl &CompressedBuffer, - CompressionLevel Level) { + +Error zlib::compress(StringRef InputBuffer, + SmallVectorImpl &CompressedBuffer, + CompressionLevel Level) { unsigned long CompressedSize = ::compressBound(InputBuffer.size()); CompressedBuffer.resize(CompressedSize); int CLevel = encodeZlibCompressionLevel(Level); - Status Res = encodeZlibReturnValue(::compress2( - (Bytef *)CompressedBuffer.data(), &CompressedSize, - (const Bytef *)InputBuffer.data(), InputBuffer.size(), CLevel)); + int Res = ::compress2((Bytef *)CompressedBuffer.data(), &CompressedSize, + (const Bytef *)InputBuffer.data(), InputBuffer.size(), + CLevel); // Tell MemorySanitizer that zlib output buffer is fully initialized. // This avoids a false report when running LLVM with uninstrumented ZLib. __msan_unpoison(CompressedBuffer.data(), CompressedSize); CompressedBuffer.resize(CompressedSize); - return Res; + return Res ? createError(convertZlibCodeToString(Res)) : Error::success(); } -zlib::Status zlib::uncompress(StringRef InputBuffer, char *UncompressedBuffer, - size_t &UncompressedSize) { - Status Res = encodeZlibReturnValue( +Error zlib::uncompress(StringRef InputBuffer, char *UncompressedBuffer, + size_t &UncompressedSize) { + int Res = ::uncompress((Bytef *)UncompressedBuffer, (uLongf *)&UncompressedSize, - (const Bytef *)InputBuffer.data(), InputBuffer.size())); + (const Bytef *)InputBuffer.data(), InputBuffer.size()); // Tell MemorySanitizer that zlib output buffer is fully initialized. // This avoids a false report when running LLVM with uninstrumented ZLib. __msan_unpoison(UncompressedBuffer, UncompressedSize); - return Res; + return Res ? createError(convertZlibCodeToString(Res)) : Error::success(); } -zlib::Status zlib::uncompress(StringRef InputBuffer, - SmallVectorImpl &UncompressedBuffer, - size_t UncompressedSize) { +Error zlib::uncompress(StringRef InputBuffer, + SmallVectorImpl &UncompressedBuffer, + size_t UncompressedSize) { UncompressedBuffer.resize(UncompressedSize); - Status Res = + Error E = uncompress(InputBuffer, UncompressedBuffer.data(), UncompressedSize); UncompressedBuffer.resize(UncompressedSize); - return Res; + return E; } uint32_t zlib::crc32(StringRef Buffer) { @@ -89,19 +100,19 @@ uint32_t zlib::crc32(StringRef Buffer) { #else bool zlib::isAvailable() { return false; } -zlib::Status zlib::compress(StringRef InputBuffer, - SmallVectorImpl &CompressedBuffer, - CompressionLevel Level) { - return zlib::StatusUnsupported; +Error zlib::compress(StringRef InputBuffer, + SmallVectorImpl &CompressedBuffer, + CompressionLevel Level) { + llvm_unreachable("zlib::compress is unavailable"); } -zlib::Status zlib::uncompress(StringRef InputBuffer, char *UncompressedBuffer, - size_t &UncompressedSize) { - return zlib::StatusUnsupported; +Error zlib::uncompress(StringRef InputBuffer, char *UncompressedBuffer, + size_t &UncompressedSize) { + llvm_unreachable("zlib::uncompress is unavailable"); } -zlib::Status zlib::uncompress(StringRef InputBuffer, - SmallVectorImpl &UncompressedBuffer, - size_t UncompressedSize) { - return zlib::StatusUnsupported; +Error zlib::uncompress(StringRef InputBuffer, + SmallVectorImpl &UncompressedBuffer, + size_t UncompressedSize) { + llvm_unreachable("zlib::uncompress is unavailable"); } uint32_t zlib::crc32(StringRef Buffer) { llvm_unreachable("zlib::crc32 is unavailable"); diff --git a/unittests/Support/CompressionTest.cpp b/unittests/Support/CompressionTest.cpp index 36b84d85f22..18a6175460d 100644 --- a/unittests/Support/CompressionTest.cpp +++ b/unittests/Support/CompressionTest.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Support/Compression.h" +#include "llvm/Support/Error.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" #include "llvm/Config/config.h" @@ -26,15 +27,21 @@ namespace { void TestZlibCompression(StringRef Input, zlib::CompressionLevel Level) { SmallString<32> Compressed; SmallString<32> Uncompressed; - EXPECT_EQ(zlib::StatusOK, zlib::compress(Input, Compressed, Level)); + + Error E = zlib::compress(Input, Compressed, Level); + EXPECT_FALSE(E); + consumeError(std::move(E)); + // Check that uncompressed buffer is the same as original. - EXPECT_EQ(zlib::StatusOK, - zlib::uncompress(Compressed, Uncompressed, Input.size())); + E = zlib::uncompress(Compressed, Uncompressed, Input.size()); + EXPECT_FALSE(E); + consumeError(std::move(E)); + EXPECT_EQ(Input, Uncompressed); if (Input.size() > 0) { // Uncompression fails if expected length is too short. - EXPECT_EQ(zlib::StatusBufferTooShort, - zlib::uncompress(Compressed, Uncompressed, Input.size() - 1)); + E = zlib::uncompress(Compressed, Uncompressed, Input.size() - 1); + EXPECT_EQ("zlib error: Z_BUF_ERROR", llvm::toString(std::move(E))); } }