# https://github.com/llvm/llvm-project/issues/55785
msan-options: use_sigaltstack=0
+ - name: Ubuntu Clang RISC-V
+ os: ubuntu-latest
+ cmake-args: -GNinja -DCMAKE_TOOLCHAIN_FILE=./cmake/toolchain-riscv.cmake -DTOOLCHAIN_PATH=${PWD}/prebuilt-riscv-toolchain-qemu/riscv-clang -DQEMU_PATH=${PWD}/prebuilt-riscv-toolchain-qemu/riscv-qemu/bin/qemu-riscv64
+ packages: build-essential cmake ninja-build
+ codecov: ubuntu_clang_toolchain_riscv
+
- name: Ubuntu Emscripten WASM32
os: ubuntu-latest
chost: wasm32
sudo apt-get update
sudo apt-get install -y --allow-downgrades --no-install-recommends ${{ matrix.packages }}
+ - name: Download prebuilt RISC-V Clang toolchain & QEMU emulator
+ if: runner.os == 'Linux' && contains(matrix.name, 'RISC-V')
+ run: |
+ gh release download ubuntu20.04_llvm16.0.0_qemu7.0.0 --repo sifive/prepare-riscv-toolchain-qemu
+ tar zxvf prebuilt-riscv-toolchain-qemu.tar.gz
+ env:
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+
- name: Install packages (Windows)
if: runner.os == 'Windows'
run: |
option(WITH_ALTIVEC "Build with AltiVec (VMX) optimisations for PowerPC" ON)
option(WITH_POWER8 "Build with optimisations for POWER8" ON)
option(WITH_POWER9 "Build with optimisations for POWER9" ON)
+elseif(BASEARCH_RISCV_FOUND)
+ option(WITH_RVV "Build with RVV intrinsics" ON)
elseif(BASEARCH_S360_FOUND)
option(WITH_DFLTCC_DEFLATE "Build with DFLTCC intrinsics for compression on IBM Z" OFF)
option(WITH_DFLTCC_INFLATE "Build with DFLTCC intrinsics for decompression on IBM Z" OFF)
WITH_ALTIVEC
WITH_POWER8
WITH_POWER9
+ WITH_RVV
WITH_INFLATE_STRICT
WITH_INFLATE_ALLOW_INVALID_DIST
WITH_UNALIGNED
set(ARCHDIR "arch/arm")
elseif(BASEARCH_PPC_FOUND)
set(ARCHDIR "arch/power")
+elseif(BASEARCH_RISCV_FOUND)
+ set(ARCHDIR "arch/riscv")
elseif(BASEARCH_S360_FOUND)
set(ARCHDIR "arch/s390")
elseif(BASEARCH_X86_FOUND)
set(WITH_POWER9 OFF)
endif()
endif()
+ elseif(BASEARCH_RISCV_FOUND)
+ if(WITH_RVV)
+ check_rvv_intrinsics()
+ if(HAVE_RVV_INTRIN)
+ add_definitions(-DRISCV_FEATURES)
+ add_definitions(-DRISCV_RVV)
+ list(APPEND ZLIB_ARCH_HDRS ${ARCHDIR}/riscv_features.h)
+ list(APPEND ZLIB_ARCH_SRCS ${ARCHDIR}/riscv_features.c)
+ else()
+ set(WITH_RVV OFF)
+ endif()
+ endif()
elseif(BASEARCH_S360_FOUND)
check_s390_intrinsics()
if(HAVE_S390_INTRIN)
add_feature_info(WITH_ALTIVEC WITH_ALTIVEC "Build with AltiVec optimisations")
add_feature_info(WITH_POWER8 WITH_POWER8 "Build with optimisations for POWER8")
add_feature_info(WITH_POWER9 WITH_POWER9 "Build with optimisations for POWER9")
+elseif(BASEARCH_RISCV_FOUND)
+ add_feature_info(WITH_RVV WITH_RVV "Build with RVV intrinsics")
elseif(BASEARCH_S360_FOUND)
add_feature_info(WITH_DFLTCC_DEFLATE WITH_DFLTCC_DEFLATE "Build with DFLTCC intrinsics for compression on IBM Z")
add_feature_info(WITH_DFLTCC_INFLATE WITH_DFLTCC_INFLATE "Build with DFLTCC intrinsics for decompression on IBM Z")
* Comprehensive set of CMake unit tests
* Code sanitizers, fuzzing, and coverage
* GitHub Actions continuous integration on Windows, macOS, and Linux
- * Emulated CI for ARM, AARCH64, PPC, PPC64, SPARC64, S390x using qemu
+ * Emulated CI for ARM, AARCH64, PPC, PPC64, RISCV, SPARC64, S390x using qemu
History
| WITH_NEON | --without-neon | Build with NEON intrinsics | ON |
| WITH_ALTIVEC | --without-altivec | Build with AltiVec (VMX) intrinsics | ON |
| WITH_POWER8 | --without-power8 | Build with POWER8 optimisations | ON |
+| WITH_RVV | | Build with RVV intrinsics | ON |
| WITH_CRC32_VX | --without-crc32-vx | Build with vectorized CRC32 on IBM Z | ON |
| WITH_DFLTCC_DEFLATE | --with-dfltcc-deflate | Build with DFLTCC intrinsics for compression on IBM Z | OFF |
| WITH_DFLTCC_INFLATE | --with-dfltcc-inflate | Build with DFLTCC intrinsics for decompression on IBM Z | OFF |
--- /dev/null
+# Building RISC-V Target with Cmake #
+
+> **Warning**
+> We cannot detect rvv support at runtime, running the rvv code on a no-rvv target is a risk. Users should disable the rvv when the target does not support it.
+>
+> We will have a better solution when the kernels update `hwcap` or `hwprobe` for risc-v.
+
+## Prerequisite: Build RISC-V Clang Toolchain and QEMU ##
+
+If you don't have prebuilt clang and riscv64 qemu, you can refer to the [script](https://github.com/sifive/prepare-riscv-toolchain-qemu/blob/main/prepare_riscv_toolchain_qemu.sh) to get the source. Copy the script to the zlib-ng root directory, and run it to download the source and build them. Modify the content according to your conditions (e.g., toolchain version).
+
+```bash
+./prepare_riscv_toolchain_qemu.sh
+```
+
+After running script, clang & qemu are built in `build-toolchain-qemu/riscv-clang/` & `build-toolchain-qemu/riscv-qemu/`.
+
+`build-toolchain-qemu/riscv-clang/` is your `TOOLCHAIN_PATH`.
+`build-toolchain-qemu/riscv-qemu/bin/qemu-riscv64` is your `QEMU_PATH`.
+
+You can also download the prebuilt toolchain & qemu from [the release page](https://github.com/sifive/prepare-riscv-toolchain-qemu/releases), and enjoy using them.
+
+## Cross-Compile for RISC-V Target ##
+
+```bash
+cmake -G Ninja -B ./build-riscv \
+ -D CMAKE_TOOLCHAIN_FILE=./cmake/toolchain-riscv.cmake \
+ -D CMAKE_INSTALL_PREFIX=./build-riscv/install \
+ -D TOOLCHAIN_PATH={TOOLCHAIN_PATH} \
+ -D QEMU_PATH={QEMU_PATH} \
+ .
+
+cmake --build ./build-riscv
+```
+
+Disable the option if there is no RVV support:
+```
+-D WITH_RVV=OFF
+```
+
+## Run Unittests on User Mode QEMU ##
+
+```bash
+cd ./build-riscv && ctest --verbose
+```
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../../zbuild.h"
+#include "riscv_features.h"
+
+/* TODO: detect risc-v cpu info at runtime when the kernel updates hwcap or hwprobe for risc-v */
+void Z_INTERNAL riscv_check_features(struct riscv_cpu_features *features) {
+#if defined(__riscv_v) && defined(__linux__)
+ features->has_rvv = 1;
+#else
+ features->has_rvv = 0;
+#endif
+}
--- /dev/null
+/* riscv_features.h -- check for riscv features.
+ *
+ * Copyright (C) 2023 SiFive, Inc. All rights reserved.
+ * Contributed by Alex Chiang <alex.chiang@sifive.com>
+ *
+ * For conditions of distribution and use, see copyright notice in zlib.h
+ */
+
+#ifndef RISCV_H_
+#define RISCV_H_
+
+struct riscv_cpu_features {
+ int has_rvv;
+};
+
+void Z_INTERNAL riscv_check_features(struct riscv_cpu_features *features);
+
+#endif /* RISCV_H_ */
set(CMAKE_REQUIRED_FLAGS)
endmacro()
+macro(check_rvv_intrinsics)
+ if(CMAKE_C_COMPILER_ID MATCHES "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang")
+ if(NOT NATIVEFLAG)
+ set(RISCVFLAG "-march=rv64gcv")
+ endif()
+ endif()
+ # Check whether compiler supports RVV
+ set(CMAKE_REQUIRED_FLAGS "${RISCVFLAG} ${NATIVEFLAG}")
+ check_c_source_compiles(
+ "#include <riscv_vector.h>
+ int main() {
+ return 0;
+ }"
+ HAVE_RVV_INTRIN
+ )
+ set(CMAKE_REQUIRED_FLAGS)
+endmacro()
+
macro(check_s390_intrinsics)
check_c_source_compiles(
"#include <sys/auxv.h>
--- /dev/null
+set(CMAKE_CROSSCOMPILING TRUE)
+set(CMAKE_SYSTEM_NAME "Linux")
+set(CMAKE_SYSTEM_PROCESSOR "riscv64")
+
+# Avoid to use system path for cross-compile
+set(CMAKE_FIND_USE_CMAKE_SYSTEM_PATH FALSE)
+
+set(TOOLCHAIN_PATH "" CACHE STRING "The toolchain path.")
+if(NOT TOOLCHAIN_PATH)
+ set(TOOLCHAIN_PATH ${CMAKE_SOURCE_DIR}/prebuilt-riscv-toolchain-qemu/riscv-clang)
+endif()
+
+set(TOOLCHAIN_PREFIX "riscv64-unknown-linux-gnu-" CACHE STRING "The toolchain prefix.")
+set(QEMU_PATH "" CACHE STRING "The qemu path.")
+if(NOT QEMU_PATH)
+ set(QEMU_PATH ${CMAKE_SOURCE_DIR}/prebuilt-riscv-toolchain-qemu/riscv-qemu/bin/qemu-riscv64)
+endif()
+
+# toolchain setting
+set(CMAKE_C_COMPILER "${TOOLCHAIN_PATH}/bin/${TOOLCHAIN_PREFIX}clang")
+set(CMAKE_CXX_COMPILER "${TOOLCHAIN_PATH}/bin/${TOOLCHAIN_PREFIX}clang++")
+
+# disable auto-vectorizer
+add_compile_options(-fno-vectorize -fno-slp-vectorize)
+
+# emulator setting
+set(QEMU_CPU_OPTION "rv64,zba=true,zbb=true,zbc=true,zbs=true,v=true,vlen=512,elen=64,vext_spec=v1.0")
+set(CMAKE_CROSSCOMPILING_EMULATOR ${QEMU_PATH} -cpu ${QEMU_CPU_OPTION} -L ${TOOLCHAIN_PATH}/sysroot/)
power_check_features(&features->power);
#elif defined(S390_FEATURES)
s390_check_features(&features->s390);
+#elif defined(RISCV_FEATURES)
+ riscv_check_features(&features->riscv);
#endif
}
# include "arch/power/power_features.h"
#elif defined(S390_FEATURES)
# include "arch/s390/s390_features.h"
+#elif defined(RISCV_FEATURES)
+# include "arch/riscv/riscv_features.h"
#endif
struct cpu_features {
struct power_cpu_features power;
#elif defined(S390_FEATURES)
struct s390_cpu_features s390;
+#elif defined(RISCV_FEATURES)
+ struct riscv_cpu_features riscv;
#else
char empty;
#endif