diff --git a/.github/workflows/rvv-1024-clang-18.yml b/.github/workflows/rvv-1024-clang-18.yml index 4ba16d02b..a22a8a8f9 100644 --- a/.github/workflows/rvv-1024-clang-18.yml +++ b/.github/workflows/rvv-1024-clang-18.yml @@ -19,11 +19,11 @@ jobs: sudo apt-get install -y cmake make g++-riscv64-linux-gnu qemu-user-static clang-18 - name: Build run: | - CXX=clang++-18 CXXFLAGS="--target=riscv64-linux-gnu -march=rv64gcv_zvbb" \ - cmake --toolchain=cmake/toolchains-ci/riscv64-linux-gnu.cmake -DCMAKE_BUILD_TYPE=Release -B build - cmake --build build/ -j$(nproc) + CC=clang-18 CXX=clang++-18 CFLAGS="--target=riscv64-linux-gnu -march=rv64gcv_zvbb" CXXFLAGS="${CFLAGS}" \ + cmake --toolchain=cmake/toolchains-ci/riscv64-linux-gnu.cmake -DSIMDJSON_DEVELOPER_MODE=ON -B build + cmake --build build/ -j$(nproc) --config Release - name: Test VLEN=1024 run: | - export QEMU_LD_PREFIX="/usr/riscv64-linux-gnu" - export QEMU_CPU="rv64,v=on,zvbb=on,vlen=1024,rvv_ta_all_1s=on,rvv_ma_all_1s=on" + QEMU_LD_PREFIX="/usr/riscv64-linux-gnu" \ + QEMU_CPU="rv64,v=on,zvbb=on,vlen=1024,rvv_ta_all_1s=on,rvv_ma_all_1s=on" \ ctest --timeout 1800 --output-on-failure --test-dir build -j $(nproc) diff --git a/.github/workflows/rvv-128-clang-17.yml b/.github/workflows/rvv-128-clang-17.yml index 65c6b794e..4030c49a7 100644 --- a/.github/workflows/rvv-128-clang-17.yml +++ b/.github/workflows/rvv-128-clang-17.yml @@ -19,11 +19,6 @@ jobs: sudo apt-get install -y cmake make g++-riscv64-linux-gnu qemu-user-static clang-17 - name: Build run: | - CXX=clang++-17 CXXFLAGS="--target=riscv64-linux-gnu -march=rv64gcv" \ - cmake --toolchain=cmake/toolchains-ci/riscv64-linux-gnu.cmake -DCMAKE_BUILD_TYPE=Release -B build - cmake --build build/ -j$(nproc) - - name: Test VLEN=128 - run: | - export QEMU_LD_PREFIX="/usr/riscv64-linux-gnu" - export QEMU_CPU="rv64,v=on,vlen=128,rvv_ta_all_1s=on,rvv_ma_all_1s=on" - ctest --timeout 1800 --output-on-failure --test-dir build -j $(nproc) + CC=clang-17 CXX=clang++-17 CFLAGS="--target=riscv64-linux-gnu -march=rv64gcv" CXXFLAGS="${CFLAGS}" \ + cmake --toolchain=cmake/toolchains-ci/riscv64-linux-gnu.cmake -DSIMDJSON_DEVELOPER_MODE=ON -B build + cmake --build build/ -j$(nproc) --config Release diff --git a/.github/workflows/rvv-128-clang-20.yml b/.github/workflows/rvv-128-clang-20.yml new file mode 100644 index 000000000..92c3f02c0 --- /dev/null +++ b/.github/workflows/rvv-128-clang-20.yml @@ -0,0 +1,39 @@ +name: Ubuntu rvv VLEN=128 (clang 20) + +on: + push: + branches: + - master + pull_request: + branches: + - master + +jobs: + build: + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + - name: Install packages + run: | + sudo apt-get update -q -y + sudo apt-get install -y cmake make g++-riscv64-linux-gnu qemu-user-static clang-20 + - name: Build + run: | + CC=clang-20 CXX=clang++-20 CFLAGS="--target=riscv64-linux-gnu -march=rv64gcv" CXXFLAGS="${CFLAGS}" \ + cmake --toolchain=cmake/toolchains-ci/riscv64-linux-gnu.cmake -DSIMDJSON_DEVELOPER_MODE=ON -B build + cmake --build build/ -j$(nproc) --config Release + - name: Test VLEN=128 + run: | + QEMU_LD_PREFIX="/usr/riscv64-linux-gnu" \ + QEMU_CPU="rv64,v=on,vlen=128,rvv_ta_all_1s=on,rvv_ma_all_1s=on" \ + ctest --timeout 1800 --output-on-failure --test-dir build -j $(nproc) + - name: Build VLS + run: | + CC=clang-20 CXX=clang++-20 CFLAGS="--target=riscv64-linux-gnu -march=rv64gcv_zvl128b_zba_zbb_zbc -mrvv-vector-bits=zvl" CXXFLAGS="${CFLAGS}" \ + cmake --toolchain=cmake/toolchains-ci/riscv64-linux-gnu.cmake -DSIMDJSON_DEVELOPER_MODE=ON -B build-vls + cmake --build build-vls/ -j$(nproc) --config Release + - name: Test VLEN=128 VLS + run: | + QEMU_LD_PREFIX="/usr/riscv64-linux-gnu" \ + QEMU_CPU="rv64,v=on,zba=on,zbb=on,zbc=on,vlen=128,rvv_ta_all_1s=on,rvv_ma_all_1s=on" \ + ctest --timeout 1800 --output-on-failure --test-dir build-vls -j $(nproc) diff --git a/.github/workflows/rvv-256-gcc-14.yml b/.github/workflows/rvv-256-gcc-14.yml index f21730a2e..be60294e1 100644 --- a/.github/workflows/rvv-256-gcc-14.yml +++ b/.github/workflows/rvv-256-gcc-14.yml @@ -19,11 +19,21 @@ jobs: sudo apt-get install -y cmake make g++-14-riscv64-linux-gnu qemu-user-static - name: Build run: | - CXX=riscv64-linux-gnu-g++-14 CXXFLAGS=-march=rv64gcv \ - cmake --toolchain=cmake/toolchains-ci/riscv64-linux-gnu.cmake -DCMAKE_BUILD_TYPE=Release -B build - cmake --build build/ -j$(nproc) + CC=riscv64-linux-gnu-gcc-14 CXX=riscv64-linux-gnu-g++-14 CFLAGS=-march=rv64gcv CXXFLAGS="${CFLAGS}" \ + cmake --toolchain=cmake/toolchains-ci/riscv64-linux-gnu.cmake -DSIMDJSON_DEVELOPER_MODE=ON -B build + cmake --build build/ -j$(nproc) --config Release - name: Test VLEN=256 run: | - export QEMU_LD_PREFIX="/usr/riscv64-linux-gnu" - export QEMU_CPU="rv64,v=on,zvbb=on,vlen=256,rvv_ta_all_1s=on,rvv_ma_all_1s=on" + QEMU_LD_PREFIX="/usr/riscv64-linux-gnu" \ + QEMU_CPU="rv64,v=on,zvbb=on,vlen=256,rvv_ta_all_1s=on,rvv_ma_all_1s=on" \ ctest --timeout 1800 --output-on-failure --test-dir build -j $(nproc) + - name: Build VLS + run: | + CC=riscv64-linux-gnu-gcc-14 CXX=riscv64-linux-gnu-g++-14 CFLAGS="-march=rv64gcv_zvl256b -mrvv-vector-bits=zvl" CXXFLAGS="${CFLAGS}" \ + cmake --toolchain=cmake/toolchains-ci/riscv64-linux-gnu.cmake -DSIMDJSON_DEVELOPER_MODE=ON -B build-vls + cmake --build build-vls/ -j$(nproc) --config Release + - name: Test VLEN=256 VLS + run: | + QEMU_LD_PREFIX="/usr/riscv64-linux-gnu" \ + QEMU_CPU="rv64,v=on,zvbb=on,vlen=256,rvv_ta_all_1s=on,rvv_ma_all_1s=on" \ + ctest --timeout 1800 --output-on-failure --test-dir build-vls -j $(nproc) diff --git a/.github/workflows/rvv-512-clang-19.yml b/.github/workflows/rvv-512-clang-19.yml new file mode 100644 index 000000000..1088779a9 --- /dev/null +++ b/.github/workflows/rvv-512-clang-19.yml @@ -0,0 +1,39 @@ +name: Ubuntu rvv VLEN=512 (clang 19) + +on: + push: + branches: + - master + pull_request: + branches: + - master + +jobs: + build: + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + - name: Install packages + run: | + sudo apt-get update -q -y + sudo apt-get install -y cmake make g++-riscv64-linux-gnu qemu-user-static clang-19 + - name: Build + run: | + CC=clang-19 CXX=clang++-19 CFLAGS="--target=riscv64-linux-gnu -march=rv64gcv" CXXFLAGS="${CFLAGS}" \ + cmake --toolchain=cmake/toolchains-ci/riscv64-linux-gnu.cmake -DSIMDJSON_DEVELOPER_MODE=ON -B build + cmake --build build/ -j$(nproc) --config Release + - name: Test VLEN=512 + run: | + QEMU_LD_PREFIX="/usr/riscv64-linux-gnu" \ + QEMU_CPU="rv64,v=on,vlen=512,rvv_ta_all_1s=on,rvv_ma_all_1s=on" \ + ctest --timeout 1800 --output-on-failure --test-dir build -j $(nproc) + - name: Build VLS + run: | + CC=clang-19 CXX=clang++-19 CFLAGS="--target=riscv64-linux-gnu -march=rv64gcv_zvl512b_zba_zbb_zbc -mrvv-vector-bits=zvl" CXXFLAGS="${CFLAGS}" \ + cmake --toolchain=cmake/toolchains-ci/riscv64-linux-gnu.cmake -DSIMDJSON_DEVELOPER_MODE=ON -B build-vls + cmake --build build-vls/ -j$(nproc) --config Release + - name: Test VLEN=512 VLS + run: | + QEMU_LD_PREFIX="/usr/riscv64-linux-gnu" \ + QEMU_CPU="rv64,v=on,zba=on,zbb=on,zbc=on,vlen=512,rvv_ta_all_1s=on,rvv_ma_all_1s=on" \ + ctest --timeout 1800 --output-on-failure --test-dir build-vls -j $(nproc) diff --git a/include/simdjson/arm64/simd.h b/include/simdjson/arm64/simd.h index 2b9a5d863..b2b76127c 100644 --- a/include/simdjson/arm64/simd.h +++ b/include/simdjson/arm64/simd.h @@ -428,6 +428,7 @@ namespace { static constexpr int NUM_CHUNKS = 64 / sizeof(simd8); static_assert(NUM_CHUNKS == 4, "ARM kernel should use four registers per 64-byte block."); const simd8 chunks[NUM_CHUNKS]; + template simd8 get() const { return idx < NUM_CHUNKS ? chunks[idx] : simd8(); } simd8x64(const simd8x64& o) = delete; // no copy allowed simd8x64& operator=(const simd8& other) = delete; // no assignment allowed diff --git a/include/simdjson/builtin.h b/include/simdjson/builtin.h index 10ce60769..6c1a877ed 100644 --- a/include/simdjson/builtin.h +++ b/include/simdjson/builtin.h @@ -24,6 +24,8 @@ #include "simdjson/lasx.h" #elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(lsx) #include "simdjson/lsx.h" +#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(rvv_vls) +#include "simdjson/rvv-vls.h" #else #error Unknown SIMDJSON_BUILTIN_IMPLEMENTATION #endif diff --git a/include/simdjson/builtin/base.h b/include/simdjson/builtin/base.h index ce1678013..95e3d9f97 100644 --- a/include/simdjson/builtin/base.h +++ b/include/simdjson/builtin/base.h @@ -21,6 +21,8 @@ namespace simdjson { namespace lsx {} #elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(lasx) namespace lasx {} +#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(rvv_vls) + namespace rvv_vls {} #else #error Unknown SIMDJSON_BUILTIN_IMPLEMENTATION #endif diff --git a/include/simdjson/builtin/builder.h b/include/simdjson/builtin/builder.h index b1e3d5b5c..41c18d83e 100644 --- a/include/simdjson/builtin/builder.h +++ b/include/simdjson/builtin/builder.h @@ -24,6 +24,8 @@ #include "simdjson/lsx/builder.h" #elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(lasx) #include "simdjson/lasx/builder.h" +#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(rvv_vls) +#include "simdjson/rvv-vls/builder.h" #else #error Unknown SIMDJSON_BUILTIN_IMPLEMENTATION #endif @@ -37,4 +39,4 @@ namespace simdjson { namespace builder = SIMDJSON_BUILTIN_IMPLEMENTATION::builder; } // namespace simdjson -#endif // SIMDJSON_BUILTIN_BUILDER_H \ No newline at end of file +#endif // SIMDJSON_BUILTIN_BUILDER_H diff --git a/include/simdjson/builtin/implementation.h b/include/simdjson/builtin/implementation.h index 51ed3cd41..09b3dc515 100644 --- a/include/simdjson/builtin/implementation.h +++ b/include/simdjson/builtin/implementation.h @@ -23,6 +23,8 @@ #include "simdjson/lsx/implementation.h" #elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(lasx) #include "simdjson/lasx/implementation.h" +#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(rvv_vls) +#include "simdjson/rvv-vls/implementation.h" #else #error Unknown SIMDJSON_BUILTIN_IMPLEMENTATION #endif @@ -39,4 +41,4 @@ namespace simdjson { const implementation * builtin_implementation(); } // namespace simdjson -#endif // SIMDJSON_BUILTIN_IMPLEMENTATION_H \ No newline at end of file +#endif // SIMDJSON_BUILTIN_IMPLEMENTATION_H diff --git a/include/simdjson/builtin/ondemand.h b/include/simdjson/builtin/ondemand.h index bd08b81e3..d73d691ef 100644 --- a/include/simdjson/builtin/ondemand.h +++ b/include/simdjson/builtin/ondemand.h @@ -24,6 +24,8 @@ #include "simdjson/lsx/ondemand.h" #elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(lasx) #include "simdjson/lasx/ondemand.h" +#elif SIMDJSON_BUILTIN_IMPLEMENTATION_IS(rvv_vls) +#include "simdjson/rvv-vls/ondemand.h" #else #error Unknown SIMDJSON_BUILTIN_IMPLEMENTATION #endif @@ -37,4 +39,4 @@ namespace simdjson { namespace ondemand = SIMDJSON_BUILTIN_IMPLEMENTATION::ondemand; } // namespace simdjson -#endif // SIMDJSON_BUILTIN_ONDEMAND_H \ No newline at end of file +#endif // SIMDJSON_BUILTIN_ONDEMAND_H diff --git a/include/simdjson/generic/base.h b/include/simdjson/generic/base.h index 4d14c0f59..37e518351 100644 --- a/include/simdjson/generic/base.h +++ b/include/simdjson/generic/base.h @@ -21,6 +21,8 @@ #include "simdjson/lasx/begin.h" #elif SIMDJSON_IMPLEMENTATION_LSX #include "simdjson/lsx/begin.h" +#elif SIMDJSON_IMPLEMENTATION_RVV_VLS +#include "simdjson/rvv-vls/begin.h" #elif SIMDJSON_IMPLEMENTATION_FALLBACK #include "simdjson/fallback/begin.h" #else @@ -48,4 +50,4 @@ enum class number_type { } // namespace SIMDJSON_IMPLEMENTATION } // namespace simdjson -#endif // SIMDJSON_GENERIC_BASE_H \ No newline at end of file +#endif // SIMDJSON_GENERIC_BASE_H diff --git a/include/simdjson/haswell/simd.h b/include/simdjson/haswell/simd.h index 9c40f4f4f..3254438b9 100644 --- a/include/simdjson/haswell/simd.h +++ b/include/simdjson/haswell/simd.h @@ -300,6 +300,7 @@ namespace simd { static constexpr int NUM_CHUNKS = 64 / sizeof(simd8); static_assert(NUM_CHUNKS == 2, "Haswell kernel should use two registers per 64-byte block."); const simd8 chunks[NUM_CHUNKS]; + template simd8 get() const { return idx < NUM_CHUNKS ? chunks[idx] : simd8(); } simd8x64(const simd8x64& o) = delete; // no copy allowed simd8x64& operator=(const simd8& other) = delete; // no assignment allowed diff --git a/include/simdjson/icelake/simd.h b/include/simdjson/icelake/simd.h index 89d896441..f4d09ff9e 100644 --- a/include/simdjson/icelake/simd.h +++ b/include/simdjson/icelake/simd.h @@ -322,6 +322,7 @@ namespace simd { static constexpr int NUM_CHUNKS = 64 / sizeof(simd8); static_assert(NUM_CHUNKS == 1, "Icelake kernel should use one register per 64-byte block."); const simd8 chunks[NUM_CHUNKS]; + template simd8 get() const { return idx < NUM_CHUNKS ? chunks[idx] : simd8(); } simd8x64(const simd8x64& o) = delete; // no copy allowed simd8x64& operator=(const simd8& other) = delete; // no assignment allowed diff --git a/include/simdjson/implementation_detection.h b/include/simdjson/implementation_detection.h index 93f671630..bea5de674 100644 --- a/include/simdjson/implementation_detection.h +++ b/include/simdjson/implementation_detection.h @@ -12,6 +12,8 @@ #define SIMDJSON_IMPLEMENTATION_ID_westmere 6 #define SIMDJSON_IMPLEMENTATION_ID_lsx 7 #define SIMDJSON_IMPLEMENTATION_ID_lasx 8 +//#define SIMDJSON_IMPLEMENTATION_ID_rvv 9 +#define SIMDJSON_IMPLEMENTATION_ID_rvv_vls 10 #define SIMDJSON_IMPLEMENTATION_ID_FOR(IMPL) SIMDJSON_CAT(SIMDJSON_IMPLEMENTATION_ID_, IMPL) #define SIMDJSON_IMPLEMENTATION_ID SIMDJSON_IMPLEMENTATION_ID_FOR(SIMDJSON_IMPLEMENTATION) @@ -126,9 +128,14 @@ #endif #define SIMDJSON_CAN_ALWAYS_RUN_LSX (SIMDJSON_IMPLEMENTATION_LSX) +#define SIMDJSON_CAN_ALWAYS_RUN_RVV_VLS SIMDJSON_IS_RVV_VLS +#ifndef SIMDJSON_IMPLEMENTATION_RVV_VLS +#define SIMDJSON_IMPLEMENTATION_RVV_VLS SIMDJSON_CAN_ALWAYS_RUN_RVV_VLS +#endif + // Default Fallback to on unless a builtin implementation has already been selected. #ifndef SIMDJSON_IMPLEMENTATION_FALLBACK -#if SIMDJSON_CAN_ALWAYS_RUN_ARM64 || SIMDJSON_CAN_ALWAYS_RUN_ICELAKE || SIMDJSON_CAN_ALWAYS_RUN_HASWELL || SIMDJSON_CAN_ALWAYS_RUN_WESTMERE || SIMDJSON_CAN_ALWAYS_RUN_PPC64 || SIMDJSON_CAN_ALWAYS_RUN_LSX || SIMDJSON_CAN_ALWAYS_RUN_LASX +#if SIMDJSON_CAN_ALWAYS_RUN_ARM64 || SIMDJSON_CAN_ALWAYS_RUN_ICELAKE || SIMDJSON_CAN_ALWAYS_RUN_HASWELL || SIMDJSON_CAN_ALWAYS_RUN_WESTMERE || SIMDJSON_CAN_ALWAYS_RUN_PPC64 || SIMDJSON_CAN_ALWAYS_RUN_LSX || SIMDJSON_CAN_ALWAYS_RUN_LASX || SIMDJSON_CAN_ALWAYS_RUN_RVV_VLS // if anything at all except fallback can always run, then disable fallback. #define SIMDJSON_IMPLEMENTATION_FALLBACK 0 #else @@ -154,6 +161,8 @@ #define SIMDJSON_BUILTIN_IMPLEMENTATION lsx #elif SIMDJSON_CAN_ALWAYS_RUN_LASX #define SIMDJSON_BUILTIN_IMPLEMENTATION lasx +#elif SIMDJSON_CAN_ALWAYS_RUN_RVV_VLS +#define SIMDJSON_BUILTIN_IMPLEMENTATION rvv_vls #elif SIMDJSON_CAN_ALWAYS_RUN_FALLBACK #define SIMDJSON_BUILTIN_IMPLEMENTATION fallback #else diff --git a/include/simdjson/internal/instruction_set.h b/include/simdjson/internal/instruction_set.h index 1dc0a81fb..cb0c435ab 100644 --- a/include/simdjson/internal/instruction_set.h +++ b/include/simdjson/internal/instruction_set.h @@ -69,6 +69,8 @@ enum instruction_set { AVX512VBMI2 = 0x10000, LSX = 0x20000, LASX = 0x40000, + //RVV = 0x80000, + RVV_VLS = 0x100000, }; } // namespace internal diff --git a/include/simdjson/lasx/simd.h b/include/simdjson/lasx/simd.h index 907a8acb9..8a899fe69 100644 --- a/include/simdjson/lasx/simd.h +++ b/include/simdjson/lasx/simd.h @@ -303,6 +303,7 @@ namespace simd { static constexpr int NUM_CHUNKS = 64 / sizeof(simd8); static_assert(NUM_CHUNKS == 2, "LASX kernel should use two registers per 64-byte block."); const simd8 chunks[NUM_CHUNKS]; + template simd8 get() const { return idx < NUM_CHUNKS ? chunks[idx] : simd8(); } simd8x64(const simd8x64& o) = delete; // no copy allowed simd8x64& operator=(const simd8& other) = delete; // no assignment allowed diff --git a/include/simdjson/lsx/simd.h b/include/simdjson/lsx/simd.h index 3f0d66560..c828fe36a 100644 --- a/include/simdjson/lsx/simd.h +++ b/include/simdjson/lsx/simd.h @@ -260,6 +260,7 @@ namespace simd { static constexpr int NUM_CHUNKS = 64 / sizeof(simd8); static_assert(NUM_CHUNKS == 4, "LSX kernel should use four registers per 64-byte block."); const simd8 chunks[NUM_CHUNKS]; + template simd8 get() const { return idx < NUM_CHUNKS ? chunks[idx] : simd8(); } simd8x64(const simd8x64& o) = delete; // no copy allowed simd8x64& operator=(const simd8& other) = delete; // no assignment allowed diff --git a/include/simdjson/portability.h b/include/simdjson/portability.h index 8c2bfb0d4..e6850d0f2 100644 --- a/include/simdjson/portability.h +++ b/include/simdjson/portability.h @@ -45,22 +45,20 @@ using std::size_t; #define SIMDJSON_IS_ARM64 1 #elif defined(__riscv) && __riscv_xlen == 64 #define SIMDJSON_IS_RISCV64 1 + #if __riscv_v_intrinsic >= 11000 #define SIMDJSON_HAS_RVV_INTRINSICS 1 #endif - #define SIMDJSON_HAS_ZVBB_INTRINSICS \ - 0 // there is currently no way to detect this - - #if SIMDJSON_HAS_RVV_INTRINSICS && __riscv_vector && \ - __riscv_v_min_vlen >= 128 && __riscv_v_elen >= 64 - // RISC-V V extension - #define SIMDJSON_IS_RVV 1 - #if SIMDJSON_HAS_ZVBB_INTRINSICS && __riscv_zvbb >= 1000000 - // RISC-V Vector Basic Bit-manipulation - #define SIMDJSON_IS_ZVBB 1 - #endif + #if SIMDJSON_HAS_RVV_INTRINSICS && __riscv_vector && __riscv_v_min_vlen >= 128 && __riscv_v_elen >= 64 + #define SIMDJSON_IS_RVV 1 // RISC-V V extension #endif + + // current toolchains don't support fixed-size SIMD types that don't match VLEN directly + #if __riscv_v_fixed_vlen >= 128 && __riscv_v_fixed_vlen <= 512 + #define SIMDJSON_IS_RVV_VLS 1 + #endif + #elif defined(__loongarch_lp64) #define SIMDJSON_IS_LOONGARCH64 1 #if defined(__loongarch_sx) && defined(__loongarch_asx) diff --git a/include/simdjson/ppc64/simd.h b/include/simdjson/ppc64/simd.h index be1a48a73..2c619c256 100644 --- a/include/simdjson/ppc64/simd.h +++ b/include/simdjson/ppc64/simd.h @@ -397,6 +397,7 @@ template struct simd8x64 { static_assert(NUM_CHUNKS == 4, "PPC64 kernel should use four registers per 64-byte block."); const simd8 chunks[NUM_CHUNKS]; + template simd8 get() const { return idx < NUM_CHUNKS ? chunks[idx] : simd8(); } simd8x64(const simd8x64 &o) = delete; // no copy allowed simd8x64 & diff --git a/include/simdjson/rvv-vls.h b/include/simdjson/rvv-vls.h new file mode 100644 index 000000000..6da545a17 --- /dev/null +++ b/include/simdjson/rvv-vls.h @@ -0,0 +1,9 @@ +#ifndef SIMDJSON_RVV_VLS_H +#define SIMDJSON_RVV_VLS_H + + +#include "simdjson/rvv-vls/begin.h" +#include "simdjson/generic/amalgamated.h" +#include "simdjson/rvv-vls/end.h" + +#endif // SIMDJSON_RVV_VLS_H diff --git a/include/simdjson/rvv-vls/base.h b/include/simdjson/rvv-vls/base.h new file mode 100644 index 000000000..03e0e1af2 --- /dev/null +++ b/include/simdjson/rvv-vls/base.h @@ -0,0 +1,19 @@ +#ifndef SIMDJSON_RVV_VLS_BASE_H +#define SIMDJSON_RVV_VLS_BASE_H + +#ifndef SIMDJSON_CONDITIONAL_INCLUDE +#include "simdjson/base.h" +#endif // SIMDJSON_CONDITIONAL_INCLUDE + +namespace simdjson { +/** + * RVV-VLS implementation. + */ +namespace rvv_vls { + +class implementation; + +} // namespace rvv_vls +} // namespace simdjson + +#endif // SIMDJSON_RVV_VLS_BASE_H diff --git a/include/simdjson/rvv-vls/begin.h b/include/simdjson/rvv-vls/begin.h new file mode 100644 index 000000000..ae111a209 --- /dev/null +++ b/include/simdjson/rvv-vls/begin.h @@ -0,0 +1,10 @@ +#define SIMDJSON_IMPLEMENTATION rvv_vls +#include "simdjson/rvv-vls/base.h" +#include "simdjson/rvv-vls/intrinsics.h" +#include "simdjson/rvv-vls/bitmanipulation.h" +#include "simdjson/rvv-vls/bitmask.h" +#include "simdjson/rvv-vls/simd.h" +#include "simdjson/rvv-vls/stringparsing_defs.h" +#include "simdjson/rvv-vls/numberparsing_defs.h" + +#define SIMDJSON_SKIP_BACKSLASH_SHORT_CIRCUIT 1 diff --git a/include/simdjson/rvv-vls/bitmanipulation.h b/include/simdjson/rvv-vls/bitmanipulation.h new file mode 100644 index 000000000..40f6c31bc --- /dev/null +++ b/include/simdjson/rvv-vls/bitmanipulation.h @@ -0,0 +1,48 @@ +#ifndef SIMDJSON_RVV_VLS_BITMANIPULATION_H +#define SIMDJSON_RVV_VLS_BITMANIPULATION_H + +#ifndef SIMDJSON_CONDITIONAL_INCLUDE +#include "simdjson/rvv-vls/base.h" +#endif // SIMDJSON_CONDITIONAL_INCLUDE + +namespace simdjson { +namespace rvv_vls { +namespace { + +// We sometimes call trailing_zero on inputs that are zero, +// but the algorithms do not end up using the returned value. +// Sadly, sanitizers are not smart enough to figure it out. +SIMDJSON_NO_SANITIZE_UNDEFINED +// This function can be used safely even if not all bytes have been +// initialized. +// See issue https://github.com/simdjson/simdjson/issues/1965 +SIMDJSON_NO_SANITIZE_MEMORY +simdjson_inline int trailing_zeroes(uint64_t input_num) { + return __builtin_ctzll(input_num); +} + +/* result might be undefined when input_num is zero */ +simdjson_inline uint64_t clear_lowest_bit(uint64_t input_num) { + return input_num & (input_num-1); +} + +/* result might be undefined when input_num is zero */ +simdjson_inline int leading_zeroes(uint64_t input_num) { + return __builtin_clzll(input_num); +} + +simdjson_inline long long int count_ones(uint64_t input_num) { + return __builtin_popcountll(input_num); +} + +simdjson_inline bool add_overflow(uint64_t value1, uint64_t value2, + uint64_t *result) { + return __builtin_uaddll_overflow(value1, value2, + reinterpret_cast(result)); +} + +} // unnamed namespace +} // namespace rvv_vls +} // namespace simdjson + +#endif // SIMDJSON_RVV_VLS_BITMANIPULATION_H diff --git a/include/simdjson/rvv-vls/bitmask.h b/include/simdjson/rvv-vls/bitmask.h new file mode 100644 index 000000000..68c1e7ab6 --- /dev/null +++ b/include/simdjson/rvv-vls/bitmask.h @@ -0,0 +1,39 @@ +#ifndef SIMDJSON_RVV_VLS_BITMASK_H +#define SIMDJSON_RVV_VLS_BITMASK_H + +#ifndef SIMDJSON_CONDITIONAL_INCLUDE +#include "simdjson/rvv-vls/base.h" +#include "simdjson/rvv-vls/intrinsics.h" +#endif // SIMDJSON_CONDITIONAL_INCLUDE + +namespace simdjson { +namespace rvv_vls { +namespace { + +// +// Perform a "cumulative bitwise xor," flipping bits each time a 1 is encountered. +// +// For example, prefix_xor(00100100) == 00011100 +// +simdjson_inline uint64_t prefix_xor(uint64_t bitmask) { +#if __riscv_zbc + return __riscv_clmul_64(bitmask, ~(uint64_t)0); +#elif __riscv_zvbc + return __riscv_vmv_x(__riscv_vclmul(__riscv_vmv_s_x_u64m1(bitmask, 1), ~(uint64_t)0, 1)); +#else + bitmask ^= bitmask << 1; + bitmask ^= bitmask << 2; + bitmask ^= bitmask << 4; + bitmask ^= bitmask << 8; + bitmask ^= bitmask << 16; + bitmask ^= bitmask << 32; +#endif + return bitmask; +} + +} // unnamed namespace +} // namespace rvv_vls +} // namespace simdjson + +#endif // SIMDJSON_RVV_VLS_BITMASK_H + diff --git a/include/simdjson/rvv-vls/builder.h b/include/simdjson/rvv-vls/builder.h new file mode 100644 index 000000000..a0b95a1bc --- /dev/null +++ b/include/simdjson/rvv-vls/builder.h @@ -0,0 +1,8 @@ +#ifndef SIMDJSON_RVV_VLS_BUILDER_H +#define SIMDJSON_RVV_VLS_BUILDER_H + +#include "simdjson/rvv-vls/begin.h" +#include "simdjson/generic/builder/amalgamated.h" +#include "simdjson/rvv-vls/end.h" + +#endif // SIMDJSON_RVV_VLS_BUILDER_H diff --git a/include/simdjson/rvv-vls/end.h b/include/simdjson/rvv-vls/end.h new file mode 100644 index 000000000..cec10737b --- /dev/null +++ b/include/simdjson/rvv-vls/end.h @@ -0,0 +1,5 @@ +#ifndef SIMDJSON_CONDITIONAL_INCLUDE +#include "simdjson/rvv-vls/base.h" +#endif // SIMDJSON_CONDITIONAL_INCLUDE + +#undef SIMDJSON_IMPLEMENTATION diff --git a/include/simdjson/rvv-vls/implementation.h b/include/simdjson/rvv-vls/implementation.h new file mode 100644 index 000000000..a40b25b8e --- /dev/null +++ b/include/simdjson/rvv-vls/implementation.h @@ -0,0 +1,34 @@ +#ifndef SIMDJSON_RVV_VLS_IMPLEMENTATION_H +#define SIMDJSON_RVV_VLS_IMPLEMENTATION_H + +#ifndef SIMDJSON_CONDITIONAL_INCLUDE +#include "simdjson/rvv-vls/base.h" +#include "simdjson/implementation.h" +#endif // SIMDJSON_CONDITIONAL_INCLUDE + +namespace simdjson { +namespace rvv_vls { + +/** + * @private + */ +class implementation final : public simdjson::implementation { +public: + simdjson_inline implementation() : simdjson::implementation( + "rvv_vls", + "RISC-V V extension", + 0 + ) {} + simdjson_warn_unused error_code create_dom_parser_implementation( + size_t capacity, + size_t max_length, + std::unique_ptr& dst + ) const noexcept final; + simdjson_warn_unused error_code minify(const uint8_t *buf, size_t len, uint8_t *dst, size_t &dst_len) const noexcept final; + simdjson_warn_unused bool validate_utf8(const char *buf, size_t len) const noexcept final; +}; + +} // namespace rvv_vls +} // namespace simdjson + +#endif // SIMDJSON_RVV_VLS_IMPLEMENTATION_H diff --git a/include/simdjson/rvv-vls/intrinsics.h b/include/simdjson/rvv-vls/intrinsics.h new file mode 100644 index 000000000..bec403b57 --- /dev/null +++ b/include/simdjson/rvv-vls/intrinsics.h @@ -0,0 +1,32 @@ +#ifndef SIMDJSON_RVV_VLS_INTRINSICS_H +#define SIMDJSON_RVV_VLS_INTRINSICS_H + +#ifndef SIMDJSON_CONDITIONAL_INCLUDE +#include "simdjson/rvv-vls/base.h" +#endif // SIMDJSON_CONDITIONAL_INCLUDE + +#include + +#define simdutf_vrgather_u8m1x2(tbl, idx) \ + __riscv_vcreate_v_u8m1_u8m2( \ + __riscv_vrgather_vv_u8m1(tbl, __riscv_vget_v_u8m2_u8m1(idx, 0), \ + __riscv_vsetvlmax_e8m1()), \ + __riscv_vrgather_vv_u8m1(tbl, __riscv_vget_v_u8m2_u8m1(idx, 1), \ + __riscv_vsetvlmax_e8m1())) + +#define simdutf_vrgather_u8m1x4(tbl, idx) \ + __riscv_vcreate_v_u8m1_u8m4( \ + __riscv_vrgather_vv_u8m1(tbl, __riscv_vget_v_u8m4_u8m1(idx, 0), \ + __riscv_vsetvlmax_e8m1()), \ + __riscv_vrgather_vv_u8m1(tbl, __riscv_vget_v_u8m4_u8m1(idx, 1), \ + __riscv_vsetvlmax_e8m1()), \ + __riscv_vrgather_vv_u8m1(tbl, __riscv_vget_v_u8m4_u8m1(idx, 2), \ + __riscv_vsetvlmax_e8m1()), \ + __riscv_vrgather_vv_u8m1(tbl, __riscv_vget_v_u8m4_u8m1(idx, 3), \ + __riscv_vsetvlmax_e8m1())) + +#if __riscv_zbc +#include +#endif + +#endif // SIMDJSON_RVV_VLS_INTRINSICS_H diff --git a/include/simdjson/rvv-vls/numberparsing_defs.h b/include/simdjson/rvv-vls/numberparsing_defs.h new file mode 100644 index 000000000..a204defa2 --- /dev/null +++ b/include/simdjson/rvv-vls/numberparsing_defs.h @@ -0,0 +1,56 @@ +#ifndef SIMDJSON_RVV_VLS_NUMBERPARSING_DEFS_H +#define SIMDJSON_RVV_VLS_NUMBERPARSING_DEFS_H + +#ifndef SIMDJSON_CONDITIONAL_INCLUDE +#include "simdjson/rvv-vls/base.h" +#include "simdjson/internal/numberparsing_tables.h" +#endif // SIMDJSON_CONDITIONAL_INCLUDE + +#include + +#ifdef JSON_TEST_NUMBERS // for unit testing +void found_invalid_number(const uint8_t *buf); +void found_integer(int64_t result, const uint8_t *buf); +void found_unsigned_integer(uint64_t result, const uint8_t *buf); +void found_float(double result, const uint8_t *buf); +#endif + +namespace simdjson { +namespace rvv_vls { +namespace numberparsing { + +// credit: https://johnnylee-sde.github.io/Fast-numeric-string-to-int/ +/** @private */ +static simdjson_inline uint32_t parse_eight_digits_unrolled(const char *chars) { + uint64_t val; +#if __riscv_misaligned_fast + memcpy(&val, chars, sizeof(uint64_t)); +#else + val = __riscv_vmv_x(__riscv_vreinterpret_u64m1(__riscv_vlmul_ext_u8m1(__riscv_vle8_v_u8mf2((uint8_t*)chars, 8)))); +#endif + val = (val & 0x0F0F0F0F0F0F0F0F) * 2561 >> 8; + val = (val & 0x00FF00FF00FF00FF) * 6553601 >> 16; + return uint32_t((val & 0x0000FFFF0000FFFF) * 42949672960001 >> 32); +} + +/** @private */ +static simdjson_inline uint32_t parse_eight_digits_unrolled(const uint8_t *chars) { + return parse_eight_digits_unrolled(reinterpret_cast(chars)); +} + +/** @private */ +simdjson_inline internal::value128 full_multiplication(uint64_t value1, uint64_t value2) { + internal::value128 answer; + __uint128_t r = (static_cast<__uint128_t>(value1)) * value2; + answer.low = uint64_t(r); + answer.high = uint64_t(r >> 64); + return answer; +} + +} // namespace numberparsing +} // namespace rvv_vls +} // namespace simdjson + +#define SIMDJSON_SWAR_NUMBER_PARSING 1 + +#endif // SIMDJSON_RVV_VLS_NUMBERPARSING_DEFS_H diff --git a/include/simdjson/rvv-vls/ondemand.h b/include/simdjson/rvv-vls/ondemand.h new file mode 100644 index 000000000..6d85535c6 --- /dev/null +++ b/include/simdjson/rvv-vls/ondemand.h @@ -0,0 +1,8 @@ +#ifndef SIMDJSON_RVV_VLS_ONDEMAND_H +#define SIMDJSON_RVV_VLS_ONDEMAND_H + +#include "simdjson/rvv-vls/begin.h" +#include "simdjson/generic/ondemand/amalgamated.h" +#include "simdjson/rvv-vls/end.h" + +#endif // SIMDJSON_RVV_VLS_ONDEMAND_H diff --git a/include/simdjson/rvv-vls/simd.h b/include/simdjson/rvv-vls/simd.h new file mode 100644 index 000000000..d2631755b --- /dev/null +++ b/include/simdjson/rvv-vls/simd.h @@ -0,0 +1,370 @@ +#ifndef SIMDJSON_RVV_VLS_SIMD_H +#define SIMDJSON_RVV_VLS_SIMD_H + +#ifndef SIMDJSON_CONDITIONAL_INCLUDE +#include "simdjson/rvv-vls/base.h" +#include "simdjson/rvv-vls/bitmanipulation.h" +#include "simdjson/internal/simdprune_tables.h" +#endif // SIMDJSON_CONDITIONAL_INCLUDE + +namespace simdjson { +namespace rvv_vls { +namespace { +namespace simd { + +#if __riscv_v_fixed_vlen >= 512 + static constexpr size_t VL8 = 512/8; + using vint8_t = vint8m1_t __attribute__((riscv_rvv_vector_bits(512))); + using vuint8_t = vuint8m1_t __attribute__((riscv_rvv_vector_bits(512))); + using vbool_t = vbool8_t __attribute__((riscv_rvv_vector_bits(512/8))); + using vbitmask_t = uint64_t; +#else + static constexpr size_t VL8 = __riscv_v_fixed_vlen/8; + using vint8_t = vint8m1_t __attribute__((riscv_rvv_vector_bits(__riscv_v_fixed_vlen))); + using vuint8_t = vuint8m1_t __attribute__((riscv_rvv_vector_bits(__riscv_v_fixed_vlen))); + using vbool_t = vbool8_t __attribute__((riscv_rvv_vector_bits(__riscv_v_fixed_vlen/8))); + #if __riscv_v_fixed_vlen == 128 + using vbitmask_t = uint16_t; + #elif __riscv_v_fixed_vlen == 256 + using vbitmask_t = uint32_t; + #endif +#endif + +#if __riscv_v_fixed_vlen == 128 + using vuint8x64_t = vuint8m4_t __attribute__((riscv_rvv_vector_bits(512))); + using vboolx64_t = vbool2_t __attribute__((riscv_rvv_vector_bits(512/8))); +#elif __riscv_v_fixed_vlen == 256 + using vuint8x64_t = vuint8m2_t __attribute__((riscv_rvv_vector_bits(512))); + using vboolx64_t = vbool4_t __attribute__((riscv_rvv_vector_bits(512/8))); +#else + using vuint8x64_t = vuint8m1_t __attribute__((riscv_rvv_vector_bits(512))); + using vboolx64_t = vbool8_t __attribute__((riscv_rvv_vector_bits(512/8))); +#endif + + template + struct simd8; + + // SIMD byte mask type (returned by things like eq and gt) + template<> + struct simd8 { + vbool_t value; + using bitmask_t = vbitmask_t; + static constexpr int SIZE = sizeof(value); + + simdjson_inline simd8(const vbool_t _value) : value(_value) {} + simdjson_inline simd8() : simd8(__riscv_vmclr_m_b8(VL8)) {} + simdjson_inline simd8(bool _value) : simd8(splat(_value)) {} + + simdjson_inline operator const vbool_t&() const { return value; } + simdjson_inline operator vbool_t&() { return value; } + + static simdjson_inline simd8 splat(bool _value) { + return __riscv_vreinterpret_b8(__riscv_vmv_v_x_u64m1(((uint64_t)!_value)-1, 1)); + } + + simdjson_inline vbitmask_t to_bitmask() const { +#if __riscv_v_fixed_vlen == 128 + return __riscv_vmv_x(__riscv_vreinterpret_u16m1(value)); +#elif __riscv_v_fixed_vlen == 256 + return __riscv_vmv_x(__riscv_vreinterpret_u32m1(value)); +#else + return __riscv_vmv_x(__riscv_vreinterpret_u64m1(value)); +#endif + } + + // Bit operations + simdjson_inline simd8 operator|(const simd8 other) const { return __riscv_vmor(*this, other, VL8); } + simdjson_inline simd8 operator&(const simd8 other) const { return __riscv_vmand(*this, other, VL8); } + simdjson_inline simd8 operator^(const simd8 other) const { return __riscv_vmxor(*this, other, VL8); } + simdjson_inline simd8 bit_andnot(const simd8 other) const { return __riscv_vmandn(other, *this, VL8); } + simdjson_inline simd8 operator~() const { return __riscv_vmnot(*this, VL8); } + simdjson_inline simd8& operator|=(const simd8 other) { auto this_cast = static_cast*>(this); *this_cast = *this_cast | other; return *this_cast; } + simdjson_inline simd8& operator&=(const simd8 other) { auto this_cast = static_cast*>(this); *this_cast = *this_cast & other; return *this_cast; } + simdjson_inline simd8& operator^=(const simd8 other) { auto this_cast = static_cast*>(this); *this_cast = *this_cast ^ other; return *this_cast; } + }; + + // Unsigned bytes + template<> + struct simd8 { + + vuint8_t value; + static constexpr int SIZE = sizeof(value); + + simdjson_inline simd8(const vuint8_t _value) : value(_value) {} + simdjson_inline simd8() : simd8(zero()) {} + simdjson_inline simd8(const uint8_t values[VL8]) : simd8(load(values)) {} + simdjson_inline simd8(uint8_t _value) : simd8(splat(_value)) {} + simdjson_inline simd8(simd8 mask) : value(__riscv_vmerge_vxm_u8m1(zero(), -1, (vbool_t)mask, VL8)) {} + + simdjson_inline operator const vuint8_t&() const { return this->value; } + simdjson_inline operator vuint8_t&() { return this->value; } + + simdjson_inline simd8( + uint8_t v0, uint8_t v1, uint8_t v2, uint8_t v3, uint8_t v4, uint8_t v5, uint8_t v6, uint8_t v7, + uint8_t v8, uint8_t v9, uint8_t v10, uint8_t v11, uint8_t v12, uint8_t v13, uint8_t v14, uint8_t v15 + ) : simd8(vuint8_t{ + v0, v1, v2, v3, v4, v5, v6, v7, + v8, v9, v10,v11,v12,v13,v14,v15 + }) {} + + // Repeat 16 values as many times as necessary (usually for lookup tables) + simdjson_inline static simd8 repeat_16( + uint8_t v0, uint8_t v1, uint8_t v2, uint8_t v3, uint8_t v4, uint8_t v5, uint8_t v6, uint8_t v7, + uint8_t v8, uint8_t v9, uint8_t v10, uint8_t v11, uint8_t v12, uint8_t v13, uint8_t v14, uint8_t v15 + ) { + return simd8( + v0, v1, v2, v3, v4, v5, v6, v7, + v8, v9, v10,v11,v12,v13,v14,v15 + ); + } + + static simdjson_inline vuint8_t splat(uint8_t _value) { return __riscv_vmv_v_x_u8m1(_value, VL8); } + static simdjson_inline vuint8_t zero() { return splat(0); } + static simdjson_inline vuint8_t load(const uint8_t values[VL8]) { return __riscv_vle8_v_u8m1(values, VL8); } + + // Bit operations + simdjson_inline simd8 operator|(const simd8 other) const { return __riscv_vor_vv_u8m1( value, other, VL8); } + simdjson_inline simd8 operator&(const simd8 other) const { return __riscv_vand_vv_u8m1( value, other, VL8); } + simdjson_inline simd8 operator^(const simd8 other) const { return __riscv_vxor_vv_u8m1( value, other, VL8); } + simdjson_inline simd8 operator~() const { return __riscv_vnot_v_u8m1(value, VL8); } +#if __riscv_zvbb + simdjson_inline simd8 bit_andnot(const simd8 other) const { return __riscv_vandn_vv_u8m1(other, value, VL8); } +#else + simdjson_inline simd8 bit_andnot(const simd8 other) const { return other & ~*this; } +#endif + simdjson_inline simd8& operator|=(const simd8 other) { value = *this | other; return *this; } + simdjson_inline simd8& operator&=(const simd8 other) { value = *this & other; return *this; } + simdjson_inline simd8& operator^=(const simd8 other) { value = *this ^ other; return *this; } + + simdjson_inline simd8 operator==(const simd8 other) const { return __riscv_vmseq(value, other, VL8); } + simdjson_inline simd8 operator==(uint8_t other) const { return __riscv_vmseq(value, other, VL8); } + + template + simdjson_inline simd8 prev(const simd8 prev_chunk) const { + return __riscv_vslideup(__riscv_vslidedown(prev_chunk, VL8-N, VL8), value, N, VL8); + } + + // Store to array + simdjson_inline void store(uint8_t dst[VL8]) const { return __riscv_vse8(dst, value, VL8); } + + // Saturated math + simdjson_inline simd8 saturating_add(const simd8 other) const { return __riscv_vsaddu(value, other, VL8); } + simdjson_inline simd8 saturating_sub(const simd8 other) const { return __riscv_vssubu(value, other, VL8); } + + // Addition/subtraction are the same for signed and unsigned + simdjson_inline simd8 operator+(const simd8 other) const { return __riscv_vadd(value, other, VL8); } + simdjson_inline simd8 operator-(const simd8 other) const { return __riscv_vsub(value, other, VL8); } + simdjson_inline simd8& operator+=(const simd8 other) { value = *this + other; return *this; } + simdjson_inline simd8& operator-=(const simd8 other) { value = *this - other; return *this; } + + // Order-specific operations + simdjson_inline simd8 operator<=(const simd8 other) const { return __riscv_vmsleu(value, other, VL8); } + simdjson_inline simd8 operator>=(const simd8 other) const { return __riscv_vmsgeu(value, other, VL8); } + simdjson_inline simd8 operator<(const simd8 other) const { return __riscv_vmsltu(value, other, VL8); } + simdjson_inline simd8 operator>(const simd8 other) const { return __riscv_vmsgtu(value, other, VL8); } + + // Same as >, but instead of guaranteeing all 1's == true, false = 0 and true = nonzero. + simdjson_inline simd8 gt_bits(const simd8 other) const { return simd8(*this > other); } + // Same as <, but instead of guaranteeing all 1's == true, false = 0 and true = nonzero. + simdjson_inline simd8 lt_bits(const simd8 other) const { return simd8(*this < other); } + + // Bit-specific operations + simdjson_inline bool any_bits_set_anywhere() const { + return __riscv_vfirst(__riscv_vmsne(value, 0, VL8), VL8) >= 0; + } + simdjson_inline bool any_bits_set_anywhere(simd8 bits) const { return (*this & bits).any_bits_set_anywhere(); } + template + simdjson_inline simd8 shr() const { return __riscv_vsrl(value, N, VL8); } + template + simdjson_inline simd8 shl() const { return __riscv_vsll(value, N, VL8); } + + + // Perform a lookup assuming the value is between 0 and 16 (undefined behavior for out of range values) + template + simdjson_inline simd8 lookup_16(simd8 lookup_table) const { + return __riscv_vrgather(lookup_table, value, VL8); + } + + // compress inactive elements, to match AVX-512 behavior + template + simdjson_inline void compress(vbitmask_t mask, L * output) const { + mask = (vbitmask_t)~mask; +#if __riscv_v_fixed_vlen == 128 + vbool8_t m = __riscv_vreinterpret_b8(__riscv_vmv_s_x_u16m1(mask, 1)); +#elif __riscv_v_fixed_vlen == 256 + vbool8_t m = __riscv_vreinterpret_b8(__riscv_vmv_s_x_u32m1(mask, 1)); +#else + vbool8_t m = __riscv_vreinterpret_b8(__riscv_vmv_s_x_u64m1(mask, 1)); +#endif + __riscv_vse8_v_u8m1(output, __riscv_vcompress(value, m, VL8), count_ones(mask)); + } + + template + simdjson_inline simd8 lookup_16( + L replace0, L replace1, L replace2, L replace3, + L replace4, L replace5, L replace6, L replace7, + L replace8, L replace9, L replace10, L replace11, + L replace12, L replace13, L replace14, L replace15) const { + return lookup_16(simd8::repeat_16( + replace0, replace1, replace2, replace3, + replace4, replace5, replace6, replace7, + replace8, replace9, replace10, replace11, + replace12, replace13, replace14, replace15 + )); + } + }; + + // Signed bytes + template<> + struct simd8 { + vint8_t value; + static constexpr int SIZE = sizeof(value); + + simdjson_inline simd8(const vint8_t _value) : value(_value) {} + simdjson_inline simd8() : simd8(zero()) {} + simdjson_inline simd8(const int8_t values[VL8]) : simd8(load(values)) {} + simdjson_inline simd8(int8_t _value) : simd8(splat(_value)) {} + + simdjson_inline operator const vint8_t&() const { return this->value; } + simdjson_inline operator vint8_t&() { return this->value; } + + simdjson_inline simd8( + int8_t v0, int8_t v1, int8_t v2, int8_t v3, int8_t v4, int8_t v5, int8_t v6, int8_t v7, + int8_t v8, int8_t v9, int8_t v10, int8_t v11, int8_t v12, int8_t v13, int8_t v14, int8_t v15 + ) : simd8(vint8_t{ + v0, v1, v2, v3, v4, v5, v6, v7, + v8, v9, v10,v11,v12,v13,v14,v15 + }) {} + + // Repeat 16 values as many times as necessary (usually for lookup tables) + simdjson_inline static simd8 repeat_16( + int8_t v0, int8_t v1, int8_t v2, int8_t v3, int8_t v4, int8_t v5, int8_t v6, int8_t v7, + int8_t v8, int8_t v9, int8_t v10, int8_t v11, int8_t v12, int8_t v13, int8_t v14, int8_t v15 + ) { + return simd8( + v0, v1, v2, v3, v4, v5, v6, v7, + v8, v9, v10,v11,v12,v13,v14,v15 + ); + } + + static simdjson_inline vint8_t splat(int8_t _value) { return __riscv_vmv_v_x_i8m1(_value, VL8); } + static simdjson_inline vint8_t zero() { return splat(0); } + static simdjson_inline vint8_t load(const int8_t values[VL8]) { return __riscv_vle8_v_i8m1(values, VL8); } + + + simdjson_inline void store(int8_t dst[VL8]) const { return __riscv_vse8(dst, value, VL8); } + + // Explicit conversion to/from unsigned + simdjson_inline explicit simd8(const vuint8_t other): simd8(__riscv_vreinterpret_i8m1(other)) {} + simdjson_inline explicit operator simd8() const { return __riscv_vreinterpret_u8m1(value); } + + // Math + simdjson_inline simd8 operator+(const simd8 other) const { return __riscv_vadd(value, other, VL8); } + simdjson_inline simd8 operator-(const simd8 other) const { return __riscv_vsub(value, other, VL8); } + simdjson_inline simd8& operator+=(const simd8 other) { value = *this + other; return *this; } + simdjson_inline simd8& operator-=(const simd8 other) { value = *this - other; return *this; } + + // Order-sensitive comparisons + simdjson_inline simd8 max_val( const simd8 other) const { return __riscv_vmax( value, other, VL8); } + simdjson_inline simd8 min_val( const simd8 other) const { return __riscv_vmin( value, other, VL8); } + simdjson_inline simd8 operator>( const simd8 other) const { return __riscv_vmsgt(value, other, VL8); } + simdjson_inline simd8 operator<( const simd8 other) const { return __riscv_vmslt(value, other, VL8); } + simdjson_inline simd8 operator==(const simd8 other) const { return __riscv_vmseq(value, other, VL8); } + + template + simdjson_inline simd8 prev(const simd8 prev_chunk) const { + return __riscv_vslideup(__riscv_vslidedown(prev_chunk, VL8-N, VL8), value, N, VL8); + } + + // Perform a lookup assuming no value is larger than 16 + template + simdjson_inline simd8 lookup_16(simd8 lookup_table) const { + return __riscv_vrgather(lookup_table, value, VL8); + } + template + simdjson_inline simd8 lookup_16( + L replace0, L replace1, L replace2, L replace3, + L replace4, L replace5, L replace6, L replace7, + L replace8, L replace9, L replace10, L replace11, + L replace12, L replace13, L replace14, L replace15) const { + return lookup_16(simd8::repeat_16( + replace0, replace1, replace2, replace3, + replace4, replace5, replace6, replace7, + replace8, replace9, replace10, replace11, + replace12, replace13, replace14, replace15 + )); + } + }; + + template + struct simd8x64; + template<> + struct simd8x64 { + static constexpr int NUM_CHUNKS = 64 / sizeof(simd8); + vuint8x64_t value; + +#if __riscv_v_fixed_vlen >= 512 + template simd8 get() const { return value; } +#else + template simd8 get() const { return __riscv_vget_u8m1(value, idx); } +#endif + + simdjson_inline operator const vuint8x64_t&() const { return this->value; } + simdjson_inline operator vuint8x64_t&() { return this->value; } + + simd8x64(const simd8x64& o) = delete; // no copy allowed + simd8x64& operator=(const simd8& other) = delete; // no assignment allowed + simd8x64() = delete; // no default constructor allowed + +#if __riscv_v_fixed_vlen == 128 + simdjson_inline simd8x64(const uint8_t *ptr, size_t n = 64) : value(__riscv_vle8_v_u8m4(ptr, n)) {} +#elif __riscv_v_fixed_vlen == 256 + simdjson_inline simd8x64(const uint8_t *ptr, size_t n = 64) : value(__riscv_vle8_v_u8m2(ptr, n)) {} +#else + simdjson_inline simd8x64(const uint8_t *ptr, size_t n = 64) : value(__riscv_vle8_v_u8m1(ptr, n)) {} +#endif + + simdjson_inline void store(uint8_t ptr[64]) const { + __riscv_vse8(ptr, value, 64); + } + + simdjson_inline bool is_ascii() const { +#if __riscv_v_fixed_vlen == 128 + return __riscv_vfirst(__riscv_vmslt(__riscv_vreinterpret_i8m4(value), 0, 64), 64) < 0; +#elif __riscv_v_fixed_vlen == 256 + return __riscv_vfirst(__riscv_vmslt(__riscv_vreinterpret_i8m2(value), 0, 64), 64) < 0; +#else + return __riscv_vfirst(__riscv_vmslt(__riscv_vreinterpret_i8m1(value), 0, 64), 64) < 0; +#endif + } + + // compress inactive elements, to match AVX-512 behavior + simdjson_inline uint64_t compress(uint64_t mask, uint8_t * output) const { + mask = ~mask; +#if __riscv_v_fixed_vlen == 128 + vboolx64_t m = __riscv_vreinterpret_b2(__riscv_vmv_s_x_u64m1(mask, 1)); +#elif __riscv_v_fixed_vlen == 256 + vboolx64_t m = __riscv_vreinterpret_b4(__riscv_vmv_s_x_u64m1(mask, 1)); +#else + vboolx64_t m = __riscv_vreinterpret_b8(__riscv_vmv_s_x_u64m1(mask, 1)); +#endif + size_t cnt = count_ones(mask); + __riscv_vse8(output, __riscv_vcompress(value, m, 64), cnt); + return cnt; + } + + simdjson_inline uint64_t eq(const uint8_t m) const { + return __riscv_vmv_x(__riscv_vreinterpret_u64m1(__riscv_vmseq(value, m, 64))); + } + + simdjson_inline uint64_t lteq(const uint8_t m) const { + return __riscv_vmv_x(__riscv_vreinterpret_u64m1(__riscv_vmsleu(value, m, 64))); + } + }; // struct simd8x64 + +} // namespace simd +} // unnamed namespace +} // namespace rvv_vls +} // namespace simdjson + +#endif // SIMDJSON_RVV_VLS_SIMD_H diff --git a/include/simdjson/rvv-vls/stringparsing_defs.h b/include/simdjson/rvv-vls/stringparsing_defs.h new file mode 100644 index 000000000..901411584 --- /dev/null +++ b/include/simdjson/rvv-vls/stringparsing_defs.h @@ -0,0 +1,58 @@ +#ifndef SIMDJSON_RVV_VLS_STRINGPARSING_DEFS_H +#define SIMDJSON_RVV_VLS_STRINGPARSING_DEFS_H + +#ifndef SIMDJSON_CONDITIONAL_INCLUDE +#include "simdjson/rvv-vls/base.h" +#endif // SIMDJSON_CONDITIONAL_INCLUDE + +namespace simdjson { +namespace rvv_vls { +namespace { + +using namespace simd; + +// Holds backslashes and quotes locations. +struct backslash_and_quote { +public: + static constexpr uint64_t BYTES_PROCESSED = sizeof(simd8); + simdjson_inline backslash_and_quote copy_and_find(const uint8_t *src, uint8_t *dst); + + simdjson_inline bool has_quote_first() { return ((bs_bits - 1) & quote_bits) != 0; } + simdjson_inline bool has_backslash() { return ((quote_bits - 1) & bs_bits) != 0; } + simdjson_inline int quote_index() { return trailing_zeroes(quote_bits); } + simdjson_inline int backslash_index() { return trailing_zeroes(bs_bits); } + + uint64_t bs_bits; + uint64_t quote_bits; +}; // struct backslash_and_quote + +simdjson_inline backslash_and_quote backslash_and_quote::copy_and_find(const uint8_t *src, uint8_t *dst) { + static_assert(SIMDJSON_PADDING >= (BYTES_PROCESSED - 1), "backslash and quote finder must process fewer than SIMDJSON_PADDING bytes"); + simd8 v(src); + v.store(dst); + return { (v == '\\').to_bitmask(), (v == '"').to_bitmask() }; +} + +struct escaping { + static constexpr uint64_t BYTES_PROCESSED = sizeof(simd8); + simdjson_inline static escaping copy_and_find(const uint8_t *src, uint8_t *dst); + + simdjson_inline bool has_escape() { return escape_bits != 0; } + simdjson_inline int escape_index() { return trailing_zeroes(escape_bits) / 4; } + + uint64_t escape_bits; +}; // struct escaping + +simdjson_inline escaping escaping::copy_and_find(const uint8_t *src, uint8_t *dst) { + static_assert(SIMDJSON_PADDING >= (BYTES_PROCESSED - 1), "escaping finder must process fewer than SIMDJSON_PADDING bytes"); + simd8 v(src); + v.store(dst); + return { ((v == '"') | (v == '\\') | (v == 32)).to_bitmask() }; +} + + +} // unnamed namespace +} // namespace rvv_vls +} // namespace simdjson + +#endif // SIMDJSON_RVV_VLS_STRINGPARSING_DEFS_H diff --git a/include/simdjson/westmere/simd.h b/include/simdjson/westmere/simd.h index 28329d964..d6605eaa6 100644 --- a/include/simdjson/westmere/simd.h +++ b/include/simdjson/westmere/simd.h @@ -265,6 +265,7 @@ namespace simd { static constexpr int NUM_CHUNKS = 64 / sizeof(simd8); static_assert(NUM_CHUNKS == 4, "Westmere kernel should use four registers per 64-byte block."); const simd8 chunks[NUM_CHUNKS]; + template simd8 get() const { return idx < NUM_CHUNKS ? chunks[idx] : simd8(); } simd8x64(const simd8x64& o) = delete; // no copy allowed simd8x64& operator=(const simd8& other) = delete; // no assignment allowed diff --git a/singleheader/amalgamate.py b/singleheader/amalgamate.py index 978f01be4..b50eab34a 100755 --- a/singleheader/amalgamate.py +++ b/singleheader/amalgamate.py @@ -108,7 +108,7 @@ else: RelativeRoot = str # Literal['src','include'] # Literal not supported in Python 3.7 (CI) RELATIVE_ROOTS: List[RelativeRoot] = ['src', 'include' ] Implementation = str # Literal['arm64', 'fallback', 'haswell', 'icelake', 'ppc64', 'westmere', 'lsx', 'lasx'] # Literal not supported in Python 3.7 (CI) -IMPLEMENTATIONS: List[Implementation] = [ 'arm64', 'haswell', 'icelake', 'lasx', 'lsx', 'ppc64', 'westmere', 'fallback' ] +IMPLEMENTATIONS: List[Implementation] = [ 'arm64', 'haswell', 'icelake', 'lasx', 'lsx', 'ppc64', 'rvv-vls', 'westmere', 'fallback' ] GENERIC_INCLUDE = "simdjson/generic" GENERIC_SRC = "generic" BUILTIN = "simdjson/builtin" diff --git a/src/generic/dom_parser_implementation.h b/src/generic/dom_parser_implementation.h index 20f7813fc..2e31fc547 100644 --- a/src/generic/dom_parser_implementation.h +++ b/src/generic/dom_parser_implementation.h @@ -18,4 +18,4 @@ simdjson_inline bool is_ascii(const simd8x64& input); } // namespace SIMDJSON_IMPLEMENTATION } // namespace simdjson -#endif // SIMDJSON_SRC_GENERIC_DOM_PARSER_IMPLEMENTATION_H \ No newline at end of file +#endif // SIMDJSON_SRC_GENERIC_DOM_PARSER_IMPLEMENTATION_H diff --git a/src/generic/stage1/utf8_lookup4_algorithm.h b/src/generic/stage1/utf8_lookup4_algorithm.h index 0a6246ce1..99d5db28d 100644 --- a/src/generic/stage1/utf8_lookup4_algorithm.h +++ b/src/generic/stage1/utf8_lookup4_algorithm.h @@ -119,7 +119,7 @@ using namespace simd; simdjson_inline simd8 is_incomplete(const simd8 input) { // If the previous input's last 3 bytes match this, they're too short (they ended at EOF): // ... 1111____ 111_____ 11______ -#if SIMDJSON_IMPLEMENTATION_ICELAKE +#if SIMDJSON_IMPLEMENTATION_ICELAKE || (SIMDJSON_IMPLEMENTATION_RVV_VLS && __riscv_v_fixed_vlen >= 512) static const uint8_t max_array[64] = { 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, @@ -180,18 +180,18 @@ using namespace simd; || (simd8x64::NUM_CHUNKS == 4), "We support one, two or four chunks per 64-byte block."); SIMDJSON_IF_CONSTEXPR (simd8x64::NUM_CHUNKS == 1) { - this->check_utf8_bytes(input.chunks[0], this->prev_input_block); + this->check_utf8_bytes(input.get<0>(), this->prev_input_block); } else SIMDJSON_IF_CONSTEXPR (simd8x64::NUM_CHUNKS == 2) { - this->check_utf8_bytes(input.chunks[0], this->prev_input_block); - this->check_utf8_bytes(input.chunks[1], input.chunks[0]); + this->check_utf8_bytes(input.get<0>(), this->prev_input_block); + this->check_utf8_bytes(input.get<1>(), input.get<0>()); } else SIMDJSON_IF_CONSTEXPR (simd8x64::NUM_CHUNKS == 4) { - this->check_utf8_bytes(input.chunks[0], this->prev_input_block); - this->check_utf8_bytes(input.chunks[1], input.chunks[0]); - this->check_utf8_bytes(input.chunks[2], input.chunks[1]); - this->check_utf8_bytes(input.chunks[3], input.chunks[2]); + this->check_utf8_bytes(input.get<0>(), this->prev_input_block); + this->check_utf8_bytes(input.get<1>(), input.get<0>()); + this->check_utf8_bytes(input.get<2>(), input.get<1>()); + this->check_utf8_bytes(input.get<3>(), input.get<2>()); } - this->prev_incomplete = is_incomplete(input.chunks[simd8x64::NUM_CHUNKS-1]); - this->prev_input_block = input.chunks[simd8x64::NUM_CHUNKS-1]; + this->prev_incomplete = is_incomplete(input.get::NUM_CHUNKS-1>()); + this->prev_input_block = input.get::NUM_CHUNKS-1>(); } } // do not forget to call check_eof! @@ -206,4 +206,4 @@ using namespace simd; } // namespace SIMDJSON_IMPLEMENTATION } // namespace simdjson -#endif // SIMDJSON_SRC_GENERIC_STAGE1_UTF8_LOOKUP4_ALGORITHM_H \ No newline at end of file +#endif // SIMDJSON_SRC_GENERIC_STAGE1_UTF8_LOOKUP4_ALGORITHM_H diff --git a/src/implementation.cpp b/src/implementation.cpp index 09f5f369e..2c044e69d 100644 --- a/src/implementation.cpp +++ b/src/implementation.cpp @@ -118,6 +118,17 @@ static const simdjson::lsx::implementation* get_lsx_singleton() { } // namespace simdjson #endif // SIMDJSON_IMPLEMENTATION_LSX +#if SIMDJSON_IMPLEMENTATION_RVV_VLS +#include +namespace simdjson { +namespace internal { +static const simdjson::rvv_vls::implementation* get_rvv_vls_singleton() { + static const simdjson::rvv_vls::implementation rvv_vls_singleton{}; + return &rvv_vls_singleton; +} +} // namespace internal +} // namespace simdjson +#endif // SIMDJSON_IMPLEMENTATION_RVV_VLS #undef SIMDJSON_CONDITIONAL_INCLUDE @@ -131,7 +142,7 @@ namespace internal { + SIMDJSON_IMPLEMENTATION_HASWELL + SIMDJSON_IMPLEMENTATION_WESTMERE \ + SIMDJSON_IMPLEMENTATION_ARM64 + SIMDJSON_IMPLEMENTATION_PPC64 \ + SIMDJSON_IMPLEMENTATION_LSX + SIMDJSON_IMPLEMENTATION_LASX \ - + SIMDJSON_IMPLEMENTATION_FALLBACK == 1) + + SIMDJSON_IMPLEMENTATION_RVV_VLS + SIMDJSON_IMPLEMENTATION_FALLBACK == 1) #if SIMDJSON_SINGLE_IMPLEMENTATION static const implementation* get_single_implementation() { @@ -157,6 +168,9 @@ namespace internal { #if SIMDJSON_IMPLEMENTATION_LASX get_lasx_singleton(); #endif +#if SIMDJSON_IMPLEMENTATION_RVV_VLS + get_rvv_vls_singleton(); +#endif #if SIMDJSON_IMPLEMENTATION_FALLBACK get_fallback_singleton(); #endif @@ -217,6 +231,9 @@ static const std::initializer_list& get_available_implem #if SIMDJSON_IMPLEMENTATION_LSX get_lsx_singleton(), #endif +#if SIMDJSON_IMPLEMENTATION_RVV_VLS + get_rvv_vls_singleton(), +#endif #if SIMDJSON_IMPLEMENTATION_FALLBACK get_fallback_singleton(), #endif diff --git a/src/internal/isadetection.h b/src/internal/isadetection.h index f8c4a5be9..19e09d2b9 100644 --- a/src/internal/isadetection.h +++ b/src/internal/isadetection.h @@ -239,6 +239,16 @@ static inline uint32_t detect_supported_architectures() { return host_isa; } +#elif SIMDJSON_IS_RISCV64 + +static inline uint32_t detect_supported_architectures() { + uint32_t host_isa = instruction_set::DEFAULT; +#if SIMDJSON_IS_RVV_VLS + host_isa |= instruction_set::RVV_VLS; +#endif + return host_isa; +} + #else // fallback diff --git a/src/rvv-vls.cpp b/src/rvv-vls.cpp new file mode 100644 index 000000000..f603be5b4 --- /dev/null +++ b/src/rvv-vls.cpp @@ -0,0 +1,132 @@ +#ifndef SIMDJSON_SRC_RVV_VLS_CPP +#define SIMDJSON_SRC_RVV_VLS_CPP + +#ifndef SIMDJSON_CONDITIONAL_INCLUDE +#include +#endif // SIMDJSON_CONDITIONAL_INCLUDE + +#include +#include + +#include +#include +#include +#include +#include + +// +// Stage 1 +// +namespace simdjson { +namespace rvv_vls { + +simdjson_warn_unused error_code implementation::create_dom_parser_implementation( + size_t capacity, + size_t max_depth, + std::unique_ptr& dst +) const noexcept { + dst.reset( new (std::nothrow) dom_parser_implementation() ); + if (!dst) { return MEMALLOC; } + if (auto err = dst->set_capacity(capacity)) + return err; + if (auto err = dst->set_max_depth(max_depth)) + return err; + return SUCCESS; +} + +namespace { + +using namespace simd; + +simdjson_inline json_character_block json_character_block::classify(const simd::simd8x64& in) { + static const uint8_t wsTable[16] = { ' ', 100, 100, 100, 17, 100, 113, 2, 100, '\t', '\n', 112, 100, '\r', 100, 100 }; + static const uint8_t opTable[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ':', '{', ',', '}', 0, 0 }; + vuint8_t vws = __riscv_vle8_v_u8m1(wsTable, 16); + vuint8_t vop = __riscv_vle8_v_u8m1(opTable, 16); + vuint8x64_t lo = __riscv_vand(in, 15, 64); + vuint8x64_t curl = __riscv_vor(in, 0x20, 64); + +#if __riscv_v_fixed_vlen == 128 + vboolx64_t mws = __riscv_vmseq(simdutf_vrgather_u8m1x4(vws, lo), in, 64); + vboolx64_t mop = __riscv_vmseq(simdutf_vrgather_u8m1x4(vop, lo), curl, 64); +#elif __riscv_v_fixed_vlen == 256 + vboolx64_t mws = __riscv_vmseq(simdutf_vrgather_u8m1x2(vws, lo), in, 64); + vboolx64_t mop = __riscv_vmseq(simdutf_vrgather_u8m1x2(vop, lo), curl, 64); +#else + vboolx64_t mws = __riscv_vmseq(__riscv_vrgather(vws, lo, 64), in, 64); + vboolx64_t mop = __riscv_vmseq(__riscv_vrgather(vop, lo, 64), curl, 64); +#endif + + return { + __riscv_vmv_x(__riscv_vreinterpret_u64m1(mws)), + __riscv_vmv_x(__riscv_vreinterpret_u64m1(mop)) + }; +} + +simdjson_inline bool is_ascii(const simd8x64& input) { + return input.is_ascii(); +} + +simdjson_inline simd8 must_be_2_3_continuation(const simd8 prev2, const simd8 prev3) { + simd8 is_third_byte = prev2.saturating_sub(0xe0u-0x80); // Only 111_____ will be >= 0x80 + simd8 is_fourth_byte = prev3.saturating_sub(0xf0u-0x80); // Only 1111____ will be >= 0x80 + return is_third_byte | is_fourth_byte; +} + +} // unnamed namespace +} // namespace rvv_vls +} // namespace simdjson + +// +// Stage 2 +// + +// +// Implementation-specific overrides +// +namespace simdjson { +namespace rvv_vls { + +simdjson_warn_unused error_code implementation::minify(const uint8_t *buf, size_t len, uint8_t *dst, size_t &dst_len) const noexcept { + return rvv_vls::stage1::json_minifier::minify<64>(buf, len, dst, dst_len); +} + +simdjson_warn_unused error_code dom_parser_implementation::stage1(const uint8_t *_buf, size_t _len, stage1_mode streaming) noexcept { + this->buf = _buf; + this->len = _len; + return rvv_vls::stage1::json_structural_indexer::index<64>(buf, len, *this, streaming); +} + +simdjson_warn_unused bool implementation::validate_utf8(const char *buf, size_t len) const noexcept { + return rvv_vls::stage1::generic_validate_utf8(buf,len); +} + +simdjson_warn_unused error_code dom_parser_implementation::stage2(dom::document &_doc) noexcept { + return stage2::tape_builder::parse_document(*this, _doc); +} + +simdjson_warn_unused error_code dom_parser_implementation::stage2_next(dom::document &_doc) noexcept { + return stage2::tape_builder::parse_document(*this, _doc); +} + +SIMDJSON_NO_SANITIZE_MEMORY +simdjson_warn_unused uint8_t *dom_parser_implementation::parse_string(const uint8_t *src, uint8_t *dst, bool allow_replacement) const noexcept { + return rvv_vls::stringparsing::parse_string(src, dst, allow_replacement); +} + +simdjson_warn_unused uint8_t *dom_parser_implementation::parse_wobbly_string(const uint8_t *src, uint8_t *dst) const noexcept { + return rvv_vls::stringparsing::parse_wobbly_string(src, dst); +} + +simdjson_warn_unused error_code dom_parser_implementation::parse(const uint8_t *_buf, size_t _len, dom::document &_doc) noexcept { + auto error = stage1(_buf, _len, stage1_mode::regular); + if (error) { return error; } + return stage2(_doc); +} + +} // namespace rvv_vls +} // namespace simdjson + +#include + +#endif // SIMDJSON_SRC_RVV_VLS_CPP diff --git a/src/simdjson.cpp b/src/simdjson.cpp index 2ea7d46ad..7ab5ac67e 100644 --- a/src/simdjson.cpp +++ b/src/simdjson.cpp @@ -41,6 +41,9 @@ SIMDJSON_PUSH_DISABLE_UNUSED_WARNINGS #if SIMDJSON_IMPLEMENTATION_LSX #include #endif +#if SIMDJSON_IMPLEMENTATION_RVV_VLS +#include +#endif #if SIMDJSON_IMPLEMENTATION_FALLBACK #include #endif diff --git a/tests/dom/CMakeLists.txt b/tests/dom/CMakeLists.txt index 040eef034..5534658b7 100644 --- a/tests/dom/CMakeLists.txt +++ b/tests/dom/CMakeLists.txt @@ -79,7 +79,7 @@ if (BASH AND (NOT WIN32) AND SIMDJSON_BASH AND (TARGET json2json)) # The scripts $ ) endif() - if(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL x86_64 OR CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL amd64) + if((CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL x86_64 OR CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL amd64) AND NOT DEFINED CMAKE_CROSSCOMPILING_EMULATOR) add_test( NAME simdjson_force_implementation_error COMMAND