From 30f0410c399dac348cf823941cc95dfc304ce7d8 Mon Sep 17 00:00:00 2001 From: Alexey Samsonov Date: Tue, 23 Apr 2013 08:28:39 +0000 Subject: [PATCH] Add basic zlib support to LLVM. This would allow to use compression/uncompression in selected LLVM tools. llvm-svn: 180083 --- CMakeLists.txt | 2 + Makefile.config.in | 3 + autoconf/configure.ac | 27 +++ cmake/config-ix.cmake | 9 + cmake/modules/LLVM-Config.cmake | 3 + cmake/modules/LLVMConfig.cmake.in | 3 + configure | 306 +++++++++++++++++++++++++- docs/CMake.rst | 4 + docs/GettingStarted.rst | 4 + include/llvm/Config/config.h.cmake | 6 + include/llvm/Config/config.h.in | 9 + include/llvm/Support/Compression.h | 58 +++++ lib/Support/CMakeLists.txt | 1 + lib/Support/Compression.cpp | 89 ++++++++ unittests/Support/CMakeLists.txt | 1 + unittests/Support/CompressionTest.cpp | 68 ++++++ 16 files changed, 589 insertions(+), 4 deletions(-) create mode 100644 include/llvm/Support/Compression.h create mode 100644 lib/Support/Compression.cpp create mode 100644 unittests/Support/CompressionTest.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index c8c3038eba0..d15a54b9e76 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -124,6 +124,8 @@ set(LLVM_TARGET_ARCH "host" option(LLVM_ENABLE_THREADS "Use threads if available." ON) +option(LLVM_ENABLE_ZLIB "Use zlib for compression/decompression if available." ON) + if( LLVM_TARGETS_TO_BUILD STREQUAL "all" ) set( LLVM_TARGETS_TO_BUILD ${LLVM_ALL_TARGETS} ) endif() diff --git a/Makefile.config.in b/Makefile.config.in index 26e3709fee0..fd4f6ef5d81 100644 --- a/Makefile.config.in +++ b/Makefile.config.in @@ -302,6 +302,9 @@ ENABLE_DOXYGEN = @ENABLE_DOXYGEN@ # Do we want to enable threads? ENABLE_THREADS := @LLVM_ENABLE_THREADS@ +# Do we want to enable zlib? +ENABLE_ZLIB := @LLVM_ENABLE_ZLIB@ + # Do we want to build with position independent code? ENABLE_PIC := @ENABLE_PIC@ diff --git a/autoconf/configure.ac b/autoconf/configure.ac index bfad23c71b3..9c116f7c006 100644 --- a/autoconf/configure.ac +++ b/autoconf/configure.ac @@ -708,6 +708,21 @@ case "$enableval" in *) AC_MSG_ERROR([Invalid setting for --enable-pthreads. Use "yes" or "no"]) ;; esac +dnl Allow disablement of zlib +AC_ARG_ENABLE(zlib, + AS_HELP_STRING([--enable-zlib], + [Use zlib for compression/decompression if + available (default is YES)]),, + enableval=default) +case "$enableval" in + yes) AC_SUBST(LLVM_ENABLE_ZLIB,[1]) ;; + no) AC_SUBST(LLVM_ENABLE_ZLIB,[0]) ;; + default) AC_SUBST(LLVM_ENABLE_ZLIB,[1]) ;; + *) AC_MSG_ERROR([Invalid setting for --enable-zlib. Use "yes" or "no"]) ;; +esac +AC_DEFINE_UNQUOTED([LLVM_ENABLE_ZLIB],$LLVM_ENABLE_ZLIB, + [Define if zlib is enabled]) + dnl Allow building without position independent code AC_ARG_ENABLE(pic, AS_HELP_STRING([--enable-pic], @@ -1368,6 +1383,11 @@ if test "$LLVM_ENABLE_THREADS" -eq 1 && test "$ENABLE_PTHREADS" -eq 1 ; then [Have pthread_getspecific])) fi +dnl zlib is optional; used for compression/uncompression +if test "$LLVM_ENABLE_ZLIB" -eq 1 ; then + AC_CHECK_LIB(z, compress2) +fi + dnl Allow extra x86-disassembler library AC_ARG_WITH(udis86, AS_HELP_STRING([--with-udis86=], @@ -1502,6 +1522,13 @@ if test "$LLVM_ENABLE_THREADS" -eq 1 && test "$ENABLE_PTHREADS" -eq 1 ; then else AC_SUBST(HAVE_PTHREAD, 0) fi +if test "$LLVM_ENABLE_ZLIB" -eq 1 ; then + AC_CHECK_HEADERS(zlib.h, + AC_SUBST(HAVE_LIBZ, 1), + AC_SUBST(HAVE_LIBZ, 0)) +else + AC_SUBST(HAVE_LIBZ, 0) +fi dnl Try to find ffi.h. if test "$llvm_cv_enable_libffi" = "yes" ; then diff --git a/cmake/config-ix.cmake b/cmake/config-ix.cmake index 7cad190c11a..c426f41f5c9 100755 --- a/cmake/config-ix.cmake +++ b/cmake/config-ix.cmake @@ -79,6 +79,7 @@ check_include_file(unistd.h HAVE_UNISTD_H) check_include_file(utime.h HAVE_UTIME_H) check_include_file(valgrind/valgrind.h HAVE_VALGRIND_VALGRIND_H) check_include_file(windows.h HAVE_WINDOWS_H) +check_include_file(zlib.h HAVE_ZLIB_H) check_include_file(fenv.h HAVE_FENV_H) check_symbol_exists(FE_ALL_EXCEPT "fenv.h" HAVE_DECL_FE_ALL_EXCEPT) check_symbol_exists(FE_INEXACT "fenv.h" HAVE_DECL_FE_INEXACT) @@ -104,6 +105,7 @@ if( NOT PURE_WINDOWS ) endif() check_library_exists(dl dlopen "" HAVE_LIBDL) check_library_exists(rt clock_gettime "" HAVE_LIBRT) + check_library_exists(z compress2 "" HAVE_LIBZ) endif() # function checks @@ -450,4 +452,11 @@ else( LLVM_ENABLE_THREADS ) message(STATUS "Threads disabled.") endif() +if (LLVM_ENABLE_ZLIB ) + # Check if zlib is available in the system. + if ( NOT HAVE_ZLIB_H OR NOT HAVE_LIBZ ) + set(LLVM_ENABLE_ZLIB 0) + endif() +endif() + set(LLVM_PREFIX ${CMAKE_INSTALL_PREFIX}) diff --git a/cmake/modules/LLVM-Config.cmake b/cmake/modules/LLVM-Config.cmake index 163401c857c..2ddc0b2bf89 100644 --- a/cmake/modules/LLVM-Config.cmake +++ b/cmake/modules/LLVM-Config.cmake @@ -13,6 +13,9 @@ function(get_system_libs return_var) if( LLVM_ENABLE_THREADS AND HAVE_LIBPTHREAD ) set(system_libs ${system_libs} pthread) endif() + if ( LLVM_ENABLE_ZLIB AND HAVE_LIBZ ) + set(system_libs ${system_libs} z) + endif() endif( MINGW ) endif( NOT MSVC ) set(${return_var} ${system_libs} PARENT_SCOPE) diff --git a/cmake/modules/LLVMConfig.cmake.in b/cmake/modules/LLVMConfig.cmake.in index c43119ed3d3..f0b8c14ec34 100644 --- a/cmake/modules/LLVMConfig.cmake.in +++ b/cmake/modules/LLVMConfig.cmake.in @@ -22,12 +22,15 @@ set(LLVM_TOOLS_BINARY_DIR @LLVM_TOOLS_BINARY_DIR@) set(LLVM_ENABLE_THREADS @LLVM_ENABLE_THREADS@) +set(LLVM_ENABLE_ZLIB @LLVM_ENABLE_ZLIB@) + set(LLVM_NATIVE_ARCH @LLVM_NATIVE_ARCH@) set(LLVM_ENABLE_PIC @LLVM_ENABLE_PIC@) set(HAVE_LIBDL @HAVE_LIBDL@) set(HAVE_LIBPTHREAD @HAVE_LIBPTHREAD@) +set(HAVE_LIBZ @HAVE_LIBZ@) set(LLVM_ON_UNIX @LLVM_ON_UNIX@) set(LLVM_ON_WIN32 @LLVM_ON_WIN32@) diff --git a/configure b/configure index 18eacfe4344..26b612d2799 100755 --- a/configure +++ b/configure @@ -703,6 +703,7 @@ ENABLE_DOCS ENABLE_DOXYGEN LLVM_ENABLE_THREADS ENABLE_PTHREADS +LLVM_ENABLE_ZLIB ENABLE_PIC ENABLE_SHARED ENABLE_EMBED_STDCXX @@ -777,6 +778,7 @@ XML2CONFIG LIBXML2_LIBS LIBXML2_INC HAVE_PTHREAD +HAVE_LIBZ HUGE_VAL_SANITY MMAP_FILE SHLIBEXT @@ -1426,6 +1428,8 @@ Optional Features: --enable-doxygen Build doxygen documentation (default is NO) --enable-threads Use threads if available (default is YES) --enable-pthreads Use pthreads if available (default is YES) + --enable-zlib Use zlib for compression/decompression if available + (default is YES) --enable-pic Build LLVM with Position Independent Code (default is YES) --enable-shared Build a shared library and link tools against it @@ -5478,6 +5482,30 @@ echo "$as_me: error: Invalid setting for --enable-pthreads. Use \"yes\" or \"no\ { (exit 1); exit 1; }; } ;; esac +# Check whether --enable-zlib was given. +if test "${enable_zlib+set}" = set; then + enableval=$enable_zlib; +else + enableval=default +fi + +case "$enableval" in + yes) LLVM_ENABLE_ZLIB=1 + ;; + no) LLVM_ENABLE_ZLIB=0 + ;; + default) LLVM_ENABLE_ZLIB=1 + ;; + *) { { echo "$as_me:$LINENO: error: Invalid setting for --enable-zlib. Use \"yes\" or \"no\"" >&5 +echo "$as_me: error: Invalid setting for --enable-zlib. Use \"yes\" or \"no\"" >&2;} + { (exit 1); exit 1; }; } ;; +esac + +cat >>confdefs.h <<_ACEOF +#define LLVM_ENABLE_ZLIB $LLVM_ENABLE_ZLIB +_ACEOF + + # Check whether --enable-pic was given. if test "${enable_pic+set}" = set; then enableval=$enable_pic; @@ -10498,7 +10526,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <&5 +echo $ECHO_N "checking for compress2 in -lz... $ECHO_C" >&6; } +if test "${ac_cv_lib_z_compress2+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lz $LIBS" +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char compress2 (); +int +main () +{ +return compress2 (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_link") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest$ac_exeext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_z_compress2=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_cv_lib_z_compress2=no +fi + +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ echo "$as_me:$LINENO: result: $ac_cv_lib_z_compress2" >&5 +echo "${ECHO_T}$ac_cv_lib_z_compress2" >&6; } +if test $ac_cv_lib_z_compress2 = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBZ 1 +_ACEOF + + LIBS="-lz $LIBS" + +fi + +fi + # Check whether --with-udis86 was given. if test "${with_udis86+set}" = set; then @@ -16294,6 +16412,184 @@ done else HAVE_PTHREAD=0 +fi +if test "$LLVM_ENABLE_ZLIB" -eq 1 ; then + +for ac_header in zlib.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + { echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } +else + # Is the header compilable? +{ echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_compile") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -z "$ac_c_werror_flag" || test ! -s conftest.err' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; } && + { ac_try='test -s conftest.$ac_objext' + { (case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_compiler=no +fi + +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6; } + +# Is the header present? +{ echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6; } +cat >conftest.$ac_ext <<_ACEOF +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + ac_cpp_err=$ac_cpp_err$ac_c_werror_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi + +rm -f conftest.err conftest.$ac_ext +{ echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in + yes:no: ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the compiler's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the compiler's result" >&2;} + ac_header_preproc=yes + ;; + no:yes:* ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: see the Autoconf documentation" >&5 +echo "$as_me: WARNING: $ac_header: see the Autoconf documentation" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&5 +echo "$as_me: WARNING: $ac_header: section \"Present But Cannot Be Compiled\"" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: in the future, the compiler will take precedence" >&5 +echo "$as_me: WARNING: $ac_header: in the future, the compiler will take precedence" >&2;} + ( cat <<\_ASBOX +## ------------------------------------ ## +## Report this to http://llvm.org/bugs/ ## +## ------------------------------------ ## +_ASBOX + ) | sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +{ echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; } +if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=\$ac_header_preproc" +fi +ac_res=`eval echo '${'$as_ac_Header'}'` + { echo "$as_me:$LINENO: result: $ac_res" >&5 +echo "${ECHO_T}$ac_res" >&6; } + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + HAVE_LIBZ=1 + +else + HAVE_LIBZ=0 + +fi + +done + +else + HAVE_LIBZ=0 + fi if test "$llvm_cv_enable_libffi" = "yes" ; then @@ -22692,6 +22988,7 @@ ENABLE_DOCS!$ENABLE_DOCS$ac_delim ENABLE_DOXYGEN!$ENABLE_DOXYGEN$ac_delim LLVM_ENABLE_THREADS!$LLVM_ENABLE_THREADS$ac_delim ENABLE_PTHREADS!$ENABLE_PTHREADS$ac_delim +LLVM_ENABLE_ZLIB!$LLVM_ENABLE_ZLIB$ac_delim ENABLE_PIC!$ENABLE_PIC$ac_delim ENABLE_SHARED!$ENABLE_SHARED$ac_delim ENABLE_EMBED_STDCXX!$ENABLE_EMBED_STDCXX$ac_delim @@ -22766,6 +23063,7 @@ XML2CONFIG!$XML2CONFIG$ac_delim LIBXML2_LIBS!$LIBXML2_LIBS$ac_delim LIBXML2_INC!$LIBXML2_INC$ac_delim HAVE_PTHREAD!$HAVE_PTHREAD$ac_delim +HAVE_LIBZ!$HAVE_LIBZ$ac_delim HUGE_VAL_SANITY!$HUGE_VAL_SANITY$ac_delim MMAP_FILE!$MMAP_FILE$ac_delim SHLIBEXT!$SHLIBEXT$ac_delim @@ -22783,8 +23081,6 @@ LLVM_CONFIGTIME!$LLVM_CONFIGTIME$ac_delim BINDINGS_TO_BUILD!$BINDINGS_TO_BUILD$ac_delim ALL_BINDINGS!$ALL_BINDINGS$ac_delim OCAML_LIBDIR!$OCAML_LIBDIR$ac_delim -ENABLE_VISIBILITY_INLINES_HIDDEN!$ENABLE_VISIBILITY_INLINES_HIDDEN$ac_delim -RPATH!$RPATH$ac_delim _ACEOF if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then @@ -22826,13 +23122,15 @@ _ACEOF ac_delim='%!_!# ' for ac_last_try in false false false false false :; do cat >conf$$subs.sed <<_ACEOF +ENABLE_VISIBILITY_INLINES_HIDDEN!$ENABLE_VISIBILITY_INLINES_HIDDEN$ac_delim +RPATH!$RPATH$ac_delim RDYNAMIC!$RDYNAMIC$ac_delim program_prefix!$program_prefix$ac_delim LIBOBJS!$LIBOBJS$ac_delim LTLIBOBJS!$LTLIBOBJS$ac_delim _ACEOF - if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 4; then + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 6; then break elif $ac_last_try; then { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 diff --git a/docs/CMake.rst b/docs/CMake.rst index 991e4ba6da9..8459081fb8b 100644 --- a/docs/CMake.rst +++ b/docs/CMake.rst @@ -271,6 +271,10 @@ LLVM-specific variables **LLVM_USE_INTEL_JITEVENTS**:BOOL Enable building support for Intel JIT Events API. Defaults to OFF +**LLVM_ENABLE_ZLIB**:BOOL + Build with zlib to support compression/uncompression in LLVM tools. + Defaults to ON. + Executing the test suite ======================== diff --git a/docs/GettingStarted.rst b/docs/GettingStarted.rst index 0bbbafc6e69..4ad2c79dc44 100644 --- a/docs/GettingStarted.rst +++ b/docs/GettingStarted.rst @@ -229,6 +229,8 @@ uses the package and provides other details. +--------------------------------------------------------------+-----------------+---------------------------------------------+ | `libtool `_ | 1.5.22 | Shared library manager\ :sup:`4` | +--------------------------------------------------------------+-----------------+---------------------------------------------+ +| `zlib `_ | >=1.2.3.4 | Compression library\ :sup:`5` | ++--------------------------------------------------------------+-----------------+---------------------------------------------+ .. note:: @@ -243,6 +245,8 @@ uses the package and provides other details. #. If you want to make changes to the configure scripts, you will need GNU autoconf (2.60), and consequently, GNU M4 (version 1.4 or higher). You will also need automake (1.9.6). We only use aclocal from that package. + #. Optional, adds compression/uncompression capabilities to selected LLVM + tools. Additionally, your compilation host is expected to have the usual plethora of Unix utilities. Specifically: diff --git a/include/llvm/Config/config.h.cmake b/include/llvm/Config/config.h.cmake index 0a268573978..408c590bebb 100644 --- a/include/llvm/Config/config.h.cmake +++ b/include/llvm/Config/config.h.cmake @@ -498,6 +498,9 @@ /* Define if the xdot.py program is available */ #cmakedefine HAVE_XDOT_PY ${HAVE_XDOT_PY} +/* Define to 1 if you have the header file. */ +#cmakedefine HAVE_ZLIB_H ${HAVE_ZLIB_H} + /* Have host's _alloca */ #cmakedefine HAVE__ALLOCA ${HAVE__ALLOCA} @@ -570,6 +573,9 @@ /* Define if threads enabled */ #cmakedefine01 LLVM_ENABLE_THREADS +/* Define if zlib compression is available */ +#cmakedefine01 LLVM_ENABLE_ZLIB + /* Installation directory for config files */ #cmakedefine LLVM_ETCDIR "${LLVM_ETCDIR}" diff --git a/include/llvm/Config/config.h.in b/include/llvm/Config/config.h.in index 5a3d02c553e..7f75f4df69c 100644 --- a/include/llvm/Config/config.h.in +++ b/include/llvm/Config/config.h.in @@ -226,6 +226,9 @@ /* Define to 1 if you have the `udis86' library (-ludis86). */ #undef HAVE_LIBUDIS86 +/* Define to 1 if you have the `z' library (-lz). */ +#undef HAVE_LIBZ + /* Define to 1 if you have the header file. */ #undef HAVE_LIMITS_H @@ -503,6 +506,9 @@ /* Define if the xdot.py program is available */ #undef HAVE_XDOT_PY +/* Define to 1 if you have the header file. */ +#undef HAVE_ZLIB_H + /* Have host's _alloca */ #undef HAVE__ALLOCA @@ -575,6 +581,9 @@ /* Define if threads enabled */ #undef LLVM_ENABLE_THREADS +/* Define if zlib is enabled */ +#undef LLVM_ENABLE_ZLIB + /* Installation directory for config files */ #undef LLVM_ETCDIR diff --git a/include/llvm/Support/Compression.h b/include/llvm/Support/Compression.h new file mode 100644 index 00000000000..9b1142d035d --- /dev/null +++ b/include/llvm/Support/Compression.h @@ -0,0 +1,58 @@ +//===-- llvm/Support/Compression.h ---Compression----------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file contains basic functions for compression/uncompression. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_SUPPORT_COMPRESSION_H +#define LLVM_SUPPORT_COMPRESSION_H + +#include "llvm/Support/DataTypes.h" + +namespace llvm { + +class MemoryBuffer; +template class OwningPtr; +class StringRef; + +namespace zlib { + +enum CompressionLevel { + NoCompression, + DefaultCompression, + BestSpeedCompression, + BestSizeCompression +}; + +enum Status { + StatusOK, + StatusUnsupported, // zlib is unavaliable + StatusOutOfMemory, // there was not enough memory + StatusBufferTooShort, // there was not enough room in the output buffer + StatusInvalidArg, // invalid input parameter + StatusInvalidData // data was corrupted or incomplete +}; + +bool isAvailable(); + +Status compress(StringRef InputBuffer, + OwningPtr &CompressedBuffer, + CompressionLevel Level = DefaultCompression); + +Status uncompress(StringRef InputBuffer, + OwningPtr &UncompressedBuffer, + size_t UncompressedSize); + +} // End of namespace zlib + +} // End of namespace llvm + +#endif + diff --git a/lib/Support/CMakeLists.txt b/lib/Support/CMakeLists.txt index 3746a810114..01565c57769 100644 --- a/lib/Support/CMakeLists.txt +++ b/lib/Support/CMakeLists.txt @@ -7,6 +7,7 @@ add_llvm_library(LLVMSupport BranchProbability.cpp circular_raw_ostream.cpp CommandLine.cpp + Compression.cpp ConstantRange.cpp ConvertUTF.c ConvertUTFWrapper.cpp diff --git a/lib/Support/Compression.cpp b/lib/Support/Compression.cpp new file mode 100644 index 00000000000..d0adf79ec78 --- /dev/null +++ b/lib/Support/Compression.cpp @@ -0,0 +1,89 @@ +//===--- Compression.cpp - Compression implementation ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements compression functions. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Compression.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Config/config.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/MemoryBuffer.h" +#if LLVM_ENABLE_ZLIB == 1 && HAVE_ZLIB_H +#include +#endif + +using namespace llvm; + +#if LLVM_ENABLE_ZLIB == 1 +static int encodeZlibCompressionLevel(zlib::CompressionLevel Level) { + switch (Level) { + case zlib::NoCompression: return 0; + case zlib::BestSpeedCompression: return 1; + case zlib::DefaultCompression: return Z_DEFAULT_COMPRESSION; + case zlib::BestSizeCompression: return 9; + } +} + +static zlib::Status encodeZlibReturnValue(int ReturnValue) { + switch (ReturnValue) { + case Z_OK: return zlib::StatusOK; + case Z_MEM_ERROR: return zlib::StatusOutOfMemory; + case Z_BUF_ERROR: return zlib::StatusBufferTooShort; + case Z_STREAM_ERROR: return zlib::StatusInvalidArg; + case Z_DATA_ERROR: return zlib::StatusInvalidData; + default: llvm_unreachable("unknown zlib return status!"); + } +} + +bool zlib::isAvailable() { return true; } +zlib::Status zlib::compress(StringRef InputBuffer, + OwningPtr &CompressedBuffer, + CompressionLevel Level) { + unsigned long CompressedSize = ::compressBound(InputBuffer.size()); + OwningArrayPtr TmpBuffer(new char[CompressedSize]); + int CLevel = encodeZlibCompressionLevel(Level); + Status Res = encodeZlibReturnValue(::compress2( + (Bytef *)TmpBuffer.get(), &CompressedSize, + (const Bytef *)InputBuffer.data(), InputBuffer.size(), CLevel)); + if (Res == StatusOK) + CompressedBuffer.reset(MemoryBuffer::getMemBufferCopy( + StringRef(TmpBuffer.get(), CompressedSize))); + return Res; +} + +zlib::Status zlib::uncompress(StringRef InputBuffer, + OwningPtr &UncompressedBuffer, + size_t UncompressedSize) { + OwningArrayPtr TmpBuffer(new char[UncompressedSize]); + Status Res = encodeZlibReturnValue( + ::uncompress((Bytef *)TmpBuffer.get(), (uLongf *)&UncompressedSize, + (const Bytef *)InputBuffer.data(), InputBuffer.size())); + if (Res == StatusOK) + UncompressedBuffer.reset(MemoryBuffer::getMemBufferCopy( + StringRef(TmpBuffer.get(), UncompressedSize))); + return Res; +} + +#else +bool zlib::isAvailable() { return false; } +zlib::Status zlib::compress(StringRef InputBuffer, + OwningPtr &CompressedBuffer, + CompressionLevel Level) { + return zlib::StatusUnsupported; +} +zlib::Status zlib::uncompress(StringRef InputBuffer, + OwningPtr &UncompressedBuffer, + size_t UncompressedSize) { + return zlib::StatusUnsupported; +} +#endif + diff --git a/unittests/Support/CMakeLists.txt b/unittests/Support/CMakeLists.txt index a5bf3aef62b..e6cafbcaf15 100644 --- a/unittests/Support/CMakeLists.txt +++ b/unittests/Support/CMakeLists.txt @@ -10,6 +10,7 @@ add_llvm_unittest(SupportTests BlockFrequencyTest.cpp Casting.cpp CommandLineTest.cpp + CompressionTest.cpp ConstantRangeTest.cpp DataExtractorTest.cpp EndianTest.cpp diff --git a/unittests/Support/CompressionTest.cpp b/unittests/Support/CompressionTest.cpp new file mode 100644 index 00000000000..aad7ed0e89a --- /dev/null +++ b/unittests/Support/CompressionTest.cpp @@ -0,0 +1,68 @@ +//===- llvm/unittest/Support/CompressionTest.cpp - Compression tests ------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements unit tests for the Compression functions. +// +//===----------------------------------------------------------------------===// + +#include "llvm/Support/Compression.h" +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Config/config.h" +#include "llvm/Support/MemoryBuffer.h" +#include "gtest/gtest.h" + +using namespace llvm; + +namespace { + +#if LLVM_ENABLE_ZLIB == 1 + +void TestZlibCompression(StringRef Input, zlib::CompressionLevel Level) { + OwningPtr Compressed; + OwningPtr Uncompressed; + EXPECT_EQ(zlib::StatusOK, zlib::compress(Input, Compressed, Level)); + // Check that uncompressed buffer is the same as original. + EXPECT_EQ(zlib::StatusOK, zlib::uncompress(Compressed->getBuffer(), + Uncompressed, Input.size())); + EXPECT_EQ(Input.size(), Uncompressed->getBufferSize()); + EXPECT_EQ(0, + memcmp(Input.data(), Uncompressed->getBufferStart(), Input.size())); + if (Input.size() > 0) { + // Uncompression fails if expected length is too short. + EXPECT_EQ(zlib::StatusBufferTooShort, + zlib::uncompress(Compressed->getBuffer(), Uncompressed, + Input.size() - 1)); + } +} + +TEST(CompressionTest, Zlib) { + TestZlibCompression("", zlib::DefaultCompression); + + TestZlibCompression("hello, world!", zlib::NoCompression); + TestZlibCompression("hello, world!", zlib::BestSizeCompression); + TestZlibCompression("hello, world!", zlib::BestSpeedCompression); + TestZlibCompression("hello, world!", zlib::DefaultCompression); + + const size_t kSize = 1024; + char BinaryData[kSize]; + for (size_t i = 0; i < kSize; ++i) { + BinaryData[i] = i & 255; + } + StringRef BinaryDataStr(BinaryData, kSize); + + TestZlibCompression(BinaryDataStr, zlib::NoCompression); + TestZlibCompression(BinaryDataStr, zlib::BestSizeCompression); + TestZlibCompression(BinaryDataStr, zlib::BestSpeedCompression); + TestZlibCompression(BinaryDataStr, zlib::DefaultCompression); +} + +#endif + +}