ckissane updated this revision to Diff 449346.
ckissane added a comment.

- feat compression "enum" with methods


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D130516/new/

https://reviews.llvm.org/D130516

Files:
  clang-tools-extra/clangd/index/Serialization.cpp
  clang-tools-extra/clangd/unittests/SerializationTests.cpp
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/lib/Serialization/ASTReader.cpp
  clang/lib/Serialization/ASTWriter.cpp
  lld/ELF/Driver.cpp
  lld/ELF/InputSection.cpp
  llvm/include/llvm/Object/Decompressor.h
  llvm/include/llvm/ProfileData/InstrProf.h
  llvm/include/llvm/Support/Compression.h
  llvm/lib/MC/ELFObjectWriter.cpp
  llvm/lib/ObjCopy/ELF/ELFObject.cpp
  llvm/lib/Object/Decompressor.cpp
  llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp
  llvm/lib/ProfileData/Coverage/CoverageMappingWriter.cpp
  llvm/lib/ProfileData/InstrProf.cpp
  llvm/lib/ProfileData/InstrProfCorrelator.cpp
  llvm/lib/ProfileData/SampleProfReader.cpp
  llvm/lib/ProfileData/SampleProfWriter.cpp
  llvm/lib/Support/Compression.cpp
  llvm/tools/llvm-mc/llvm-mc.cpp
  llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
  llvm/unittests/ProfileData/InstrProfTest.cpp
  llvm/unittests/Support/CompressionTest.cpp

Index: llvm/unittests/Support/CompressionTest.cpp
===================================================================
--- llvm/unittests/Support/CompressionTest.cpp
+++ llvm/unittests/Support/CompressionTest.cpp
@@ -22,31 +22,41 @@
 
 namespace {
 
-#if LLVM_ENABLE_ZLIB
-static void testZlibCompression(StringRef Input, int Level) {
+static void testCompressionAlgorithm(
+    StringRef Input, int Level, compression::CompressionKind CompressionScheme,
+    std::string ExpectedDestinationBufferTooSmallErrorMessage) {
   SmallVector<uint8_t, 0> Compressed;
   SmallVector<uint8_t, 0> Uncompressed;
-  zlib::compress(arrayRefFromStringRef(Input), Compressed, Level);
+  CompressionScheme->compress(arrayRefFromStringRef(Input), Compressed, Level);
 
   // Check that uncompressed buffer is the same as original.
-  Error E = zlib::uncompress(Compressed, Uncompressed, Input.size());
+  Error E =
+      CompressionScheme->decompress(Compressed, Uncompressed, Input.size());
   consumeError(std::move(E));
 
   EXPECT_EQ(Input, toStringRef(Uncompressed));
   if (Input.size() > 0) {
     // Uncompression fails if expected length is too short.
-    E = zlib::uncompress(Compressed, Uncompressed, Input.size() - 1);
-    EXPECT_EQ("zlib error: Z_BUF_ERROR", llvm::toString(std::move(E)));
+    E = CompressionScheme->decompress(Compressed, Uncompressed,
+                                      Input.size() - 1);
+    EXPECT_EQ(ExpectedDestinationBufferTooSmallErrorMessage,
+              llvm::toString(std::move(E)));
   }
 }
 
+#if LLVM_ENABLE_ZLIB
+static void testZlibCompression(StringRef Input, int Level) {
+  testCompressionAlgorithm(Input, Level, CompressionKind::Zlib,
+                           "zlib error: Z_BUF_ERROR");
+}
+
 TEST(CompressionTest, Zlib) {
-  testZlibCompression("", zlib::DefaultCompression);
+  compression::CompressionKind CompressionScheme = CompressionKind::Zlib;
+  testZlibCompression("", CompressionScheme->getDefaultLevel());
 
-  testZlibCompression("hello, world!", zlib::NoCompression);
-  testZlibCompression("hello, world!", zlib::BestSizeCompression);
-  testZlibCompression("hello, world!", zlib::BestSpeedCompression);
-  testZlibCompression("hello, world!", zlib::DefaultCompression);
+  testZlibCompression("hello, world!", CompressionScheme->getBestSizeLevel());
+  testZlibCompression("hello, world!", CompressionScheme->getBestSpeedLevel());
+  testZlibCompression("hello, world!", CompressionScheme->getDefaultLevel());
 
   const size_t kSize = 1024;
   char BinaryData[kSize];
@@ -54,38 +64,26 @@
     BinaryData[i] = i & 255;
   StringRef BinaryDataStr(BinaryData, kSize);
 
-  testZlibCompression(BinaryDataStr, zlib::NoCompression);
-  testZlibCompression(BinaryDataStr, zlib::BestSizeCompression);
-  testZlibCompression(BinaryDataStr, zlib::BestSpeedCompression);
-  testZlibCompression(BinaryDataStr, zlib::DefaultCompression);
+  testZlibCompression(BinaryDataStr, CompressionScheme->getBestSizeLevel());
+  testZlibCompression(BinaryDataStr, CompressionScheme->getBestSpeedLevel());
+  testZlibCompression(BinaryDataStr, CompressionScheme->getDefaultLevel());
 }
 #endif
 
 #if LLVM_ENABLE_ZSTD
-static void testZstdCompression(StringRef Input, int Level) {
-  SmallVector<uint8_t, 0> Compressed;
-  SmallVector<uint8_t, 0> Uncompressed;
-  zstd::compress(arrayRefFromStringRef(Input), Compressed, Level);
 
-  // Check that uncompressed buffer is the same as original.
-  Error E = zstd::uncompress(Compressed, Uncompressed, Input.size());
-  consumeError(std::move(E));
-
-  EXPECT_EQ(Input, toStringRef(Uncompressed));
-  if (Input.size() > 0) {
-    // Uncompression fails if expected length is too short.
-    E = zstd::uncompress(Compressed, Uncompressed, Input.size() - 1);
-    EXPECT_EQ("Destination buffer is too small", llvm::toString(std::move(E)));
-  }
+static void testZStdCompression(StringRef Input, int Level) {
+  testCompressionAlgorithm(Input, Level, CompressionKind::ZStd,
+                           "Destination buffer is too small");
 }
 
 TEST(CompressionTest, Zstd) {
-  testZstdCompression("", zstd::DefaultCompression);
+  compression::CompressionKind CompressionScheme = CompressionKind::ZStd;
+  testZStdCompression("", CompressionScheme->getDefaultLevel());
 
-  testZstdCompression("hello, world!", zstd::NoCompression);
-  testZstdCompression("hello, world!", zstd::BestSizeCompression);
-  testZstdCompression("hello, world!", zstd::BestSpeedCompression);
-  testZstdCompression("hello, world!", zstd::DefaultCompression);
+  testZStdCompression("hello, world!", CompressionScheme->getBestSizeLevel());
+  testZStdCompression("hello, world!", CompressionScheme->getBestSpeedLevel());
+  testZStdCompression("hello, world!", CompressionScheme->getDefaultLevel());
 
   const size_t kSize = 1024;
   char BinaryData[kSize];
@@ -93,10 +91,9 @@
     BinaryData[i] = i & 255;
   StringRef BinaryDataStr(BinaryData, kSize);
 
-  testZstdCompression(BinaryDataStr, zstd::NoCompression);
-  testZstdCompression(BinaryDataStr, zstd::BestSizeCompression);
-  testZstdCompression(BinaryDataStr, zstd::BestSpeedCompression);
-  testZstdCompression(BinaryDataStr, zstd::DefaultCompression);
+  testZStdCompression(BinaryDataStr, CompressionScheme->getBestSizeLevel());
+  testZStdCompression(BinaryDataStr, CompressionScheme->getBestSpeedLevel());
+  testZStdCompression(BinaryDataStr, CompressionScheme->getDefaultLevel());
 }
 #endif
 }
Index: llvm/unittests/ProfileData/InstrProfTest.cpp
===================================================================
--- llvm/unittests/ProfileData/InstrProfTest.cpp
+++ llvm/unittests/ProfileData/InstrProfTest.cpp
@@ -6,6 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "llvm/ADT/Optional.h"
 #include "llvm/IR/Function.h"
 #include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/LLVMContext.h"
@@ -1146,19 +1147,23 @@
   for (bool DoCompression : {false, true}) {
     // Compressing:
     std::string FuncNameStrings1;
-    EXPECT_THAT_ERROR(collectPGOFuncNameStrings(
-                          FuncNames1,
-                          (DoCompression && compression::zlib::isAvailable()),
-                          FuncNameStrings1),
-                      Succeeded());
+    EXPECT_THAT_ERROR(
+        collectPGOFuncNameStrings(
+            FuncNames1,
+            (compression::CompressionKind::Zlib && DoCompression) ||
+                llvm::NoneType(),
+            FuncNameStrings1),
+        Succeeded());
 
     // Compressing:
     std::string FuncNameStrings2;
-    EXPECT_THAT_ERROR(collectPGOFuncNameStrings(
-                          FuncNames2,
-                          (DoCompression && compression::zlib::isAvailable()),
-                          FuncNameStrings2),
-                      Succeeded());
+    EXPECT_THAT_ERROR(
+        collectPGOFuncNameStrings(
+            FuncNames2,
+            (compression::CompressionKind::Zlib && DoCompression) ||
+                llvm::NoneType(),
+            FuncNameStrings2),
+        Succeeded());
 
     for (int Padding = 0; Padding < 2; Padding++) {
       // Join with paddings :
Index: llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
===================================================================
--- llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
+++ llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
@@ -728,10 +728,16 @@
           errc::invalid_argument,
           "invalid or unsupported --compress-debug-sections format: %s",
           A->getValue());
-    if (!compression::zlib::isAvailable())
-      return createStringError(
-          errc::invalid_argument,
-          "LLVM was not compiled with LLVM_ENABLE_ZLIB: can not compress");
+    switch (Config.CompressionType) {
+    case DebugCompressionType::None:
+      break;
+    case DebugCompressionType::Z:
+      if (!compression::CompressionKind::Zlib)
+        return createStringError(
+            errc::invalid_argument,
+            "LLVM was not compiled with LLVM_ENABLE_ZLIB: can not compress");
+      break;
+    }
   }
 
   Config.AddGnuDebugLink = InputArgs.getLastArgValue(OBJCOPY_add_gnu_debuglink);
@@ -993,7 +999,7 @@
         "--decompress-debug-sections");
   }
 
