Compression.cpp 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  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. #include "llvm/Support/Compression.h"
  13. #include "llvm/ADT/SmallVector.h"
  14. #include "llvm/ADT/StringRef.h"
  15. #include "llvm/Config/config.h"
  16. #include "llvm/Support/Compiler.h"
  17. #include "llvm/Support/Error.h"
  18. #include "llvm/Support/ErrorHandling.h"
  19. #if LLVM_ENABLE_ZLIB
  20. #include <zlib.h>
  21. #endif
  22. #if LLVM_ENABLE_ZSTD
  23. #error #include <zstd.h>
  24. #endif
  25. using namespace llvm;
  26. using namespace llvm::compression;
  27. const char *compression::getReasonIfUnsupported(compression::Format F) {
  28. switch (F) {
  29. case compression::Format::Zlib:
  30. if (zlib::isAvailable())
  31. return nullptr;
  32. return "LLVM was not built with LLVM_ENABLE_ZLIB or did not find zlib at "
  33. "build time";
  34. case compression::Format::Zstd:
  35. if (zstd::isAvailable())
  36. return nullptr;
  37. return "LLVM was not built with LLVM_ENABLE_ZSTD or did not find zstd at "
  38. "build time";
  39. }
  40. llvm_unreachable("");
  41. }
  42. void compression::compress(Params P, ArrayRef<uint8_t> Input,
  43. SmallVectorImpl<uint8_t> &Output) {
  44. switch (P.format) {
  45. case compression::Format::Zlib:
  46. zlib::compress(Input, Output, P.level);
  47. break;
  48. case compression::Format::Zstd:
  49. zstd::compress(Input, Output, P.level);
  50. break;
  51. }
  52. }
  53. Error compression::decompress(DebugCompressionType T, ArrayRef<uint8_t> Input,
  54. uint8_t *Output, size_t UncompressedSize) {
  55. switch (formatFor(T)) {
  56. case compression::Format::Zlib:
  57. return zlib::decompress(Input, Output, UncompressedSize);
  58. case compression::Format::Zstd:
  59. return zstd::decompress(Input, Output, UncompressedSize);
  60. }
  61. llvm_unreachable("");
  62. }
  63. Error compression::decompress(compression::Format F, ArrayRef<uint8_t> Input,
  64. SmallVectorImpl<uint8_t> &Output,
  65. size_t UncompressedSize) {
  66. switch (F) {
  67. case compression::Format::Zlib:
  68. return zlib::decompress(Input, Output, UncompressedSize);
  69. case compression::Format::Zstd:
  70. return zstd::decompress(Input, Output, UncompressedSize);
  71. }
  72. llvm_unreachable("");
  73. }
  74. Error compression::decompress(DebugCompressionType T, ArrayRef<uint8_t> Input,
  75. SmallVectorImpl<uint8_t> &Output,
  76. size_t UncompressedSize) {
  77. return decompress(formatFor(T), Input, Output, UncompressedSize);
  78. }
  79. #if LLVM_ENABLE_ZLIB
  80. static StringRef convertZlibCodeToString(int Code) {
  81. switch (Code) {
  82. case Z_MEM_ERROR:
  83. return "zlib error: Z_MEM_ERROR";
  84. case Z_BUF_ERROR:
  85. return "zlib error: Z_BUF_ERROR";
  86. case Z_STREAM_ERROR:
  87. return "zlib error: Z_STREAM_ERROR";
  88. case Z_DATA_ERROR:
  89. return "zlib error: Z_DATA_ERROR";
  90. case Z_OK:
  91. default:
  92. llvm_unreachable("unknown or unexpected zlib status code");
  93. }
  94. }
  95. bool zlib::isAvailable() { return true; }
  96. void zlib::compress(ArrayRef<uint8_t> Input,
  97. SmallVectorImpl<uint8_t> &CompressedBuffer, int Level) {
  98. unsigned long CompressedSize = ::compressBound(Input.size());
  99. CompressedBuffer.resize_for_overwrite(CompressedSize);
  100. int Res = ::compress2((Bytef *)CompressedBuffer.data(), &CompressedSize,
  101. (const Bytef *)Input.data(), Input.size(), Level);
  102. if (Res == Z_MEM_ERROR)
  103. report_bad_alloc_error("Allocation failed");
  104. assert(Res == Z_OK);
  105. // Tell MemorySanitizer that zlib output buffer is fully initialized.
  106. // This avoids a false report when running LLVM with uninstrumented ZLib.
  107. __msan_unpoison(CompressedBuffer.data(), CompressedSize);
  108. if (CompressedSize < CompressedBuffer.size())
  109. CompressedBuffer.truncate(CompressedSize);
  110. }
  111. Error zlib::decompress(ArrayRef<uint8_t> Input, uint8_t *Output,
  112. size_t &UncompressedSize) {
  113. int Res = ::uncompress((Bytef *)Output, (uLongf *)&UncompressedSize,
  114. (const Bytef *)Input.data(), Input.size());
  115. // Tell MemorySanitizer that zlib output buffer is fully initialized.
  116. // This avoids a false report when running LLVM with uninstrumented ZLib.
  117. __msan_unpoison(Output, UncompressedSize);
  118. return Res ? make_error<StringError>(convertZlibCodeToString(Res),
  119. inconvertibleErrorCode())
  120. : Error::success();
  121. }
  122. Error zlib::decompress(ArrayRef<uint8_t> Input,
  123. SmallVectorImpl<uint8_t> &Output,
  124. size_t UncompressedSize) {
  125. Output.resize_for_overwrite(UncompressedSize);
  126. Error E = zlib::decompress(Input, Output.data(), UncompressedSize);
  127. if (UncompressedSize < Output.size())
  128. Output.truncate(UncompressedSize);
  129. return E;
  130. }
  131. #else
  132. bool zlib::isAvailable() { return false; }
  133. void zlib::compress(ArrayRef<uint8_t> Input,
  134. SmallVectorImpl<uint8_t> &CompressedBuffer, int Level) {
  135. llvm_unreachable("zlib::compress is unavailable");
  136. }
  137. Error zlib::decompress(ArrayRef<uint8_t> Input, uint8_t *UncompressedBuffer,
  138. size_t &UncompressedSize) {
  139. llvm_unreachable("zlib::decompress is unavailable");
  140. }
  141. Error zlib::decompress(ArrayRef<uint8_t> Input,
  142. SmallVectorImpl<uint8_t> &UncompressedBuffer,
  143. size_t UncompressedSize) {
  144. llvm_unreachable("zlib::decompress is unavailable");
  145. }
  146. #endif
  147. #if LLVM_ENABLE_ZSTD
  148. bool zstd::isAvailable() { return true; }
  149. void zstd::compress(ArrayRef<uint8_t> Input,
  150. SmallVectorImpl<uint8_t> &CompressedBuffer, int Level) {
  151. unsigned long CompressedBufferSize = ::ZSTD_compressBound(Input.size());
  152. CompressedBuffer.resize_for_overwrite(CompressedBufferSize);
  153. unsigned long CompressedSize =
  154. ::ZSTD_compress((char *)CompressedBuffer.data(), CompressedBufferSize,
  155. (const char *)Input.data(), Input.size(), Level);
  156. if (ZSTD_isError(CompressedSize))
  157. report_bad_alloc_error("Allocation failed");
  158. // Tell MemorySanitizer that zstd output buffer is fully initialized.
  159. // This avoids a false report when running LLVM with uninstrumented ZLib.
  160. __msan_unpoison(CompressedBuffer.data(), CompressedSize);
  161. if (CompressedSize < CompressedBuffer.size())
  162. CompressedBuffer.truncate(CompressedSize);
  163. }
  164. Error zstd::decompress(ArrayRef<uint8_t> Input, uint8_t *Output,
  165. size_t &UncompressedSize) {
  166. const size_t Res = ::ZSTD_decompress(
  167. Output, UncompressedSize, (const uint8_t *)Input.data(), Input.size());
  168. UncompressedSize = Res;
  169. // Tell MemorySanitizer that zstd output buffer is fully initialized.
  170. // This avoids a false report when running LLVM with uninstrumented ZLib.
  171. __msan_unpoison(Output, UncompressedSize);
  172. return ZSTD_isError(Res) ? make_error<StringError>(ZSTD_getErrorName(Res),
  173. inconvertibleErrorCode())
  174. : Error::success();
  175. }
  176. Error zstd::decompress(ArrayRef<uint8_t> Input,
  177. SmallVectorImpl<uint8_t> &Output,
  178. size_t UncompressedSize) {
  179. Output.resize_for_overwrite(UncompressedSize);
  180. Error E = zstd::decompress(Input, Output.data(), UncompressedSize);
  181. if (UncompressedSize < Output.size())
  182. Output.truncate(UncompressedSize);
  183. return E;
  184. }
  185. #else
  186. bool zstd::isAvailable() { return false; }
  187. void zstd::compress(ArrayRef<uint8_t> Input,
  188. SmallVectorImpl<uint8_t> &CompressedBuffer, int Level) {
  189. llvm_unreachable("zstd::compress is unavailable");
  190. }
  191. Error zstd::decompress(ArrayRef<uint8_t> Input, uint8_t *Output,
  192. size_t &UncompressedSize) {
  193. llvm_unreachable("zstd::decompress is unavailable");
  194. }
  195. Error zstd::decompress(ArrayRef<uint8_t> Input,
  196. SmallVectorImpl<uint8_t> &Output,
  197. size_t UncompressedSize) {
  198. llvm_unreachable("zstd::decompress is unavailable");
  199. }
  200. #endif