[llvm] Implement streaming compression for compressed ELF sections. (PR #87211)

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 25 23:16:13 PDT 2024


================
@@ -201,6 +261,51 @@ void zstd::compress(ArrayRef<uint8_t> Input,
     CompressedBuffer.truncate(CompressedSize);
 }
 
+void zstd::compressToStream(ArrayRef<uint8_t> Input, raw_ostream &OS, int Level,
+                            bool EnableLdm) {
+  // Allocate a buffer to hold the output.
+  size_t OutBufferSize = ZSTD_CStreamOutSize();
+  auto OutBuffer = std::make_unique<char[]>(OutBufferSize);
+
+  ZSTD_CStream *CStream = ZSTD_createCStream();
+  if (!CStream)
+    report_bad_alloc_error("Failed to create ZSTD_CCtx");
+
+  // Ensure that the ZSTD_CStream is cleaned up on all exit paths.
+  auto FreeCStreamOnExit =
+      make_scope_exit([=]() { ZSTD_freeCStream(CStream); });
+
+  if (ZSTD_isError(ZSTD_CCtx_setParameter(
+          CStream, ZSTD_c_enableLongDistanceMatching, EnableLdm ? 1 : 0))) {
+    report_bad_alloc_error("Failed to set ZSTD_c_enableLongDistanceMatching");
+  }
+
+  if (ZSTD_isError(
+          ZSTD_CCtx_setParameter(CStream, ZSTD_c_compressionLevel, Level))) {
+    report_bad_alloc_error("Failed to set ZSTD_c_compressionLevel");
+  }
+
+  ZSTD_inBuffer ZInput = {Input.data(), Input.size(), 0};
+
+  // Repeatedly compress into the output buffer and flush it into the
+  // output stream. Repeat until we have drained the entire compression
+  // state.
+  size_t ZRet;
+  do {
+    ZSTD_outBuffer ZOutput = {OutBuffer.get(), OutBufferSize, 0};
+    ZRet = ZSTD_compressStream2(CStream, &ZOutput, &ZInput, ZSTD_e_end);
----------------
MaskRay wrote:

With suitable input and output buffers, ZSTD_compressStream2 will never fail. So `assert !isError` should be fine.

https://github.com/llvm/llvm-project/pull/87211


More information about the llvm-commits mailing list