-  if (Config.DecompressDebugSections && !compression::zlib::isAvailable())
+  if (Config.DecompressDebugSections && !compression::CompressionKind::Zlib)
     return createStringError(
         errc::invalid_argument,
         "LLVM was not compiled with LLVM_ENABLE_ZLIB: cannot decompress");
Index: llvm/tools/llvm-mc/llvm-mc.cpp
===================================================================
--- llvm/tools/llvm-mc/llvm-mc.cpp
+++ llvm/tools/llvm-mc/llvm-mc.cpp
@@ -401,7 +401,7 @@
   MAI->setRelaxELFRelocations(RelaxELFRel);
 
   if (CompressDebugSections != DebugCompressionType::None) {
-    if (!compression::zlib::isAvailable()) {
+    if (!compression::CompressionKind::Zlib) {
       WithColor::error(errs(), ProgName)
           << "build tools with zlib to enable -compress-debug-sections";
       return 1;
Index: llvm/lib/Support/Compression.cpp
===================================================================
--- llvm/lib/Support/Compression.cpp
+++ llvm/lib/Support/Compression.cpp
@@ -27,6 +27,52 @@
 using namespace llvm;
 using namespace llvm::compression;
 
+CompressionAlgorithm *CompressionKind::operator->() const {
+  switch (uint8_t(x)) {
+  case uint8_t(CompressionKind::Zlib):
+    static llvm::compression::ZlibCompressionAlgorithm ZlibI;
+    return &ZlibI;
+  case uint8_t(CompressionKind::ZStd):
+    static llvm::compression::ZStdCompressionAlgorithm ZStdI;
+    return &ZStdI;
+  default:
+    static llvm::compression::UnknownCompressionAlgorithm UnknownI;
+    return &UnknownI;
+  }
+}
+
+bool llvm::compression::CompressionKind::operator==(
+    llvm::compression::CompressionKind other) const {
+  return x == uint8_t(other);
+}
+
+constexpr CompressionKind UnknownCompressionAlgorithm::AlgorithmId;
+constexpr StringRef UnknownCompressionAlgorithm::Name;
+constexpr int UnknownCompressionAlgorithm::BestSpeedCompression;
+constexpr int UnknownCompressionAlgorithm::DefaultCompression;
+constexpr int UnknownCompressionAlgorithm::BestSizeCompression;
+
+bool UnknownCompressionAlgorithm::Supported() { return false; };
+
+void UnknownCompressionAlgorithm::Compress(
+    ArrayRef<uint8_t> Input, SmallVectorImpl<uint8_t> &CompressedBuffer,
+    int Level) {
+  llvm_unreachable("method:\"compress\" is unsupported for compression "
+                   "algorithm:\"unknown\", reason:\"can't call on unknown\"");
+};
+Error UnknownCompressionAlgorithm::Decompress(ArrayRef<uint8_t> Input,
+                                              uint8_t *UncompressedBuffer,
+                                              size_t &UncompressedSize) {
+  llvm_unreachable("method:\"decompress\" is unsupported for compression "
+                   "algorithm:\"unknown\", reason:\"can't call on unknown\"");
+}
+
+constexpr CompressionKind ZlibCompressionAlgorithm::AlgorithmId;
+constexpr StringRef ZlibCompressionAlgorithm::Name;
+constexpr int ZlibCompressionAlgorithm::BestSpeedCompression;
+constexpr int ZlibCompressionAlgorithm::DefaultCompression;
+constexpr int ZlibCompressionAlgorithm::BestSizeCompression;
+
 #if LLVM_ENABLE_ZLIB
 
 static StringRef convertZlibCodeToString(int Code) {
@@ -45,10 +91,11 @@
   }
 }
 
-bool zlib::isAvailable() { return true; }
+bool ZlibCompressionAlgorithm::Supported() { return true; };
 
-void zlib::compress(ArrayRef<uint8_t> Input,
-                    SmallVectorImpl<uint8_t> &CompressedBuffer, int Level) {
+void ZlibCompressionAlgorithm::Compress(
+    ArrayRef<uint8_t> Input, SmallVectorImpl<uint8_t> &CompressedBuffer,
+    int Level) {
   unsigned long CompressedSize = ::compressBound(Input.size());
   CompressedBuffer.resize_for_overwrite(CompressedSize);
   int Res = ::compress2((Bytef *)CompressedBuffer.data(), &CompressedSize,
@@ -61,10 +108,10 @@
   __msan_unpoison(CompressedBuffer.data(), CompressedSize);
   if (CompressedSize < CompressedBuffer.size())
     CompressedBuffer.truncate(CompressedSize);
-}
-
-Error zlib::uncompress(ArrayRef<uint8_t> Input, uint8_t *UncompressedBuffer,
-                       size_t &UncompressedSize) {
+};
+Error ZlibCompressionAlgorithm::Decompress(ArrayRef<uint8_t> Input,
+                                           uint8_t *UncompressedBuffer,
+                                           size_t &UncompressedSize) {
   int Res =
       ::uncompress((Bytef *)UncompressedBuffer, (uLongf *)&UncompressedSize,
                    (const Bytef *)Input.data(), Input.size());
@@ -74,42 +121,41 @@
   return Res ? make_error<StringError>(convertZlibCodeToString(Res),
                                        inconvertibleErrorCode())
              : Error::success();
-}
-
-Error zlib::uncompress(ArrayRef<uint8_t> Input,
-                       SmallVectorImpl<uint8_t> &UncompressedBuffer,
-                       size_t UncompressedSize) {
-  UncompressedBuffer.resize_for_overwrite(UncompressedSize);
-  Error E =
-      zlib::uncompress(Input, UncompressedBuffer.data(), UncompressedSize);
-  if (UncompressedSize < UncompressedBuffer.size())
-    UncompressedBuffer.truncate(UncompressedSize);
-  return E;
-}
+};
 
 #else
-bool zlib::isAvailable() { return false; }
-void zlib::compress(ArrayRef<uint8_t> Input,
-                    SmallVectorImpl<uint8_t> &CompressedBuffer, int Level) {
-  llvm_unreachable("zlib::compress is unavailable");
-}
-Error zlib::uncompress(ArrayRef<uint8_t> Input, uint8_t *UncompressedBuffer,
-                       size_t &UncompressedSize) {
-  llvm_unreachable("zlib::uncompress is unavailable");
-}
-Error zlib::uncompress(ArrayRef<uint8_t> Input,
-                       SmallVectorImpl<uint8_t> &UncompressedBuffer,
-                       size_t UncompressedSize) {
-  llvm_unreachable("zlib::uncompress is unavailable");
-}
+bool ZlibCompressionAlgorithm::Supported() { return false; };
+
+void ZlibCompressionAlgorithm::Compress(
+    ArrayRef<uint8_t> Input, SmallVectorImpl<uint8_t> &CompressedBuffer,
+    int Level) {
+  llvm_unreachable(
+      "method:\"compress\" is unsupported for compression algorithm:\"zlib\", "
+      "reason:\"llvm not compiled with zlib support\"");
+};
+Error ZlibCompressionAlgorithm::Decompress(ArrayRef<uint8_t> Input,
+                                           uint8_t *UncompressedBuffer,
+                                           size_t &UncompressedSize) {
+  llvm_unreachable(
+      "method:\"decompress\" is unsupported for compression "
+      "algorithm:\"zlib\", reason:\"llvm not compiled with zlib support\"");
+};
+
 #endif
 
+constexpr CompressionKind ZStdCompressionAlgorithm::AlgorithmId;
+constexpr StringRef ZStdCompressionAlgorithm::Name;
+constexpr int ZStdCompressionAlgorithm::BestSpeedCompression;
+constexpr int ZStdCompressionAlgorithm::DefaultCompression;
+constexpr int ZStdCompressionAlgorithm::BestSizeCompression;
+
 #if LLVM_ENABLE_ZSTD
 
-bool zstd::isAvailable() { return true; }
+bool ZStdCompressionAlgorithm::Supported() { return true; };
 
-void zstd::compress(ArrayRef<uint8_t> Input,
-                    SmallVectorImpl<uint8_t> &CompressedBuffer, int Level) {
+void ZStdCompressionAlgorithm::Compress(
+    ArrayRef<uint8_t> Input, SmallVectorImpl<uint8_t> &CompressedBuffer,
+    int Level) {
   unsigned long CompressedBufferSize = ::ZSTD_compressBound(Input.size());
   CompressedBuffer.resize_for_overwrite(CompressedBufferSize);
   unsigned long CompressedSize =
@@ -122,10 +168,10 @@
   __msan_unpoison(CompressedBuffer.data(), CompressedSize);
   if (CompressedSize < CompressedBuffer.size())
     CompressedBuffer.truncate(CompressedSize);
-}
-
-Error zstd::uncompress(ArrayRef<uint8_t> Input, uint8_t *UncompressedBuffer,
-                       size_t &UncompressedSize) {
+};
+Error ZStdCompressionAlgorithm::Decompress(ArrayRef<uint8_t> Input,
+                                           uint8_t *UncompressedBuffer,
+                                           size_t &UncompressedSize) {
   const size_t Res =
       ::ZSTD_decompress(UncompressedBuffer, UncompressedSize,
                         (const uint8_t *)Input.data(), Input.size());
@@ -136,32 +182,24 @@
   return ZSTD_isError(Res) ? make_error<StringError>(ZSTD_getErrorName(Res),
                                                      inconvertibleErrorCode())
                            : Error::success();
-}
-
-Error zstd::uncompress(ArrayRef<uint8_t> Input,
-                       SmallVectorImpl<uint8_t> &UncompressedBuffer,
-                       size_t UncompressedSize) {
-  UncompressedBuffer.resize_for_overwrite(UncompressedSize);
-  Error E =
-      zstd::uncompress(Input, UncompressedBuffer.data(), UncompressedSize);
-  if (UncompressedSize < UncompressedBuffer.size())
-    UncompressedBuffer.truncate(UncompressedSize);
-  return E;
-}
+};
 
 #else
-bool zstd::isAvailable() { return false; }
-void zstd::compress(ArrayRef<uint8_t> Input,
-                    SmallVectorImpl<uint8_t> &CompressedBuffer, int Level) {
-  llvm_unreachable("zstd::compress is unavailable");
-}
-Error zstd::uncompress(ArrayRef<uint8_t> Input, uint8_t *UncompressedBuffer,
-                       size_t &UncompressedSize) {
-  llvm_unreachable("zstd::uncompress is unavailable");
-}
-Error zstd::uncompress(ArrayRef<uint8_t> Input,
-                       SmallVectorImpl<uint8_t> &UncompressedBuffer,
-                       size_t UncompressedSize) {
-  llvm_unreachable("zstd::uncompress is unavailable");
-}
+bool ZStdCompressionAlgorithm::Supported() { return false; };
+
+void ZStdCompressionAlgorithm::Compress(
+    ArrayRef<uint8_t> Input, SmallVectorImpl<uint8_t> &CompressedBuffer,
+    int Level) {
+  llvm_unreachable(
+      "method:\"compress\" is unsupported for compression algorithm:\"zstd\", "
+      "reason:\"llvm not compiled with zstd support\"");
+};
+Error ZStdCompressionAlgorithm::Decompress(ArrayRef<uint8_t> Input,
+                                           uint8_t *UncompressedBuffer,
+                                           size_t &UncompressedSize) {
+  llvm_unreachable(
+      "method:\"decompress\" is unsupported for compression "
+      "algorithm:\"zstd\", reason:\"llvm not compiled with zstd support\"");
+};
+
 #endif
Index: llvm/lib/ProfileData/SampleProfWriter.cpp
===================================================================
--- llvm/lib/ProfileData/SampleProfWriter.cpp
+++ llvm/lib/ProfileData/SampleProfWriter.cpp
@@ -78,7 +78,9 @@
 }
 
 std::error_code SampleProfileWriterExtBinaryBase::compressAndOutput() {
-  if (!llvm::compression::zlib::isAvailable())
+  compression::CompressionKind CompressionScheme =
+      compression::CompressionKind::Zlib;
+  if (!CompressionScheme)
     return sampleprof_error::zlib_unavailable;
   std::string &UncompressedStrings =
       static_cast<raw_string_ostream *>(LocalBufStream.get())->str();
@@ -86,9 +88,9 @@
     return sampleprof_error::success;
   auto &OS = *OutputStream;
   SmallVector<uint8_t, 128> CompressedStrings;
-  compression::zlib::compress(arrayRefFromStringRef(UncompressedStrings),
+  CompressionScheme->compress(arrayRefFromStringRef(UncompressedStrings),
                               CompressedStrings,
-                              compression::zlib::BestSizeCompression);
+                              CompressionScheme->getBestSizeLevel());
   encodeULEB128(UncompressedStrings.size(), OS);
   encodeULEB128(CompressedStrings.size(), OS);
   OS << toStringRef(CompressedStrings);
Index: llvm/lib/ProfileData/SampleProfReader.cpp
===================================================================
--- llvm/lib/ProfileData/SampleProfReader.cpp
+++ llvm/lib/ProfileData/SampleProfReader.cpp
@@ -877,12 +877,12 @@
   if (std::error_code EC = CompressSize.getError())
     return EC;
 
-  if (!llvm::compression::zlib::isAvailable())
+  if (!llvm::compression::CompressionKind::Zlib)
     return sampleprof_error::zlib_unavailable;
 
   uint8_t *Buffer = Allocator.Allocate<uint8_t>(DecompressBufSize);
   size_t UCSize = DecompressBufSize;
-  llvm::Error E = compression::zlib::uncompress(
+  llvm::Error E = compression::CompressionKind::Zlib->decompress(
       makeArrayRef(Data, *CompressSize), Buffer, UCSize);
   if (E)
     return sampleprof_error::uncompress_failed;
Index: llvm/lib/ProfileData/InstrProfCorrelator.cpp
===================================================================
--- llvm/lib/ProfileData/InstrProfCorrelator.cpp
+++ llvm/lib/ProfileData/InstrProfCorrelator.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/ProfileData/InstrProfCorrelator.h"
+#include "llvm/ADT/Optional.h"
 #include "llvm/DebugInfo/DIContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFDie.h"
@@ -15,6 +16,7 @@
 #include "llvm/DebugInfo/DWARF/DWARFLocationExpression.h"
 #include "llvm/DebugInfo/DWARF/DWARFUnit.h"
 #include "llvm/Object/MachO.h"
+#include "llvm/Support/Compression.h"
 #include "llvm/Support/Debug.h"
 
 #define DEBUG_TYPE "correlator"
@@ -149,7 +151,8 @@
         instrprof_error::unable_to_correlate_profile,
         "could not find any profile metadata in debug info");
   auto Result =
-      collectPGOFuncNameStrings(NamesVec, /*doCompression=*/false, Names);
+      collectPGOFuncNameStrings(NamesVec,
+                                /*CompressionScheme=*/llvm::NoneType(), Names);
   CounterOffsets.clear();
   NamesVec.clear();
   return Result;
Index: llvm/lib/ProfileData/InstrProf.cpp
===================================================================
--- llvm/lib/ProfileData/InstrProf.cpp
+++ llvm/lib/ProfileData/InstrProf.cpp
@@ -435,8 +435,10 @@
   return 0;
 }
 
-Error collectPGOFuncNameStrings(ArrayRef<std::string> NameStrs,
-                                bool doCompression, std::string &Result) {
+Error collectPGOFuncNameStrings(
+    ArrayRef<std::string> NameStrs,
+    compression::OptionalCompressionKind OptionalCompressionScheme,
+    std::string &Result) {
   assert(!NameStrs.empty() && "No name data to emit");
 
   uint8_t Header[16], *P = Header;
@@ -460,14 +462,13 @@
     return Error::success();
   };
 
-  if (!doCompression) {
+  if ((!OptionalCompressionScheme) || (!(*OptionalCompressionScheme)))
     return WriteStringToResult(0, UncompressedNameStrings);
-  }
-
+  compression::CompressionKind CompressionScheme = *OptionalCompressionScheme;
   SmallVector<uint8_t, 128> CompressedNameStrings;
-  compression::zlib::compress(arrayRefFromStringRef(UncompressedNameStrings),
+  CompressionScheme->compress(arrayRefFromStringRef(UncompressedNameStrings),
                               CompressedNameStrings,
-                              compression::zlib::BestSizeCompression);
+                              CompressionScheme->getBestSizeLevel());
 
   return WriteStringToResult(CompressedNameStrings.size(),
                              toStringRef(CompressedNameStrings));
@@ -486,8 +487,12 @@
   for (auto *NameVar : NameVars) {
     NameStrs.push_back(std::string(getPGOFuncNameVarInitializer(NameVar)));
   }
+  compression::OptionalCompressionKind OptionalCompressionScheme =
+      compression::CompressionKind::Zlib;
   return collectPGOFuncNameStrings(
-      NameStrs, compression::zlib::isAvailable() && doCompression, Result);
+      NameStrs,
+      (OptionalCompressionScheme && (doCompression)) || llvm::NoneType(),
+      Result);
 }
 
 Error readPGOFuncNameStrings(StringRef NameStrings, InstrProfSymtab &Symtab) {
@@ -503,10 +508,12 @@
     SmallVector<uint8_t, 128> UncompressedNameStrings;
     StringRef NameStrings;
     if (isCompressed) {
-      if (!llvm::compression::zlib::isAvailable())
+      compression::CompressionKind CompressionScheme =
+          compression::CompressionKind::Zlib;
+      if (!CompressionScheme)
         return make_error<InstrProfError>(instrprof_error::zlib_unavailable);
 
-      if (Error E = compression::zlib::uncompress(
+      if (Error E = CompressionScheme->decompress(
               makeArrayRef(P, CompressedSize), UncompressedNameStrings,
               UncompressedSize)) {
         consumeError(std::move(E));
Index: llvm/lib/ProfileData/Coverage/CoverageMappingWriter.cpp
===================================================================
--- llvm/lib/ProfileData/Coverage/CoverageMappingWriter.cpp
+++ llvm/lib/ProfileData/Coverage/CoverageMappingWriter.cpp
@@ -11,10 +11,11 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "llvm/ProfileData/InstrProf.h"
 #include "llvm/ProfileData/Coverage/CoverageMappingWriter.h"
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/Optional.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ProfileData/InstrProf.h"
 #include "llvm/Support/Compression.h"
 #include "llvm/Support/LEB128.h"
 #include "llvm/Support/raw_ostream.h"
@@ -47,12 +48,20 @@
   }
 
   SmallVector<uint8_t, 128> CompressedStr;
-  bool doCompression = Compress && compression::zlib::isAvailable() &&
-                       DoInstrProfNameCompression;
-  if (doCompression)
-    compression::zlib::compress(arrayRefFromStringRef(FilenamesStr),
+  compression::OptionalCompressionKind OptionalCompressionScheme =
+      compression::CompressionKind::Zlib;
+
+  OptionalCompressionScheme =
+      (OptionalCompressionScheme && (Compress && DoInstrProfNameCompression)) ||
+      llvm::NoneType();
+  bool doCompression = bool(OptionalCompressionScheme);
+
+  if (doCompression) {
+    compression::CompressionKind CompressionScheme = *OptionalCompressionScheme;
+    CompressionScheme->compress(arrayRefFromStringRef(FilenamesStr),
                                 CompressedStr,
-                                compression::zlib::BestSizeCompression);
+                                CompressionScheme->getBestSizeLevel());
+  }
 
   // ::= <num-filenames>
   //     <uncompressed-len>
Index: llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp
===================================================================
--- llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp
+++ llvm/lib/ProfileData/Coverage/CoverageMappingReader.cpp
@@ -119,7 +119,7 @@
     return Err;
 
   if (CompressedLen > 0) {
-    if (!compression::zlib::isAvailable())
+    if (!compression::CompressionKind::Zlib)
       return make_error<CoverageMapError>(
           coveragemap_error::decompression_failed);
 
@@ -129,7 +129,7 @@
     // Read compressed filenames.
     StringRef CompressedFilenames = Data.substr(0, CompressedLen);
     Data = Data.substr(CompressedLen);
-    auto Err = compression::zlib::uncompress(
+    auto Err = compression::CompressionKind::Zlib->decompress(
         arrayRefFromStringRef(CompressedFilenames), StorageBuf,
         UncompressedLen);
     if (Err) {
Index: llvm/lib/Object/Decompressor.cpp
===================================================================
--- llvm/lib/Object/Decompressor.cpp
+++ llvm/lib/Object/Decompressor.cpp
@@ -19,11 +19,9 @@
 
 Expected<Decompressor> Decompressor::create(StringRef Name, StringRef Data,
                                             bool IsLE, bool Is64Bit) {
-  if (!compression::zlib::isAvailable())
-    return createError("zlib is not available");
 
   Decompressor D(Data);
-  if (Error Err = D.consumeCompressedZLibHeader(Is64Bit, IsLE))
+  if (Error Err = D.consumeCompressedSectionHeader(Is64Bit, IsLE))
     return std::move(Err);
   return D;
 }
@@ -31,8 +29,8 @@
 Decompressor::Decompressor(StringRef Data)
     : SectionData(Data), DecompressedSize(0) {}
 
-Error Decompressor::consumeCompressedZLibHeader(bool Is64Bit,
-                                                bool IsLittleEndian) {
+Error Decompressor::consumeCompressedSectionHeader(bool Is64Bit,
+                                                   bool IsLittleEndian) {
   using namespace ELF;
   uint64_t HdrSize = Is64Bit ? sizeof(Elf64_Chdr) : sizeof(Elf32_Chdr);
   if (SectionData.size() < HdrSize)
@@ -40,10 +38,15 @@
 
   DataExtractor Extractor(SectionData, IsLittleEndian, 0);
   uint64_t Offset = 0;
-  if (Extractor.getUnsigned(&Offset, Is64Bit ? sizeof(Elf64_Word)
-                                             : sizeof(Elf32_Word)) !=
-      ELFCOMPRESS_ZLIB)
+  uint64_t ELFCompressionSchemeId = Extractor.getUnsigned(
+      &Offset, Is64Bit ? sizeof(Elf64_Word) : sizeof(Elf32_Word));
+  if (ELFCompressionSchemeId == ELFCOMPRESS_ZLIB) {
+    CompressionScheme = compression::CompressionKind::Zlib;
+  } else {
     return createError("unsupported compression type");
+  }
+  if (!CompressionScheme)
+    return createError(CompressionScheme->getName() + " is not available");
 
   // Skip Elf64_Chdr::ch_reserved field.
   if (Is64Bit)
@@ -57,6 +60,6 @@
 
 Error Decompressor::decompress(MutableArrayRef<uint8_t> Buffer) {
   size_t Size = Buffer.size();
-  return compression::zlib::uncompress(arrayRefFromStringRef(SectionData),
+  return CompressionScheme->decompress(arrayRefFromStringRef(SectionData),
                                        Buffer.data(), Size);
 }
Index: llvm/lib/ObjCopy/ELF/ELFObject.cpp
===================================================================
--- llvm/lib/ObjCopy/ELF/ELFObject.cpp
+++ llvm/lib/ObjCopy/ELF/ELFObject.cpp
@@ -439,10 +439,25 @@
   ArrayRef<uint8_t> Compressed =
       Sec.OriginalData.slice(sizeof(Elf_Chdr_Impl<ELFT>));
   SmallVector<uint8_t, 128> DecompressedContent;
-  if (Error Err = compression::zlib::uncompress(Compressed, DecompressedContent,
-                                                static_cast<size_t>(Sec.Size)))
-    return createStringError(errc::invalid_argument,
-                             "'" + Sec.Name + "': " + toString(std::move(Err)));
+  DebugCompressionType CompressionType =
+      reinterpret_cast<const Elf_Chdr_Impl<ELFT> *>(Sec.OriginalData.data())
+                  ->ch_type == ELF::ELFCOMPRESS_ZLIB
+          ? DebugCompressionType::Z
+          : DebugCompressionType::None;
+
+  switch (CompressionType) {
+  case DebugCompressionType::Z:
+    if (Error Err1 = compression::CompressionKind::Zlib->decompress(
+            Compressed, DecompressedContent, static_cast<size_t>(Sec.Size))) {
+      return createStringError(errc::invalid_argument,
+                               "'" + Sec.Name +
+                                   "': " + toString(std::move(Err1)));
+    }
+    break;
+  case DebugCompressionType::None:
+    llvm_unreachable("unexpected DebugCompressionType::None");
+    break;
+  }
 
   uint8_t *Buf = reinterpret_cast<uint8_t *>(Out.getBufferStart()) + Sec.Offset;
   std::copy(DecompressedContent.begin(), DecompressedContent.end(), Buf);
@@ -512,7 +527,13 @@
                                      DebugCompressionType CompressionType)
     : SectionBase(Sec), CompressionType(CompressionType),
       DecompressedSize(Sec.OriginalData.size()), DecompressedAlign(Sec.Align) {
-  compression::zlib::compress(OriginalData, CompressedData);
+  switch (CompressionType) {
+  case DebugCompressionType::Z:
+    compression::CompressionKind::Zlib->compress(OriginalData, CompressedData);
+    break;
+  case DebugCompressionType::None:
+    break;
+  }
 
   assert(CompressionType != DebugCompressionType::None);
   Flags |= ELF::SHF_COMPRESSED;
Index: llvm/lib/MC/ELFObjectWriter.cpp
===================================================================
--- llvm/lib/MC/ELFObjectWriter.cpp
+++ llvm/lib/MC/ELFObjectWriter.cpp
@@ -847,15 +847,14 @@
 
   auto &MC = Asm.getContext();
   const auto &MAI = MC.getAsmInfo();
-
-  bool CompressionEnabled =
-      MAI->compressDebugSections() != DebugCompressionType::None;
+  const DebugCompressionType CompressionType = MAI->compressDebugSections();
+  bool CompressionEnabled = CompressionType != DebugCompressionType::None;
   if (!CompressionEnabled || !SectionName.startswith(".debug_")) {
     Asm.writeSectionData(W.OS, &Section, Layout);
     return;
   }
 
-  assert(MAI->compressDebugSections() == DebugCompressionType::Z &&
+  assert(CompressionType == DebugCompressionType::Z &&
          "expected zlib style compression");
 
   SmallVector<char, 128> UncompressedData;
@@ -864,7 +863,7 @@
 
   SmallVector<uint8_t, 128> Compressed;
   const uint32_t ChType = ELF::ELFCOMPRESS_ZLIB;
-  compression::zlib::compress(
+  compression::CompressionKind::Zlib->compress(
       makeArrayRef(reinterpret_cast<uint8_t *>(UncompressedData.data()),
                    UncompressedData.size()),
       Compressed);
Index: llvm/include/llvm/Support/Compression.h
===================================================================
--- llvm/include/llvm/Support/Compression.h
+++ llvm/include/llvm/Support/Compression.h
@@ -14,56 +14,236 @@
 #define LLVM_SUPPORT_COMPRESSION_H
 
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/Optional.h"
 #include "llvm/Support/DataTypes.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/ErrorHandling.h"
 
 namespace llvm {
 template <typename T> class SmallVectorImpl;
 class Error;
 
 namespace compression {
-namespace zlib {
 
-constexpr int NoCompression = 0;
-constexpr int BestSpeedCompression = 1;
-constexpr int DefaultCompression = 6;
-constexpr int BestSizeCompression = 9;
-
-bool isAvailable();
-
-void compress(ArrayRef<uint8_t> Input,
-              SmallVectorImpl<uint8_t> &CompressedBuffer,
-              int Level = DefaultCompression);
-
-Error uncompress(ArrayRef<uint8_t> Input, uint8_t *UncompressedBuffer,
-                 size_t &UncompressedSize);
-
-Error uncompress(ArrayRef<uint8_t> Input,
-                 SmallVectorImpl<uint8_t> &UncompressedBuffer,
-                 size_t UncompressedSize);
-
-} // End of namespace zlib
-
-namespace zstd {
-
-constexpr int NoCompression = -5;
-constexpr int BestSpeedCompression = 1;
-constexpr int DefaultCompression = 5;
-constexpr int BestSizeCompression = 12;
-
-bool isAvailable();
-
-void compress(ArrayRef<uint8_t> Input,
-              SmallVectorImpl<uint8_t> &CompressedBuffer,
-              int Level = DefaultCompression);
-
-Error uncompress(ArrayRef<uint8_t> Input, uint8_t *UncompressedBuffer,
-                 size_t &UncompressedSize);
-
-Error uncompress(ArrayRef<uint8_t> Input,
-                 SmallVectorImpl<uint8_t> &UncompressedBuffer,
-                 size_t UncompressedSize);
-
-} // End of namespace zstd
+class CompressionAlgorithm;
+
+class CompressionKind {
+private:
+  uint8_t x;
+
+protected:
+  friend constexpr llvm::Optional<CompressionKind>
+  getOptionalCompressionKind(uint8_t y);
+  constexpr CompressionKind(uint8_t y) : x(y) {
+    if (!(y == 1 || y == 2 || y == 255)) {
+      llvm_unreachable("unknown compression id");
+    }
+  }
+
+public:
+  constexpr operator uint8_t() const { return x; }
+  CompressionAlgorithm *operator->() const;
+
+  constexpr operator bool() const;
+
+  bool operator==(llvm::compression::CompressionKind other) const;
+  static const llvm::compression::CompressionKind Unknown, Zlib, ZStd;
+};
+constexpr inline const llvm::compression::CompressionKind
+    llvm::compression::CompressionKind::Unknown{255}, ///< Abstract compression
+    llvm::compression::CompressionKind::Zlib{1}, ///< zlib style complession
+    llvm::compression::CompressionKind::ZStd{2}; ///< zstd style complession
+typedef llvm::Optional<CompressionKind> OptionalCompressionKind;
+
+constexpr CompressionKind::operator bool() const {
+  switch (uint8_t(x)) {
+  case uint8_t(CompressionKind::Zlib):
+#if LLVM_ENABLE_ZLIB
+    return true;
+#else
+    return false;
+#endif
+  case uint8_t(CompressionKind::ZStd):
+#if LLVM_ENABLE_ZSTD
+    return true;
+#else
+    return false;
+#endif
+  default:
+    return false;
+  }
+}
+
+constexpr OptionalCompressionKind operator&&(CompressionKind left, bool right) {
+  if (right) {
+    return left;
+  }
+  return NoneType();
+}
+constexpr OptionalCompressionKind operator&&(OptionalCompressionKind left,
+                                             bool right) {
+  if (right) {
+    return left;
+  }
+  return NoneType();
+}
+
+constexpr OptionalCompressionKind operator||(CompressionKind left,
+                                             OptionalCompressionKind right) {
+  if (bool(left)) {
+    return left;
+  }
+  return right;
+}
+constexpr OptionalCompressionKind operator||(OptionalCompressionKind left,
+                                             OptionalCompressionKind right) {
+  if (!left || (!bool(*left))) {
+    return right;
+  }
+  return left;
+}
+
+constexpr OptionalCompressionKind getOptionalCompressionKind(uint8_t y) {
+  if (y == 0) {
+    return NoneType();
+  }
+  return CompressionKind(y);
+}
+// This is the base class of all compression algorithms that llvm support
+// handles.
+class CompressionAlgorithm {
+public:
+  virtual CompressionKind getAlgorithmId() = 0;
+
+  virtual StringRef getName() = 0;
+
+  virtual bool supported() = 0;
+
+  virtual int getBestSpeedLevel() = 0;
+  virtual int getDefaultLevel() = 0;
+  virtual int getBestSizeLevel() = 0;
+
+  virtual void compress(ArrayRef<uint8_t> Input,
+                        SmallVectorImpl<uint8_t> &CompressedBuffer,
+                        int Level) = 0;
+  virtual void compress(ArrayRef<uint8_t> Input,
+                        SmallVectorImpl<uint8_t> &CompressedBuffer) = 0;
+
+  virtual Error decompress(ArrayRef<uint8_t> Input, uint8_t *UncompressedBuffer,
+                           size_t &UncompressedSize) = 0;
+  virtual Error decompress(ArrayRef<uint8_t> Input,
+                           SmallVectorImpl<uint8_t> &UncompressedBuffer,
+                           size_t UncompressedSize) = 0;
+};
+class UnknownCompressionAlgorithm;
+class ZStdCompressionAlgorithm;
+class ZlibCompressionAlgorithm;
+
+template <class CompressionAlgorithmType>
+class CompressionAlgorithmImpl : public CompressionAlgorithm {
+public:
+  virtual CompressionKind getAlgorithmId() {
+    return CompressionAlgorithmType::AlgorithmId;
+  }
+
+  virtual StringRef getName() { return CompressionAlgorithmType::Name; }
+
+  virtual bool supported() { return CompressionAlgorithmType::Supported(); }
+
+  virtual int getBestSpeedLevel() {
+    return CompressionAlgorithmType::BestSpeedCompression;
+  }
+  virtual int getDefaultLevel() {
+    return CompressionAlgorithmType::DefaultCompression;
+  }
+  virtual int getBestSizeLevel() {
+    return CompressionAlgorithmType::BestSizeCompression;
+  }
+
+  virtual void compress(ArrayRef<uint8_t> Input,
+                        SmallVectorImpl<uint8_t> &CompressedBuffer, int Level) {
+
+    return CompressionAlgorithmType::Compress(Input, CompressedBuffer, Level);
+  }
+  virtual void compress(ArrayRef<uint8_t> Input,
+                        SmallVectorImpl<uint8_t> &CompressedBuffer) {
+    return CompressionAlgorithmType::Compress(
+        Input, CompressedBuffer, CompressionAlgorithmType::DefaultCompression);
+  }
+
+  virtual Error decompress(ArrayRef<uint8_t> Input, uint8_t *UncompressedBuffer,
+                           size_t &UncompressedSize) {
+    return CompressionAlgorithmType::Decompress(Input, UncompressedBuffer,
+                                                UncompressedSize);
+  }
+  virtual Error decompress(ArrayRef<uint8_t> Input,
+                           SmallVectorImpl<uint8_t> &UncompressedBuffer,
+                           size_t UncompressedSize) {
+    UncompressedBuffer.resize_for_overwrite(UncompressedSize);
+    Error E = CompressionAlgorithmType::Decompress(
+        Input, UncompressedBuffer.data(), UncompressedSize);
+    if (UncompressedSize < UncompressedBuffer.size())
+      UncompressedBuffer.truncate(UncompressedSize);
+    return E;
+  }
+};
+
+class ZStdCompressionAlgorithm
+    : public CompressionAlgorithmImpl<ZStdCompressionAlgorithm> {
+public:
+  constexpr static CompressionKind AlgorithmId = CompressionKind::ZStd;
+  constexpr static StringRef Name = "zstd";
+  constexpr static int BestSpeedCompression = 1;
+  constexpr static int DefaultCompression = 5;
+  constexpr static int BestSizeCompression = 12;
+  static void Compress(ArrayRef<uint8_t> Input,
+                       SmallVectorImpl<uint8_t> &CompressedBuffer, int Level);
+  static Error Decompress(ArrayRef<uint8_t> Input, uint8_t *UncompressedBuffer,
+                          size_t &UncompressedSize);
+  static bool Supported();
+
+protected:
+  friend CompressionAlgorithm *CompressionKind::operator->() const;
+  constexpr ZStdCompressionAlgorithm(){};
+};
+
+class ZlibCompressionAlgorithm
+    : public CompressionAlgorithmImpl<ZlibCompressionAlgorithm> {
+public:
+  constexpr static CompressionKind AlgorithmId = CompressionKind::Zlib;
+  constexpr static StringRef Name = "zlib";
+  constexpr static int BestSpeedCompression = 1;
+  constexpr static int DefaultCompression = 6;
+  constexpr static int BestSizeCompression = 9;
+  static void Compress(ArrayRef<uint8_t> Input,
+                       SmallVectorImpl<uint8_t> &CompressedBuffer, int Level);
+  static Error Decompress(ArrayRef<uint8_t> Input, uint8_t *UncompressedBuffer,
+                          size_t &UncompressedSize);
+  static bool Supported();
+
+protected:
+  friend CompressionAlgorithm *CompressionKind::operator->() const;
+  constexpr ZlibCompressionAlgorithm(){};
+};
+
+class UnknownCompressionAlgorithm
+    : public CompressionAlgorithmImpl<UnknownCompressionAlgorithm> {
+public:
+  constexpr static CompressionKind AlgorithmId = CompressionKind::Unknown;
+  constexpr static StringRef Name = "unknown";
+  constexpr static int BestSpeedCompression = -999;
+  constexpr static int DefaultCompression = -999;
+  constexpr static int BestSizeCompression = -999;
+  static void Compress(ArrayRef<uint8_t> Input,
+                       SmallVectorImpl<uint8_t> &CompressedBuffer, int Level);
+  static Error Decompress(ArrayRef<uint8_t> Input, uint8_t *UncompressedBuffer,
+                          size_t &UncompressedSize);
+  static bool Supported();
+
+protected:
+  friend CompressionAlgorithm *CompressionKind::operator->() const;
+  constexpr UnknownCompressionAlgorithm(){};
+};
 
 } // End of namespace compression
 
Index: llvm/include/llvm/ProfileData/InstrProf.h
===================================================================
--- llvm/include/llvm/ProfileData/InstrProf.h
+++ llvm/include/llvm/ProfileData/InstrProf.h
@@ -26,6 +26,7 @@
 #include "llvm/ProfileData/InstrProfData.inc"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Compiler.h"
+#include "llvm/Support/Compression.h"
 #include "llvm/Support/Endian.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/ErrorHandling.h"
@@ -214,8 +215,10 @@
 ///  third field is the uncompressed strings; otherwise it is the
 /// compressed string. When the string compression is off, the
 /// second field will have value zero.
-Error collectPGOFuncNameStrings(ArrayRef<std::string> NameStrs,
-                                bool doCompression, std::string &Result);
+Error collectPGOFuncNameStrings(
+    ArrayRef<std::string> NameStrs,
+    compression::OptionalCompressionKind OptionalCompressionScheme,
+    std::string &Result);
 
 /// Produce \c Result string with the same format described above. The input
 /// is vector of PGO function name variables that are referenced.
Index: llvm/include/llvm/Object/Decompressor.h
===================================================================
--- llvm/include/llvm/Object/Decompressor.h
+++ llvm/include/llvm/Object/Decompressor.h
@@ -11,6 +11,7 @@
 
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/Support/Compression.h"
 #include "llvm/Support/Error.h"
 
 namespace llvm {
@@ -44,10 +45,12 @@
 private:
   Decompressor(StringRef Data);
 
-  Error consumeCompressedZLibHeader(bool Is64Bit, bool IsLittleEndian);
+  Error consumeCompressedSectionHeader(bool Is64Bit, bool IsLittleEndian);
 
   StringRef SectionData;
   uint64_t DecompressedSize;
+  compression::CompressionKind CompressionScheme =
+      compression::CompressionKind::Zlib;
 };
 
 } // end namespace object
Index: lld/ELF/InputSection.cpp
===================================================================
--- lld/ELF/InputSection.cpp
+++ lld/ELF/InputSection.cpp
@@ -119,7 +119,8 @@
     uncompressedBuf = bAlloc().Allocate<uint8_t>(size);
   }
 
-  if (Error e = compression::zlib::uncompress(rawData, uncompressedBuf, size))
+  if (Error e = compression::CompressionKind::Zlib->decompress(
+          rawData, uncompressedBuf, size))
     fatal(toString(this) +
           ": uncompress failed: " + llvm::toString(std::move(e)));
   rawData = makeArrayRef(uncompressedBuf, size);
@@ -209,7 +210,7 @@
 
   auto *hdr = reinterpret_cast<const typename ELFT::Chdr *>(rawData.data());
   if (hdr->ch_type == ELFCOMPRESS_ZLIB) {
-    if (!compression::zlib::isAvailable())
+    if (!compression::CompressionKind::Zlib)
       error(toString(this) + " is compressed with ELFCOMPRESS_ZLIB, but lld is "
                              "not built with zlib support");
   } else {
@@ -220,7 +221,6 @@
 
   uncompressedSize = hdr->ch_size;
   alignment = std::max<uint32_t>(hdr->ch_addralign, 1);
-  rawData = rawData.slice(sizeof(*hdr));
 }
 
 InputSection *InputSectionBase::getLinkOrderDep() const {
@@ -1218,10 +1218,24 @@
   // If this is a compressed section, uncompress section contents directly
   // to the buffer.
   if (uncompressedSize >= 0) {
+    auto *hdr = reinterpret_cast<const typename ELFT::Chdr *>(rawData.data());
     size_t size = uncompressedSize;
-    if (Error e = compression::zlib::uncompress(rawData, buf, size))
-      fatal(toString(this) +
-            ": uncompress failed: " + llvm::toString(std::move(e)));
+    if (hdr->ch_type == ELFCOMPRESS_ZLIB) {
+      if (!compression::CompressionKind::Zlib) {
+        error(toString(this) +
+              " is compressed with ELFCOMPRESS_ZLIB, but lld is "
+              "not built with zlib support");
+      } else {
+        if (Error e = compression::CompressionKind::Zlib->decompress(
+                rawData.slice(sizeof(typename ELFT::Chdr)), buf, size))
+          fatal(toString(this) +
+                ": uncompress failed: " + llvm::toString(std::move(e)));
+      }
+    } else {
+      error(toString(this) + ": unsupported compression type (" +
+            Twine(hdr->ch_type) + ")");
+      return;
+    }
     uint8_t *bufEnd = buf + size;
     relocate<ELFT>(buf, bufEnd);
     return;
Index: lld/ELF/Driver.cpp
===================================================================
--- lld/ELF/Driver.cpp
+++ lld/ELF/Driver.cpp
@@ -954,12 +954,15 @@
 
 static bool getCompressDebugSections(opt::InputArgList &args) {
   StringRef s = args.getLastArgValue(OPT_compress_debug_sections, "none");
-  if (s == "none")
+  if (s == "none") {
     return false;
-  if (s != "zlib")
+  } else if (s == "zlib") {
+    if (!compression::ZlibCompressionAlgorithm::Supported())
+      error("--compress-debug-sections: zlib is not available");
+  } else {
     error("unknown --compress-debug-sections value: " + s);
-  if (!compression::zlib::isAvailable())
-    error("--compress-debug-sections: zlib is not available");
+  }
+
   return true;
 }
 
Index: clang/lib/Serialization/ASTWriter.cpp
===================================================================
--- clang/lib/Serialization/ASTWriter.cpp
+++ clang/lib/Serialization/ASTWriter.cpp
@@ -1999,10 +1999,17 @@
 
   // Compress the buffer if possible. We expect that almost all PCM
   // consumers will not want its contents.
-  SmallVector<uint8_t, 0> CompressedBuffer;
-  if (llvm::compression::zlib::isAvailable()) {
-    llvm::compression::zlib::compress(
-        llvm::arrayRefFromStringRef(Blob.drop_back(1)), CompressedBuffer);
+  llvm::compression::OptionalCompressionKind OptionalCompressionScheme =
+      llvm::compression::CompressionKind::Zlib;
+
+  OptionalCompressionScheme = OptionalCompressionScheme || llvm::NoneType();
+  if (OptionalCompressionScheme) {
+    llvm::compression::CompressionKind CompressionScheme =
+        *OptionalCompressionScheme;
+    SmallVector<uint8_t, 0> CompressedBuffer;
+
+    CompressionScheme->compress(llvm::arrayRefFromStringRef(Blob.drop_back(1)),
+                                CompressedBuffer);
     RecordDataType Record[] = {SM_SLOC_BUFFER_BLOB_COMPRESSED, Blob.size() - 1};
     Stream.EmitRecordWithBlob(SLocBufferBlobCompressedAbbrv, Record,
                               llvm::toStringRef(CompressedBuffer));
Index: clang/lib/Serialization/ASTReader.cpp
===================================================================
--- clang/lib/Serialization/ASTReader.cpp
+++ clang/lib/Serialization/ASTReader.cpp
@@ -1462,12 +1462,21 @@
     unsigned RecCode = MaybeRecCode.get();
 
     if (RecCode == SM_SLOC_BUFFER_BLOB_COMPRESSED) {
-      if (!llvm::compression::zlib::isAvailable()) {
-        Error("zlib is not available");
+      uint8_t CompressionSchemeId = llvm::compression::CompressionKind::Zlib;
+      llvm::compression::OptionalCompressionKind OptionalCompressionScheme =
+          llvm::compression::getOptionalCompressionKind(CompressionSchemeId);
+      if (!OptionalCompressionScheme) {
+        return llvm::MemoryBuffer::getMemBuffer(Blob, Name, true);
+      }
+      llvm::compression::CompressionKind CompressionScheme =
+          *OptionalCompressionScheme;
+      if (!CompressionScheme) {
+        Error("compression class " +
+              (CompressionScheme->getName() + " is not available").str());
         return nullptr;
       }
       SmallVector<uint8_t, 0> Uncompressed;
-      if (llvm::Error E = llvm::compression::zlib::uncompress(
+      if (llvm::Error E = CompressionScheme->decompress(
               llvm::arrayRefFromStringRef(Blob), Uncompressed, Record[0])) {
         Error("could not decompress embedded file contents: " +
               llvm::toString(std::move(E)));
Index: clang/lib/Driver/ToolChains/Clang.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -1139,7 +1139,7 @@
     if (Value == "none") {
       CmdArgs.push_back("--compress-debug-sections=none");
     } else if (Value == "zlib") {
-      if (llvm::compression::zlib::isAvailable()) {
+      if (llvm::compression::ZlibCompressionAlgorithm::Supported()) {
         CmdArgs.push_back(
             Args.MakeArgString("--compress-debug-sections=" + Twine(Value)));
       } else {
Index: clang-tools-extra/clangd/unittests/SerializationTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/SerializationTests.cpp
+++ clang-tools-extra/clangd/unittests/SerializationTests.cpp
@@ -391,7 +391,7 @@
 // Check we detect invalid string table size size without allocating it first.
 // If this detection fails, the test should allocate a huge array and crash.
 TEST(SerializationTest, NoCrashOnBadStringTableSize) {
-  if (!llvm::compression::zlib::isAvailable()) {
+  if (!llvm::compression::ZlibCompressionAlgorithm::Supported()) {
     log("skipping test, no zlib");
     return;
   }
Index: clang-tools-extra/clangd/index/Serialization.cpp
===================================================================
--- clang-tools-extra/clangd/index/Serialization.cpp
+++ clang-tools-extra/clangd/index/Serialization.cpp
@@ -16,6 +16,7 @@
 #include "support/Logger.h"
 #include "support/Trace.h"
 #include "clang/Tooling/CompilationDatabase.h"
+#include "llvm/ADT/Optional.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/Compression.h"
@@ -190,10 +191,15 @@
       RawTable.append(std::string(S));
       RawTable.push_back(0);
     }
-    if (llvm::compression::zlib::isAvailable()) {
+    llvm::compression::OptionalCompressionKind OptionalCompressionScheme =
+        llvm::compression::CompressionKind::Zlib;
+    OptionalCompressionScheme = OptionalCompressionScheme || llvm::NoneType();
+    if (OptionalCompressionScheme) {
+      llvm::compression::CompressionKind CompressionScheme =
+          *OptionalCompressionScheme;
       llvm::SmallVector<uint8_t, 0> Compressed;
-      llvm::compression::zlib::compress(llvm::arrayRefFromStringRef(RawTable),
-                                        Compressed);
+      CompressionScheme->compress(llvm::arrayRefFromStringRef(RawTable),
+                                  Compressed);
       write32(RawTable.size(), OS);
       OS << llvm::toStringRef(Compressed);
     } else {
@@ -224,23 +230,29 @@
   llvm::SmallVector<uint8_t, 0> UncompressedStorage;
   if (UncompressedSize == 0) // No compression
     Uncompressed = R.rest();
-  else if (llvm::compression::zlib::isAvailable()) {
-    // Don't allocate a massive buffer if UncompressedSize was corrupted
-    // This is effective for sharded index, but not big monolithic ones, as
-    // once compressed size reaches 4MB nothing can be ruled out.
-    // Theoretical max ratio from https://zlib.net/zlib_tech.html
-    constexpr int MaxCompressionRatio = 1032;
-    if (UncompressedSize / MaxCompressionRatio > R.rest().size())
-      return error("Bad stri table: uncompress {0} -> {1} bytes is implausible",
-                   R.rest().size(), UncompressedSize);
-
-    if (llvm::Error E = llvm::compression::zlib::uncompress(
-            llvm::arrayRefFromStringRef(R.rest()), UncompressedStorage,
-            UncompressedSize))
-      return std::move(E);
-    Uncompressed = toStringRef(UncompressedStorage);
-  } else
-    return error("Compressed string table, but zlib is unavailable");
+  else {
+    llvm::compression::CompressionKind CompressionScheme =
+        llvm::compression::CompressionKind::Zlib;
+    if (CompressionScheme->supported()) {
+      // Don't allocate a massive buffer if UncompressedSize was corrupted
+      // This is effective for sharded index, but not big monolithic ones, as
+      // once compressed size reaches 4MB nothing can be ruled out.
+      // Theoretical max ratio from https://zlib.net/zlib_tech.html
+      constexpr int MaxCompressionRatio = 1032;
+      if (UncompressedSize / MaxCompressionRatio > R.rest().size())
+        return error(
+            "Bad stri table: uncompress {0} -> {1} bytes is implausible",
+            R.rest().size(), UncompressedSize);
+
+      if (llvm::Error E = CompressionScheme->decompress(
+              llvm::arrayRefFromStringRef(R.rest()), UncompressedStorage,
+              UncompressedSize))
+        return std::move(E);
+      Uncompressed = toStringRef(UncompressedStorage);
+    } else
+      return error("Compressed string table, but " +
+                   (CompressionScheme->getName() + " is unavailable").str());
+  }
 
   StringTableIn Table;
   llvm::StringSaver Saver(Table.Arena);
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to