LLVM  17.0.0git
Compression.cpp
Go to the documentation of this file.
1 //===--- Compression.cpp - Compression implementation ---------------------===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file implements compression functions.
10 //
11 //===----------------------------------------------------------------------===//
12 
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"
20 #if LLVM_ENABLE_ZLIB
21 #include <zlib.h>
22 #endif
23 #if LLVM_ENABLE_ZSTD
24 #include <zstd.h>
25 #endif
26 
27 using namespace llvm;
28 using namespace llvm::compression;
29 
31  switch (F) {
33  if (zlib::isAvailable())
34  return nullptr;
35  return "LLVM was not built with LLVM_ENABLE_ZLIB or did not find zlib at "
36  "build time";
38  if (zstd::isAvailable())
39  return nullptr;
40  return "LLVM was not built with LLVM_ENABLE_ZSTD or did not find zstd at "
41  "build time";
42  }
43  llvm_unreachable("");
44 }
45 
47  SmallVectorImpl<uint8_t> &Output) {
48  switch (P.format) {
50  zlib::compress(Input, Output, P.level);
51  break;
53  zstd::compress(Input, Output, P.level);
54  break;
55  }
56 }
57 
59  uint8_t *Output, size_t UncompressedSize) {
60  switch (formatFor(T)) {
62  return zlib::decompress(Input, Output, UncompressedSize);
64  return zstd::decompress(Input, Output, UncompressedSize);
65  }
66  llvm_unreachable("");
67 }
68 
71  size_t UncompressedSize) {
72  switch (F) {
74  return zlib::decompress(Input, Output, UncompressedSize);
76  return zstd::decompress(Input, Output, UncompressedSize);
77  }
78  llvm_unreachable("");
79 }
80 
83  size_t UncompressedSize) {
84  return decompress(formatFor(T), Input, Output, UncompressedSize);
85 }
86 
87 #if LLVM_ENABLE_ZLIB
88 
90  switch (Code) {
91  case Z_MEM_ERROR:
92  return "zlib error: Z_MEM_ERROR";
93  case Z_BUF_ERROR:
94  return "zlib error: Z_BUF_ERROR";
95  case Z_STREAM_ERROR:
96  return "zlib error: Z_STREAM_ERROR";
97  case Z_DATA_ERROR:
98  return "zlib error: Z_DATA_ERROR";
99  case Z_OK:
100  default:
101  llvm_unreachable("unknown or unexpected zlib status code");
102  }
103 }
104 
105 bool zlib::isAvailable() { return true; }
106 
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");
115  assert(Res == Z_OK);
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);
121 }
122 
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),
132  : Error::success();
133 }
134 
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);
142  return E;
143 }
144 
145 #else
146 bool zlib::isAvailable() { return false; }
148  SmallVectorImpl<uint8_t> &CompressedBuffer, int Level) {
149  llvm_unreachable("zlib::compress is unavailable");
150 }
151 Error zlib::decompress(ArrayRef<uint8_t> Input, uint8_t *UncompressedBuffer,
152  size_t &UncompressedSize) {
153  llvm_unreachable("zlib::decompress is unavailable");
154 }
156  SmallVectorImpl<uint8_t> &UncompressedBuffer,
157  size_t UncompressedSize) {
158  llvm_unreachable("zlib::decompress is unavailable");
159 }
160 #endif
161 
162 #if LLVM_ENABLE_ZSTD
163 
164 bool zstd::isAvailable() { return true; }
165 
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);
180 }
181 
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),
192  : Error::success();
193 }
194 
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);
202  return E;
203 }
204 
205 #else
206 bool zstd::isAvailable() { return false; }
208  SmallVectorImpl<uint8_t> &CompressedBuffer, int Level) {
209  llvm_unreachable("zstd::compress is unavailable");
210 }
211 Error zstd::decompress(ArrayRef<uint8_t> Input, uint8_t *Output,
212  size_t &UncompressedSize) {
213  llvm_unreachable("zstd::decompress is unavailable");
214 }
216  SmallVectorImpl<uint8_t> &Output,
217  size_t UncompressedSize) {
218  llvm_unreachable("zstd::decompress is unavailable");
219 }
220 #endif
llvm::coverage::coveragemap_error::success
@ success
Compression.h
llvm::compression::zlib::decompress
Error decompress(ArrayRef< uint8_t > Input, uint8_t *Output, size_t &UncompressedSize)
Definition: Compression.cpp:123
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
llvm::compression::Params
Definition: Compression.h:93
llvm::compression::Format
Format
Definition: Compression.h:76
T
StringRef.h
llvm::RISCVRVC::uncompress
bool uncompress(MCInst &OutInst, const MCInst &MI, const MCSubtargetInfo &STI)
Definition: RISCVBaseInfo.cpp:212
P
This currently compiles esp xmm0 movsd esp eax eax esp ret We should use not the dag combiner This is because dagcombine2 needs to be able to see through the X86ISD::Wrapper which DAGCombine can t really do The code for turning x load into a single vector load is target independent and should be moved to the dag combiner The code for turning x load into a vector load can only handle a direct load from a global or a direct load from the stack It should be generalized to handle any load from P
Definition: README-SSE.txt:411
ErrorHandling.h
llvm::Error::success
static ErrorSuccess success()
Create a success value.
Definition: Error.h:330
Error.h
llvm::ArrayRef::data
const T * data() const
Definition: ArrayRef.h:160
F
#define F(x, y, z)
Definition: MD5.cpp:55
llvm::SmallVectorImpl::truncate
void truncate(size_type N)
Like resize, but requires that N is less than size().
Definition: SmallVector.h:648
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
llvm::compression::zlib::isAvailable
bool isAvailable()
Definition: Compression.cpp:105
convertZlibCodeToString
static StringRef convertZlibCodeToString(int Code)
Definition: Compression.cpp:89
llvm::SmallVectorImpl::resize_for_overwrite
void resize_for_overwrite(size_type N)
Like resize, but T is POD, the new values won't be initialized.
Definition: SmallVector.h:645
llvm::report_bad_alloc_error
void report_bad_alloc_error(const char *Reason, bool GenCrashDiag=true)
Reports a bad alloc error, calling any user defined bad alloc error handler.
Definition: ErrorHandling.cpp:146
llvm::compression::zstd::decompress
Error decompress(ArrayRef< uint8_t > Input, uint8_t *Output, size_t &UncompressedSize)
Definition: Compression.cpp:211
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::compression
Definition: Compression.h:33
llvm::ArrayRef< uint8_t >
llvm::DebugCompressionType
DebugCompressionType
Definition: Compression.h:27
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
__msan_unpoison
#define __msan_unpoison(p, size)
Definition: Compiler.h:398
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:143
Compiler.h
llvm::compression::zstd::compress
void compress(ArrayRef< uint8_t > Input, SmallVectorImpl< uint8_t > &CompressedBuffer, int Level=DefaultCompression)
Definition: Compression.cpp:207
llvm::compression::compress
void compress(Params P, ArrayRef< uint8_t > Input, SmallVectorImpl< uint8_t > &Output)
Definition: Compression.cpp:46
llvm::compression::zstd::isAvailable
bool isAvailable()
Definition: Compression.cpp:206
llvm::inconvertibleErrorCode
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Definition: Error.cpp:79
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:156
llvm::compression::zlib::compress
void compress(ArrayRef< uint8_t > Input, SmallVectorImpl< uint8_t > &CompressedBuffer, int Level=DefaultCompression)
Definition: Compression.cpp:107
llvm::compression::getReasonIfUnsupported
const char * getReasonIfUnsupported(Format F)
Definition: Compression.cpp:30
llvm::compression::formatFor
Format formatFor(DebugCompressionType Type)
Definition: Compression.h:81
SmallVector.h
llvm::ArrayRef::size
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:163
llvm::SmallVectorImpl< uint8_t >
llvm::compression::Format::Zlib
@ Zlib
llvm::compression::decompress
Error decompress(DebugCompressionType T, ArrayRef< uint8_t > Input, uint8_t *Output, size_t UncompressedSize)
Definition: Compression.cpp:58
llvm::compression::Format::Zstd
@ Zstd