1 //===--- Compression.cpp - Compression implementation ---------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file implements compression functions.
11 //===----------------------------------------------------------------------===//
13 #include "llvm/Support/Compression.h"
14 #include "llvm/ADT/SmallVector.h"
15 #include "llvm/ADT/StringRef.h"
16 #include "llvm/Config/config.h"
17 #include "llvm/Support/Compiler.h"
18 #include "llvm/Support/Error.h"
19 #include "llvm/Support/ErrorHandling.h"
28 using namespace llvm::compression
;
30 const char *compression::getReasonIfUnsupported(compression::Format F
) {
32 case compression::Format::Zlib
:
33 if (zlib::isAvailable())
35 return "LLVM was not built with LLVM_ENABLE_ZLIB or did not find zlib at "
37 case compression::Format::Zstd
:
38 if (zstd::isAvailable())
40 return "LLVM was not built with LLVM_ENABLE_ZSTD or did not find zstd at "
46 void compression::compress(Params P
, ArrayRef
<uint8_t> Input
,
47 SmallVectorImpl
<uint8_t> &Output
) {
49 case compression::Format::Zlib
:
50 zlib::compress(Input
, Output
, P
.level
);
52 case compression::Format::Zstd
:
53 zstd::compress(Input
, Output
, P
.level
);
58 Error
compression::decompress(DebugCompressionType T
, ArrayRef
<uint8_t> Input
,
59 uint8_t *Output
, size_t UncompressedSize
) {
60 switch (formatFor(T
)) {
61 case compression::Format::Zlib
:
62 return zlib::decompress(Input
, Output
, UncompressedSize
);
63 case compression::Format::Zstd
:
64 return zstd::decompress(Input
, Output
, UncompressedSize
);
69 Error
compression::decompress(compression::Format F
, ArrayRef
<uint8_t> Input
,
70 SmallVectorImpl
<uint8_t> &Output
,
71 size_t UncompressedSize
) {
73 case compression::Format::Zlib
:
74 return zlib::decompress(Input
, Output
, UncompressedSize
);
75 case compression::Format::Zstd
:
76 return zstd::decompress(Input
, Output
, UncompressedSize
);
81 Error
compression::decompress(DebugCompressionType T
, ArrayRef
<uint8_t> Input
,
82 SmallVectorImpl
<uint8_t> &Output
,
83 size_t UncompressedSize
) {
84 return decompress(formatFor(T
), Input
, Output
, UncompressedSize
);
89 static StringRef
convertZlibCodeToString(int Code
) {
92 return "zlib error: Z_MEM_ERROR";
94 return "zlib error: Z_BUF_ERROR";
96 return "zlib error: Z_STREAM_ERROR";
98 return "zlib error: Z_DATA_ERROR";
101 llvm_unreachable("unknown or unexpected zlib status code");
105 bool zlib::isAvailable() { return true; }
107 void zlib::compress(ArrayRef
<uint8_t> Input
,
108 SmallVectorImpl
<uint8_t> &CompressedBuffer
, int Level
) {
109 unsigned long CompressedSize
= ::compressBound(Input
.size());
110 CompressedBuffer
.resize_for_overwrite(CompressedSize
);
111 int Res
= ::compress2((Bytef
*)CompressedBuffer
.data(), &CompressedSize
,
112 (const Bytef
*)Input
.data(), Input
.size(), Level
);
113 if (Res
== Z_MEM_ERROR
)
114 report_bad_alloc_error("Allocation failed");
116 // Tell MemorySanitizer that zlib output buffer is fully initialized.
117 // This avoids a false report when running LLVM with uninstrumented ZLib.
118 __msan_unpoison(CompressedBuffer
.data(), CompressedSize
);
119 if (CompressedSize
< CompressedBuffer
.size())
120 CompressedBuffer
.truncate(CompressedSize
);
123 Error
zlib::decompress(ArrayRef
<uint8_t> Input
, uint8_t *Output
,
124 size_t &UncompressedSize
) {
125 int Res
= ::uncompress((Bytef
*)Output
, (uLongf
*)&UncompressedSize
,
126 (const Bytef
*)Input
.data(), Input
.size());
127 // Tell MemorySanitizer that zlib output buffer is fully initialized.
128 // This avoids a false report when running LLVM with uninstrumented ZLib.
129 __msan_unpoison(Output
, UncompressedSize
);
130 return Res
? make_error
<StringError
>(convertZlibCodeToString(Res
),
131 inconvertibleErrorCode())
135 Error
zlib::decompress(ArrayRef
<uint8_t> Input
,
136 SmallVectorImpl
<uint8_t> &Output
,
137 size_t UncompressedSize
) {
138 Output
.resize_for_overwrite(UncompressedSize
);
139 Error E
= zlib::decompress(Input
, Output
.data(), UncompressedSize
);
140 if (UncompressedSize
< Output
.size())
141 Output
.truncate(UncompressedSize
);
146 bool zlib::isAvailable() { return false; }
147 void zlib::compress(ArrayRef
<uint8_t> Input
,
148 SmallVectorImpl
<uint8_t> &CompressedBuffer
, int Level
) {
149 llvm_unreachable("zlib::compress is unavailable");
151 Error
zlib::decompress(ArrayRef
<uint8_t> Input
, uint8_t *UncompressedBuffer
,
152 size_t &UncompressedSize
) {
153 llvm_unreachable("zlib::decompress is unavailable");
155 Error
zlib::decompress(ArrayRef
<uint8_t> Input
,
156 SmallVectorImpl
<uint8_t> &UncompressedBuffer
,
157 size_t UncompressedSize
) {
158 llvm_unreachable("zlib::decompress is unavailable");
164 bool zstd::isAvailable() { return true; }
166 void zstd::compress(ArrayRef
<uint8_t> Input
,
167 SmallVectorImpl
<uint8_t> &CompressedBuffer
, int Level
) {
168 unsigned long CompressedBufferSize
= ::ZSTD_compressBound(Input
.size());
169 CompressedBuffer
.resize_for_overwrite(CompressedBufferSize
);
170 unsigned long CompressedSize
=
171 ::ZSTD_compress((char *)CompressedBuffer
.data(), CompressedBufferSize
,
172 (const char *)Input
.data(), Input
.size(), Level
);
173 if (ZSTD_isError(CompressedSize
))
174 report_bad_alloc_error("Allocation failed");
175 // Tell MemorySanitizer that zstd output buffer is fully initialized.
176 // This avoids a false report when running LLVM with uninstrumented ZLib.
177 __msan_unpoison(CompressedBuffer
.data(), CompressedSize
);
178 if (CompressedSize
< CompressedBuffer
.size())
179 CompressedBuffer
.truncate(CompressedSize
);
182 Error
zstd::decompress(ArrayRef
<uint8_t> Input
, uint8_t *Output
,
183 size_t &UncompressedSize
) {
184 const size_t Res
= ::ZSTD_decompress(
185 Output
, UncompressedSize
, (const uint8_t *)Input
.data(), Input
.size());
186 UncompressedSize
= Res
;
187 // Tell MemorySanitizer that zstd output buffer is fully initialized.
188 // This avoids a false report when running LLVM with uninstrumented ZLib.
189 __msan_unpoison(Output
, UncompressedSize
);
190 return ZSTD_isError(Res
) ? make_error
<StringError
>(ZSTD_getErrorName(Res
),
191 inconvertibleErrorCode())
195 Error
zstd::decompress(ArrayRef
<uint8_t> Input
,
196 SmallVectorImpl
<uint8_t> &Output
,
197 size_t UncompressedSize
) {
198 Output
.resize_for_overwrite(UncompressedSize
);
199 Error E
= zstd::decompress(Input
, Output
.data(), UncompressedSize
);
200 if (UncompressedSize
< Output
.size())
201 Output
.truncate(UncompressedSize
);
206 bool zstd::isAvailable() { return false; }
207 void zstd::compress(ArrayRef
<uint8_t> Input
,
208 SmallVectorImpl
<uint8_t> &CompressedBuffer
, int Level
) {
209 llvm_unreachable("zstd::compress is unavailable");
211 Error
zstd::decompress(ArrayRef
<uint8_t> Input
, uint8_t *Output
,
212 size_t &UncompressedSize
) {
213 llvm_unreachable("zstd::decompress is unavailable");
215 Error
zstd::decompress(ArrayRef
<uint8_t> Input
,
216 SmallVectorImpl
<uint8_t> &Output
,
217 size_t UncompressedSize
) {
218 llvm_unreachable("zstd::decompress is unavailable");